# 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.1127 # drivers/char/rio/riointr.c 1.4 -> 1.5 # drivers/video/tcx.c 1.1 -> 1.4 # 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/ia64/kernel/fsys.S 1.5 -> 1.9 # 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 # arch/i386/mm/fault.c 1.23 -> 1.24 # drivers/block/cciss.h 1.18 -> 1.19 # drivers/scsi/scsi_error.c 1.38 -> 1.40 # include/asm-ia64/topology.h 1.6 -> 1.7 # 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 # 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 # include/linux/jiffies.h 1.7 -> 1.8 # drivers/pci/quirks.c 1.23 -> 1.24 # net/ipv4/xfrm_input.c 1.4 -> 1.5 # 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/init.h 1.24 -> 1.25 # 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 # net/llc/llc_conn.c 1.23 -> 1.24 # arch/i386/oprofile/op_model_p4.c 1.2 -> 1.3 # 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 # arch/ia64/ia32/ia32_support.c 1.6 -> 1.7 # arch/arm/mach-sa1100/cpu-sa1100.c 1.13 -> 1.15 # include/asm-arm/posix_types.h 1.1 -> 1.2 # 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 # include/linux/netfilter_bridge/ebt_mark_t.h 1.1 -> 1.2 # kernel/fork.c 1.111 -> 1.112 # include/linux/sched.h 1.136 -> 1.137 # include/asm-ia64/machvec_hpzx1.h 1.4 -> 1.5 # Makefile 1.392 -> 1.394 # drivers/cpufreq/userspace.c 1.1 -> 1.2 # net/bridge/netfilter/ebt_log.c 1.2 -> 1.3 # include/asm-ia64/unistd.h 1.23 -> 1.25 # 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 # drivers/s390/char/sclp_tty.c 1.4 -> 1.5 # include/asm-i386/bug.h 1.1 -> 1.2 # arch/ia64/kernel/ivt.S 1.13 -> 1.14 # include/linux/elf.h 1.19 -> 1.20 # net/ax25/ax25_in.c 1.8 -> 1.9 # net/ipx/af_ipx.c 1.23 -> 1.24 # 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 # arch/ia64/kernel/time.c 1.13.1.1 -> 1.16 # net/ipv6/netfilter/ip6t_frag.c 1.1 -> 1.2 # fs/cifs/cifssmb.c 1.9 -> 1.11 # include/asm-ppc/pgtable.h 1.19 -> 1.20 # include/net/ip6_route.h 1.4 -> 1.5 # arch/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 # arch/um/drivers/stdio_console.c 1.7 -> 1.8 # net/x25/x25_subr.c 1.8 -> 1.9 # 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 # 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/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 # drivers/video/cg6.c 1.1 -> 1.4 # include/asm-ia64/machvec_dig.h 1.2 -> 1.3 # drivers/char/rio/rioinit.c 1.4 -> 1.5 # drivers/serial/clps711x.c 1.13 -> 1.14 # fs/cifs/transport.c 1.5 -> 1.6 # 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 # arch/i386/kernel/io_apic.c 1.52 -> 1.54 # drivers/hotplug/acpiphp_glue.c 1.7 -> 1.8 # arch/mips/vmlinux.lds.S 1.7 -> 1.8 # 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/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 # 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 # 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 # arch/arm/kernel/bios32.c 1.17 -> 1.18 # 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/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 # 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.40 # drivers/usb/serial/pl2303.c 1.35 -> 1.36 # 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/usb/core/hub.c 1.56 -> 1.57 # 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 # arch/arm/mach-integrator/cpu.c 1.13 -> 1.15 # 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.14 # 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 # 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 # 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/ia64/mm/hugetlbpage.c 1.9 -> 1.10 # 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 # include/asm-alpha/core_cia.h 1.5 -> 1.6 # arch/arm/Kconfig 1.9 -> 1.11 # 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 # drivers/net/mac8390.c 1.10 -> 1.11 # drivers/usb/serial/pl2303.h 1.7 -> 1.8 # include/asm-ia64/machvec_hpsim.h 1.2 -> 1.3 # fs/cifs/cifsfs.c 1.7 -> 1.9 # mm/mremap.c 1.28 -> 1.29 # 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 # include/asm-ia64/perfmon.h 1.11 -> 1.12 # fs/intermezzo/replicator.c 1.3 -> 1.4 # 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 # 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 # 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 # 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 # 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 # mm/mmap.c 1.72 -> 1.73 # include/linux/netfilter_bridge/ebt_redirect.h 1.1 -> 1.2 # 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 # include/linux/if_wanpipe_common.h 1.3 -> 1.4 # net/rose/rose_timer.c 1.7 -> 1.8 # init/do_mounts.h 1.3 -> 1.4 # include/linux/wanpipe.h 1.5 -> 1.6 # drivers/net/sk_mca.c 1.8 -> 1.9 # include/asm-ia64/ptrace.h 1.8 -> 1.9 # drivers/net/sk98lin/h/skgepnm2.h 1.2 -> 1.3 # arch/arm/mach-sa1100/generic.h 1.5 -> 1.6 # include/asm-ia64/machvec_sn1.h 1.5 -> 1.6 # net/packet/af_packet.c 1.18 -> 1.19 # 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/oprofile/oprofile_stats.c 1.2 -> 1.3 # drivers/s390/char/con3215.c 1.12 -> 1.13 # net/ax25/ax25_ds_in.c 1.4 -> 1.5 # drivers/net/wan/sdla_x25.c 1.20 -> 1.21 # 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/usb/host/ohci-pci.c 1.9 -> 1.10 # drivers/net/shaper.c 1.12 -> 1.13 # 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 # 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 # net/ipv6/route.c 1.19 -> 1.21 # drivers/serial/21285.c 1.14 -> 1.15 # net/ipv4/tcp_input.c 1.33 -> 1.34 # 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 # arch/arm/kernel/ecard.c 1.20 -> 1.21 # fs/filesystems.c 1.11 -> 1.12 # drivers/scsi/scsi_scan.c 1.63 -> 1.64 # 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.167 # drivers/media/video/planb.c 1.12 -> 1.13 # arch/ia64/kernel/sigframe.h 1.3 -> 1.4 # include/asm-i386/pgtable-3level.h 1.10 -> 1.11 # scripts/Makefile.build 1.31 -> 1.32 # arch/ia64/kernel/gate.S 1.13 -> 1.14 # net/ipv6/netfilter/ip6t_hbh.c 1.1 -> 1.2 # drivers/ide/ide-io.c 1.3 -> 1.4 # drivers/s390/char/tuball.c 1.8 -> 1.9 # net/bridge/netfilter/ebt_redirect.c 1.1 -> 1.2 # 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/acorn/net/etherh.c 1.12 -> 1.13 # arch/sparc64/Kconfig 1.14 -> 1.15 # arch/ia64/kernel/irq.c 1.18 -> 1.19 # 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 # fs/hugetlbfs/inode.c 1.21 -> 1.22 # net/bridge/netfilter/ebtable_filter.c 1.2 -> 1.3 # 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/pci/Makefile 1.23 -> 1.24 # arch/arm/common/sa1111.c 1.22 -> 1.23 # 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 # include/net/dst.h 1.10 -> 1.11 # 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 # fs/locks.c 1.37 -> 1.38 # drivers/char/rio/riotable.c 1.7 -> 1.8 # drivers/oprofile/cpu_buffer.h 1.3 -> 1.4 # arch/ia64/Kconfig 1.14 -> 1.17 # 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 # 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.75 # 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/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/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 # net/x25/x25_in.c 1.9 -> 1.10 # include/linux/if_wanpipe.h 1.3 -> 1.4 # net/ipv4/igmp.c 1.13 -> 1.14 # 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 # fs/inode.c 1.83 -> 1.84 # arch/ia64/kernel/smp.c 1.22 -> 1.23 # 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.48 # 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/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 # include/asm-ia64/thread_info.h 1.6 -> 1.8 # arch/arm/mach-sa1100/Makefile 1.24 -> 1.26 # net/ipv6/netfilter/ip6t_ipv6header.c 1.1 -> 1.2 # include/asm-arm/arch-sa1100/time.h 1.6 -> 1.7 # 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 # 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 # (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 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 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.18.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.18.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.126.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 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 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 torvalds@home.transmeta.com 1.1126 # Avoid warning due to missing return value # -------------------------------------------- # 03/03/07 torvalds@home.transmeta.com 1.1127 # Ignore initramfs cpio file # -------------------------------------------- # diff -Nru a/Documentation/ia64/fsys.txt b/Documentation/ia64/fsys.txt --- a/Documentation/ia64/fsys.txt Fri Mar 7 20:40:17 2003 +++ b/Documentation/ia64/fsys.txt Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/MAINTAINERS Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/Makefile Fri Mar 7 20:40:16 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/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c --- a/arch/alpha/kernel/core_marvel.c Fri Mar 7 20:40:16 2003 +++ b/arch/alpha/kernel/core_marvel.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/arch/alpha/kernel/core_titan.c Fri Mar 7 20:40:16 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/pci.c b/arch/alpha/kernel/pci.c --- a/arch/alpha/kernel/pci.c Fri Mar 7 20:40:16 2003 +++ b/arch/alpha/kernel/pci.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/arch/alpha/kernel/sys_nautilus.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/arch/alpha/mm/fault.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:17 2003 +++ b/arch/alpha/vmlinux.lds.S Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/arch/arm/Kconfig Fri Mar 7 20:40:17 2003 @@ -534,15 +534,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 Fri Mar 7 20:40:18 2003 +++ b/arch/arm/common/sa1111.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 2003 +++ b/arch/arm/kernel/Makefile Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:16 2003 +++ b/arch/arm/kernel/bios32.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:17 2003 +++ b/arch/arm/kernel/ecard.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/arch/arm/kernel/entry-armv.S Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/arch/arm/kernel/entry-common.S Fri Mar 7 20:40:16 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/pm.c b/arch/arm/kernel/pm.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/kernel/pm.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:17 2003 +++ b/arch/arm/kernel/time.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:18 2003 +++ b/arch/arm/mach-integrator/Makefile Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:17 2003 +++ b/arch/arm/mach-integrator/cpu.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:18 2003 +++ b/arch/arm/mach-sa1100/Kconfig Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 2003 +++ b/arch/arm/mach-sa1100/Makefile Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:16 2003 +++ b/arch/arm/mach-sa1100/cpu-sa1100.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/arch/arm/mach-sa1100/cpu-sa1110.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/arch/arm/mach-sa1100/generic.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:17 2003 +++ b/arch/arm/mach-sa1100/generic.h Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:18 2003 +++ b/arch/arm/mach-sa1100/irq.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:16 2003 +++ b/arch/arm/mach-sa1100/pm.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 2003 +++ b/arch/arm/mach-sa1100/system3.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:17 2003 +++ b/arch/arm/mm/fault-common.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/arch/arm/tools/mach-types Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:18 2003 +++ b/arch/arm/vmlinux-armo.lds.in Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:16 2003 +++ b/arch/arm/vmlinux-armv.lds.in Fri Mar 7 20:40:16 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/vmlinux.lds.S b/arch/cris/vmlinux.lds.S --- a/arch/cris/vmlinux.lds.S Fri Mar 7 20:40:17 2003 +++ b/arch/cris/vmlinux.lds.S Fri Mar 7 20:40:17 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/Makefile b/arch/i386/Makefile --- a/arch/i386/Makefile Fri Mar 7 20:40:16 2003 +++ b/arch/i386/Makefile Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/arch/i386/boot/Makefile Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:17 2003 +++ b/arch/i386/boot/bootsect.S Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:17 2003 +++ b/arch/i386/boot/tools/build.c Fri Mar 7 20:40:17 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/io_apic.c b/arch/i386/kernel/io_apic.c --- a/arch/i386/kernel/io_apic.c Fri Mar 7 20:40:16 2003 +++ b/arch/i386/kernel/io_apic.c Fri Mar 7 20:40:16 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; @@ -1566,7 +1583,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/mm/fault.c b/arch/i386/mm/fault.c --- a/arch/i386/mm/fault.c Fri Mar 7 20:40:16 2003 +++ b/arch/i386/mm/fault.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:17 2003 +++ b/arch/i386/mm/init.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/arch/i386/mm/ioremap.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:18 2003 +++ b/arch/i386/mm/pgtable.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 2003 +++ b/arch/i386/oprofile/nmi_int.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:16 2003 +++ b/arch/i386/oprofile/op_model_p4.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:18 2003 +++ b/arch/i386/pci/irq.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:16 2003 +++ b/arch/i386/vmlinux.lds.S Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:18 2003 +++ b/arch/ia64/Kconfig Fri Mar 7 20:40:18 2003 @@ -26,7 +26,7 @@ bool default y -config RWSEM_GENERIC_SPINLOCK +config RWSEM_XCHGADD_ALGORITHM bool default y @@ -424,6 +424,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 +886,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 Fri Mar 7 20:40:16 2003 +++ b/arch/ia64/Makefile Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:17 2003 +++ b/arch/ia64/hp/sim/simscsi.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/arch/ia64/hp/sim/simserial.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/arch/ia64/ia32/ia32_entry.S Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/arch/ia64/ia32/ia32_support.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:17 2003 +++ b/arch/ia64/ia32/sys_ia32.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/arch/ia64/kernel/acpi.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/arch/ia64/kernel/entry.S Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/arch/ia64/kernel/fsys.S Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:18 2003 +++ b/arch/ia64/kernel/gate.S Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 2003 +++ b/arch/ia64/kernel/init_task.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:17 2003 +++ b/arch/ia64/kernel/iosapic.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:18 2003 +++ b/arch/ia64/kernel/irq.c Fri Mar 7 20:40:18 2003 @@ -340,12 +340,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 Fri Mar 7 20:40:16 2003 +++ b/arch/ia64/kernel/ivt.S Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:17 2003 +++ b/arch/ia64/kernel/machvec.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/arch/ia64/kernel/mca.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/arch/ia64/kernel/palinfo.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:18 2003 +++ b/arch/ia64/kernel/perfmon.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:17 2003 +++ b/arch/ia64/kernel/process.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:18 2003 +++ b/arch/ia64/kernel/ptrace.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:16 2003 +++ b/arch/ia64/kernel/setup.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:18 2003 +++ b/arch/ia64/kernel/sigframe.h Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:17 2003 +++ b/arch/ia64/kernel/signal.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:18 2003 +++ b/arch/ia64/kernel/smp.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:17 2003 +++ b/arch/ia64/kernel/sys_ia64.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/arch/ia64/kernel/time.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:18 2003 +++ b/arch/ia64/kernel/unwind.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:17 2003 +++ b/arch/ia64/kernel/unwind_i.h Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:18 2003 +++ b/arch/ia64/mm/fault.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:17 2003 +++ b/arch/ia64/mm/hugetlbpage.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/arch/ia64/mm/tlb.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/arch/ia64/pci/pci.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/arch/ia64/sn/io/Makefile Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:16 2003 +++ b/arch/ia64/sn/kernel/mca.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/arch/ia64/sn/kernel/setup.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 2003 +++ b/arch/ia64/tools/print_offsets.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 2003 +++ b/arch/ia64/vmlinux.lds.S Fri Mar 7 20:40:18 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/vmlinux-std.lds b/arch/m68k/vmlinux-std.lds --- a/arch/m68k/vmlinux-std.lds Fri Mar 7 20:40:18 2003 +++ b/arch/m68k/vmlinux-std.lds Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:16 2003 +++ b/arch/m68k/vmlinux-sun3.lds Fri Mar 7 20:40:16 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/mips/arc/arc_con.c b/arch/mips/arc/arc_con.c --- a/arch/mips/arc/arc_con.c Fri Mar 7 20:40:18 2003 +++ b/arch/mips/arc/arc_con.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:16 2003 +++ b/arch/mips/au1000/common/serial.c Fri Mar 7 20:40:16 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/vmlinux.lds.S b/arch/mips/vmlinux.lds.S --- a/arch/mips/vmlinux.lds.S Fri Mar 7 20:40:16 2003 +++ b/arch/mips/vmlinux.lds.S Fri Mar 7 20:40:16 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/vmlinux.lds.S b/arch/mips64/vmlinux.lds.S --- a/arch/mips64/vmlinux.lds.S Fri Mar 7 20:40:17 2003 +++ b/arch/mips64/vmlinux.lds.S Fri Mar 7 20:40:17 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/vmlinux.lds.S b/arch/parisc/vmlinux.lds.S --- a/arch/parisc/vmlinux.lds.S Fri Mar 7 20:40:16 2003 +++ b/arch/parisc/vmlinux.lds.S Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:17 2003 +++ b/arch/ppc/8xx_io/uart.c Fri Mar 7 20:40:17 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/boot/simple/rw4/ppc_40x.h b/arch/ppc/boot/simple/rw4/ppc_40x.h --- a/arch/ppc/boot/simple/rw4/ppc_40x.h Fri Mar 7 20:40:16 2003 +++ b/arch/ppc/boot/simple/rw4/ppc_40x.h Fri Mar 7 20:40:16 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/vmlinux.lds.S b/arch/ppc/vmlinux.lds.S --- a/arch/ppc/vmlinux.lds.S Fri Mar 7 20:40:18 2003 +++ b/arch/ppc/vmlinux.lds.S Fri Mar 7 20:40:18 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/vmlinux.lds.S b/arch/ppc64/vmlinux.lds.S --- a/arch/ppc64/vmlinux.lds.S Fri Mar 7 20:40:17 2003 +++ b/arch/ppc64/vmlinux.lds.S Fri Mar 7 20:40:17 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/vmlinux.lds.S b/arch/s390/vmlinux.lds.S --- a/arch/s390/vmlinux.lds.S Fri Mar 7 20:40:16 2003 +++ b/arch/s390/vmlinux.lds.S Fri Mar 7 20:40:16 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/vmlinux.lds.S b/arch/s390x/vmlinux.lds.S --- a/arch/s390x/vmlinux.lds.S Fri Mar 7 20:40:16 2003 +++ b/arch/s390x/vmlinux.lds.S Fri Mar 7 20:40:16 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/vmlinux.lds.S b/arch/sh/vmlinux.lds.S --- a/arch/sh/vmlinux.lds.S Fri Mar 7 20:40:17 2003 +++ b/arch/sh/vmlinux.lds.S Fri Mar 7 20:40:17 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/vmlinux.lds.S b/arch/sparc/vmlinux.lds.S --- a/arch/sparc/vmlinux.lds.S Fri Mar 7 20:40:16 2003 +++ b/arch/sparc/vmlinux.lds.S Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:18 2003 +++ b/arch/sparc64/Kconfig Fri Mar 7 20:40:18 2003 @@ -151,9 +151,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/vmlinux.lds.S b/arch/sparc64/vmlinux.lds.S --- a/arch/sparc64/vmlinux.lds.S Fri Mar 7 20:40:18 2003 +++ b/arch/sparc64/vmlinux.lds.S Fri Mar 7 20:40:18 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/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c --- a/arch/um/drivers/stdio_console.c Fri Mar 7 20:40:16 2003 +++ b/arch/um/drivers/stdio_console.c Fri Mar 7 20:40:16 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/kernel/mem.c b/arch/um/kernel/mem.c --- a/arch/um/kernel/mem.c Fri Mar 7 20:40:16 2003 +++ b/arch/um/kernel/mem.c Fri Mar 7 20:40:16 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/x86_64/boot/Makefile b/arch/x86_64/boot/Makefile --- a/arch/x86_64/boot/Makefile Fri Mar 7 20:40:16 2003 +++ b/arch/x86_64/boot/Makefile Fri Mar 7 20:40:16 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/vmlinux.lds.S b/arch/x86_64/vmlinux.lds.S --- a/arch/x86_64/vmlinux.lds.S Fri Mar 7 20:40:16 2003 +++ b/arch/x86_64/vmlinux.lds.S Fri Mar 7 20:40:16 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/net/ether1.c b/drivers/acorn/net/ether1.c --- a/drivers/acorn/net/ether1.c Fri Mar 7 20:40:17 2003 +++ b/drivers/acorn/net/ether1.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/acorn/net/ether3.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/acorn/net/etherh.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/atm/firestream.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/base/platform.c Fri Mar 7 20:40:16 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/cciss.c b/drivers/block/cciss.c --- a/drivers/block/cciss.c Fri Mar 7 20:40:18 2003 +++ b/drivers/block/cciss.c Fri Mar 7 20:40:18 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; @@ -2155,6 +2155,20 @@ printk("address 0 = %x\n", c->paddr); #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); diff -Nru a/drivers/block/cciss.h b/drivers/block/cciss.h --- a/drivers/block/cciss.h Fri Mar 7 20:40:16 2003 +++ b/drivers/block/cciss.h Fri Mar 7 20:40:16 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/char/amiserial.c b/drivers/char/amiserial.c --- a/drivers/char/amiserial.c Fri Mar 7 20:40:18 2003 +++ b/drivers/char/amiserial.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/char/decserial.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/char/hvc_console.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/char/random.c Fri Mar 7 20:40:16 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/rio/rio_linux.c b/drivers/char/rio/rio_linux.c --- a/drivers/char/rio/rio_linux.c Fri Mar 7 20:40:17 2003 +++ b/drivers/char/rio/rio_linux.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/char/rio/rioboot.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/char/rio/riocmd.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/char/rio/rioctrl.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/char/rio/rioinit.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/char/rio/riointr.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/char/rio/rioparam.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/char/rio/rioroute.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/char/rio/riotable.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/char/rio/riotty.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/char/rtc.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/char/serial167.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/char/serial_tx3912.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/char/sh-sci.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/char/tty_io.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/char/vme_scc.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/char/vt.c Fri Mar 7 20:40:18 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/cpufreq/userspace.c b/drivers/cpufreq/userspace.c --- a/drivers/cpufreq/userspace.c Fri Mar 7 20:40:16 2003 +++ b/drivers/cpufreq/userspace.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/hotplug/acpiphp_glue.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/hotplug/cpci_hotplug_pci.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/hotplug/cpqphp_pci.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/hotplug/ibmphp_core.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/ide/Makefile Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/ide/ide-disk.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/ide/ide-dma.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/ide/ide-floppy.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/ide/ide-io.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/ide/ide-iops.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/ide/ide-lib.c Fri Mar 7 20:40:18 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-taskfile.c b/drivers/ide/ide-taskfile.c --- a/drivers/ide/ide-taskfile.c Fri Mar 7 20:40:16 2003 +++ b/drivers/ide/ide-taskfile.c Fri Mar 7 20:40:16 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/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c --- a/drivers/ide/pci/amd74xx.c Fri Mar 7 20:40:18 2003 +++ b/drivers/ide/pci/amd74xx.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/ide/pci/via82cxxx.c Fri Mar 7 20:40:16 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/macintosh/macserial.c b/drivers/macintosh/macserial.c --- a/drivers/macintosh/macserial.c Fri Mar 7 20:40:18 2003 +++ b/drivers/macintosh/macserial.c Fri Mar 7 20:40:18 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/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c --- a/drivers/media/video/bw-qcam.c Fri Mar 7 20:40:16 2003 +++ b/drivers/media/video/bw-qcam.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/media/video/planb.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/media/video/zoran.h Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/media/video/zr36120.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/message/fusion/lsi/mpi_raid.h Fri Mar 7 20:40:17 2003 @@ -184,7 +184,7 @@ /****************************************************************************/ -/* Mailbox reqeust structure */ +/* Mailbox request structure */ /****************************************************************************/ typedef struct _MSG_MAILBOX_REQUEST diff -Nru a/drivers/net/dgrs.c b/drivers/net/dgrs.c --- a/drivers/net/dgrs.c Fri Mar 7 20:40:16 2003 +++ b/drivers/net/dgrs.c Fri Mar 7 20:40:16 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/eth16i.c b/drivers/net/eth16i.c --- a/drivers/net/eth16i.c Fri Mar 7 20:40:18 2003 +++ b/drivers/net/eth16i.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/net/mac8390.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/net/pppoe.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/net/shaper.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/net/sis900.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/net/sk98lin/h/skgepnm2.h Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/net/sk_mca.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/net/wan/comx-hw-munich.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/net/wan/pc300_tty.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/net/wan/sdla_chdlc.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/net/wan/sdla_fr.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/net/wan/sdla_ft1.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/net/wan/sdla_ppp.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/net/wan/sdla_x25.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/net/wan/sdladrv.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/net/wan/sdlamain.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/net/wan/wanpipe_multppp.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/oprofile/buffer_sync.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/oprofile/cpu_buffer.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/oprofile/cpu_buffer.h Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/oprofile/oprofile_stats.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/parport/ieee1284.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/parport/ieee1284_ops.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/pci/Makefile Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/pci/probe.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/pci/quirks.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/pci/setup-bus.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/pci/setup-res.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/pcmcia/hd64465_ss.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/pcmcia/i82365.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/pcmcia/sa1100_generic.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/pcmcia/tcic.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/s390/block/dasd_3990_erp.c Fri Mar 7 20:40:18 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/char/con3215.c b/drivers/s390/char/con3215.c --- a/drivers/s390/char/con3215.c Fri Mar 7 20:40:17 2003 +++ b/drivers/s390/char/con3215.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/s390/char/sclp_con.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/s390/char/sclp_tty.c Fri Mar 7 20:40:16 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/tuball.c b/drivers/s390/char/tuball.c --- a/drivers/s390/char/tuball.c Fri Mar 7 20:40:18 2003 +++ b/drivers/s390/char/tuball.c Fri Mar 7 20:40:18 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/scsi/aic7xxx/aicasm/Makefile b/drivers/scsi/aic7xxx/aicasm/Makefile --- a/drivers/scsi/aic7xxx/aicasm/Makefile Fri Mar 7 20:40:18 2003 +++ b/drivers/scsi/aic7xxx/aicasm/Makefile Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/scsi/i91uscsi.h Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/scsi/imm.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/scsi/inia100.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/scsi/inia100.h Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/scsi/qlogicfc.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/scsi/scsi.h Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/scsi/scsi_error.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/scsi/scsi_scan.c Fri Mar 7 20:40:17 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/serial/21285.c b/drivers/serial/21285.c --- a/drivers/serial/21285.c Fri Mar 7 20:40:17 2003 +++ b/drivers/serial/21285.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/serial/68328serial.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/serial/8250.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/serial/amba.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/serial/anakin.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/serial/clps711x.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/serial/core.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/serial/mcfserial.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/serial/sa1100.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/serial/uart00.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/sgi/char/sgiserial.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/usb/class/usb-midi.h Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/usb/core/hub.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/usb/core/message.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/usb/core/urb.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/usb/core/usb.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/usb/host/ohci-pci.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/usb/serial/io_edgeport.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/usb/serial/pl2303.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/usb/serial/pl2303.h Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/usb/serial/usb-serial.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/usb/serial/visor.c Fri Mar 7 20:40:16 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/usb/storage/transport.c Fri Mar 7 20:40:16 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/bw2.c b/drivers/video/bw2.c --- a/drivers/video/bw2.c Fri Mar 7 20:40:17 2003 +++ b/drivers/video/bw2.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:18 2003 +++ b/drivers/video/cg14.c Fri Mar 7 20:40:18 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 Fri Mar 7 20:40:17 2003 +++ b/drivers/video/cg3.c Fri Mar 7 20:40:17 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 Fri Mar 7 20:40:16 2003 +++ b/drivers/video/cg6.c Fri Mar 7 20:40:16 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/ffb.c b/drivers/video/ffb.c --- a/drivers/video/ffb.c Fri Mar 7 20:40:18 2003 +++ b/drivers/video/ffb.c Fri Mar 7 20:40:18 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/p9100.c b/drivers/video/p9100.c --- a/drivers/video/p9100.c Fri Mar 7 20:40:17 2003 +++ b/drivers/video/p9100.c Fri Mar 7 20:40:17 2003 @@ -27,13 +27,13 @@ * Local functions. */ -static int p9100_check_var(struct fb_var_screeninfo *, struct fb_info *); -static int p9100_set_par(struct fb_info *); static int p9100_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int p9100_blank(int, struct fb_info *); static int p9100_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int p9100_ioctl(struct inode *, struct file *, unsigned int, + unsigned long, struct fb_info *); /* * Frame buffer operations @@ -41,14 +41,13 @@ static struct fb_ops p9100_ops = { .owner = THIS_MODULE, - .fb_check_var = p9100_check_var, - .fb_set_par = p9100_set_par, .fb_setcolreg = p9100_setcolreg, .fb_blank = p9100_blank, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_mmap = p9100_mmap, + .fb_ioctl = p9100_ioctl, .fb_cursor = soft_cursor, }; @@ -143,39 +142,6 @@ }; /** - * p9100_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 p9100_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; -} - -/** - * p9100_set_par - Optional function. Alters the hardware state. - * @info: frame buffer structure that represents a single frame buffer - */ -static int -p9100_set_par(struct fb_info *info) -{ - return 0; -} - -/** * p9100_setcolreg - Optional function. Sets a color register. * @regno: boolean, 0 copy local, 1 get_user() function * @red: frame buffer colormap structure @@ -265,6 +231,16 @@ vma); } +static int p9100_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) +{ + struct p9100_par *par = (struct p9100_par *) info->par; + + /* Make it look like a cg3. */ + return sbusfb_ioctl_helper(cmd, arg, info, + FBTYPE_SUN3COLOR, 8, par->fbsize); +} + /* * Initialisation */ @@ -344,7 +320,6 @@ return; } - p9100_set_par(&all->info); p9100_init_fix(&all->info, linebytes); if (register_framebuffer(&all->info) < 0) { diff -Nru a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c --- a/drivers/video/sa1100fb.c Fri Mar 7 20:40:16 2003 +++ b/drivers/video/sa1100fb.c Fri Mar 7 20:40:16 2003 @@ -1590,11 +1590,21 @@ struct sa1100fb_info *fbi = TO_INF(nb, freq_policy); struct cpufreq_policy *policy = data; - if (val == CPUFREQ_INCOMPATIBLE) { + switch (val) { + case CPUFREQ_ADJUST: + case CPUFREQ_INCOMPATIBLE: printk(KERN_DEBUG "min dma period: %d ps, " "new clock %d kHz\n", sa1100fb_min_dma_period(fbi), policy->max); /* todo: fill in min/max values */ + break; + case CPUFREQ_NOTIFY: + do {} while(0); + /* todo: panic if min/max values aren't fulfilled + * [can't really happen unless there's a bug in the + * CPU policy verififcation process * + */ + break; } return 0; } diff -Nru a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c --- a/drivers/video/sbuslib.c Fri Mar 7 20:40:16 2003 +++ b/drivers/video/sbuslib.c Fri Mar 7 20:40:16 2003 @@ -9,6 +9,7 @@ #include #include +#include #include "sbuslib.h" @@ -83,3 +84,84 @@ return 0; } +EXPORT_SYMBOL(sbusfb_mmap_helper); + +int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg, + struct fb_info *info, + int type, int fb_depth, unsigned long fb_size) +{ + switch(cmd) { + case FBIOGTYPE: { + struct fbtype *f = (struct fbtype *) arg; + + if (put_user(type, &f->fb_type) || + __put_user(info->var.yres, &f->fb_height) || + __put_user(info->var.xres, &f->fb_width) || + __put_user(fb_depth, &f->fb_depth) || + __put_user(0, &f->fb_cmsize) || + __put_user(fb_size, &f->fb_cmsize)) + return -EFAULT; + return 0; + } + case FBIOPUTCMAP_SPARC: { + struct fbcmap *c = (struct fbcmap *) arg; + struct fb_cmap cmap; + u16 red, green, blue; + unsigned char *ured, *ugreen, *ublue; + int index, count, i; + + if (get_user(index, &c->index) || + __get_user(count, &c->count) || + __get_user(ured, &c->red) || + __get_user(ugreen, &c->green) || + __get_user(ublue, &c->blue)) + return -EFAULT; + + cmap.len = 1; + cmap.red = &red; + cmap.green = &green; + cmap.blue = &blue; + for (i = 0; i < count; i++) { + int err; + + if (get_user(red, &ured[i]) || + get_user(green, &ugreen[i]) || + get_user(blue, &ublue[i])) + return -EFAULT; + + cmap.start = index + i; + err = fb_set_cmap(&cmap, 0, info); + if (err) + return err; + } + return 0; + } + case FBIOGETCMAP_SPARC: { + struct fbcmap *c = (struct fbcmap *) arg; + unsigned char *ured, *ugreen, *ublue; + struct fb_cmap *cmap = &info->cmap; + int index, count, i; + + if (get_user(index, &c->index) || + __get_user(count, &c->count) || + __get_user(ured, &c->red) || + __get_user(ugreen, &c->green) || + __get_user(ublue, &c->blue)) + return -EFAULT; + + if (index + count > cmap->len) + return -EINVAL; + + for (i = 0; i < count; i++) { + if (put_user(cmap->red[index + i], &ured[i]) || + put_user(cmap->green[index + i], &ugreen[i]) || + put_user(cmap->blue[index + i], &ublue[i])) + return -EFAULT; + } + return 0; + } + default: + return -EINVAL; + }; +} +EXPORT_SYMBOL(sbusfb_ioctl_helper); diff -Nru a/drivers/video/sbuslib.h b/drivers/video/sbuslib.h --- a/drivers/video/sbuslib.h Fri Mar 7 20:40:16 2003 +++ b/drivers/video/sbuslib.h Fri Mar 7 20:40:16 2003 @@ -17,5 +17,8 @@ unsigned long physbase, unsigned long fbsize, unsigned long iospace, struct vm_area_struct *vma); +int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg, + struct fb_info *info, + int type, int fb_depth, unsigned long fb_size); #endif /* _SBUSLIB_H */ diff -Nru a/drivers/video/tcx.c b/drivers/video/tcx.c --- a/drivers/video/tcx.c Fri Mar 7 20:40:16 2003 +++ b/drivers/video/tcx.c Fri Mar 7 20:40:16 2003 @@ -29,13 +29,13 @@ * Local functions. */ -static int tcx_check_var(struct fb_var_screeninfo *, struct fb_info *); -static int tcx_set_par(struct fb_info *); static int tcx_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int tcx_blank(int, struct fb_info *); static int tcx_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int tcx_ioctl(struct inode *, struct file *, unsigned int, + unsigned long, struct fb_info *); /* * Frame buffer operations @@ -43,14 +43,13 @@ static struct fb_ops tcx_ops = { .owner = THIS_MODULE, - .fb_check_var = tcx_check_var, - .fb_set_par = tcx_set_par, .fb_setcolreg = tcx_setcolreg, .fb_blank = tcx_blank, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_mmap = tcx_mmap, + .fb_ioctl = tcx_ioctl, .fb_cursor = soft_cursor, }; @@ -155,39 +154,6 @@ } /** - * tcx_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 tcx_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; -} - -/** - * tcx_set_par - Optional function. Alters the hardware state. - * @info: frame buffer structure that represents a single frame buffer - */ -static int -tcx_set_par(struct fb_info *info) -{ - return 0; -} - -/** * tcx_setcolreg - Optional function. Sets a color register. * @regno: boolean, 0 copy local, 1 get_user() function * @red: frame buffer colormap structure @@ -298,6 +264,17 @@ vma); } +static int tcx_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) +{ + struct tcx_par *par = (struct tcx_par *) info->par; + + return sbusfb_ioctl_helper(cmd, arg, info, + FBTYPE_TCXCOLOR, + (par->lowdepth ? 8 : 24), + par->fbsize); +} + /* * Initialisation */ @@ -431,7 +408,6 @@ return; } - tcx_set_par(&all->info); tcx_init_fix(&all->info, linebytes); if (register_framebuffer(&all->info) < 0) { diff -Nru a/fs/aio.c b/fs/aio.c --- a/fs/aio.c Fri Mar 7 20:40:17 2003 +++ b/fs/aio.c Fri Mar 7 20:40:17 2003 @@ -76,7 +76,7 @@ aio_wq = create_workqueue("aio"); - printk(KERN_NOTICE "aio_setup: sizeof(struct page) = %d\n", (int)sizeof(struct page)); + pr_debug("aio_setup: sizeof(struct page) = %d\n", (int)sizeof(struct page)); return 0; } @@ -1193,7 +1193,7 @@ if (NULL != cancel) { struct io_event tmp; - printk("calling cancel\n"); + pr_debug("calling cancel\n"); memset(&tmp, 0, sizeof(tmp)); tmp.obj = (u64)(unsigned long)kiocb->ki_user_obj; tmp.data = kiocb->ki_user_data; diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c --- a/fs/binfmt_elf.c Fri Mar 7 20:40:17 2003 +++ b/fs/binfmt_elf.c Fri Mar 7 20:40:17 2003 @@ -10,7 +10,7 @@ */ #include - +#include #include #include #include @@ -256,8 +256,8 @@ #ifndef elf_map -static inline unsigned long -elf_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type) +static unsigned long elf_map(struct file *filep, unsigned long addr, + struct elf_phdr *eppnt, int prot, int type) { unsigned long map_addr; @@ -934,7 +934,7 @@ * * I think we should skip something. But I am not sure how. H.J. */ -static inline int maydump(struct vm_area_struct *vma) +static int maydump(struct vm_area_struct *vma) { /* * If we may not read the contents, don't allow us to dump @@ -1046,7 +1046,7 @@ return; } -static inline void fill_note(struct memelfnote *note, const char *name, int type, +static void fill_note(struct memelfnote *note, const char *name, int type, unsigned int sz, void *data) { note->name = name; @@ -1060,7 +1060,8 @@ * fill up all the fields in prstatus from the given task struct, except registers * which need to be filled up separately. */ -static inline void fill_prstatus(struct elf_prstatus *prstatus, struct task_struct *p, long signr) +static void fill_prstatus(struct elf_prstatus *prstatus, + struct task_struct *p, long signr) { prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; prstatus->pr_sigpend = p->pending.signal.sig[0]; @@ -1075,7 +1076,7 @@ jiffies_to_timeval(p->cstime, &prstatus->pr_cstime); } -static inline void fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p) +static void fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p) { int i, len; @@ -1175,41 +1176,64 @@ */ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) { +#define NUM_NOTES 5 int has_dumped = 0; mm_segment_t fs; int segs; size_t size = 0; int i; struct vm_area_struct *vma; - struct elfhdr elf; + struct elfhdr *elf = NULL; off_t offset = 0, dataoff; unsigned long limit = current->rlim[RLIMIT_CORE].rlim_cur; - int numnote = 5; - struct memelfnote notes[5]; - struct elf_prstatus prstatus; /* NT_PRSTATUS */ - struct elf_prpsinfo psinfo; /* NT_PRPSINFO */ + int numnote = NUM_NOTES; + struct memelfnote *notes = NULL; + struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */ + struct elf_prpsinfo *psinfo = NULL; /* NT_PRPSINFO */ struct task_struct *g, *p; LIST_HEAD(thread_list); struct list_head *t; - elf_fpregset_t fpu; + elf_fpregset_t *fpu = NULL; #ifdef ELF_CORE_COPY_XFPREGS - elf_fpxregset_t xfpu; + elf_fpxregset_t *xfpu = NULL; #endif int thread_status_size = 0; - - /* We no longer stop all vm operations + + /* + * We no longer stop all VM operations. * - * This because those proceses that could possibly - * change map_count or the mmap / vma pages are now blocked in do_exit on current finishing + * This is because those proceses that could possibly change map_count or + * the mmap / vma pages are now blocked in do_exit on current finishing * this core dump. * * Only ptrace can touch these memory addresses, but it doesn't change - * the map_count or the pages allocated. So no possibility of crashing exists while dumping - * the mm->vm_next areas to the core file. - * + * the map_count or the pages allocated. So no possibility of crashing + * exists while dumping the mm->vm_next areas to the core file. */ - - /* capture the status of all other threads */ + + /* alloc memory for large data structures: too large to be on stack */ + elf = kmalloc(sizeof(*elf), GFP_KERNEL); + if (!elf) + goto cleanup; + prstatus = kmalloc(sizeof(*prstatus), GFP_KERNEL); + if (!prstatus) + goto cleanup; + psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL); + if (!psinfo) + goto cleanup; + notes = kmalloc(NUM_NOTES * sizeof(struct memelfnote), GFP_KERNEL); + if (!notes) + goto cleanup; + fpu = kmalloc(sizeof(*fpu), GFP_KERNEL); + if (!fpu) + goto cleanup; +#ifdef ELF_CORE_COPY_XFPREGS + xfpu = kmalloc(sizeof(*xfpu), GFP_KERNEL); + if (!xfpu) + goto cleanup; +#endif + + /* capture the status of all other threads */ if (signr) { read_lock(&tasklist_lock); do_each_thread(g,p) @@ -1226,14 +1250,14 @@ } /* now collect the dump for the current */ - memset(&prstatus, 0, sizeof(prstatus)); - fill_prstatus(&prstatus, current, signr); - elf_core_copy_regs(&prstatus.pr_reg, regs); + memset(prstatus, 0, sizeof(*prstatus)); + fill_prstatus(prstatus, current, signr); + elf_core_copy_regs(&prstatus->pr_reg, regs); segs = current->mm->map_count; /* Set up header */ - fill_elf_header(&elf, segs+1); /* including notes section*/ + fill_elf_header(elf, segs+1); /* including notes section */ has_dumped = 1; current->flags |= PF_DUMPCORE; @@ -1243,32 +1267,32 @@ * with info from their /proc. */ - fill_note(¬es[0], "CORE", NT_PRSTATUS, sizeof(prstatus), &prstatus); + fill_note(notes +0, "CORE", NT_PRSTATUS, sizeof(*prstatus), prstatus); - fill_psinfo(&psinfo, current->group_leader); - fill_note(¬es[1], "CORE", NT_PRPSINFO, sizeof(psinfo), &psinfo); + fill_psinfo(psinfo, current->group_leader); + fill_note(notes +1, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo); - fill_note(¬es[2], "CORE", NT_TASKSTRUCT, sizeof(*current), current); + fill_note(notes +2, "CORE", NT_TASKSTRUCT, sizeof(*current), current); /* Try to dump the FPU. */ - if ((prstatus.pr_fpvalid = elf_core_copy_task_fpregs(current, &fpu))) - fill_note(¬es[3], "CORE", NT_PRFPREG, sizeof(fpu), &fpu); + if ((prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, fpu))) + fill_note(notes +3, "CORE", NT_PRFPREG, sizeof(*fpu), fpu); else --numnote; #ifdef ELF_CORE_COPY_XFPREGS - if (elf_core_copy_task_xfpregs(current, &xfpu)) - fill_note(¬es[4], "LINUX", NT_PRXFPREG, sizeof(xfpu), &xfpu); + if (elf_core_copy_task_xfpregs(current, xfpu)) + fill_note(notes +4, "LINUX", NT_PRXFPREG, sizeof(*xfpu), xfpu); else --numnote; #else - numnote --; + numnote--; #endif fs = get_fs(); set_fs(KERNEL_DS); - DUMP_WRITE(&elf, sizeof(elf)); - offset += sizeof(elf); /* Elf header */ + DUMP_WRITE(elf, sizeof(*elf)); + offset += sizeof(*elf); /* Elf header */ offset += (segs+1) * sizeof(struct elf_phdr); /* Program headers */ /* Write notes phdr entry */ @@ -1276,8 +1300,8 @@ struct elf_phdr phdr; int sz = 0; - for(i = 0; i < numnote; i++) - sz += notesize(¬es[i]); + for (i = 0; i < numnote; i++) + sz += notesize(notes + i); sz += thread_status_size; @@ -1290,7 +1314,7 @@ dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); /* Write program headers for segments dump */ - for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { + for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { struct elf_phdr phdr; size_t sz; @@ -1312,8 +1336,8 @@ } /* write out the notes section */ - for(i = 0; i < numnote; i++) - if (!writenote(¬es[i], file)) + for (i = 0; i < numnote; i++) + if (!writenote(notes + i, file)) goto end_coredump; /* write out the thread status notes section */ @@ -1326,7 +1350,7 @@ DUMP_SEEK(dataoff); - for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { + for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { unsigned long addr; if (!maydump(vma)) @@ -1373,7 +1397,16 @@ kfree(list_entry(tmp, struct elf_thread_status, list)); } + kfree(elf); + kfree(prstatus); + kfree(psinfo); + kfree(notes); + kfree(fpu); +#ifdef ELF_CORE_COPY_XFPREGS + kfree(xfpu); +#endif return has_dumped; +#undef NUM_NOTES } #endif /* USE_ELF_CORE_DUMP */ diff -Nru a/fs/cifs/CHANGES b/fs/cifs/CHANGES --- a/fs/cifs/CHANGES Fri Mar 7 20:40:18 2003 +++ b/fs/cifs/CHANGES Fri Mar 7 20:40:18 2003 @@ -1,3 +1,16 @@ +Version 0.70 +------------ +Fix oops in get dfs referral (triggered when null path sent in to +mount). Add support for overriding rsize at mount time. + +Version 0.69 +------------ +Fix buffer overrun in readdir which caused intermittent kernel oopses. +Fix writepage code to release kmap on write data. Allow "-ip=" new +mount option to be passed in on parameter distinct from the first part +(server name portion of) the UNC name. Allow override of the +tcp port of the target server via new mount option "-port=" + Version 0.68 ------------ Fix search handle leak on rewind. Fix setuid and gid so that they are diff -Nru a/fs/cifs/TODO b/fs/cifs/TODO --- a/fs/cifs/TODO Fri Mar 7 20:40:18 2003 +++ b/fs/cifs/TODO Fri Mar 7 20:40:18 2003 @@ -42,13 +42,24 @@ m) finish support for IPv6 -KNOWN BUGS (updated February 15, 2003) +n) send oplock break response when sent (oplock currently disabled in +/proc/fs/cifs) + +o) remove calls to set end of file by name when we already have file open +(use the existing handle since some servers only support that and it +reduces the oplock breaks coming from windows). Piggyback identical +file opens on top of each other by incrementing reference count rather +than resending (helps reduce server resource utilization and avoid +spurious oplock breaks). + +KNOWN BUGS (updated March 7, 2003) ==================================== 1) existing symbolic links (Windows reparse points) are recognized but can not be created remotely. They are implemented for Samba and those that support the CIFS Unix extensions but Samba has a bug currently handling symlink text beginning with slash 2) delete of file with read-only attribute set will fail (may be ok) +3) mount helper syntax not quite matching man page Misc testing to do ================= diff -Nru a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c --- a/fs/cifs/cifs_debug.c Fri Mar 7 20:40:17 2003 +++ b/fs/cifs/cifs_debug.c Fri Mar 7 20:40:17 2003 @@ -227,7 +227,7 @@ if (pde) pde->write_proc = traceSMB_write; - pde = create_proc_read_entry("oplockEnabled", 0, proc_fs_cifs, + pde = create_proc_read_entry("OplockEnabled", 0, proc_fs_cifs, oplockEnabled_read, 0); if (pde) pde->write_proc = oplockEnabled_write; @@ -269,7 +269,7 @@ remove_proc_entry("SimultaneousOps", proc_fs_cifs); remove_proc_entry("TotalOps", proc_fs_cifs); remove_proc_entry("MultiuserMount", proc_fs_cifs); - remove_proc_entry("oplockEnabled", proc_fs_cifs); + remove_proc_entry("OplockEnabled", proc_fs_cifs); remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); remove_proc_entry("ExtendedSecurity",proc_fs_cifs); remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); diff -Nru a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h --- a/fs/cifs/cifs_fs_sb.h Fri Mar 7 20:40:16 2003 +++ b/fs/cifs/cifs_fs_sb.h Fri Mar 7 20:40:16 2003 @@ -20,8 +20,9 @@ struct cifs_sb_info { struct cifsTconInfo *tcon; /* primary mount */ - /* list of implicit mounts beneath this mount point - needed in dfs case */ struct list_head nested_tcon_q; struct nls_table *local_nls; + unsigned int rsize; + unsigned int wsize; }; #endif /* _CIFS_FS_SB_H */ diff -Nru a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c --- a/fs/cifs/cifsfs.c Fri Mar 7 20:40:17 2003 +++ b/fs/cifs/cifsfs.c Fri Mar 7 20:40:17 2003 @@ -52,6 +52,7 @@ unsigned int extended_security = 0; unsigned int ntlmv2_support = 0; unsigned int sign_CIFS_PDUs = 0; +unsigned int CIFSMaximumBufferSize = CIFS_MAX_MSGSIZE; extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, char *); @@ -83,8 +84,11 @@ sb->s_magic = CIFS_MAGIC_NUMBER; sb->s_op = &cifs_super_ops; - sb->s_blocksize = CIFS_MAX_MSGSIZE; /* BB check SMBSessSetup negotiated size */ - sb->s_blocksize_bits = 10; /* 2**10 = CIFS_MAX_MSGSIZE */ + if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512) + sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; + else + sb->s_blocksize = CIFSMaximumBufferSize; + sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */ inode = iget(sb, ROOT_I); if (!inode) @@ -162,6 +166,12 @@ return 0; /* always return success? what if volume is no longer available? */ } +static int cifs_permission(struct inode * inode, int mask) +{ + /* the server does permission checks, we do not need to do it here */ + return 0; +} + static kmem_cache_t *cifs_inode_cachep; kmem_cache_t *cifs_req_cachep; kmem_cache_t *cifs_mid_cachep; @@ -270,6 +280,7 @@ .mkdir = cifs_mkdir, .rmdir = cifs_rmdir, .rename = cifs_rename, + .permission = cifs_permission, /* revalidate:cifs_revalidate, */ .setattr = cifs_setattr, .symlink = cifs_symlink, @@ -280,18 +291,19 @@ .setattr = cifs_setattr, .getattr = cifs_getattr, /* do we need this anymore? */ .rename = cifs_rename, + .permission = cifs_permission, #ifdef CIFS_XATTR .setxattr = cifs_setxattr, .getxattr = cifs_getxattr, .listxattr = cifs_listxattr, .removexattr = cifs_removexattr, - .permission = cifs_permission, #endif }; struct inode_operations cifs_symlink_inode_ops = { .readlink = cifs_readlink, .follow_link = cifs_follow_link, + .permission = cifs_permission, /* BB add the following two eventually */ /* revalidate: cifs_revalidate, setattr: cifs_notify_change, *//* BB do we need notify change */ @@ -318,6 +330,7 @@ struct file_operations cifs_dir_ops = { .readdir = cifs_readdir, .release = cifs_closedir, + .read = generic_read_dir, }; static void diff -Nru a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c --- a/fs/cifs/cifssmb.c Fri Mar 7 20:40:16 2003 +++ b/fs/cifs/cifssmb.c Fri Mar 7 20:40:16 2003 @@ -519,8 +519,7 @@ pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF); pSMB->OffsetHigh = cpu_to_le32(lseek >> 32); pSMB->Remaining = 0; - pSMB->MaxCount = cpu_to_le16(min_t(const unsigned int, count, - (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & 0xFFFFFF00)); + pSMB->MaxCount = cpu_to_le16(count); pSMB->MaxCountHigh = 0; pSMB->ByteCount = 0; /* no need to do le conversion since it is 0 */ @@ -710,9 +709,9 @@ , nls_codepage); name_len++; /* trailing null */ name_len *= 2; - pSMB->OldFileName[name_len] = 0; /* pad */ + pSMB->OldFileName[name_len] = 0x04; /* pad */ /* protocol requires ASCII signature byte on Unicode string */ - pSMB->OldFileName[name_len + 1] = 0x04; + pSMB->OldFileName[name_len + 1] = 0x00; name_len2 = cifs_strtoUCS((wchar_t *) & pSMB-> OldFileName[name_len + 2], toName, 530, diff -Nru a/fs/cifs/connect.c b/fs/cifs/connect.c --- a/fs/cifs/connect.c Fri Mar 7 20:40:18 2003 +++ b/fs/cifs/connect.c Fri Mar 7 20:40:18 2003 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include "cifspdu.h" @@ -56,6 +57,9 @@ mode_t file_mode; mode_t dir_mode; int rw; + unsigned int rsize; + unsigned int wsize; + unsigned short int port; }; int ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket); @@ -343,11 +347,7 @@ char *value; char *data; - vol->username = NULL; - vol->password = NULL; - vol->domainname = NULL; - vol->UNC = NULL; - vol->UNCip = NULL; + memset(vol,0,sizeof(struct smb_vol)); vol->linux_uid = current->uid; /* current->euid instead? */ vol->linux_gid = current->gid; vol->rw = TRUE; @@ -381,6 +381,15 @@ printk(KERN_WARNING "CIFS: password too long\n"); return 1; } + } else if (strnicmp(data, "ip", 2) == 0) { + if (!value || !*value) { + vol->UNCip = NULL; + } else if (strnlen(value, 35) < 35) { + vol->UNCip = value; + } else { + printk(KERN_WARNING "CIFS: ip address too long\n"); + return 1; + } } else if ((strnicmp(data, "unc", 3) == 0) || (strnicmp(data, "target", 6) == 0) || (strnicmp(data, "path", 4) == 0)) { @@ -399,7 +408,6 @@ "CIFS: UNC Path does not begin with // or \\\\ \n"); return 1; } - vol->UNCip = &vol->UNC[2]; } else { printk(KERN_WARNING "CIFS: UNC name too long\n"); return 1; @@ -420,22 +428,37 @@ } else if (strnicmp(data, "uid", 3) == 0) { if (value && *value) { vol->linux_uid = - simple_strtoul(value, &value, 0); + simple_strtoul(value, &value, 0); } } else if (strnicmp(data, "gid", 3) == 0) { if (value && *value) { vol->linux_gid = - simple_strtoul(value, &value, 0); + simple_strtoul(value, &value, 0); } } else if (strnicmp(data, "file_mode", 4) == 0) { if (value && *value) { vol->file_mode = - simple_strtoul(value, &value, 0); + simple_strtoul(value, &value, 0); } } else if (strnicmp(data, "dir_mode", 3) == 0) { if (value && *value) { vol->dir_mode = - simple_strtoul(value, &value, 0); + simple_strtoul(value, &value, 0); + } + } else if (strnicmp(data, "port", 4) == 0) { + if (value && *value) { + vol->port = + simple_strtoul(value, &value, 0); + } + } else if (strnicmp(data, "rsize", 5) == 0) { + if (value && *value) { + vol->rsize = + simple_strtoul(value, &value, 0); + } + } else if (strnicmp(data, "wsize", 5) == 0) { + if (value && *value) { + vol->wsize = + simple_strtoul(value, &value, 0); } } else if (strnicmp(data, "version", 3) == 0) { /* ignore */ @@ -458,12 +481,14 @@ printk(KERN_WARNING "CIFS: UNC Path does not begin with // or \\\\ \n"); return 1; } - vol->UNCip = &vol->UNC[2]; } else { printk(KERN_WARNING "CIFS: UNC name too long\n"); return 1; } } + if(vol->UNCip == 0) + vol->UNCip = &vol->UNC[2]; + return 0; } @@ -553,20 +578,16 @@ unsigned char *referrals = NULL; if (pSesInfo->ipc_tid == 0) { - temp_unc = - kmalloc(2 + - strnlen(pSesInfo->serverName, - SERVER_NAME_LEN_WITH_NULL * 2) + 1 + - 4 /* IPC$ */ + 1, GFP_KERNEL); + temp_unc = kmalloc(2 /* for slashes */ + + strnlen(pSesInfo->serverName,SERVER_NAME_LEN_WITH_NULL * 2) + + 1 + 4 /* slash IPC$ */ + 2, + GFP_KERNEL); if (temp_unc == NULL) return -ENOMEM; temp_unc[0] = '\\'; temp_unc[1] = '\\'; - strncpy(temp_unc + 2, pSesInfo->serverName, - SERVER_NAME_LEN_WITH_NULL * 2); - strncpy(temp_unc + 2 + - strnlen(pSesInfo->serverName, - SERVER_NAME_LEN_WITH_NULL * 2), "\\IPC$", 6); + strcpy(temp_unc + 2, pSesInfo->serverName); + strcpy(temp_unc + 2 + strlen(pSesInfo->serverName), "\\IPC$"); rc = CIFSTCon(xid, pSesInfo, temp_unc, NULL, nls_codepage); cFYI(1, ("CIFS Tcon rc = %d ipc_tid = %d", rc,pSesInfo->ipc_tid)); @@ -587,6 +608,7 @@ char ntlm_session_key[CIFS_SESSION_KEY_SIZE]; int ntlmv2_flag = FALSE; + /* what if server changes its buffer size after dropping the session? */ if(pSesInfo->server->maxBuf == 0) /* no need to send on reconnect */ rc = CIFSSMBNegotiate(xid, pSesInfo); pSesInfo->capabilities = pSesInfo->server->capabilities; @@ -670,11 +692,23 @@ } psin_server->sin_family = AF_INET; - psin_server->sin_port = htons(CIFS_PORT); + if(psin_server->sin_port) { /* user overrode default port */ + rc = (*csocket)->ops->connect(*csocket, + (struct sockaddr *) psin_server, + sizeof (struct sockaddr_in),0); + if (rc >= 0) { + return rc; + } + } + + /* do not retry on the same port we just failed on */ + if(psin_server->sin_port != htons(CIFS_PORT)) { + psin_server->sin_port = htons(CIFS_PORT); - rc = (*csocket)->ops->connect(*csocket, + rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) psin_server, sizeof (struct sockaddr_in),0); + } if (rc < 0) { psin_server->sin_port = htons(RFC1001_PORT); rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) @@ -703,13 +737,24 @@ } psin_server->sin6_family = AF_INET6; - psin_server->sin6_port = htons(CIFS_PORT); + if(psin_server->sin6_port) { /* user overrode default port */ + rc = (*csocket)->ops->connect(*csocket, + (struct sockaddr *) psin_server, + sizeof (struct sockaddr_in6),0); + if (rc >= 0) { + return rc; + } + } - rc = (*csocket)->ops->connect(*csocket, - (struct sockaddr *) psin_server, - sizeof (struct sockaddr_in6), 0 -/* BB fix the timeout to be shorter - and check flags */ - ); + /* do not retry on the same port we just failed on */ + if(psin_server->sin6_port != htons(CIFS_PORT)) { + psin_server->sin6_port = htons(CIFS_PORT); + + rc = (*csocket)->ops->connect(*csocket, + (struct sockaddr *) psin_server, + sizeof (struct sockaddr_in6), 0); +/* BB fix the timeout to be shorter above - and check flags */ + } if (rc < 0) { psin_server->sin6_port = htons(RFC1001_PORT); rc = (*csocket)->ops->connect(*csocket, (struct sockaddr *) @@ -744,7 +789,7 @@ struct TCP_Server_Info *srvTcp = NULL; xid = GetXid(); - cFYI(0, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); + cFYI(1, ("Entering cifs_mount. Xid: %d with: %s", xid, mount_data)); if(parse_mount_options(mount_data, devname, &volume_info)) { FreeXid(xid); @@ -778,7 +823,9 @@ volume_info.username, &srvTcp); if (srvTcp) { cFYI(1, ("Existing tcp session with server found ")); - } else { /* create socket */ + } else { /* create socket */ + if(volume_info.port) + sin_server.sin_port = htons(volume_info.port); rc = ipv4_connect(&sin_server, &csocket); if (rc < 0) { cERROR(1, @@ -839,9 +886,23 @@ atomic_inc(&srvTcp->socketUseCount); } } - + /* search for existing tcon to this server share */ if (!rc) { + if((volume_info.rsize) && (volume_info.rsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf)) + cifs_sb->rsize = volume_info.rsize; + else + cifs_sb->rsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */ + if((volume_info.wsize) && (volume_info.wsize + MAX_CIFS_HDR_SIZE < srvTcp->maxBuf)) + cifs_sb->wsize = volume_info.wsize; + else + cifs_sb->wsize = srvTcp->maxBuf - MAX_CIFS_HDR_SIZE; /* default */ + if(cifs_sb->rsize < PAGE_CACHE_SIZE) { + cifs_sb->rsize = PAGE_CACHE_SIZE; + cERROR(1,("Attempt to set readsize for mount to less than one page (4096)")); + } + + tcon = find_unc(sin_server.sin_addr.s_addr, volume_info.UNC, volume_info.username); @@ -944,7 +1005,7 @@ if (smb_buffer == 0) { return -ENOMEM; } - smb_buffer_response = smb_buffer; + smb_buffer_response = smb_buffer; pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer; /* send SMBsessionSetup here */ diff -Nru a/fs/cifs/file.c b/fs/cifs/file.c --- a/fs/cifs/file.c Fri Mar 7 20:40:16 2003 +++ b/fs/cifs/file.c Fri Mar 7 20:40:16 2003 @@ -393,7 +393,7 @@ { struct address_space *mapping = page->mapping; loff_t offset = (loff_t)page->index << PAGE_CACHE_SHIFT; - char * write_data = kmap(page); + char * write_data; int rc = -EFAULT; int bytes_written = 0; struct cifs_sb_info *cifs_sb; @@ -411,8 +411,9 @@ /* figure out which file struct to use if (file->private_data == NULL) { - FreeXid(xid); - return -EBADF; + kunmap(page); + FreeXid(xid); + return -EBADF; } */ if (!mapping) { @@ -424,15 +425,17 @@ } offset += (loff_t)from; + write_data = kmap(page); write_data += from; if((to > PAGE_CACHE_SIZE) || (from > to) || (offset > mapping->host->i_size)) { + kunmap(page); FreeXid(xid); return -EIO; } /* check to make sure that we are not extending the file */ - if(mapping->host->i_size - offset < (loff_t)to) + if(mapping->host->i_size - offset < (loff_t)to) to = (unsigned)(mapping->host->i_size - offset); @@ -459,6 +462,7 @@ rc = -EIO; } + kunmap(page); FreeXid(xid); return rc; } @@ -604,6 +608,7 @@ int rc = -EACCES; int bytes_read = 0; int total_read; + int current_read_size; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; int xid; @@ -620,10 +625,11 @@ for (total_read = 0,current_offset=read_data; read_size > total_read; total_read += bytes_read,current_offset+=bytes_read) { + current_read_size = min_t(const int,read_size - total_read,cifs_sb->rsize); rc = CIFSSMBRead(xid, pTcon, ((struct cifsFileInfo *) file-> private_data)->netfid, - read_size - total_read, *poffset, + current_read_size, *poffset, &bytes_read, ¤t_offset); if (rc || (bytes_read == 0)) { if (total_read) { @@ -740,6 +746,8 @@ num_pages-i, (unsigned long) offset)); read_size = (num_pages - i) * PAGE_CACHE_SIZE; + /* Read size needs to be in multiples of one page */ + read_size = min_t(const unsigned int,read_size,cifs_sb->rsize & PAGE_CACHE_MASK); rc = CIFSSMBRead(xid, pTcon, ((struct cifsFileInfo *) file-> private_data)->netfid, @@ -1061,11 +1069,11 @@ xid = GetXid(); - data = kmalloc(4096, GFP_KERNEL); - pfindData = (FILE_DIRECTORY_INFO *) data; - cifs_sb = CIFS_SB(file->f_dentry->d_sb); pTcon = cifs_sb->tcon; + data = kmalloc(pTcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE, + GFP_KERNEL); + pfindData = (FILE_DIRECTORY_INFO *) data; full_path = build_wildcard_path_from_dentry(file->f_dentry); diff -Nru a/fs/cifs/misc.c b/fs/cifs/misc.c --- a/fs/cifs/misc.c Fri Mar 7 20:40:18 2003 +++ b/fs/cifs/misc.c Fri Mar 7 20:40:18 2003 @@ -153,7 +153,8 @@ /* We could use negotiated size instead of max_msgsize - but it may be more efficient to always alloc same size - albeit slightly larger */ + albeit slightly larger than necessary and maxbuffersize + defaults to this and can not be bigger */ ret_buf = (struct smb_hdr *) kmem_cache_alloc(cifs_req_cachep, SLAB_KERNEL); diff -Nru a/fs/cifs/transport.c b/fs/cifs/transport.c --- a/fs/cifs/transport.c Fri Mar 7 20:40:16 2003 +++ b/fs/cifs/transport.c Fri Mar 7 20:40:16 2003 @@ -159,7 +159,7 @@ midQ = AllocMidQEntry(in_buf, ses); if (midQ == NULL) return -EIO; - if (in_buf->smb_buf_length > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE) { + if (in_buf->smb_buf_length > CIFS_MAX_MSGSIZE + MAX_CIFS_HDR_SIZE - 4) { cERROR(1, ("Illegal length, greater than maximum frame, %d ", in_buf->smb_buf_length)); diff -Nru a/fs/ext3/dir.c b/fs/ext3/dir.c --- a/fs/ext3/dir.c Fri Mar 7 20:40:17 2003 +++ b/fs/ext3/dir.c Fri Mar 7 20:40:17 2003 @@ -105,8 +105,10 @@ if (is_dx(inode)) { err = ext3_dx_readdir(filp, dirent, filldir); - if (err != ERR_BAD_DX_DIR) + if (err != ERR_BAD_DX_DIR) { + unlock_kernel(); return err; + } /* * We don't set the inode dirty flag since it's not * critical that it get flushed back to the disk. diff -Nru a/fs/ext3/super.c b/fs/ext3/super.c --- a/fs/ext3/super.c Fri Mar 7 20:40:18 2003 +++ b/fs/ext3/super.c Fri Mar 7 20:40:18 2003 @@ -1154,7 +1154,7 @@ if (!bh) { printk(KERN_ERR "EXT3-fs: Can't read superblock on 2nd try.\n"); - return -EINVAL; + goto failed_mount; } es = (struct ext3_super_block *)(((char *)bh->b_data) + offset); sbi->s_es = es; diff -Nru a/fs/filesystems.c b/fs/filesystems.c --- a/fs/filesystems.c Fri Mar 7 20:40:17 2003 +++ b/fs/filesystems.c Fri Mar 7 20:40:17 2003 @@ -125,9 +125,7 @@ if (!res) { /* we implicitly possess reference to @fs during registration, * so it cannot be unregister from under us. */ - if (register_fs_subsys(fs)) - printk(KERN_WARNING "Failed to register '%s' in sysfs\n", - fs->name); + register_fs_subsys(fs); } return res; } diff -Nru a/fs/inode.c b/fs/inode.c --- a/fs/inode.c Fri Mar 7 20:40:18 2003 +++ b/fs/inode.c Fri Mar 7 20:40:18 2003 @@ -453,8 +453,13 @@ } /* - * This is called from kswapd when we think we need some - * more memory. + * shrink_icache_memory() will attempt to reclaim some unused inodes. Here, + * "unused" means that no dentries are referring to the inodes: the files are + * not open and the dcache references to those inodes have already been + * reclaimed. + * + * This function is passed the number of inodes to scan, and it returns the + * total number of remaining possibly-reclaimable inodes. */ static int shrink_icache_memory(int nr, unsigned int gfp_mask) { @@ -467,7 +472,7 @@ if (gfp_mask & __GFP_FS) prune_icache(nr); } - return inodes_stat.nr_inodes; + return inodes_stat.nr_unused; } /* diff -Nru a/fs/intermezzo/cache.c b/fs/intermezzo/cache.c --- a/fs/intermezzo/cache.c Fri Mar 7 20:40:17 2003 +++ b/fs/intermezzo/cache.c Fri Mar 7 20:40:17 2003 @@ -22,7 +22,6 @@ #define __NO_VERSION__ #include -#include #include #include #include diff -Nru a/fs/intermezzo/dir.c b/fs/intermezzo/dir.c --- a/fs/intermezzo/dir.c Fri Mar 7 20:40:16 2003 +++ b/fs/intermezzo/dir.c Fri Mar 7 20:40:16 2003 @@ -22,8 +22,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include - #include #include #include diff -Nru a/fs/intermezzo/file.c b/fs/intermezzo/file.c --- a/fs/intermezzo/file.c Fri Mar 7 20:40:17 2003 +++ b/fs/intermezzo/file.c Fri Mar 7 20:40:17 2003 @@ -29,8 +29,6 @@ * */ -#include - #include #include #include diff -Nru a/fs/intermezzo/fileset.c b/fs/intermezzo/fileset.c --- a/fs/intermezzo/fileset.c Fri Mar 7 20:40:16 2003 +++ b/fs/intermezzo/fileset.c Fri Mar 7 20:40:16 2003 @@ -23,7 +23,6 @@ */ #define __NO_VERSION__ -#include #include #include diff -Nru a/fs/intermezzo/intermezzo_lib.h b/fs/intermezzo/intermezzo_lib.h --- a/fs/intermezzo/intermezzo_lib.h Fri Mar 7 20:40:16 2003 +++ b/fs/intermezzo/intermezzo_lib.h Fri Mar 7 20:40:16 2003 @@ -32,12 +32,6 @@ # include #endif -#undef MIN -#define MIN(a,b) (((a)<(b)) ? (a): (b)) -#undef MAX -#define MAX(a,b) (((a)>(b)) ? (a): (b)) -#define MKSTR(ptr) ((ptr))? (ptr) : "" - static inline int size_round (int val) { return (val + 3) & (~0x3); diff -Nru a/fs/intermezzo/methods.c b/fs/intermezzo/methods.c --- a/fs/intermezzo/methods.c Fri Mar 7 20:40:18 2003 +++ b/fs/intermezzo/methods.c Fri Mar 7 20:40:18 2003 @@ -25,8 +25,6 @@ * */ -#include - #include #include #include diff -Nru a/fs/intermezzo/replicator.c b/fs/intermezzo/replicator.c --- a/fs/intermezzo/replicator.c Fri Mar 7 20:40:17 2003 +++ b/fs/intermezzo/replicator.c Fri Mar 7 20:40:17 2003 @@ -25,7 +25,6 @@ #define __NO_VERSION__ #include -#include #include #include diff -Nru a/fs/intermezzo/super.c b/fs/intermezzo/super.c --- a/fs/intermezzo/super.c Fri Mar 7 20:40:18 2003 +++ b/fs/intermezzo/super.c Fri Mar 7 20:40:18 2003 @@ -26,8 +26,6 @@ static char rcsid[] __attribute ((unused)) = "$Id: super.c,v 1.4 2002/10/12 02:16:19 rread Exp $"; #define INTERMEZZO_VERSION "$Revision: 1.4 $" -#include - #include #include #include diff -Nru a/fs/locks.c b/fs/locks.c --- a/fs/locks.c Fri Mar 7 20:40:18 2003 +++ b/fs/locks.c Fri Mar 7 20:40:18 2003 @@ -143,15 +143,9 @@ static kmem_cache_t *filelock_cache; /* Allocate an empty lock structure. */ -static struct file_lock *locks_alloc_lock(int account) +static struct file_lock *locks_alloc_lock(void) { - struct file_lock *fl; - if (account && current->locks >= current->rlim[RLIMIT_LOCKS].rlim_cur) - return NULL; - fl = kmem_cache_alloc(filelock_cache, SLAB_KERNEL); - if (fl) - current->locks++; - return fl; + return kmem_cache_alloc(filelock_cache, SLAB_KERNEL); } /* Free a lock which is not in use. */ @@ -161,7 +155,6 @@ BUG(); return; } - current->locks--; if (waitqueue_active(&fl->fl_wait)) panic("Attempting to free lock with active wait queue"); @@ -248,7 +241,7 @@ if (type < 0) return type; - fl = locks_alloc_lock(1); + fl = locks_alloc_lock(); if (fl == NULL) return -ENOMEM; @@ -382,7 +375,7 @@ /* Allocate a file_lock initialised to this type of lease */ static int lease_alloc(struct file *filp, int type, struct file_lock **flp) { - struct file_lock *fl = locks_alloc_lock(1); + struct file_lock *fl = locks_alloc_lock(); if (fl == NULL) return -ENOMEM; @@ -427,13 +420,22 @@ /* Remove waiter from blocker's block list. * When blocker ends up pointing to itself then the list is empty. */ -static void locks_delete_block(struct file_lock *waiter) +static inline void __locks_delete_block(struct file_lock *waiter) { list_del_init(&waiter->fl_block); list_del_init(&waiter->fl_link); waiter->fl_next = NULL; } +/* + */ +static void locks_delete_block(struct file_lock *waiter) +{ + lock_kernel(); + __locks_delete_block(waiter); + unlock_kernel(); +} + /* Insert waiter into blocker's block list. * We use a circular list so that processes can be easily woken up in * the order they blocked. The documentation doesn't require this but @@ -446,7 +448,7 @@ printk(KERN_ERR "locks_insert_block: removing duplicated lock " "(pid=%d %Ld-%Ld type=%d)\n", waiter->fl_pid, waiter->fl_start, waiter->fl_end, waiter->fl_type); - locks_delete_block(waiter); + __locks_delete_block(waiter); } list_add_tail(&waiter->fl_block, &blocker->fl_block); waiter->fl_next = blocker; @@ -462,7 +464,7 @@ while (!list_empty(&blocker->fl_block)) { struct file_lock *waiter = list_entry(blocker->fl_block.next, struct file_lock, fl_block); - locks_delete_block(waiter); + __locks_delete_block(waiter); if (waiter->fl_notify) waiter->fl_notify(waiter); else @@ -589,7 +591,7 @@ int result; locks_insert_block(blocker, waiter); result = interruptible_sleep_on_locked(&waiter->fl_wait, time); - locks_delete_block(waiter); + __locks_delete_block(waiter); return result; } @@ -726,8 +728,8 @@ * We may need two file_lock structures for this operation, * so we get them in advance to avoid races. */ - new_fl = locks_alloc_lock(0); - new_fl2 = locks_alloc_lock(0); + new_fl = locks_alloc_lock(); + new_fl2 = locks_alloc_lock(); lock_kernel(); if (request->fl_type != F_UNLCK) { @@ -977,9 +979,7 @@ continue; } - lock_kernel(); locks_delete_block(&fl); - unlock_kernel(); break; } @@ -1332,9 +1332,7 @@ if (!error) continue; - lock_kernel(); locks_delete_block(lock); - unlock_kernel(); break; } @@ -1416,7 +1414,7 @@ */ int fcntl_setlk(struct file *filp, unsigned int cmd, struct flock *l) { - struct file_lock *file_lock = locks_alloc_lock(0); + struct file_lock *file_lock = locks_alloc_lock(); struct flock flock; struct inode *inode; int error; @@ -1489,9 +1487,7 @@ if (!error) continue; - lock_kernel(); locks_delete_block(file_lock); - unlock_kernel(); break; } @@ -1556,7 +1552,7 @@ */ int fcntl_setlk64(struct file *filp, unsigned int cmd, struct flock64 *l) { - struct file_lock *file_lock = locks_alloc_lock(0); + struct file_lock *file_lock = locks_alloc_lock(); struct flock64 flock; struct inode *inode; int error; @@ -1629,9 +1625,7 @@ if (!error) continue; - lock_kernel(); locks_delete_block(file_lock); - unlock_kernel(); break; } @@ -1648,14 +1642,15 @@ */ void locks_remove_posix(struct file *filp, fl_owner_t owner) { - struct file_lock lock; + struct file_lock lock, **before; /* * If there are no locks held on this file, we don't need to call * posix_lock_file(). Another process could be setting a lock on this * file at the same time, but we wouldn't remove that lock anyway. */ - if (!filp->f_dentry->d_inode->i_flock) + before = &filp->f_dentry->d_inode->i_flock; + if (*before == NULL) return; lock.fl_type = F_UNLCK; @@ -1671,7 +1666,19 @@ /* Ignore any error -- we must remove the locks anyway */ } - posix_lock_file(filp, &lock); + /* Can't use posix_lock_file here; we need to remove it no matter + * which pid we have. + */ + lock_kernel(); + while (*before != NULL) { + struct file_lock *fl = *before; + if (IS_POSIX(fl) && (fl->fl_owner == owner)) { + locks_delete_lock(before); + continue; + } + before = &fl->fl_next; + } + unlock_kernel(); } /* @@ -1699,6 +1706,7 @@ lease_modify(before, F_UNLCK); continue; } + BUG(); } before = &fl->fl_next; } @@ -1733,7 +1741,7 @@ */ lock_kernel(); if (waiter->fl_next) { - locks_delete_block(waiter); + __locks_delete_block(waiter); unlock_kernel(); } else { unlock_kernel(); @@ -1785,19 +1793,19 @@ ? (fl->fl_type & F_UNLCK) ? "UNLCK" : "READ " : (fl->fl_type & F_WRLCK) ? "WRITE" : "READ "); } -#if WE_CAN_BREAK_LSLK_NOW if (inode) { +#if WE_CAN_BREAK_LSLK_NOW out += sprintf(out, "%d %s:%ld ", fl->fl_pid, inode->i_sb->s_id, inode->i_ino); +#else + /* userspace relies on this representation of dev_t ;-( */ + out += sprintf(out, "%d %02x:%02x:%ld ", fl->fl_pid, + MAJOR(inode->i_sb->s_dev), + MINOR(inode->i_sb->s_dev), inode->i_ino); +#endif } else { out += sprintf(out, "%d :0 ", fl->fl_pid); } -#else - /* kdevname is a broken interface. but we expose it to userspace */ - out += sprintf(out, "%d %s:%ld ", fl->fl_pid, - inode ? kdevname(to_kdev_t(inode->i_sb->s_dev)) : "", - inode ? inode->i_ino : 0); -#endif if (IS_POSIX(fl)) { if (fl->fl_end == OFFSET_MAX) out += sprintf(out, "%Ld EOF\n", fl->fl_start); diff -Nru a/fs/namei.c b/fs/namei.c --- a/fs/namei.c Fri Mar 7 20:40:16 2003 +++ b/fs/namei.c Fri Mar 7 20:40:16 2003 @@ -342,8 +342,18 @@ * * FIXME! This could use version numbering or similar to * avoid unnecessary cache lookups. + * + * The "dcache_lock" is purely to protect the RCU list walker + * from concurrent renames at this point (we mustn't get false + * negatives from the RCU list walk here, unlike the optimistic + * fast walk). + * + * We really should do a sequence number thing to avoid this + * all. */ + spin_lock(&dcache_lock); result = d_lookup(parent, name); + spin_unlock(&dcache_lock); if (!result) { struct dentry * dentry = d_alloc(parent, name); result = ERR_PTR(-ENOMEM); diff -Nru a/fs/sysfs/bin.c b/fs/sysfs/bin.c --- a/fs/sysfs/bin.c Fri Mar 7 20:40:17 2003 +++ b/fs/sysfs/bin.c Fri Mar 7 20:40:17 2003 @@ -50,6 +50,10 @@ ret = count; } Done: + if (buffer && buffer->data) { + kfree(buffer->data); + buffer->data = NULL; + } return ret; } @@ -66,7 +70,7 @@ static int fill_write(struct file * file, const char * userbuf, struct sysfs_bin_buffer * buffer) { - return copy_from_user(buffer,userbuf,buffer->count) ? + return copy_from_user(buffer->data,userbuf,buffer->count) ? -EFAULT : 0; } diff -Nru a/fs/sysfs/dir.c b/fs/sysfs/dir.c --- a/fs/sysfs/dir.c Fri Mar 7 20:40:17 2003 +++ b/fs/sysfs/dir.c Fri Mar 7 20:40:17 2003 @@ -71,7 +71,7 @@ void sysfs_remove_dir(struct kobject * kobj) { - struct list_head * node, * next; + struct list_head * node; struct dentry * dentry = dget(kobj->dentry); struct dentry * parent; @@ -83,31 +83,28 @@ down(&parent->d_inode->i_sem); down(&dentry->d_inode->i_sem); - list_for_each_safe(node,next,&dentry->d_subdirs) { - struct dentry * d = dget(list_entry(node,struct dentry,d_child)); - /** - * Make sure dentry is still there - */ - pr_debug(" o %s: ",d->d_name.name); - if (d->d_inode) { + spin_lock(&dcache_lock); + node = dentry->d_subdirs.next; + while (node != &dentry->d_subdirs) { + struct dentry * d = list_entry(node,struct dentry,d_child); + list_del_init(node); + pr_debug(" o %s (%d): ",d->d_name.name,atomic_read(&d->d_count)); + if (d->d_inode) { + d = dget_locked(d); pr_debug("removing"); + /** * Unlink and unhash. */ - simple_unlink(dentry->d_inode,d); + spin_unlock(&dcache_lock); d_delete(d); - - /** - * Drop reference from initial sysfs_get_dentry(). - */ + simple_unlink(dentry->d_inode,d); dput(d); + spin_lock(&dcache_lock); } - pr_debug(" done (%d)\n",atomic_read(&d->d_count)); - /** - * drop reference from dget() above. - */ - dput(d); + pr_debug(" done\n"); + node = dentry->d_subdirs.next; } up(&dentry->d_inode->i_sem); diff -Nru a/fs/sysfs/mount.c b/fs/sysfs/mount.c --- a/fs/sysfs/mount.c Fri Mar 7 20:40:18 2003 +++ b/fs/sysfs/mount.c Fri Mar 7 20:40:18 2003 @@ -33,7 +33,7 @@ sb->s_op = &sysfs_ops; sysfs_sb = sb; - inode = sysfs_new_inode(S_IFDIR | S_IRUGO | S_IWUSR); + inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO); if (inode) { inode->i_op = &simple_dir_inode_operations; inode->i_fop = &simple_dir_operations; diff -Nru a/include/asm-alpha/core_cia.h b/include/asm-alpha/core_cia.h --- a/include/asm-alpha/core_cia.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-alpha/core_cia.h Fri Mar 7 20:40:17 2003 @@ -293,7 +293,7 @@ #ifdef __KERNEL__ #ifndef __EXTERN_INLINE -#define __EXTERN_INLINE extern inline +#define __EXTERN_INLINE static inline #define __IO_EXTERN_INLINE #endif diff -Nru a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h --- a/include/asm-alpha/pgtable.h Fri Mar 7 20:40:16 2003 +++ b/include/asm-alpha/pgtable.h Fri Mar 7 20:40:16 2003 @@ -273,7 +273,6 @@ /* to find an entry in a page-table-directory. */ #define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) -#define __pgd_offset(address) pgd_index(address) #define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address)) /* Find an entry in the second-level page table.. */ diff -Nru a/include/asm-arm/arch-anakin/time.h b/include/asm-arm/arch-anakin/time.h --- a/include/asm-arm/arch-anakin/time.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-arm/arch-anakin/time.h Fri Mar 7 20:40:17 2003 @@ -23,7 +23,6 @@ void __init time_init(void) { timer_irq.handler = anakin_timer_interrupt; - timer_irq.flags = SA_INTERRUPT; setup_irq(IRQ_TICK, &timer_irq); } diff -Nru a/include/asm-arm/arch-sa1100/time.h b/include/asm-arm/arch-sa1100/time.h --- a/include/asm-arm/arch-sa1100/time.h Fri Mar 7 20:40:18 2003 +++ b/include/asm-arm/arch-sa1100/time.h Fri Mar 7 20:40:18 2003 @@ -75,15 +75,12 @@ static void sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { unsigned int next_match; - unsigned long flags; do { do_leds(); - local_irq_save(flags); do_timer(regs); OSSR = OSSR_M0; /* Clear match on timer 0 */ next_match = (OSMR0 += LATCH); - local_irq_restore(flags); do_set_rtc(); } while ((signed long)(next_match - OSCR) <= 0); diff -Nru a/include/asm-arm/arch-shark/time.h b/include/asm-arm/arch-shark/time.h --- a/include/asm-arm/arch-shark/time.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-arm/arch-shark/time.h Fri Mar 7 20:40:17 2003 @@ -34,6 +34,5 @@ xtime.tv_sec = 0; timer_irq.handler = timer_interrupt; - timer_irq.flags = SA_INTERRUPT; /* FIXME: really? */ setup_irq(IRQ_TIMER, &timer_irq); } diff -Nru a/include/asm-arm/ecard.h b/include/asm-arm/ecard.h --- a/include/asm-arm/ecard.h Fri Mar 7 20:40:18 2003 +++ b/include/asm-arm/ecard.h Fri Mar 7 20:40:18 2003 @@ -267,6 +267,7 @@ struct ecard_driver { int (*probe)(struct expansion_card *, const struct ecard_id *id); void (*remove)(struct expansion_card *); + void (*shutdown)(struct expansion_card *); const struct ecard_id *id_table; unsigned int id; struct device_driver drv; diff -Nru a/include/asm-arm/ide.h b/include/asm-arm/ide.h --- a/include/asm-arm/ide.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-arm/ide.h Fri Mar 7 20:40:17 2003 @@ -26,16 +26,10 @@ #define ide_default_io_base(i) ((ide_ioreg_t)0) #define ide_default_irq(b) (0) -#define ide_request_irq(irq,hand,flg,dev,id) request_irq((irq),(hand),(flg),(dev),(id)) -#define ide_free_irq(irq,dev_id) free_irq((irq), (dev_id)) -#define ide_check_region(from,extent) check_region((from), (extent)) -#define ide_request_region(from,extent,name) request_region((from), (extent), (name)) -#define ide_release_region(from,extent) release_region((from), (extent)) - -/* - * The following are not needed for the non-m68k ports - */ -#define ide_ack_intr(hwif) (1) +#define __ide_mm_insw(port,addr,len) readsw(port,addr,len) +#define __ide_mm_insl(port,addr,len) readsl(port,addr,len) +#define __ide_mm_outsw(port,addr,len) writesw(port,addr,len) +#define __ide_mm_outsl(port,addr,len) writesl(port,addr,len) #endif /* __KERNEL__ */ diff -Nru a/include/asm-arm/pci.h b/include/asm-arm/pci.h --- a/include/asm-arm/pci.h Fri Mar 7 20:40:16 2003 +++ b/include/asm-arm/pci.h Fri Mar 7 20:40:16 2003 @@ -131,7 +131,10 @@ /* * Return the index of the PCI controller for device PDEV. */ -#define pci_controller_num(PDEV) (0) +static inline int pci_controller_num(struct pci_dev *dev) +{ + return 0; +} #if defined(CONFIG_SA1111) && !defined(CONFIG_PCI) diff -Nru a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h --- a/include/asm-arm/pgtable.h Fri Mar 7 20:40:16 2003 +++ b/include/asm-arm/pgtable.h Fri Mar 7 20:40:16 2003 @@ -110,13 +110,13 @@ #define pgd_bad(pgd) (0) #define pgd_present(pgd) (1) #define pgd_clear(pgdp) do { } while (0) +#define set_pgd(pgd,pgdp) do { } while (0) #define page_pte_prot(page,prot) mk_pte(page, prot) #define page_pte(page) mk_pte(page, __pgprot(0)) /* to find an entry in a page-table-directory */ #define pgd_index(addr) ((addr) >> PGDIR_SHIFT) -#define __pgd_offset(addr) pgd_index(addr) #define pgd_offset(mm, addr) ((mm)->pgd+pgd_index(addr)) diff -Nru a/include/asm-arm/posix_types.h b/include/asm-arm/posix_types.h --- a/include/asm-arm/posix_types.h Fri Mar 7 20:40:16 2003 +++ b/include/asm-arm/posix_types.h Fri Mar 7 20:40:16 2003 @@ -34,6 +34,8 @@ typedef long __kernel_time_t; typedef long __kernel_suseconds_t; typedef long __kernel_clock_t; +typedef int __kernel_timer_t; +typedef int __kernel_clockid_t; typedef int __kernel_daddr_t; typedef char * __kernel_caddr_t; typedef unsigned short __kernel_uid16_t; diff -Nru a/include/asm-arm/proc-armv/tlbflush.h b/include/asm-arm/proc-armv/tlbflush.h --- a/include/asm-arm/proc-armv/tlbflush.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-arm/proc-armv/tlbflush.h Fri Mar 7 20:40:17 2003 @@ -1,7 +1,7 @@ /* * linux/include/asm-arm/proc-armv/tlbflush.h * - * Copyright (C) 1999-2002 Russell King + * Copyright (C) 1999-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 @@ -38,21 +38,31 @@ #define v3_tlb_flags (TLB_V3_FULL | TLB_V3_PAGE) #if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710) +# define v3_possible_flags v3_tlb_flags +# define v3_always_flags v3_tlb_flags # ifdef _TLB # define MULTI_TLB 1 # else # define _TLB v3 # endif +#else +# define v3_possible_flags 0 +# define v3_always_flags (-1UL) #endif #define v4_tlb_flags (TLB_V4_U_FULL | TLB_V4_U_PAGE) #if defined(CONFIG_CPU_ARM720T) +# define v4_possible_flags v4_tlb_flags +# define v4_always_flags v4_tlb_flags # ifdef _TLB # define MULTI_TLB 1 # else # define _TLB v4 # endif +#else +# define v4_possible_flags 0 +# define v4_always_flags (-1UL) #endif #define v4wbi_tlb_flags (TLB_WB | \ @@ -62,11 +72,16 @@ #if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \ defined(CONFIG_CPU_ARM926T) || defined(CONFIG_CPU_ARM1020) || \ defined(CONFIG_CPU_XSCALE) +# define v4wbi_possible_flags v4wbi_tlb_flags +# define v4wbi_always_flags v4wbi_tlb_flags # ifdef _TLB # define MULTI_TLB 1 # else # define _TLB v4wbi # endif +#else +# define v4wbi_possible_flags 0 +# define v4wbi_always_flags (-1UL) #endif #define v4wb_tlb_flags (TLB_WB | \ @@ -74,11 +89,16 @@ TLB_V4_D_PAGE) #if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100) +# define v4wb_possible_flags v4wb_tlb_flags +# define v4wb_always_flags v4wb_tlb_flags # ifdef _TLB # define MULTI_TLB 1 # else # define _TLB v4wb # endif +#else +# define v4wb_possible_flags 0 +# define v4wb_always_flags (-1UL) #endif #ifndef _TLB @@ -98,23 +118,23 @@ */ #ifdef MULTI_TLB -extern struct cpu_tlb_fns cpu_tlb; - #define __cpu_flush_user_tlb_range cpu_tlb.flush_user_range #define __cpu_flush_kern_tlb_range cpu_tlb.flush_kern_range -#define __cpu_tlb_flags cpu_tlb.tlb_flags #else #define __cpu_flush_user_tlb_range __glue(_TLB,_flush_user_tlb_range) #define __cpu_flush_kern_tlb_range __glue(_TLB,_flush_kern_tlb_range) -#define __cpu_tlb_flags __glue(_TLB,_tlb_flags) extern void __cpu_flush_user_tlb_range(unsigned long, unsigned long, struct vm_area_struct *); extern void __cpu_flush_kern_tlb_range(unsigned long, unsigned long); #endif +extern struct cpu_tlb_fns cpu_tlb; + +#define __cpu_tlb_flags cpu_tlb.tlb_flags + /* * TLB Management * ============== @@ -158,11 +178,34 @@ * - kaddr - Kernel virtual memory address */ -#define tlb_flag(f) (__cpu_tlb_flags & (f)) +/* + * We optimise the code below by: + * - building a set of TLB flags that might be set in __cpu_tlb_flags + * - building a set of TLB flags that will always be set in __cpu_tlb_flags + * - if we're going to need __cpu_tlb_flags, access it once and only once + * + * This allows us to build optimal assembly for the single-CPU type case, + * and as close to optimal given the compiler constrants for multi-CPU + * case. We could do better for the multi-CPU case if the compiler + * implemented the "%?" method, but this has been discontinued due to too + * many people getting it wrong. + */ +#define possible_tlb_flags (v3_possible_flags | \ + v4_possible_flags | \ + v4wbi_possible_flags | \ + v4wb_possible_flags) + +#define always_tlb_flags (v3_always_flags & \ + v4_always_flags & \ + v4wbi_always_flags & \ + v4wb_always_flags) + +#define tlb_flag(f) ((always_tlb_flags & (f)) || (__tlb_flag & possible_tlb_flags & (f))) static inline void flush_tlb_all(void) { const int zero = 0; + const unsigned int __tlb_flag = __cpu_tlb_flags; if (tlb_flag(TLB_WB)) asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero)); @@ -180,6 +223,7 @@ static inline void flush_tlb_mm(struct mm_struct *mm) { const int zero = 0; + const unsigned int __tlb_flag = __cpu_tlb_flags; if (tlb_flag(TLB_WB)) asm("mcr%? p15, 0, %0, c7, c10, 4" : : "r" (zero)); @@ -200,6 +244,7 @@ flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr) { const int zero = 0; + const unsigned int __tlb_flag = __cpu_tlb_flags; uaddr &= PAGE_MASK; @@ -223,6 +268,7 @@ static inline void flush_tlb_kernel_page(unsigned long kaddr) { const int zero = 0; + const unsigned int __tlb_flag = __cpu_tlb_flags; kaddr &= PAGE_MASK; @@ -240,6 +286,10 @@ if (!tlb_flag(TLB_V4_I_PAGE) && tlb_flag(TLB_V4_I_FULL)) asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero)); } + +#undef tlb_flag +#undef always_tlb_flags +#undef possible_tlb_flags /* * Convert calls to our calling convention. diff -Nru a/include/asm-arm/proc-fns.h b/include/asm-arm/proc-fns.h --- a/include/asm-arm/proc-fns.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-arm/proc-fns.h Fri Mar 7 20:40:17 2003 @@ -122,15 +122,4 @@ #include CPU_INCLUDE_NAME #endif /* __KERNEL__ */ - -#if 0 - * The following is to fool mkdep into generating the correct - * dependencies. Without this, it can't figure out that this - * file does indeed depend on the cpu-*.h files. -#include -#include -#include - * -#endif - #endif /* __ASM_PROCFNS_H */ diff -Nru a/include/asm-arm/system.h b/include/asm-arm/system.h --- a/include/asm-arm/system.h Fri Mar 7 20:40:16 2003 +++ b/include/asm-arm/system.h Fri Mar 7 20:40:16 2003 @@ -14,16 +14,6 @@ extern unsigned int system_serial_high; extern unsigned int mem_fclk_21285; -/* - * This tells us if we have an ISA bridge - * present in a PCI system. - */ -#ifdef CONFIG_PCI -extern int have_isa_bridge; -#else -#define have_isa_bridge (0) -#endif - struct pt_regs; void die(const char *msg, struct pt_regs *regs, int err) @@ -75,7 +65,7 @@ * The `mb' is to tell GCC not to cache `current' across this call. */ struct thread_info; -extern struct task_struct *__switch_to(struct thread_info *, struct thread_info *); +extern struct thread_info *__switch_to(struct thread_info *, struct thread_info *); #define switch_to(prev,next,last) \ do { \ diff -Nru a/include/asm-i386/bug.h b/include/asm-i386/bug.h --- a/include/asm-i386/bug.h Fri Mar 7 20:40:16 2003 +++ b/include/asm-i386/bug.h Fri Mar 7 20:40:16 2003 @@ -4,8 +4,7 @@ #include /* - * Tell the user there is some problem. Beep too, so we can - * see^H^H^Hhear bugs in early bootup as well! + * Tell the user there is some problem. * The offending file and line are encoded after the "officially * undefined" opcode for parsing in the trap handler. */ diff -Nru a/include/asm-i386/hdreg.h b/include/asm-i386/hdreg.h --- a/include/asm-i386/hdreg.h Fri Mar 7 20:40:16 2003 +++ b/include/asm-i386/hdreg.h Fri Mar 7 20:40:16 2003 @@ -7,6 +7,5 @@ #ifndef __ASMi386_HDREG_H #define __ASMi386_HDREG_H -typedef unsigned long ide_ioreg_t; #endif /* __ASMi386_HDREG_H */ diff -Nru a/include/asm-i386/mach-bigsmp/mach_apic.h b/include/asm-i386/mach-bigsmp/mach_apic.h --- a/include/asm-i386/mach-bigsmp/mach_apic.h Fri Mar 7 20:40:18 2003 +++ b/include/asm-i386/mach-bigsmp/mach_apic.h Fri Mar 7 20:40:18 2003 @@ -19,7 +19,7 @@ } #define APIC_DFR_VALUE (APIC_DFR_CLUSTER) -#define TARGET_CPUS ((cpu_online_map < 0xf)?cpu_online_map:0xf) +#define TARGET_CPUS ((cpu_callout_map < 0xf)?cpu_callout_map:0xf) #define INT_DELIVERY_MODE dest_LowestPrio #define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */ diff -Nru a/include/asm-i386/mach-default/mach_apic.h b/include/asm-i386/mach-default/mach_apic.h --- a/include/asm-i386/mach-default/mach_apic.h Fri Mar 7 20:40:18 2003 +++ b/include/asm-i386/mach-default/mach_apic.h Fri Mar 7 20:40:18 2003 @@ -4,7 +4,7 @@ #define APIC_DFR_VALUE (APIC_DFR_FLAT) #ifdef CONFIG_SMP - #define TARGET_CPUS (cpu_online_map) + #define TARGET_CPUS (cpu_callout_map) #else #define TARGET_CPUS 0x01 #endif diff -Nru a/include/asm-i386/mach-summit/mach_apic.h b/include/asm-i386/mach-summit/mach_apic.h --- a/include/asm-i386/mach-summit/mach_apic.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-i386/mach-summit/mach_apic.h Fri Mar 7 20:40:17 2003 @@ -13,7 +13,7 @@ ((phys_apic) & XAPIC_DEST_CLUSTER_MASK) ) #define APIC_DFR_VALUE (x86_summit ? APIC_DFR_CLUSTER : APIC_DFR_FLAT) -#define TARGET_CPUS (x86_summit ? XAPIC_DEST_CPUS_MASK : cpu_online_map) +#define TARGET_CPUS (x86_summit ? XAPIC_DEST_CPUS_MASK : cpu_callout_map) #define INT_DELIVERY_MODE (x86_summit ? dest_Fixed : dest_LowestPrio) #define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */ diff -Nru a/include/asm-i386/pgtable-3level.h b/include/asm-i386/pgtable-3level.h --- a/include/asm-i386/pgtable-3level.h Fri Mar 7 20:40:18 2003 +++ b/include/asm-i386/pgtable-3level.h Fri Mar 7 20:40:18 2003 @@ -69,7 +69,7 @@ /* Find an entry in the second-level page table.. */ #define pmd_offset(dir, address) ((pmd_t *) pgd_page(*(dir)) + \ - __pmd_offset(address)) + pmd_index(address)) static inline pte_t ptep_get_and_clear(pte_t *ptep) { diff -Nru a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h --- a/include/asm-i386/pgtable.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-i386/pgtable.h Fri Mar 7 20:40:17 2003 @@ -49,8 +49,6 @@ #endif -#define __beep() asm("movb $0x3,%al; outb %al,$0x61") - #define PMD_SIZE (1UL << PMD_SHIFT) #define PMD_MASK (~(PMD_SIZE-1)) #define PGDIR_SIZE (1UL << PGDIR_SHIFT) @@ -236,32 +234,30 @@ /* to find an entry in a page-table-directory. */ #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) -#define __pgd_offset(address) pgd_index(address) - #define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address)) /* to find an entry in a kernel page-table-directory */ #define pgd_offset_k(address) pgd_offset(&init_mm, address) -#define __pmd_offset(address) \ +#define pmd_index(address) \ (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) /* Find an entry in the third-level page table.. */ -#define __pte_offset(address) \ +#define pte_index(address) \ (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) #define pte_offset_kernel(dir, address) \ - ((pte_t *) pmd_page_kernel(*(dir)) + __pte_offset(address)) + ((pte_t *) pmd_page_kernel(*(dir)) + pte_index(address)) #if defined(CONFIG_HIGHPTE) #define pte_offset_map(dir, address) \ - ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + __pte_offset(address)) + ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + pte_index(address)) #define pte_offset_map_nested(dir, address) \ - ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + __pte_offset(address)) + ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + pte_index(address)) #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0) #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1) #else #define pte_offset_map(dir, address) \ - ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address)) + ((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address)) #define pte_offset_map_nested(dir, address) pte_offset_map(dir, address) #define pte_unmap(pte) do { } while (0) #define pte_unmap_nested(pte) do { } while (0) diff -Nru a/include/asm-i386/serial.h b/include/asm-i386/serial.h --- a/include/asm-i386/serial.h Fri Mar 7 20:40:18 2003 +++ b/include/asm-i386/serial.h Fri Mar 7 20:40:18 2003 @@ -50,12 +50,19 @@ #define C_P(card,port) (((card)<<6|(port)<<3) + 1) +#ifndef CONFIG_X86_PC9800 #define STD_SERIAL_PORT_DEFNS \ /* UART CLK PORT IRQ FLAGS */ \ { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ \ { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */ \ { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \ { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */ +#else +#define STD_SERIAL_PORT_DEFNS \ + /* UART CLK PORT IRQ FLAGS */ \ + { 0, BASE_BAUD, 0x30, 4, STD_COM_FLAGS }, /* ttyS0 */ \ + { 0, BASE_BAUD, 0x238, 5, STD_COM_FLAGS }, /* ttyS1 */ +#endif /* CONFIG_X86_PC9800 */ #ifdef CONFIG_SERIAL_MANY_PORTS diff -Nru a/include/asm-ia64/hardirq.h b/include/asm-ia64/hardirq.h --- a/include/asm-ia64/hardirq.h Fri Mar 7 20:40:16 2003 +++ b/include/asm-ia64/hardirq.h Fri Mar 7 20:40:16 2003 @@ -32,18 +32,18 @@ * * - bits 0-7 are the preemption count (max preemption depth: 256) * - bits 8-15 are the softirq count (max # of softirqs: 256) - * - bits 16-31 are the hardirq count (max # of hardirqs: 65536) + * - bits 16-29 are the hardirq count (max # of hardirqs: 16384) * * - (bit 63 is the PREEMPT_ACTIVE flag---not currently implemented.) * * PREEMPT_MASK: 0x000000ff * SOFTIRQ_MASK: 0x0000ff00 - * HARDIRQ_MASK: 0xffff0000 + * HARDIRQ_MASK: 0x3fff0000 */ #define PREEMPT_BITS 8 #define SOFTIRQ_BITS 8 -#define HARDIRQ_BITS 16 +#define HARDIRQ_BITS 14 #define PREEMPT_SHIFT 0 #define SOFTIRQ_SHIFT (PREEMPT_SHIFT + PREEMPT_BITS) @@ -83,13 +83,13 @@ #define hardirq_trylock() (!in_interrupt()) #define hardirq_endlock() do { } while (0) -#define in_atomic() (preempt_count() != 0) #define irq_enter() (preempt_count() += HARDIRQ_OFFSET) #if CONFIG_PREEMPT -# error CONFIG_PREEMT currently not supported. +# define in_atomic() ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked()) # define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1) #else +# define in_atomic() (preempt_count() != 0) # define IRQ_EXIT_OFFSET HARDIRQ_OFFSET #endif diff -Nru a/include/asm-ia64/ide.h b/include/asm-ia64/ide.h --- a/include/asm-ia64/ide.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-ia64/ide.h Fri Mar 7 20:40:17 2003 @@ -91,6 +91,8 @@ #endif } +#include + #endif /* __KERNEL__ */ #endif /* __ASM_IA64_IDE_H */ diff -Nru a/include/asm-ia64/intrinsics.h b/include/asm-ia64/intrinsics.h --- a/include/asm-ia64/intrinsics.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-ia64/intrinsics.h Fri Mar 7 20:40:17 2003 @@ -35,24 +35,34 @@ } \ }) -#define ia64_fetch_and_add(i,v) \ -({ \ - __u64 _tmp; \ - volatile __typeof__(*(v)) *_v = (v); \ - switch (i) { \ - case -16: IA64_FETCHADD(_tmp, _v, -16, sizeof(*(v))); break; \ - case -8: IA64_FETCHADD(_tmp, _v, -8, sizeof(*(v))); break; \ - case -4: IA64_FETCHADD(_tmp, _v, -4, sizeof(*(v))); break; \ - case -1: IA64_FETCHADD(_tmp, _v, -1, sizeof(*(v))); break; \ - case 1: IA64_FETCHADD(_tmp, _v, 1, sizeof(*(v))); break; \ - case 4: IA64_FETCHADD(_tmp, _v, 4, sizeof(*(v))); break; \ - case 8: IA64_FETCHADD(_tmp, _v, 8, sizeof(*(v))); break; \ - case 16: IA64_FETCHADD(_tmp, _v, 16, sizeof(*(v))); break; \ - default: \ - _tmp = __bad_increment_for_ia64_fetch_and_add(); \ - break; \ - } \ - (__typeof__(*(v))) (_tmp + (i)); /* return new value */ \ +#define ia64_fetch_and_add(i,v) \ +({ \ + __u64 _tmp; \ + volatile __typeof__(*(v)) *_v = (v); \ + /* Can't use a switch () here: gcc isn't always smart enough for that... */ \ + if ((i) == -16) \ + IA64_FETCHADD(_tmp, _v, -16, sizeof(*(v))); \ + else if ((i) == -8) \ + IA64_FETCHADD(_tmp, _v, -8, sizeof(*(v))); \ + else if ((i) == -4) \ + IA64_FETCHADD(_tmp, _v, -4, sizeof(*(v))); \ + else if ((i) == -2) \ + IA64_FETCHADD(_tmp, _v, -2, sizeof(*(v))); \ + else if ((i) == -1) \ + IA64_FETCHADD(_tmp, _v, -1, sizeof(*(v))); \ + else if ((i) == 1) \ + IA64_FETCHADD(_tmp, _v, 1, sizeof(*(v))); \ + else if ((i) == 2) \ + IA64_FETCHADD(_tmp, _v, 2, sizeof(*(v))); \ + else if ((i) == 4) \ + IA64_FETCHADD(_tmp, _v, 4, sizeof(*(v))); \ + else if ((i) == 8) \ + IA64_FETCHADD(_tmp, _v, 8, sizeof(*(v))); \ + else if ((i) == 16) \ + IA64_FETCHADD(_tmp, _v, 16, sizeof(*(v))); \ + else \ + _tmp = __bad_increment_for_ia64_fetch_and_add(); \ + (__typeof__(*(v))) (_tmp + (i)); /* return new value */ \ }) /* diff -Nru a/include/asm-ia64/iosapic.h b/include/asm-ia64/iosapic.h --- a/include/asm-ia64/iosapic.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-ia64/iosapic.h Fri Mar 7 20:40:17 2003 @@ -51,26 +51,23 @@ #ifndef __ASSEMBLY__ -extern void __devinit iosapic_init (unsigned long address, - unsigned int gsi_base, - int pcat_compat); +extern void __init iosapic_system_init (int pcat_compat); +extern void __init iosapic_init (unsigned long address, + unsigned int gsi_base); extern int gsi_to_vector (unsigned int gsi); extern int gsi_to_irq (unsigned int gsi); -extern void iosapic_parse_prt (void); +extern void __init iosapic_parse_prt (void); extern int iosapic_register_intr (unsigned int gsi, unsigned long polarity, - unsigned long edge_triggered, - u32 gsi_base, char *iosapic_address); -extern void iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, + unsigned long trigger); +extern void __init iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, unsigned long polarity, - unsigned long edge_triggered); -extern int iosapic_register_platform_intr (u32 int_type, + unsigned long trigger); +extern int __init iosapic_register_platform_intr (u32 int_type, unsigned int gsi, int pmi_vector, u16 eid, u16 id, unsigned long polarity, - unsigned long edge_triggered, - unsigned int gsi_base, - char *iosapic_address); + unsigned long trigger); extern unsigned int iosapic_version (char *addr); extern void iosapic_pci_fixup (int); diff -Nru a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h --- a/include/asm-ia64/machvec.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-ia64/machvec.h Fri Mar 7 20:40:17 2003 @@ -23,8 +23,6 @@ typedef void ia64_mv_setup_t (char **); typedef void ia64_mv_cpu_init_t(void); typedef void ia64_mv_irq_init_t (void); -typedef void ia64_mv_pci_fixup_t (int); -typedef unsigned long ia64_mv_map_nr_t (unsigned long); typedef void ia64_mv_mca_init_t (void); typedef void ia64_mv_mca_handler_t (void); typedef void ia64_mv_cmci_handler_t (int, void *, struct pt_regs *); @@ -115,13 +113,16 @@ # define platofrm_mmiob ia64_mv.mmiob # endif +/* __attribute__((__aligned__(16))) is required to make size of the + * structure multiple of 16 bytes. + * This will fillup the holes created because of section 3.3.1 in + * Software Conventions guide. + */ struct ia64_machine_vector { const char *name; ia64_mv_setup_t *setup; ia64_mv_cpu_init_t *cpu_init; ia64_mv_irq_init_t *irq_init; - ia64_mv_pci_fixup_t *pci_fixup; - ia64_mv_map_nr_t *map_nr; ia64_mv_mca_init_t *mca_init; ia64_mv_mca_handler_t *mca_handler; ia64_mv_cmci_handler_t *cmci_handler; @@ -149,7 +150,7 @@ ia64_mv_outw_t *outw; ia64_mv_outl_t *outl; ia64_mv_mmiob_t *mmiob; -}; +} __attribute__((__aligned__(16))); #define MACHVEC_INIT(name) \ { \ diff -Nru a/include/asm-ia64/machvec_dig.h b/include/asm-ia64/machvec_dig.h --- a/include/asm-ia64/machvec_dig.h Fri Mar 7 20:40:16 2003 +++ b/include/asm-ia64/machvec_dig.h Fri Mar 7 20:40:16 2003 @@ -3,8 +3,6 @@ extern ia64_mv_setup_t dig_setup; extern ia64_mv_irq_init_t dig_irq_init; -extern ia64_mv_pci_fixup_t iosapic_pci_fixup; -extern ia64_mv_map_nr_t map_nr_dense; /* * This stuff has dual use! diff -Nru a/include/asm-ia64/machvec_hpsim.h b/include/asm-ia64/machvec_hpsim.h --- a/include/asm-ia64/machvec_hpsim.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-ia64/machvec_hpsim.h Fri Mar 7 20:40:17 2003 @@ -3,7 +3,6 @@ extern ia64_mv_setup_t hpsim_setup; extern ia64_mv_irq_init_t hpsim_irq_init; -extern ia64_mv_map_nr_t map_nr_dense; /* * This stuff has dual use! diff -Nru a/include/asm-ia64/machvec_hpzx1.h b/include/asm-ia64/machvec_hpzx1.h --- a/include/asm-ia64/machvec_hpzx1.h Fri Mar 7 20:40:16 2003 +++ b/include/asm-ia64/machvec_hpzx1.h Fri Mar 7 20:40:16 2003 @@ -2,8 +2,6 @@ #define _ASM_IA64_MACHVEC_HPZX1_h extern ia64_mv_setup_t dig_setup; -extern ia64_mv_pci_fixup_t hpzx1_pci_fixup; -extern ia64_mv_map_nr_t map_nr_dense; extern ia64_mv_pci_alloc_consistent sba_alloc_consistent; extern ia64_mv_pci_free_consistent sba_free_consistent; extern ia64_mv_pci_map_single sba_map_single; diff -Nru a/include/asm-ia64/machvec_sn1.h b/include/asm-ia64/machvec_sn1.h --- a/include/asm-ia64/machvec_sn1.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-ia64/machvec_sn1.h Fri Mar 7 20:40:17 2003 @@ -36,10 +36,8 @@ extern ia64_mv_setup_t sn1_setup; extern ia64_mv_cpu_init_t sn_cpu_init; extern ia64_mv_irq_init_t sn1_irq_init; -extern ia64_mv_map_nr_t sn1_map_nr; extern ia64_mv_send_ipi_t sn1_send_IPI; extern ia64_mv_global_tlb_purge_t sn1_global_tlb_purge; -extern ia64_mv_pci_fixup_t sn1_pci_fixup; extern ia64_mv_inb_t sn1_inb; extern ia64_mv_inw_t sn1_inw; extern ia64_mv_inl_t sn1_inl; diff -Nru a/include/asm-ia64/machvec_sn2.h b/include/asm-ia64/machvec_sn2.h --- a/include/asm-ia64/machvec_sn2.h Fri Mar 7 20:40:16 2003 +++ b/include/asm-ia64/machvec_sn2.h Fri Mar 7 20:40:16 2003 @@ -36,13 +36,11 @@ extern ia64_mv_setup_t sn_setup; extern ia64_mv_cpu_init_t sn_cpu_init; extern ia64_mv_irq_init_t sn_irq_init; -extern ia64_mv_map_nr_t sn2_map_nr; extern ia64_mv_send_ipi_t sn2_send_IPI; extern ia64_mv_global_tlb_purge_t sn2_global_tlb_purge; extern ia64_mv_irq_desc sn_irq_desc; extern ia64_mv_irq_to_vector sn_irq_to_vector; extern ia64_mv_local_vector_to_irq sn_local_vector_to_irq; -extern ia64_mv_pci_fixup_t sn_pci_fixup; extern ia64_mv_inb_t sn_inb; extern ia64_mv_inw_t sn_inw; extern ia64_mv_inl_t sn_inl; @@ -72,10 +70,8 @@ #define platform_setup sn_setup #define platform_cpu_init sn_cpu_init #define platform_irq_init sn_irq_init -#define platform_map_nr sn2_map_nr #define platform_send_ipi sn2_send_IPI #define platform_global_tlb_purge sn2_global_tlb_purge -#define platform_pci_fixup sn_pci_fixup #define platform_inb sn_inb #define platform_inw sn_inw #define platform_inl sn_inl diff -Nru a/include/asm-ia64/mmzone.h b/include/asm-ia64/mmzone.h --- a/include/asm-ia64/mmzone.h Fri Mar 7 20:40:18 2003 +++ b/include/asm-ia64/mmzone.h Fri Mar 7 20:40:18 2003 @@ -76,7 +76,7 @@ #define pfn_to_page(pfn) (struct page *)(node_mem_map(pfn_to_nid(pfn)) + node_localnr(pfn, pfn_to_nid(pfn))) -#define pfn_to_nid(pfn) local_node_data->node_id_map[(pfn << PAGE_SHIFT) >> DIG_BANKSHIFT] +#define pfn_to_nid(pfn) local_node_data->node_id_map[(pfn << PAGE_SHIFT) >> BANKSHIFT] #define page_to_pfn(page) (long)((page - page_zone(page)->zone_mem_map) + page_zone(page)->zone_start_pfn) @@ -110,15 +110,15 @@ */ #define NR_BANKS_PER_NODE 32 #if defined(CONFIG_IA64_NODESIZE_16GB) -# define DIG_BANKSHIFT 29 +# define BANKSHIFT 29 #elif defined(CONFIG_IA64_NODESIZE_64GB) -# define DIG_BANKSHIFT 31 +# define BANKSHIFT 31 #elif defined(CONFIG_IA64_NODESIZE_256GB) -# define DIG_BANKSHIFT 33 +# define BANKSHIFT 33 #else # error Unsupported bank and nodesize! #endif -#define BANKSIZE (1UL << DIG_BANKSHIFT) +#define BANKSIZE (1UL << BANKSHIFT) #define BANK_OFFSET(addr) ((unsigned long)(addr) & (BANKSIZE-1)) #define NR_BANKS (NR_BANKS_PER_NODE * NR_NODES) @@ -134,7 +134,30 @@ * entry for the first page of the bank. */ #define BANK_MEM_MAP_INDEX(kaddr) \ - (((unsigned long)(kaddr) & (MAX_PHYS_MEMORY-1)) >> DIG_BANKSHIFT) + (((unsigned long)(kaddr) & (MAX_PHYS_MEMORY-1)) >> BANKSHIFT) + +#elif defined(CONFIG_IA64_SGI_SN2) +/* + * SGI SN2 discontig definitions + */ +#define MAX_PHYSNODE_ID 2048 /* 2048 node ids (also called nasid) */ +#define NR_NODES 128 /* Maximum number of nodes in SSI */ +#define MAX_PHYS_MEMORY (1UL << 49) + +#define BANKSHIFT 38 +#define NR_BANKS_PER_NODE 4 +#define SN2_NODE_SIZE (64UL*1024*1024*1024) /* 64GB per node */ +#define BANKSIZE (SN2_NODE_SIZE/NR_BANKS_PER_NODE) +#define BANK_OFFSET(addr) ((unsigned long)(addr) & (BANKSIZE-1)) +#define NR_BANKS (NR_BANKS_PER_NODE * NR_NODES) +#define VALID_MEM_KADDR(kaddr) 1 + +/* + * Given a nodeid & a bank number, find the address of the mem_map + * entry for the first page of the bank. + */ +#define BANK_MEM_MAP_INDEX(kaddr) \ + (((unsigned long)(kaddr) & (MAX_PHYS_MEMORY-1)) >> BANKSHIFT) #endif /* CONFIG_IA64_DIG */ #endif /* _ASM_IA64_MMZONE_H */ diff -Nru a/include/asm-ia64/page.h b/include/asm-ia64/page.h --- a/include/asm-ia64/page.h Fri Mar 7 20:40:16 2003 +++ b/include/asm-ia64/page.h Fri Mar 7 20:40:16 2003 @@ -57,16 +57,7 @@ # define REGION_SHIFT 61 # define HPAGE_SIZE (__IA64_UL_CONST(1) << HPAGE_SHIFT) # define HPAGE_MASK (~(HPAGE_SIZE - 1)) -static inline int -check_valid_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; -} -#define ARCH_HAS_VALID_HUGEPAGE_RANGE +# define HAVE_ARCH_HUGETLB_UNMAPPED_AREA #endif /* CONFIG_HUGETLB_PAGE */ #ifdef __ASSEMBLY__ @@ -133,6 +124,9 @@ # define htlbpage_to_page(x) ((REGION_NUMBER(x) << 61) \ | (REGION_OFFSET(x) >> (HPAGE_SHIFT-PAGE_SHIFT))) # define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) +extern int is_invalid_hugepage_range(unsigned long addr, unsigned long len); +#else +#define is_invalid_hugepage_range(addr, len) 0 #endif static __inline__ int diff -Nru a/include/asm-ia64/pci.h b/include/asm-ia64/pci.h --- a/include/asm-ia64/pci.h Fri Mar 7 20:40:18 2003 +++ b/include/asm-ia64/pci.h Fri Mar 7 20:40:18 2003 @@ -44,6 +44,9 @@ /* We don't do dynamic PCI IRQ allocation */ } +#define HAVE_ARCH_PCI_MWI 1 +extern int pcibios_prep_mwi (struct pci_dev *); + /* * Dynamic DMA mapping API. See Documentation/DMA-mapping.txt for details. */ diff -Nru a/include/asm-ia64/perfmon.h b/include/asm-ia64/perfmon.h --- a/include/asm-ia64/perfmon.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-ia64/perfmon.h Fri Mar 7 20:40:17 2003 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2002 Hewlett-Packard Co + * Copyright (C) 2001-2003 Hewlett-Packard Co * Stephane Eranian */ diff -Nru a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h --- a/include/asm-ia64/pgtable.h Fri Mar 7 20:40:16 2003 +++ b/include/asm-ia64/pgtable.h Fri Mar 7 20:40:16 2003 @@ -317,8 +317,8 @@ * Find an entry in the third-level page table. This looks more complicated than it * should be because some platforms place page tables in high memory. */ -#define __pte_offset(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) -#define pte_offset_kernel(dir,addr) ((pte_t *) pmd_page_kernel(*(dir)) + __pte_offset(addr)) +#define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) +#define pte_offset_kernel(dir,addr) ((pte_t *) pmd_page_kernel(*(dir)) + pte_index(addr)) #define pte_offset_map(dir,addr) pte_offset_kernel(dir, addr) #define pte_offset_map_nested(dir,addr) pte_offset_map(dir, addr) #define pte_unmap(pte) do { } while (0) diff -Nru a/include/asm-ia64/posix_types.h b/include/asm-ia64/posix_types.h --- a/include/asm-ia64/posix_types.h Fri Mar 7 20:40:16 2003 +++ b/include/asm-ia64/posix_types.h Fri Mar 7 20:40:16 2003 @@ -6,8 +6,8 @@ * be a little careful about namespace pollution etc. Also, we cannot * assume GCC is being used. * - * Copyright (C) 1998-2000 Hewlett-Packard Co - * Copyright (C) 1998-2000 David Mosberger-Tang + * Copyright (C) 1998-2000, 2003 Hewlett-Packard Co + * David Mosberger-Tang */ typedef unsigned int __kernel_dev_t; @@ -26,6 +26,8 @@ typedef long __kernel_time_t; typedef long __kernel_suseconds_t; typedef long __kernel_clock_t; +typedef int __kernel_timer_t; +typedef int __kernel_clockid_t; typedef int __kernel_daddr_t; typedef char * __kernel_caddr_t; typedef unsigned long __kernel_sigset_t; /* at least 32 bits */ diff -Nru a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h --- a/include/asm-ia64/processor.h Fri Mar 7 20:40:16 2003 +++ b/include/asm-ia64/processor.h Fri Mar 7 20:40:16 2003 @@ -68,11 +68,11 @@ /* - * This shift should be large enough to be able to represent - * 1000000/itc_freq with good accuracy while being small enough to fit - * 1000000<. */ #define PTRACE_SINGLEBLOCK 12 /* resume execution until next branch */ -#define PTRACE_GETSIGINFO 13 /* get child's siginfo structure */ -#define PTRACE_SETSIGINFO 14 /* set child's siginfo structure */ +#define PTRACE_OLD_GETSIGINFO 13 /* (replaced by PTRACE_GETSIGINFO in ) */ +#define PTRACE_OLD_SETSIGINFO 14 /* (replaced by PTRACE_SETSIGINFO in ) */ #define PTRACE_GETREGS 18 /* get all registers (pt_all_user_regs) in one shot */ #define PTRACE_SETREGS 19 /* set all registers (pt_all_user_regs) in one shot */ diff -Nru a/include/asm-ia64/rwsem.h b/include/asm-ia64/rwsem.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-ia64/rwsem.h Fri Mar 7 20:40:18 2003 @@ -0,0 +1,188 @@ +/* + * asm-ia64/rwsem.h: R/W semaphores for ia64 + * + * Copyright (C) 2003 Ken Chen + * Copyright (C) 2003 Asit Mallick + * + * Based on asm-i386/rwsem.h and other architecture implementation. + * + * The MSW of the count is the negated number of active writers and + * waiting lockers, and the LSW is the total number of active locks. + * + * The lock count is initialized to 0 (no active and no waiting lockers). + * + * When a writer subtracts WRITE_BIAS, it'll get 0xffff0001 for the case + * of an uncontended lock. Readers increment by 1 and see a positive value + * when uncontended, negative if there are writers (and maybe) readers + * waiting (in which case it goes to sleep). + */ + +#ifndef _ASM_IA64_RWSEM_H +#define _ASM_IA64_RWSEM_H + +#include +#include + +/* + * the semaphore definition + */ +struct rw_semaphore { + signed int count; + spinlock_t wait_lock; + struct list_head wait_list; +#if RWSEM_DEBUG + int debug; +#endif +}; + +#define RWSEM_UNLOCKED_VALUE 0x00000000 +#define RWSEM_ACTIVE_BIAS 0x00000001 +#define RWSEM_ACTIVE_MASK 0x0000ffff +#define RWSEM_WAITING_BIAS (-0x00010000) +#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS +#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) + +/* + * initialization + */ +#if RWSEM_DEBUG +#define __RWSEM_DEBUG_INIT , 0 +#else +#define __RWSEM_DEBUG_INIT /* */ +#endif + +#define __RWSEM_INITIALIZER(name) \ + { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \ + LIST_HEAD_INIT((name).wait_list) \ + __RWSEM_DEBUG_INIT } + +#define DECLARE_RWSEM(name) \ + struct rw_semaphore name = __RWSEM_INITIALIZER(name) + +extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem); +extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem); +extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem); +extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem); + +static inline void +init_rwsem (struct rw_semaphore *sem) +{ + sem->count = RWSEM_UNLOCKED_VALUE; + spin_lock_init(&sem->wait_lock); + INIT_LIST_HEAD(&sem->wait_list); +#if RWSEM_DEBUG + sem->debug = 0; +#endif +} + +/* + * lock for reading + */ +static inline void +__down_read (struct rw_semaphore *sem) +{ + int result; + __asm__ __volatile__ ("fetchadd4.acq %0=[%1],1" : + "=r"(result) : "r"(&sem->count) : "memory"); + if (result < 0) + rwsem_down_read_failed(sem); +} + +/* + * lock for writing + */ +static inline void +__down_write (struct rw_semaphore *sem) +{ + int old, new; + + do { + old = sem->count; + new = old + RWSEM_ACTIVE_WRITE_BIAS; + } while (cmpxchg_acq(&sem->count, old, new) != old); + + if (old != 0) + rwsem_down_write_failed(sem); +} + +/* + * unlock after reading + */ +static inline void +__up_read (struct rw_semaphore *sem) +{ + int result; + __asm__ __volatile__ ("fetchadd4.rel %0=[%1],-1" : + "=r"(result) : "r"(&sem->count) : "memory"); + if (result < 0 && (--result & RWSEM_ACTIVE_MASK) == 0) + rwsem_wake(sem); +} + +/* + * unlock after writing + */ +static inline void +__up_write (struct rw_semaphore *sem) +{ + int old, new; + + do { + old = sem->count; + new = old - RWSEM_ACTIVE_WRITE_BIAS; + } while (cmpxchg_rel(&sem->count, old, new) != old); + + if (new < 0 && (new & RWSEM_ACTIVE_MASK) == 0) + rwsem_wake(sem); +} + +/* + * trylock for reading -- returns 1 if successful, 0 if contention + */ +static inline int +__down_read_trylock (struct rw_semaphore *sem) +{ + int tmp; + while ((tmp = sem->count) >= 0) { + if (tmp == cmpxchg_acq(&sem->count, tmp, tmp+1)) { + return 1; + } + } + return 0; +} + +/* + * trylock for writing -- returns 1 if successful, 0 if contention + */ +static inline int +__down_write_trylock (struct rw_semaphore *sem) +{ + int tmp = cmpxchg_acq(&sem->count, RWSEM_UNLOCKED_VALUE, + RWSEM_ACTIVE_WRITE_BIAS); + return tmp == RWSEM_UNLOCKED_VALUE; +} + +/* + * downgrade write lock to read lock + */ +static inline void +__downgrade_write (struct rw_semaphore *sem) +{ + int old, new; + + do { + old = sem->count; + new = old - RWSEM_WAITING_BIAS; + } while (cmpxchg_rel(&sem->count, old, new) != old); + + if (old < 0) + rwsem_downgrade_wake(sem); +} + +/* + * Implement atomic add functionality. These used to be "inline" functions, but GCC v3.1 + * doesn't quite optimize this stuff right and ends up with bad calls to fetchandadd. + */ +#define rwsem_atomic_add(delta, sem) atomic_add(delta, (atomic_t *)(&(sem)->count)) +#define rwsem_atomic_update(delta, sem) atomic_add_return(delta, (atomic_t *)(&(sem)->count)) + +#endif /* _ASM_IA64_RWSEM_H */ diff -Nru a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h --- a/include/asm-ia64/sal.h Fri Mar 7 20:40:18 2003 +++ b/include/asm-ia64/sal.h Fri Mar 7 20:40:18 2003 @@ -10,8 +10,8 @@ * Copyright (C) 2001 Intel * Copyright (C) 2002 Jenna Hall * Copyright (C) 2001 Fred Lewis - * Copyright (C) 1998, 1999, 2001 Hewlett-Packard Co - * Copyright (C) 1998, 1999, 2001 David Mosberger-Tang + * Copyright (C) 1998, 1999, 2001, 2003 Hewlett-Packard Co + * David Mosberger-Tang * Copyright (C) 1999 Srinivasa Prasad Thirumalachar * * 02/01/04 J. Hall Updated Error Record Structures to conform to July 2001 @@ -19,7 +19,7 @@ * 01/01/03 fvlewis Updated Error Record Structures to conform with Nov. 2000 * revision of the SAL spec. * 99/09/29 davidm Updated for SAL 2.6. - * 00/03/29 cfleck Updated SAL Error Logging info for processor (SAL 2.6) + * 00/03/29 cfleck Updated SAL Error Logging info for processor (SAL 2.6) * (plus examples of platform error info structures from smariset @ Intel) */ @@ -208,30 +208,30 @@ /* SAL information type encodings */ enum { - SAL_INFO_TYPE_MCA = 0, /* Machine check abort information */ - SAL_INFO_TYPE_INIT = 1, /* Init information */ - SAL_INFO_TYPE_CMC = 2, /* Corrected machine check information */ - SAL_INFO_TYPE_CPE = 3 /* Corrected platform error information */ + SAL_INFO_TYPE_MCA = 0, /* Machine check abort information */ + SAL_INFO_TYPE_INIT = 1, /* Init information */ + SAL_INFO_TYPE_CMC = 2, /* Corrected machine check information */ + SAL_INFO_TYPE_CPE = 3 /* Corrected platform error information */ }; /* Encodings for machine check parameter types */ enum { - SAL_MC_PARAM_RENDEZ_INT = 1, /* Rendezevous interrupt */ - SAL_MC_PARAM_RENDEZ_WAKEUP = 2, /* Wakeup */ - SAL_MC_PARAM_CPE_INT = 3 /* Corrected Platform Error Int */ + SAL_MC_PARAM_RENDEZ_INT = 1, /* Rendezevous interrupt */ + SAL_MC_PARAM_RENDEZ_WAKEUP = 2, /* Wakeup */ + SAL_MC_PARAM_CPE_INT = 3 /* Corrected Platform Error Int */ }; /* Encodings for rendezvous mechanisms */ enum { - SAL_MC_PARAM_MECHANISM_INT = 1, /* Use interrupt */ - SAL_MC_PARAM_MECHANISM_MEM = 2 /* Use memory synchronization variable*/ + SAL_MC_PARAM_MECHANISM_INT = 1, /* Use interrupt */ + SAL_MC_PARAM_MECHANISM_MEM = 2 /* Use memory synchronization variable*/ }; /* Encodings for vectors which can be registered by the OS with SAL */ enum { - SAL_VECTOR_OS_MCA = 0, - SAL_VECTOR_OS_INIT = 1, - SAL_VECTOR_OS_BOOT_RENDEZ = 2 + SAL_VECTOR_OS_MCA = 0, + SAL_VECTOR_OS_INIT = 1, + SAL_VECTOR_OS_BOOT_RENDEZ = 2 }; /* Encodings for mca_opt parameter sent to SAL_MC_SET_PARAMS */ @@ -239,387 +239,370 @@ #define SAL_MC_PARAM_BINIT_ESCALATE 0x10 /* -** Definition of the SAL Error Log from the SAL spec -*/ + * Definition of the SAL Error Log from the SAL spec + */ /* SAL Error Record Section GUID Definitions */ #define SAL_PROC_DEV_ERR_SECT_GUID \ - EFI_GUID ( 0xe429faf1, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \ - 0xc7, 0x3c, 0x88, 0x81 ) + EFI_GUID(0xe429faf1, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81) #define SAL_PLAT_MEM_DEV_ERR_SECT_GUID \ - EFI_GUID( 0xe429faf2, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \ - 0xc7, 0x3c, 0x88, 0x81 ) + EFI_GUID(0xe429faf2, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81) #define SAL_PLAT_SEL_DEV_ERR_SECT_GUID \ - EFI_GUID( 0xe429faf3, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \ - 0xc7, 0x3c, 0x88, 0x81 ) + EFI_GUID(0xe429faf3, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81) #define SAL_PLAT_PCI_BUS_ERR_SECT_GUID \ - EFI_GUID( 0xe429faf4, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \ - 0xc7, 0x3c, 0x88, 0x81 ) + EFI_GUID(0xe429faf4, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81) #define SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID \ - EFI_GUID( 0xe429faf5, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \ - 0xc7, 0x3c, 0x88, 0x81 ) + EFI_GUID(0xe429faf5, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81) #define SAL_PLAT_PCI_COMP_ERR_SECT_GUID \ - EFI_GUID( 0xe429faf6, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \ - 0xc7, 0x3c, 0x88, 0x81 ) + EFI_GUID(0xe429faf6, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81) #define SAL_PLAT_SPECIFIC_ERR_SECT_GUID \ - EFI_GUID( 0xe429faf7, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \ - 0xc7, 0x3c, 0x88, 0x81 ) + EFI_GUID(0xe429faf7, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81) #define SAL_PLAT_HOST_CTLR_ERR_SECT_GUID \ - EFI_GUID( 0xe429faf8, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \ - 0xc7, 0x3c, 0x88, 0x81 ) + EFI_GUID(0xe429faf8, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81) #define SAL_PLAT_BUS_ERR_SECT_GUID \ - EFI_GUID( 0xe429faf9, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, \ - 0xc7, 0x3c, 0x88, 0x81 ) + EFI_GUID(0xe429faf9, 0x3cb7, 0x11d4, 0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81) -#define MAX_CACHE_ERRORS 6 -#define MAX_TLB_ERRORS 6 -#define MAX_BUS_ERRORS 1 +#define MAX_CACHE_ERRORS 6 +#define MAX_TLB_ERRORS 6 +#define MAX_BUS_ERRORS 1 /* Definition of version according to SAL spec for logging purposes */ -typedef struct sal_log_revision -{ - u8 minor; /* BCD (0..99) */ - u8 major; /* BCD (0..99) */ +typedef struct sal_log_revision { + u8 minor; /* BCD (0..99) */ + u8 major; /* BCD (0..99) */ } sal_log_revision_t; /* Definition of timestamp according to SAL spec for logging purposes */ -typedef struct sal_log_timestamp -{ +typedef struct sal_log_timestamp { u8 slh_second; /* Second (0..59) */ - u8 slh_minute; /* Minute (0..59) */ - u8 slh_hour; /* Hour (0..23) */ - u8 slh_reserved; - u8 slh_day; /* Day (1..31) */ - u8 slh_month; /* Month (1..12) */ - u8 slh_year; /* Year (00..99) */ - u8 slh_century; /* Century (19, 20, 21, ...) */ + u8 slh_minute; /* Minute (0..59) */ + u8 slh_hour; /* Hour (0..23) */ + u8 slh_reserved; + u8 slh_day; /* Day (1..31) */ + u8 slh_month; /* Month (1..12) */ + u8 slh_year; /* Year (00..99) */ + u8 slh_century; /* Century (19, 20, 21, ...) */ } sal_log_timestamp_t; /* Definition of log record header structures */ -typedef struct sal_log_record_header -{ - u64 id; /* Unique monotonically increasing ID */ - sal_log_revision_t revision; /* Major and Minor revision of header */ - u16 severity; /* Error Severity */ - u32 len; /* Length of this error log in bytes */ - sal_log_timestamp_t timestamp; /* Timestamp */ - efi_guid_t platform_guid; /* Unique OEM Platform ID */ +typedef struct sal_log_record_header { + u64 id; /* Unique monotonically increasing ID */ + sal_log_revision_t revision; /* Major and Minor revision of header */ + u16 severity; /* Error Severity */ + u32 len; /* Length of this error log in bytes */ + sal_log_timestamp_t timestamp; /* Timestamp */ + efi_guid_t platform_guid; /* Unique OEM Platform ID */ } sal_log_record_header_t; /* Definition of log section header structures */ -typedef struct sal_log_sec_header -{ - efi_guid_t guid; /* Unique Section ID */ - sal_log_revision_t revision; /* Major and Minor revision of Section */ - u16 reserved; - u32 len; /* Section length */ +typedef struct sal_log_sec_header { + efi_guid_t guid; /* Unique Section ID */ + sal_log_revision_t revision; /* Major and Minor revision of Section */ + u16 reserved; + u32 len; /* Section length */ } sal_log_section_hdr_t; -typedef struct sal_log_mod_error_info -{ - struct - { - u64 check_info : 1, - requestor_identifier : 1, - responder_identifier : 1, - target_identifier : 1, - precise_ip : 1, - reserved : 59; - } valid; - u64 check_info; - u64 requestor_identifier; - u64 responder_identifier; - u64 target_identifier; - u64 precise_ip; +typedef struct sal_log_mod_error_info { + struct { + u64 check_info : 1, + requestor_identifier : 1, + responder_identifier : 1, + target_identifier : 1, + precise_ip : 1, + reserved : 59; + } valid; + u64 check_info; + u64 requestor_identifier; + u64 responder_identifier; + u64 target_identifier; + u64 precise_ip; } sal_log_mod_error_info_t; -typedef struct sal_processor_static_info -{ - struct - { - u64 minstate : 1, - br : 1, - cr : 1, - ar : 1, - rr : 1, - fr : 1, - reserved : 58; - } valid; - pal_min_state_area_t min_state_area; - u64 br[8]; - u64 cr[128]; - u64 ar[128]; - u64 rr[8]; - struct ia64_fpreg fr[128]; +typedef struct sal_processor_static_info { + struct { + u64 minstate : 1, + br : 1, + cr : 1, + ar : 1, + rr : 1, + fr : 1, + reserved : 58; + } valid; + pal_min_state_area_t min_state_area; + u64 br[8]; + u64 cr[128]; + u64 ar[128]; + u64 rr[8]; + struct ia64_fpreg fr[128]; } sal_processor_static_info_t; -typedef struct sal_log_processor_info -{ - sal_log_section_hdr_t header; - struct - { - u64 proc_error_map : 1, - proc_state_param : 1, - proc_cr_lid : 1, - psi_static_struct : 1, - num_cache_check : 4, - num_tlb_check : 4, - num_bus_check : 4, - num_reg_file_check : 4, - num_ms_check : 4, - cpuid_info : 1, - reserved1 : 39; - } valid; - u64 proc_error_map; - u64 proc_state_parameter; - u64 proc_cr_lid; - sal_log_mod_error_info_t cache_check_info[16]; - sal_log_mod_error_info_t tlb_check_info[16]; - sal_log_mod_error_info_t bus_check_info[16]; - sal_log_mod_error_info_t reg_file_check_info[16]; - sal_log_mod_error_info_t ms_check_info[16]; - struct - { - u64 regs[5]; - u64 reserved; - } cpuid_info; - sal_processor_static_info_t processor_static_info; +struct sal_cpuid_info { + u64 regs[5]; + u64 reserved; +}; + +typedef struct sal_log_processor_info { + sal_log_section_hdr_t header; + struct { + u64 proc_error_map : 1, + proc_state_param : 1, + proc_cr_lid : 1, + psi_static_struct : 1, + num_cache_check : 4, + num_tlb_check : 4, + num_bus_check : 4, + num_reg_file_check : 4, + num_ms_check : 4, + cpuid_info : 1, + reserved1 : 39; + } valid; + u64 proc_error_map; + u64 proc_state_parameter; + u64 proc_cr_lid; + /* + * The rest of this structure consists of variable-length arrays, which can't be + * expressed in C. + */ + sal_log_mod_error_info_t info[0]; + /* + * This is what the rest looked like if C supported variable-length arrays: + * + * sal_log_mod_error_info_t cache_check_info[.valid.num_cache_check]; + * sal_log_mod_error_info_t tlb_check_info[.valid.num_tlb_check]; + * sal_log_mod_error_info_t bus_check_info[.valid.num_bus_check]; + * sal_log_mod_error_info_t reg_file_check_info[.valid.num_reg_file_check]; + * sal_log_mod_error_info_t ms_check_info[.valid.num_ms_check]; + * struct sal_cpuid_info cpuid_info; + * sal_processor_static_info_t processor_static_info; + */ } sal_log_processor_info_t; +/* Given a sal_log_processor_info_t pointer, return a pointer to the processor_static_info: */ +#define SAL_LPI_PSI_INFO(l) \ +({ sal_log_processor_info_t *_l = (l); \ + ((sal_processor_static_info_t *) \ + ((char *) _l->info + ((_l->valid.num_cache_check + _l->valid.num_tlb_check \ + + _l->valid.num_bus_check + _l->valid.num_reg_file_check \ + + _l->valid.num_ms_check) * sizeof(sal_log_mod_error_info_t) \ + + sizeof(struct sal_cpuid_info)))); \ +}) + /* platform error log structures */ -typedef struct sal_log_mem_dev_err_info -{ - sal_log_section_hdr_t header; - struct - { - u64 error_status : 1, - physical_addr : 1, - addr_mask : 1, - node : 1, - card : 1, - module : 1, - bank : 1, - device : 1, - row : 1, - column : 1, - bit_position : 1, - requestor_id : 1, - responder_id : 1, - target_id : 1, - bus_spec_data : 1, - oem_id : 1, - oem_data : 1, - reserved : 47; - } valid; - u64 error_status; - u64 physical_addr; - u64 addr_mask; - u16 node; - u16 card; - u16 module; - u16 bank; - u16 device; - u16 row; - u16 column; - u16 bit_position; - u64 requestor_id; - u64 responder_id; - u64 target_id; - u64 bus_spec_data; - u8 oem_id[16]; - u8 oem_data[1]; /* Variable length data */ +typedef struct sal_log_mem_dev_err_info { + sal_log_section_hdr_t header; + struct { + u64 error_status : 1, + physical_addr : 1, + addr_mask : 1, + node : 1, + card : 1, + module : 1, + bank : 1, + device : 1, + row : 1, + column : 1, + bit_position : 1, + requestor_id : 1, + responder_id : 1, + target_id : 1, + bus_spec_data : 1, + oem_id : 1, + oem_data : 1, + reserved : 47; + } valid; + u64 error_status; + u64 physical_addr; + u64 addr_mask; + u16 node; + u16 card; + u16 module; + u16 bank; + u16 device; + u16 row; + u16 column; + u16 bit_position; + u64 requestor_id; + u64 responder_id; + u64 target_id; + u64 bus_spec_data; + u8 oem_id[16]; + u8 oem_data[1]; /* Variable length data */ } sal_log_mem_dev_err_info_t; -typedef struct sal_log_sel_dev_err_info -{ - sal_log_section_hdr_t header; - struct - { - u64 record_id : 1, - record_type : 1, - generator_id : 1, - evm_rev : 1, - sensor_type : 1, - sensor_num : 1, - event_dir : 1, - event_data1 : 1, - event_data2 : 1, - event_data3 : 1, - reserved : 54; - } valid; - u16 record_id; - u8 record_type; - u8 timestamp[4]; - u16 generator_id; - u8 evm_rev; - u8 sensor_type; - u8 sensor_num; - u8 event_dir; - u8 event_data1; - u8 event_data2; - u8 event_data3; +typedef struct sal_log_sel_dev_err_info { + sal_log_section_hdr_t header; + struct { + u64 record_id : 1, + record_type : 1, + generator_id : 1, + evm_rev : 1, + sensor_type : 1, + sensor_num : 1, + event_dir : 1, + event_data1 : 1, + event_data2 : 1, + event_data3 : 1, + reserved : 54; + } valid; + u16 record_id; + u8 record_type; + u8 timestamp[4]; + u16 generator_id; + u8 evm_rev; + u8 sensor_type; + u8 sensor_num; + u8 event_dir; + u8 event_data1; + u8 event_data2; + u8 event_data3; } sal_log_sel_dev_err_info_t; -typedef struct sal_log_pci_bus_err_info -{ - sal_log_section_hdr_t header; - struct - { - u64 err_status : 1, - err_type : 1, - bus_id : 1, - bus_address : 1, - bus_data : 1, - bus_cmd : 1, - requestor_id : 1, - responder_id : 1, - target_id : 1, - oem_data : 1, - reserved : 54; - } valid; - u64 err_status; - u16 err_type; - u16 bus_id; - u32 reserved; - u64 bus_address; - u64 bus_data; - u64 bus_cmd; - u64 requestor_id; - u64 responder_id; - u64 target_id; - u8 oem_data[1]; /* Variable length data */ +typedef struct sal_log_pci_bus_err_info { + sal_log_section_hdr_t header; + struct { + u64 err_status : 1, + err_type : 1, + bus_id : 1, + bus_address : 1, + bus_data : 1, + bus_cmd : 1, + requestor_id : 1, + responder_id : 1, + target_id : 1, + oem_data : 1, + reserved : 54; + } valid; + u64 err_status; + u16 err_type; + u16 bus_id; + u32 reserved; + u64 bus_address; + u64 bus_data; + u64 bus_cmd; + u64 requestor_id; + u64 responder_id; + u64 target_id; + u8 oem_data[1]; /* Variable length data */ } sal_log_pci_bus_err_info_t; -typedef struct sal_log_smbios_dev_err_info -{ - sal_log_section_hdr_t header; - struct - { - u64 event_type : 1, - length : 1, - time_stamp : 1, - data : 1, - reserved1 : 60; - } valid; - u8 event_type; - u8 length; - u8 time_stamp[6]; - u8 data[1]; // data of variable length, length == slsmb_length +typedef struct sal_log_smbios_dev_err_info { + sal_log_section_hdr_t header; + struct { + u64 event_type : 1, + length : 1, + time_stamp : 1, + data : 1, + reserved1 : 60; + } valid; + u8 event_type; + u8 length; + u8 time_stamp[6]; + u8 data[1]; /* data of variable length, length == slsmb_length */ } sal_log_smbios_dev_err_info_t; -typedef struct sal_log_pci_comp_err_info -{ - sal_log_section_hdr_t header; - struct - { - u64 err_status : 1, - comp_info : 1, - num_mem_regs : 1, - num_io_regs : 1, - reg_data_pairs : 1, - oem_data : 1, - reserved : 58; - } valid; - u64 err_status; - struct - { - u16 vendor_id; - u16 device_id; - u8 class_code[3]; - u8 func_num; - u8 dev_num; - u8 bus_num; - u8 seg_num; - u8 reserved[5]; - } comp_info; - u32 num_mem_regs; - u32 num_io_regs; - u64 reg_data_pairs[1]; - /* array of address/data register pairs is num_mem_regs + num_io_regs - elements long. Each array element consists of a u64 address followed - by a u64 data value. The oem_data array immediately follows the - reg_data_pairs array */ - u8 oem_data[1]; /* Variable length data */ +typedef struct sal_log_pci_comp_err_info { + sal_log_section_hdr_t header; + struct { + u64 err_status : 1, + comp_info : 1, + num_mem_regs : 1, + num_io_regs : 1, + reg_data_pairs : 1, + oem_data : 1, + reserved : 58; + } valid; + u64 err_status; + struct { + u16 vendor_id; + u16 device_id; + u8 class_code[3]; + u8 func_num; + u8 dev_num; + u8 bus_num; + u8 seg_num; + u8 reserved[5]; + } comp_info; + u32 num_mem_regs; + u32 num_io_regs; + u64 reg_data_pairs[1]; + /* + * array of address/data register pairs is num_mem_regs + num_io_regs elements + * long. Each array element consists of a u64 address followed by a u64 data + * value. The oem_data array immediately follows the reg_data_pairs array + */ + u8 oem_data[1]; /* Variable length data */ } sal_log_pci_comp_err_info_t; -typedef struct sal_log_plat_specific_err_info -{ - sal_log_section_hdr_t header; - struct - { - u64 err_status : 1, - guid : 1, - oem_data : 1, - reserved : 61; - } valid; - u64 err_status; - efi_guid_t guid; - u8 oem_data[1]; /* platform specific variable length data */ +typedef struct sal_log_plat_specific_err_info { + sal_log_section_hdr_t header; + struct { + u64 err_status : 1, + guid : 1, + oem_data : 1, + reserved : 61; + } valid; + u64 err_status; + efi_guid_t guid; + u8 oem_data[1]; /* platform specific variable length data */ } sal_log_plat_specific_err_info_t; -typedef struct sal_log_host_ctlr_err_info -{ - sal_log_section_hdr_t header; - struct - { - u64 err_status : 1, - requestor_id : 1, - responder_id : 1, - target_id : 1, - bus_spec_data : 1, - oem_data : 1, - reserved : 58; - } valid; - u64 err_status; - u64 requestor_id; - u64 responder_id; - u64 target_id; - u64 bus_spec_data; - u8 oem_data[1]; /* Variable length OEM data */ +typedef struct sal_log_host_ctlr_err_info { + sal_log_section_hdr_t header; + struct { + u64 err_status : 1, + requestor_id : 1, + responder_id : 1, + target_id : 1, + bus_spec_data : 1, + oem_data : 1, + reserved : 58; + } valid; + u64 err_status; + u64 requestor_id; + u64 responder_id; + u64 target_id; + u64 bus_spec_data; + u8 oem_data[1]; /* Variable length OEM data */ } sal_log_host_ctlr_err_info_t; -typedef struct sal_log_plat_bus_err_info -{ - sal_log_section_hdr_t header; - struct - { - u64 err_status : 1, - requestor_id : 1, - responder_id : 1, - target_id : 1, - bus_spec_data : 1, - oem_data : 1, - reserved : 58; - } valid; - u64 err_status; - u64 requestor_id; - u64 responder_id; - u64 target_id; - u64 bus_spec_data; - u8 oem_data[1]; /* Variable length OEM data */ +typedef struct sal_log_plat_bus_err_info { + sal_log_section_hdr_t header; + struct { + u64 err_status : 1, + requestor_id : 1, + responder_id : 1, + target_id : 1, + bus_spec_data : 1, + oem_data : 1, + reserved : 58; + } valid; + u64 err_status; + u64 requestor_id; + u64 responder_id; + u64 target_id; + u64 bus_spec_data; + u8 oem_data[1]; /* Variable length OEM data */ } sal_log_plat_bus_err_info_t; /* Overall platform error section structure */ -typedef union sal_log_platform_err_info -{ - sal_log_mem_dev_err_info_t mem_dev_err; - sal_log_sel_dev_err_info_t sel_dev_err; - sal_log_pci_bus_err_info_t pci_bus_err; - sal_log_smbios_dev_err_info_t smbios_dev_err; - sal_log_pci_comp_err_info_t pci_comp_err; - sal_log_plat_specific_err_info_t plat_specific_err; - sal_log_host_ctlr_err_info_t host_ctlr_err; - sal_log_plat_bus_err_info_t plat_bus_err; +typedef union sal_log_platform_err_info { + sal_log_mem_dev_err_info_t mem_dev_err; + sal_log_sel_dev_err_info_t sel_dev_err; + sal_log_pci_bus_err_info_t pci_bus_err; + sal_log_smbios_dev_err_info_t smbios_dev_err; + sal_log_pci_comp_err_info_t pci_comp_err; + sal_log_plat_specific_err_info_t plat_specific_err; + sal_log_host_ctlr_err_info_t host_ctlr_err; + sal_log_plat_bus_err_info_t plat_bus_err; } sal_log_platform_err_info_t; /* SAL log over-all, multi-section error record structure (processor+platform) */ -typedef struct err_rec -{ - sal_log_record_header_t sal_elog_header; - sal_log_processor_info_t proc_err; - sal_log_platform_err_info_t plat_err; - u8 oem_data_pad[1024]; +typedef struct err_rec { + sal_log_record_header_t sal_elog_header; + sal_log_processor_info_t proc_err; + sal_log_platform_err_info_t plat_err; + u8 oem_data_pad[1024]; } ia64_err_rec_t; /* @@ -648,7 +631,6 @@ } - /* Initialize all the processor and platform level instruction and data caches */ static inline s64 ia64_sal_cache_init (void) @@ -658,8 +640,9 @@ return isrv.status; } -/* Clear the processor and platform information logged by SAL with respect to the - * machine state at the time of MCA's, INITs, CMCs, or CPEs. +/* + * Clear the processor and platform information logged by SAL with respect to the machine + * state at the time of MCA's, INITs, CMCs, or CPEs. */ static inline s64 ia64_sal_clear_state_info (u64 sal_info_type) @@ -684,9 +667,11 @@ return 0; return isrv.v0; -} -/* Get the maximum size of the information logged by SAL with respect to the machine - * state at the time of MCAs, INITs, CMCs, or CPEs. +} + +/* + * Get the maximum size of the information logged by SAL with respect to the machine state + * at the time of MCAs, INITs, CMCs, or CPEs. */ static inline u64 ia64_sal_get_state_info_size (u64 sal_info_type) @@ -699,8 +684,9 @@ return isrv.v0; } -/* Causes the processor to go into a spin loop within SAL where SAL awaits a wakeup - * from the monarch processor. +/* + * Causes the processor to go into a spin loop within SAL where SAL awaits a wakeup from + * the monarch processor. */ static inline s64 ia64_sal_mc_rendez (void) @@ -710,15 +696,17 @@ return isrv.status; } -/* Allow the OS to specify the interrupt number to be used by SAL to interrupt OS during - * the machine check rendezvous sequence as well as the mechanism to wake up the +/* + * Allow the OS to specify the interrupt number to be used by SAL to interrupt OS during + * the machine check rendezvous sequence as well as the mechanism to wake up the * non-monarch processor at the end of machine check processing. */ static inline s64 ia64_sal_mc_set_params (u64 param_type, u64 i_or_m, u64 i_or_m_val, u64 timeout, u64 rz_always) { struct ia64_sal_retval isrv; - SAL_CALL(isrv, SAL_MC_SET_PARAMS, param_type, i_or_m, i_or_m_val, timeout, rz_always, 0, 0); + SAL_CALL(isrv, SAL_MC_SET_PARAMS, param_type, i_or_m, i_or_m_val, + timeout, rz_always, 0, 0); return isrv.status; } @@ -744,8 +732,8 @@ } /* - * Register physical addresses of locations needed by SAL when SAL - * procedures are invoked in virtual mode. + * Register physical addresses of locations needed by SAL when SAL procedures are invoked + * in virtual mode. */ static inline s64 ia64_sal_register_physical_addr (u64 phys_entry, u64 phys_addr) @@ -756,9 +744,10 @@ return isrv.status; } -/* Register software dependent code locations within SAL. These locations are handlers - * or entry points where SAL will pass control for the specified event. These event - * handlers are for the bott rendezvous, MCAs and INIT scenarios. +/* + * Register software dependent code locations within SAL. These locations are handlers or + * entry points where SAL will pass control for the specified event. These event handlers + * are for the bott rendezvous, MCAs and INIT scenarios. */ static inline s64 ia64_sal_set_vectors (u64 vector_type, @@ -768,10 +757,11 @@ struct ia64_sal_retval isrv; SAL_CALL(isrv, SAL_SET_VECTORS, vector_type, handler_addr1, gp1, handler_len1, - handler_addr2, gp2, handler_len2); + handler_addr2, gp2, handler_len2); return isrv.status; -} +} + /* Update the contents of PAL block in the non-volatile storage device */ static inline s64 ia64_sal_update_pal (u64 param_buf, u64 scratch_buf, u64 scratch_buf_size, diff -Nru a/include/asm-ia64/siginfo.h b/include/asm-ia64/siginfo.h --- a/include/asm-ia64/siginfo.h Fri Mar 7 20:40:18 2003 +++ b/include/asm-ia64/siginfo.h Fri Mar 7 20:40:18 2003 @@ -33,8 +33,11 @@ /* POSIX.1b timers */ struct { - unsigned int _timer1; - unsigned int _timer2; + timer_t _tid; /* timer id */ + int _overrun; /* overrun count */ + char _pad[sizeof(__ARCH_SI_UID_T) - sizeof(int)]; + sigval_t _sigval; /* must overlay ._rt._sigval! */ + int _sys_private; /* not to be passed to user */ } _timer; /* POSIX.1b signals */ diff -Nru a/include/asm-ia64/sn/geo.h b/include/asm-ia64/sn/geo.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-ia64/sn/geo.h Fri Mar 7 20:40:18 2003 @@ -0,0 +1,54 @@ +/* $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. + */ + +#ifndef __SYS_GEO_H__ +#define __SYS_GEO_H__ + +/* Include a platform-specific geo.h. It must define at least: + * geoid_t: Geographic identifier data type + * geo_type_t: Data type for the kind of geoid this is + * GEO_TYPE_xxx: Values for geo_type_t vars, eg. GEO_TYPE_NODE + * GEO_MAX_LEN: The maximum length of a geoid, formatted for printing + */ + +#include + +#ifdef CONFIG_IA64_SGI_SN2 +#include +#else + +#error <> + +#endif /* !SN2 && ... */ + +/* Declarations applicable to all platforms */ + +/* parameter for hwcfg_format_geoid() */ +#define GEO_FORMAT_HWGRAPH 1 +#define GEO_FORMAT_BRIEF 2 + +/* (the parameter for hwcfg_format_geoid_compt() is defined in the + * platform-specific geo.h file) */ + +/* Routines for manipulating geoid_t values */ + +extern moduleid_t geo_module(geoid_t g); +extern slabid_t geo_slab(geoid_t g); +extern geo_type_t geo_type(geoid_t g); +extern int geo_valid(geoid_t g); +extern int geo_cmp(geoid_t g0, geoid_t g1); +extern geoid_t geo_new(geo_type_t type, ...); + +extern geoid_t hwcfg_parse_geoid(char *buffer); +extern void hwcfg_format_geoid(char *buffer, geoid_t m, int fmt); +extern void hwcfg_format_geoid_compt(char *buffer, geoid_t m, int compt); +extern geoid_t hwcfg_geo_get_self(geo_type_t type); +extern geoid_t hwcfg_geo_get_by_nasid(geo_type_t type, nasid_t nasid); + +#endif /* __SYS_GEO_H__ */ diff -Nru a/include/asm-ia64/sn/ioconfig_bus.h b/include/asm-ia64/sn/ioconfig_bus.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-ia64/sn/ioconfig_bus.h Fri Mar 7 20:40:18 2003 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/NoticeExplan + */ + +#define IOCONFIG_PCIBUS "/boot/efi/ioconfig_pcibus" +#define POUND_CHAR '#' +#define MAX_LINE_LEN 128 +#define MAXPATHLEN 128 + +struct ioconfig_parm { + unsigned long ioconfig_activated; + unsigned long number; + void *buffer; +}; + +struct ascii_moduleid{ + unsigned char io_moduleid[8]; /* pci path name */ +}; diff -Nru a/include/asm-ia64/sn/module.h b/include/asm-ia64/sn/module.h --- a/include/asm-ia64/sn/module.h Fri Mar 7 20:40:16 2003 +++ b/include/asm-ia64/sn/module.h Fri Mar 7 20:40:16 2003 @@ -273,6 +273,9 @@ cnodeid_t nodes[MODULE_MAX_NODES]; #ifdef CONFIG_IA64_SGI_SN2 geoid_t geoid[MODULE_MAX_NODES]; + struct { + char moduleid[8]; + } io[MODULE_MAX_NODES]; #endif int nodecnt; /* Number of nodes in array */ diff -Nru a/include/asm-ia64/sn/pci/pic.h b/include/asm-ia64/sn/pci/pic.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-ia64/sn/pci/pic.h Fri Mar 7 20:40:18 2003 @@ -0,0 +1,2001 @@ +/* $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. + */ +#ifndef _ASM_SN_PCI_PIC_H +#define _ASM_SN_PCI_PIC_H + + +/* + * The PIC ASIC is a follow-on to the Bridge and Xbridge ASICs. + * It shares many of the same registers as those chips and therefore + * the primary structure for the PIC will be bridge_s as defined + * in irix/kern/sys/PCI/bridge.h. This file is intended as a complement + * to bridge.h, which includes this file. + */ + +/* + * PIC AS DEVICE ZERO + * ------------------ + * + * PIC handles PCI/X busses. PCI/X requires that the 'bridge' (i.e. PIC) + * be designated as 'device 0'. That is a departure from earlier SGI + * PCI bridges. Because of that we use config space 1 to access the + * config space of the first actual PCI device on the bus. + * Here's what the PIC manual says: + * + * The current PCI-X bus specification now defines that the parent + * hosts bus bridge (PIC for example) must be device 0 on bus 0. PIC + * reduced the total number of devices from 8 to 4 and removed the + * device registers and windows, now only supporting devices 0,1,2, and + * 3. PIC did leave all 8 configuration space windows. The reason was + * there was nothing to gain by removing them. Here in lies the problem. + * The device numbering we do using 0 through 3 is unrelated to the device + * numbering which PCI-X requires in configuration space. In the past we + * correlated Configs pace and our device space 0 <-> 0, 1 <-> 1, etc. + * PCI-X requires we start a 1, not 0 and currently the PX brick + * does associate our: + * + * device 0 with configuration space window 1, + * device 1 with configuration space window 2, + * device 2 with configuration space window 3, + * device 3 with configuration space window 4. + * + * The net effect is that all config space access are off-by-one with + * relation to other per-slot accesses on the PIC. + * Here is a table that shows some of that: + * + * Internal Slot# + * | + * | 0 1 2 3 + * ----------|--------------------------------------- + * config | 0x21000 0x22000 0x23000 0x24000 + * | + * even rrb | 0[0] n/a 1[0] n/a [] == implied even/odd + * | + * odd rrb | n/a 0[1] n/a 1[1] + * | + * int dev | 00 01 10 11 + * | + * ext slot# | 1 2 3 4 + * ----------|--------------------------------------- + */ + + +#ifndef __ASSEMBLY__ + +#ifdef __cplusplus +extern "C" { +#endif + +// #include +#include + + +/********************************************************************* + * bus provider function table + * + * Normally, this table is only handed off explicitly + * during provider initialization, and the PCI generic + * layer will stash a pointer to it in the vertex; however, + * exporting it explicitly enables a performance hack in + * the generic PCI provider where if we know at compile + * time that the only possible PCI provider is a + * pcibr, we can go directly to this ops table. + */ + +extern pciio_provider_t pci_pic_provider; + + +/********************************************************************* + * misc defines + * + */ +#define PIC_WIDGET_PART_NUM_BUS0 0xd102 +#define PIC_WIDGET_PART_NUM_BUS1 0xd112 +#define PIC_WIDGET_MFGR_NUM 0x24 +#define PIC_WIDGET_REV_A 0x1 + +#define IS_PIC_PART_REV_A(rev) \ + ((rev == (PIC_WIDGET_PART_NUM_BUS0 << 4 | PIC_WIDGET_REV_A)) || \ + (rev == (PIC_WIDGET_PART_NUM_BUS1 << 4 | PIC_WIDGET_REV_A))) + +/********************************************************************* + * register offset defines + * + */ + /* Identification Register -- read-only */ +#define PIC_IDENTIFICATION 0x00000000 + + /* Status Register -- read-only */ +#define PIC_STATUS 0x00000008 + + /* Upper Address Holding Register Bus Side Errors -- read-only */ +#define PIC_UPPER_ADDR_REG_BUS_SIDE_ERRS 0x00000010 + + /* Lower Address Holding Register Bus Side Errors -- read-only */ +#define PIC_LOWER_ADDR_REG_BUS_SIDE_ERRS 0x00000018 + + /* Control Register -- read/write */ +#define PIC_CONTROL 0x00000020 + + /* PCI Request Time-out Value Register -- read/write */ +#define PIC_PCI_REQ_TIME_OUT_VALUE 0x00000028 + + /* Interrupt Destination Upper Address Register -- read/write */ +#define PIC_INTR_DEST_UPPER_ADDR 0x00000030 + + /* Interrupt Destination Lower Address Register -- read/write */ +#define PIC_INTR_DEST_LOWER_ADDR 0x00000038 + + /* Command Word Holding Register Bus Side -- read-only */ +#define PIC_CMD_WORD_REG_BUS_SIDE 0x00000040 + + /* LLP Configuration Register (Bus 0 Only) -- read/write */ +#define PIC_LLP_CFG_REG_(BUS_0_ONLY) 0x00000048 + + /* PCI Target Flush Register -- read-only */ +#define PIC_PCI_TARGET_FLUSH 0x00000050 + + /* Command Word Holding Register Link Side -- read-only */ +#define PIC_CMD_WORD_REG_LINK_SIDE 0x00000058 + + /* Response Buffer Error Upper Address Holding -- read-only */ +#define PIC_RESP_BUF_ERR_UPPER_ADDR_ 0x00000060 + + /* Response Buffer Error Lower Address Holding -- read-only */ +#define PIC_RESP_BUF_ERR_LOWER_ADDR_ 0x00000068 + + /* Test Pin Control Register -- read/write */ +#define PIC_TEST_PIN_CONTROL 0x00000070 + + /* Address Holding Register Link Side Errors -- read-only */ +#define PIC_ADDR_REG_LINK_SIDE_ERRS 0x00000078 + + /* Direct Map Register -- read/write */ +#define PIC_DIRECT_MAP 0x00000080 + + /* PCI Map Fault Address Register -- read-only */ +#define PIC_PCI_MAP_FAULT_ADDR 0x00000090 + + /* Arbitration Priority Register -- read/write */ +#define PIC_ARBITRATION_PRIORITY 0x000000A0 + + /* Internal Ram Parity Error Register -- read-only */ +#define PIC_INTERNAL_RAM_PARITY_ERR 0x000000B0 + + /* PCI Time-out Register -- read/write */ +#define PIC_PCI_TIME_OUT 0x000000C0 + + /* PCI Type 1 Configuration Register -- read/write */ +#define PIC_PCI_TYPE_1_CFG 0x000000C8 + + /* PCI Bus Error Upper Address Holding Register -- read-only */ +#define PIC_PCI_BUS_ERR_UPPER_ADDR_ 0x000000D0 + + /* PCI Bus Error Lower Address Holding Register -- read-only */ +#define PIC_PCI_BUS_ERR_LOWER_ADDR_ 0x000000D8 + + /* PCIX Error Address Register -- read-only */ +#define PIC_PCIX_ERR_ADDR 0x000000E0 + + /* PCIX Error Attribute Register -- read-only */ +#define PIC_PCIX_ERR_ATTRIBUTE 0x000000E8 + + /* PCIX Error Data Register -- read-only */ +#define PIC_PCIX_ERR_DATA 0x000000F0 + + /* PCIX Read Request Timeout Error Register -- read-only */ +#define PIC_PCIX_READ_REQ_TIMEOUT_ERR 0x000000F8 + + /* Interrupt Status Register -- read-only */ +#define PIC_INTR_STATUS 0x00000100 + + /* Interrupt Enable Register -- read/write */ +#define PIC_INTR_ENABLE 0x00000108 + + /* Reset Interrupt Status Register -- write-only */ +#define PIC_RESET_INTR_STATUS 0x00000110 + + /* Interrupt Mode Register -- read/write */ +#define PIC_INTR_MODE 0x00000118 + + /* Interrupt Device Register -- read/write */ +#define PIC_INTR_DEVICE 0x00000120 + + /* Host Error Field Register -- read/write */ +#define PIC_HOST_ERR_FIELD 0x00000128 + + /* Interrupt Pin 0 Host Address Register -- read/write */ +#define PIC_INTR_PIN_0_HOST_ADDR 0x00000130 + + /* Interrupt Pin 1 Host Address Register -- read/write */ +#define PIC_INTR_PIN_1_HOST_ADDR 0x00000138 + + /* Interrupt Pin 2 Host Address Register -- read/write */ +#define PIC_INTR_PIN_2_HOST_ADDR 0x00000140 + + /* Interrupt Pin 3 Host Address Register -- read/write */ +#define PIC_INTR_PIN_3_HOST_ADDR 0x00000148 + + /* Interrupt Pin 4 Host Address Register -- read/write */ +#define PIC_INTR_PIN_4_HOST_ADDR 0x00000150 + + /* Interrupt Pin 5 Host Address Register -- read/write */ +#define PIC_INTR_PIN_5_HOST_ADDR 0x00000158 + + /* Interrupt Pin 6 Host Address Register -- read/write */ +#define PIC_INTR_PIN_6_HOST_ADDR 0x00000160 + + /* Interrupt Pin 7 Host Address Register -- read/write */ +#define PIC_INTR_PIN_7_HOST_ADDR 0x00000168 + + /* Error Interrupt View Register -- read-only */ +#define PIC_ERR_INTR_VIEW 0x00000170 + + /* Multiple Interrupt Register -- read-only */ +#define PIC_MULTIPLE_INTR 0x00000178 + + /* Force Always Interrupt 0 Register -- write-only */ +#define PIC_FORCE_ALWAYS_INTR_0 0x00000180 + + /* Force Always Interrupt 1 Register -- write-only */ +#define PIC_FORCE_ALWAYS_INTR_1 0x00000188 + + /* Force Always Interrupt 2 Register -- write-only */ +#define PIC_FORCE_ALWAYS_INTR_2 0x00000190 + + /* Force Always Interrupt 3 Register -- write-only */ +#define PIC_FORCE_ALWAYS_INTR_3 0x00000198 + + /* Force Always Interrupt 4 Register -- write-only */ +#define PIC_FORCE_ALWAYS_INTR_4 0x000001A0 + + /* Force Always Interrupt 5 Register -- write-only */ +#define PIC_FORCE_ALWAYS_INTR_5 0x000001A8 + + /* Force Always Interrupt 6 Register -- write-only */ +#define PIC_FORCE_ALWAYS_INTR_6 0x000001B0 + + /* Force Always Interrupt 7 Register -- write-only */ +#define PIC_FORCE_ALWAYS_INTR_7 0x000001B8 + + /* Force w/Pin Interrupt 0 Register -- write-only */ +#define PIC_FORCE_PIN_INTR_0 0x000001C0 + + /* Force w/Pin Interrupt 1 Register -- write-only */ +#define PIC_FORCE_PIN_INTR_1 0x000001C8 + + /* Force w/Pin Interrupt 2 Register -- write-only */ +#define PIC_FORCE_PIN_INTR_2 0x000001D0 + + /* Force w/Pin Interrupt 3 Register -- write-only */ +#define PIC_FORCE_PIN_INTR_3 0x000001D8 + + /* Force w/Pin Interrupt 4 Register -- write-only */ +#define PIC_FORCE_PIN_INTR_4 0x000001E0 + + /* Force w/Pin Interrupt 5 Register -- write-only */ +#define PIC_FORCE_PIN_INTR_5 0x000001E8 + + /* Force w/Pin Interrupt 6 Register -- write-only */ +#define PIC_FORCE_PIN_INTR_6 0x000001F0 + + /* Force w/Pin Interrupt 7 Register -- write-only */ +#define PIC_FORCE_PIN_INTR_7 0x000001F8 + + /* Device 0 Register -- read/write */ +#define PIC_DEVICE_0 0x00000200 + + /* Device 1 Register -- read/write */ +#define PIC_DEVICE_1 0x00000208 + + /* Device 2 Register -- read/write */ +#define PIC_DEVICE_2 0x00000210 + + /* Device 3 Register -- read/write */ +#define PIC_DEVICE_3 0x00000218 + + /* Device 0 Write Request Buffer Register -- read-only */ +#define PIC_DEVICE_0_WRITE_REQ_BUF 0x00000240 + + /* Device 1 Write Request Buffer Register -- read-only */ +#define PIC_DEVICE_1_WRITE_REQ_BUF 0x00000248 + + /* Device 2 Write Request Buffer Register -- read-only */ +#define PIC_DEVICE_2_WRITE_REQ_BUF 0x00000250 + + /* Device 3 Write Request Buffer Register -- read-only */ +#define PIC_DEVICE_3_WRITE_REQ_BUF 0x00000258 + + /* Even Device Response Buffer Register -- read/write */ +#define PIC_EVEN_DEVICE_RESP_BUF 0x00000280 + + /* Odd Device Response Buffer Register -- read/write */ +#define PIC_ODD_DEVICE_RESP_BUF 0x00000288 + + /* Read Response Buffer Status Register -- read-only */ +#define PIC_READ_RESP_BUF_STATUS 0x00000290 + + /* Read Response Buffer Clear Register -- write-only */ +#define PIC_READ_RESP_BUF_CLEAR 0x00000298 + + /* PCI RR 0 Upper Address Match Register -- read-only */ +#define PIC_PCI_RR_0_UPPER_ADDR_MATCH 0x00000300 + + /* PCI RR 0 Lower Address Match Register -- read-only */ +#define PIC_PCI_RR_0_LOWER_ADDR_MATCH 0x00000308 + + /* PCI RR 1 Upper Address Match Register -- read-only */ +#define PIC_PCI_RR_1_UPPER_ADDR_MATCH 0x00000310 + + /* PCI RR 1 Lower Address Match Register -- read-only */ +#define PIC_PCI_RR_1_LOWER_ADDR_MATCH 0x00000318 + + /* PCI RR 2 Upper Address Match Register -- read-only */ +#define PIC_PCI_RR_2_UPPER_ADDR_MATCH 0x00000320 + + /* PCI RR 2 Lower Address Match Register -- read-only */ +#define PIC_PCI_RR_2_LOWER_ADDR_MATCH 0x00000328 + + /* PCI RR 3 Upper Address Match Register -- read-only */ +#define PIC_PCI_RR_3_UPPER_ADDR_MATCH 0x00000330 + + /* PCI RR 3 Lower Address Match Register -- read-only */ +#define PIC_PCI_RR_3_LOWER_ADDR_MATCH 0x00000338 + + /* PCI RR 4 Upper Address Match Register -- read-only */ +#define PIC_PCI_RR_4_UPPER_ADDR_MATCH 0x00000340 + + /* PCI RR 4 Lower Address Match Register -- read-only */ +#define PIC_PCI_RR_4_LOWER_ADDR_MATCH 0x00000348 + + /* PCI RR 5 Upper Address Match Register -- read-only */ +#define PIC_PCI_RR_5_UPPER_ADDR_MATCH 0x00000350 + + /* PCI RR 5 Lower Address Match Register -- read-only */ +#define PIC_PCI_RR_5_LOWER_ADDR_MATCH 0x00000358 + + /* PCI RR 6 Upper Address Match Register -- read-only */ +#define PIC_PCI_RR_6_UPPER_ADDR_MATCH 0x00000360 + + /* PCI RR 6 Lower Address Match Register -- read-only */ +#define PIC_PCI_RR_6_LOWER_ADDR_MATCH 0x00000368 + + /* PCI RR 7 Upper Address Match Register -- read-only */ +#define PIC_PCI_RR_7_UPPER_ADDR_MATCH 0x00000370 + + /* PCI RR 7 Lower Address Match Register -- read-only */ +#define PIC_PCI_RR_7_LOWER_ADDR_MATCH 0x00000378 + + /* PCI RR 8 Upper Address Match Register -- read-only */ +#define PIC_PCI_RR_8_UPPER_ADDR_MATCH 0x00000380 + + /* PCI RR 8 Lower Address Match Register -- read-only */ +#define PIC_PCI_RR_8_LOWER_ADDR_MATCH 0x00000388 + + /* PCI RR 9 Upper Address Match Register -- read-only */ +#define PIC_PCI_RR_9_UPPER_ADDR_MATCH 0x00000390 + + /* PCI RR 9 Lower Address Match Register -- read-only */ +#define PIC_PCI_RR_9_LOWER_ADDR_MATCH 0x00000398 + + /* PCI RR 10 Upper Address Match Register -- read-only */ +#define PIC_PCI_RR_10_UPPER_ADDR_MATCH 0x000003A0 + + /* PCI RR 10 Lower Address Match Register -- read-only */ +#define PIC_PCI_RR_10_LOWER_ADDR_MATCH 0x000003A8 + + /* PCI RR 11 Upper Address Match Register -- read-only */ +#define PIC_PCI_RR_11_UPPER_ADDR_MATCH 0x000003B0 + + /* PCI RR 11 Lower Address Match Register -- read-only */ +#define PIC_PCI_RR_11_LOWER_ADDR_MATCH 0x000003B8 + + /* PCI RR 12 Upper Address Match Register -- read-only */ +#define PIC_PCI_RR_12_UPPER_ADDR_MATCH 0x000003C0 + + /* PCI RR 12 Lower Address Match Register -- read-only */ +#define PIC_PCI_RR_12_LOWER_ADDR_MATCH 0x000003C8 + + /* PCI RR 13 Upper Address Match Register -- read-only */ +#define PIC_PCI_RR_13_UPPER_ADDR_MATCH 0x000003D0 + + /* PCI RR 13 Lower Address Match Register -- read-only */ +#define PIC_PCI_RR_13_LOWER_ADDR_MATCH 0x000003D8 + + /* PCI RR 14 Upper Address Match Register -- read-only */ +#define PIC_PCI_RR_14_UPPER_ADDR_MATCH 0x000003E0 + + /* PCI RR 14 Lower Address Match Register -- read-only */ +#define PIC_PCI_RR_14_LOWER_ADDR_MATCH 0x000003E8 + + /* PCI RR 15 Upper Address Match Register -- read-only */ +#define PIC_PCI_RR_15_UPPER_ADDR_MATCH 0x000003F0 + + /* PCI RR 15 Lower Address Match Register -- read-only */ +#define PIC_PCI_RR_15_LOWER_ADDR_MATCH 0x000003F8 + + /* Buffer 0 Flush Count with Data Touch Register -- read/write */ +#define PIC_BUF_0_FLUSH_CNT_WITH_DATA_TOUCH 0x00000400 + + /* Buffer 0 Flush Count w/o Data Touch Register -- read/write */ +#define PIC_BUF_0_FLUSH_CNT_W_O_DATA_TOUCH 0x00000408 + + /* Buffer 0 Request in Flight Count Register -- read/write */ +#define PIC_BUF_0_REQ_IN_FLIGHT_CNT 0x00000410 + + /* Buffer 0 Prefetch Request Count Register -- read/write */ +#define PIC_BUF_0_PREFETCH_REQ_CNT 0x00000418 + + /* Buffer 0 Total PCI Retry Count Register -- read/write */ +#define PIC_BUF_0_TOTAL_PCI_RETRY_CNT 0x00000420 + + /* Buffer 0 Max PCI Retry Count Register -- read/write */ +#define PIC_BUF_0_MAX_PCI_RETRY_CNT 0x00000428 + + /* Buffer 0 Max Latency Count Register -- read/write */ +#define PIC_BUF_0_MAX_LATENCY_CNT 0x00000430 + + /* Buffer 0 Clear All Register -- read/write */ +#define PIC_BUF_0_CLEAR_ALL 0x00000438 + + /* Buffer 2 Flush Count with Data Touch Register -- read/write */ +#define PIC_BUF_2_FLUSH_CNT_WITH_DATA_TOUCH 0x00000440 + + /* Buffer 2 Flush Count w/o Data Touch Register -- read/write */ +#define PIC_BUF_2_FLUSH_CNT_W_O_DATA_TOUCH 0x00000448 + + /* Buffer 2 Request in Flight Count Register -- read/write */ +#define PIC_BUF_2_REQ_IN_FLIGHT_CNT 0x00000450 + + /* Buffer 2 Prefetch Request Count Register -- read/write */ +#define PIC_BUF_2_PREFETCH_REQ_CNT 0x00000458 + + /* Buffer 2 Total PCI Retry Count Register -- read/write */ +#define PIC_BUF_2_TOTAL_PCI_RETRY_CNT 0x00000460 + + /* Buffer 2 Max PCI Retry Count Register -- read/write */ +#define PIC_BUF_2_MAX_PCI_RETRY_CNT 0x00000468 + + /* Buffer 2 Max Latency Count Register -- read/write */ +#define PIC_BUF_2_MAX_LATENCY_CNT 0x00000470 + + /* Buffer 2 Clear All Register -- read/write */ +#define PIC_BUF_2_CLEAR_ALL 0x00000478 + + /* Buffer 4 Flush Count with Data Touch Register -- read/write */ +#define PIC_BUF_4_FLUSH_CNT_WITH_DATA_TOUCH 0x00000480 + + /* Buffer 4 Flush Count w/o Data Touch Register -- read/write */ +#define PIC_BUF_4_FLUSH_CNT_W_O_DATA_TOUCH 0x00000488 + + /* Buffer 4 Request in Flight Count Register -- read/write */ +#define PIC_BUF_4_REQ_IN_FLIGHT_CNT 0x00000490 + + /* Buffer 4 Prefetch Request Count Register -- read/write */ +#define PIC_BUF_4_PREFETCH_REQ_CNT 0x00000498 + + /* Buffer 4 Total PCI Retry Count Register -- read/write */ +#define PIC_BUF_4_TOTAL_PCI_RETRY_CNT 0x000004A0 + + /* Buffer 4 Max PCI Retry Count Register -- read/write */ +#define PIC_BUF_4_MAX_PCI_RETRY_CNT 0x000004A8 + + /* Buffer 4 Max Latency Count Register -- read/write */ +#define PIC_BUF_4_MAX_LATENCY_CNT 0x000004B0 + + /* Buffer 4 Clear All Register -- read/write */ +#define PIC_BUF_4_CLEAR_ALL 0x000004B8 + + /* Buffer 6 Flush Count with Data Touch Register -- read/write */ +#define PIC_BUF_6_FLUSH_CNT_WITH_DATA_TOUCH 0x000004C0 + + /* Buffer 6 Flush Count w/o Data Touch Register -- read/write */ +#define PIC_BUF_6_FLUSH_CNT_W_O_DATA_TOUCH 0x000004C8 + + /* Buffer 6 Request in Flight Count Register -- read/write */ +#define PIC_BUF_6_REQ_IN_FLIGHT_CNT 0x000004D0 + + /* Buffer 6 Prefetch Request Count Register -- read/write */ +#define PIC_BUF_6_PREFETCH_REQ_CNT 0x000004D8 + + /* Buffer 6 Total PCI Retry Count Register -- read/write */ +#define PIC_BUF_6_TOTAL_PCI_RETRY_CNT 0x000004E0 + + /* Buffer 6 Max PCI Retry Count Register -- read/write */ +#define PIC_BUF_6_MAX_PCI_RETRY_CNT 0x000004E8 + + /* Buffer 6 Max Latency Count Register -- read/write */ +#define PIC_BUF_6_MAX_LATENCY_CNT 0x000004F0 + + /* Buffer 6 Clear All Register -- read/write */ +#define PIC_BUF_6_CLEAR_ALL 0x000004F8 + + /* Buffer 8 Flush Count with Data Touch Register -- read/write */ +#define PIC_BUF_8_FLUSH_CNT_WITH_DATA_TOUCH 0x00000500 + + /* Buffer 8 Flush Count w/o Data Touch Register -- read/write */ +#define PIC_BUF_8_FLUSH_CNT_W_O_DATA_TOUCH 0x00000508 + + /* Buffer 8 Request in Flight Count Register -- read/write */ +#define PIC_BUF_8_REQ_IN_FLIGHT_CNT 0x00000510 + + /* Buffer 8 Prefetch Request Count Register -- read/write */ +#define PIC_BUF_8_PREFETCH_REQ_CNT 0x00000518 + + /* Buffer 8 Total PCI Retry Count Register -- read/write */ +#define PIC_BUF_8_TOTAL_PCI_RETRY_CNT 0x00000520 + + /* Buffer 8 Max PCI Retry Count Register -- read/write */ +#define PIC_BUF_8_MAX_PCI_RETRY_CNT 0x00000528 + + /* Buffer 8 Max Latency Count Register -- read/write */ +#define PIC_BUF_8_MAX_LATENCY_CNT 0x00000530 + + /* Buffer 8 Clear All Register -- read/write */ +#define PIC_BUF_8_CLEAR_ALL 0x00000538 + + /* Buffer 10 Flush Count with Data Touch Register -- read/write */ +#define PIC_BUF_10_FLUSH_CNT_WITH_DATA_TOUCH 0x00000540 + + /* Buffer 10 Flush Count w/o Data Touch Register -- read/write */ +#define PIC_BUF_10_FLUSH_CNT_W_O_DATA_TOUCH 0x00000548 + + /* Buffer 10 Request in Flight Count Register -- read/write */ +#define PIC_BUF_10_REQ_IN_FLIGHT_CNT 0x00000550 + + /* Buffer 10 Prefetch Request Count Register -- read/write */ +#define PIC_BUF_10_PREFETCH_REQ_CNT 0x00000558 + + /* Buffer 10 Total PCI Retry Count Register -- read/write */ +#define PIC_BUF_10_TOTAL_PCI_RETRY_CNT 0x00000560 + + /* Buffer 10 Max PCI Retry Count Register -- read/write */ +#define PIC_BUF_10_MAX_PCI_RETRY_CNT 0x00000568 + + /* Buffer 10 Max Latency Count Register -- read/write */ +#define PIC_BUF_10_MAX_LATENCY_CNT 0x00000570 + + /* Buffer 10 Clear All Register -- read/write */ +#define PIC_BUF_10_CLEAR_ALL 0x00000578 + + /* Buffer 12 Flush Count with Data Touch Register -- read/write */ +#define PIC_BUF_12_FLUSH_CNT_WITH_DATA_TOUCH 0x00000580 + + /* Buffer 12 Flush Count w/o Data Touch Register -- read/write */ +#define PIC_BUF_12_FLUSH_CNT_W_O_DATA_TOUCH 0x00000588 + + /* Buffer 12 Request in Flight Count Register -- read/write */ +#define PIC_BUF_12_REQ_IN_FLIGHT_CNT 0x00000590 + + /* Buffer 12 Prefetch Request Count Register -- read/write */ +#define PIC_BUF_12_PREFETCH_REQ_CNT 0x00000598 + + /* Buffer 12 Total PCI Retry Count Register -- read/write */ +#define PIC_BUF_12_TOTAL_PCI_RETRY_CNT 0x000005A0 + + /* Buffer 12 Max PCI Retry Count Register -- read/write */ +#define PIC_BUF_12_MAX_PCI_RETRY_CNT 0x000005A8 + + /* Buffer 12 Max Latency Count Register -- read/write */ +#define PIC_BUF_12_MAX_LATENCY_CNT 0x000005B0 + + /* Buffer 12 Clear All Register -- read/write */ +#define PIC_BUF_12_CLEAR_ALL 0x000005B8 + + /* Buffer 14 Flush Count with Data Touch Register -- read/write */ +#define PIC_BUF_14_FLUSH_CNT_WITH_DATA_TOUCH 0x000005C0 + + /* Buffer 14 Flush Count w/o Data Touch Register -- read/write */ +#define PIC_BUF_14_FLUSH_CNT_W_O_DATA_TOUCH 0x000005C8 + + /* Buffer 14 Request in Flight Count Register -- read/write */ +#define PIC_BUF_14_REQ_IN_FLIGHT_CNT 0x000005D0 + + /* Buffer 14 Prefetch Request Count Register -- read/write */ +#define PIC_BUF_14_PREFETCH_REQ_CNT 0x000005D8 + + /* Buffer 14 Total PCI Retry Count Register -- read/write */ +#define PIC_BUF_14_TOTAL_PCI_RETRY_CNT 0x000005E0 + + /* Buffer 14 Max PCI Retry Count Register -- read/write */ +#define PIC_BUF_14_MAX_PCI_RETRY_CNT 0x000005E8 + + /* Buffer 14 Max Latency Count Register -- read/write */ +#define PIC_BUF_14_MAX_LATENCY_CNT 0x000005F0 + + /* Buffer 14 Clear All Register -- read/write */ +#define PIC_BUF_14_CLEAR_ALL 0x000005F8 + + /* PCIX Read Buffer 0 Address Register -- read-only */ +#define PIC_PCIX_READ_BUF_0_ADDR 0x00000A00 + + /* PCIX Read Buffer 0 Attribute Register -- read-only */ +#define PIC_PCIX_READ_BUF_0_ATTRIBUTE 0x00000A08 + + /* PCIX Read Buffer 1 Address Register -- read-only */ +#define PIC_PCIX_READ_BUF_1_ADDR 0x00000A10 + + /* PCIX Read Buffer 1 Attribute Register -- read-only */ +#define PIC_PCIX_READ_BUF_1_ATTRIBUTE 0x00000A18 + + /* PCIX Read Buffer 2 Address Register -- read-only */ +#define PIC_PCIX_READ_BUF_2_ADDR 0x00000A20 + + /* PCIX Read Buffer 2 Attribute Register -- read-only */ +#define PIC_PCIX_READ_BUF_2_ATTRIBUTE 0x00000A28 + + /* PCIX Read Buffer 3 Address Register -- read-only */ +#define PIC_PCIX_READ_BUF_3_ADDR 0x00000A30 + + /* PCIX Read Buffer 3 Attribute Register -- read-only */ +#define PIC_PCIX_READ_BUF_3_ATTRIBUTE 0x00000A38 + + /* PCIX Read Buffer 4 Address Register -- read-only */ +#define PIC_PCIX_READ_BUF_4_ADDR 0x00000A40 + + /* PCIX Read Buffer 4 Attribute Register -- read-only */ +#define PIC_PCIX_READ_BUF_4_ATTRIBUTE 0x00000A48 + + /* PCIX Read Buffer 5 Address Register -- read-only */ +#define PIC_PCIX_READ_BUF_5_ADDR 0x00000A50 + + /* PCIX Read Buffer 5 Attribute Register -- read-only */ +#define PIC_PCIX_READ_BUF_5_ATTRIBUTE 0x00000A58 + + /* PCIX Read Buffer 6 Address Register -- read-only */ +#define PIC_PCIX_READ_BUF_6_ADDR 0x00000A60 + + /* PCIX Read Buffer 6 Attribute Register -- read-only */ +#define PIC_PCIX_READ_BUF_6_ATTRIBUTE 0x00000A68 + + /* PCIX Read Buffer 7 Address Register -- read-only */ +#define PIC_PCIX_READ_BUF_7_ADDR 0x00000A70 + + /* PCIX Read Buffer 7 Attribute Register -- read-only */ +#define PIC_PCIX_READ_BUF_7_ATTRIBUTE 0x00000A78 + + /* PCIX Read Buffer 8 Address Register -- read-only */ +#define PIC_PCIX_READ_BUF_8_ADDR 0x00000A80 + + /* PCIX Read Buffer 8 Attribute Register -- read-only */ +#define PIC_PCIX_READ_BUF_8_ATTRIBUTE 0x00000A88 + + /* PCIX Read Buffer 9 Address Register -- read-only */ +#define PIC_PCIX_READ_BUF_9_ADDR 0x00000A90 + + /* PCIX Read Buffer 9 Attribute Register -- read-only */ +#define PIC_PCIX_READ_BUF_9_ATTRIBUTE 0x00000A98 + + /* PCIX Read Buffer 10 Address Register -- read-only */ +#define PIC_PCIX_READ_BUF_10_ADDR 0x00000AA0 + + /* PCIX Read Buffer 10 Attribute Register -- read-only */ +#define PIC_PCIX_READ_BUF_10_ATTRIBUTE 0x00000AA8 + + /* PCIX Read Buffer 11 Address Register -- read-only */ +#define PIC_PCIX_READ_BUF_11_ADDR 0x00000AB0 + + /* PCIX Read Buffer 11 Attribute Register -- read-only */ +#define PIC_PCIX_READ_BUF_11_ATTRIBUTE 0x00000AB8 + + /* PCIX Read Buffer 12 Address Register -- read-only */ +#define PIC_PCIX_READ_BUF_12_ADDR 0x00000AC0 + + /* PCIX Read Buffer 12 Attribute Register -- read-only */ +#define PIC_PCIX_READ_BUF_12_ATTRIBUTE 0x00000AC8 + + /* PCIX Read Buffer 13 Address Register -- read-only */ +#define PIC_PCIX_READ_BUF_13_ADDR 0x00000AD0 + + /* PCIX Read Buffer 13 Attribute Register -- read-only */ +#define PIC_PCIX_READ_BUF_13_ATTRIBUTE 0x00000AD8 + + /* PCIX Read Buffer 14 Address Register -- read-only */ +#define PIC_PCIX_READ_BUF_14_ADDR 0x00000AE0 + + /* PCIX Read Buffer 14 Attribute Register -- read-only */ +#define PIC_PCIX_READ_BUF_14_ATTRIBUTE 0x00000AE8 + + /* PCIX Read Buffer 15 Address Register -- read-only */ +#define PIC_PCIX_READ_BUF_15_ADDR 0x00000AF0 + + /* PCIX Read Buffer 15 Attribute Register -- read-only */ +#define PIC_PCIX_READ_BUF_15_ATTRIBUTE 0x00000AF8 + + /* PCIX Write Buffer 0 Address Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_0_ADDR 0x00000B00 + + /* PCIX Write Buffer 0 Attribute Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_0_ATTRIBUTE 0x00000B08 + + /* PCIX Write Buffer 0 Valid Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_0_VALID 0x00000B10 + + /* PCIX Write Buffer 1 Address Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_1_ADDR 0x00000B20 + + /* PCIX Write Buffer 1 Attribute Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_1_ATTRIBUTE 0x00000B28 + + /* PCIX Write Buffer 1 Valid Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_1_VALID 0x00000B30 + + /* PCIX Write Buffer 2 Address Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_2_ADDR 0x00000B40 + + /* PCIX Write Buffer 2 Attribute Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_2_ATTRIBUTE 0x00000B48 + + /* PCIX Write Buffer 2 Valid Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_2_VALID 0x00000B50 + + /* PCIX Write Buffer 3 Address Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_3_ADDR 0x00000B60 + + /* PCIX Write Buffer 3 Attribute Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_3_ATTRIBUTE 0x00000B68 + + /* PCIX Write Buffer 3 Valid Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_3_VALID 0x00000B70 + + /* PCIX Write Buffer 4 Address Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_4_ADDR 0x00000B80 + + /* PCIX Write Buffer 4 Attribute Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_4_ATTRIBUTE 0x00000B88 + + /* PCIX Write Buffer 4 Valid Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_4_VALID 0x00000B90 + + /* PCIX Write Buffer 5 Address Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_5_ADDR 0x00000BA0 + + /* PCIX Write Buffer 5 Attribute Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_5_ATTRIBUTE 0x00000BA8 + + /* PCIX Write Buffer 5 Valid Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_5_VALID 0x00000BB0 + + /* PCIX Write Buffer 6 Address Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_6_ADDR 0x00000BC0 + + /* PCIX Write Buffer 6 Attribute Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_6_ATTRIBUTE 0x00000BC8 + + /* PCIX Write Buffer 6 Valid Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_6_VALID 0x00000BD0 + + /* PCIX Write Buffer 7 Address Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_7_ADDR 0x00000BE0 + + /* PCIX Write Buffer 7 Attribute Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_7_ATTRIBUTE 0x00000BE8 + + /* PCIX Write Buffer 7 Valid Register -- read-only */ +#define PIC_PCIX_WRITE_BUF_7_VALID 0x00000BF0 + +/********************************************************************* + * misc typedefs + * + */ +typedef uint64_t picreg_t; + +/********************************************************************* + * PIC register structures + * + */ + +/* + * Identification Register + * + * The Identification register is a read only register used by the host CPU + * during configuration to determine the type of the widget. The format is + * the same as defined in IEEE 1149.1 JTAG Device Identification Register. + */ + typedef union pic_id_reg_u { + picreg_t pic_id_reg_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t rev_num : 4; /* 31:28 */ + picreg_t part_num : 16; /* 27:12 */ + picreg_t mfg_num : 11; /* 11:1 */ + picreg_t : 1; /* 0:0 */ + } pic_id_reg_fld_s; + } pic_id_reg_u_t; +/* + * Status Register + * + * The status register is a read register which holds status information of the + * Bus Subsection. + */ + typedef union pic_stat_reg_u { + picreg_t pic_stat_reg_regval; + struct { + picreg_t : 28; /* 63:36 */ + picreg_t pci_x_speed : 2; /* 35:34 */ + picreg_t pci_x_active : 1; /* 33:33 */ + picreg_t : 1; /* 32:32 */ + picreg_t llp_rec_cnt : 8; /* 31:24 */ + picreg_t llp_tx_cnt : 8; /* 23:16 */ + picreg_t rx_credit_cnt : 4; /* 15:12 */ + picreg_t tx_credit_cnt : 4; /* 11:8 */ + picreg_t pci_misc_input : 8; /* 7:0 */ + } pic_stat_reg_fld_s; + } pic_stat_reg_u_t; +/* + * Upper Address Holding Register Bus Side Errors + * + * The upper address holding register is a read only register which contains + * the upper 16-bits of the address when certain error occurs (see error cases + * chapter). Subsequent errors are not logged until the error is cleared. The + * last logged value is held until the group is cleared and enabled. + */ + typedef union pic_upper_bus_err_u { + picreg_t pic_upper_bus_err_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 16; /* 31:16 */ + picreg_t upp_addr : 16; /* 15:0 */ + } pic_upper_bus_err_fld_s; + } pic_upper_bus_err_u_t; +/* + * Lower Address Holding Register Bus Side Errors + * + * The lower address holding register is a read only register which contains + * the address which either can be accessed as a word or double word. Sub- + * sequent errors are not logged until the error is cleared. The last logged + * value is held until the group is cleared and enabled. + */ + typedef union pic_lower_bus_err_u { + picreg_t pic_lower_bus_err_regval; + struct { + picreg_t : 16; /* 63:48 */ + picreg_t upp_addr : 16; /* 47:32 */ + picreg_t low_addr : 32; /* 31:0 */ + } pic_lower_bus_err_fld_s; + } pic_lower_bus_err_u_t; +/* + * Control Register + * + * The control register is a read/write register which holds control informa- + * tion for the bus subsection. + */ + typedef union pic_control_reg_u { + picreg_t pic_control_reg_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 4; /* 31:28 */ + picreg_t rst_pin_n : 4; /* 27:24 */ + picreg_t : 1; /* 23:23 */ + picreg_t mem_swap : 1; /* 22:22 */ + picreg_t page_size : 1; /* 21:21 */ + picreg_t : 4; /* 20:17 */ + picreg_t f_bad_pkt : 1; /* 16:16 */ + picreg_t llp_xbar_crd : 4; /* 15:12 */ + picreg_t clr_rllp_cnt : 1; /* 11:11 */ + picreg_t clr_tllp_cnt : 1; /* 10:10 */ + picreg_t sys_end : 1; /* 9:9 */ + picreg_t : 3; /* 8:6 */ + picreg_t pci_speed : 2; /* 5:4 */ + picreg_t widget_id : 4; /* 3:0 */ + } pic_control_reg_fld_s; + } pic_control_reg_u_t; +/* + * PCI/PCI-X Request Time-out Value Register + * + * This register contains the reload value for the response timer. The request + * timer counts every 960 nS (32 PCI clocks) + */ + typedef union pic_pci_req_to_u { + picreg_t pic_pci_req_to_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 12; /* 31:20 */ + picreg_t time_out : 20; /* 19:0 */ + } pic_pci_req_to_fld_s; + } pic_pci_req_to_u_t; +/* + * Interrupt Destination Upper Address Register + * + * The interrupt destination upper address register is a read/write register + * containing the upper 16-bits of address of the host to which the interrupt + * is targeted. In addition the target ID is also contained in this register for + * use in Crosstalk mode. + */ + typedef union pic_int_desc_upper_u { + picreg_t pic_int_desc_upper_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 12; /* 31:20 */ + picreg_t target_id : 4; /* 19:16 */ + picreg_t upp_addr : 16; /* 15:0 */ + } pic_int_desc_upper_fld_s; + } pic_int_desc_upper_u_t; +/* + * Interrupt Destination Lower Address Register + * + * The interrupt destination lower address register is a read/write register + * which contains the entire address of the host to which the interrupt is tar- + * geted. In addition the target ID is also contained in this register for use in + * Crosstalk mode. + */ + typedef union pic_int_desc_lower_u { + picreg_t pic_int_desc_lower_regval; + struct { + picreg_t : 12; /* 63:52 */ + picreg_t target_id : 4; /* 51:48 */ + picreg_t upp_addr : 16; /* 47:32 */ + picreg_t low_addr : 32; /* 31:0 */ + } pic_int_desc_lower_fld_s; + } pic_int_desc_lower_u_t; +/* + * Command Word Holding Register Bus Side Errors + * + * The command word holding is a read register that holds the command + * word of a Crosstalk packet when errors occur on the link side (see error + * chapter). Errors are indicated with error bits in the interrupt status regis- + * ter. Subsequent errors are not logged until the interrupt is cleared.. + */ + typedef union pic_cmd_word_bus_err_u { + picreg_t pic_cmd_word_bus_err_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t didn : 4; /* 31:28 */ + picreg_t sidn : 4; /* 27:24 */ + picreg_t pactyp : 4; /* 23:20 */ + picreg_t tnum : 5; /* 19:15 */ + picreg_t coherent : 1; /* 14:14 */ + picreg_t ds : 2; /* 13:12 */ + picreg_t gbr : 1; /* 11:11 */ + picreg_t vbpm : 1; /* 10:10 */ + picreg_t error : 1; /* 9:9 */ + picreg_t barrier : 1; /* 8:8 */ + picreg_t : 8; /* 7:0 */ + } pic_cmd_word_bus_err_fld_s; + } pic_cmd_word_bus_err_u_t; +/* + * LLP Configuration Register + * + * This register contains the configuration information for the LLP modules + * and is only valid on bus 0 side. + */ + typedef union pic_llp_cfg_u { + picreg_t pic_llp_cfg_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 6; /* 31:26 */ + picreg_t llp_maxretry : 10; /* 25:16 */ + picreg_t llp_nulltimeout : 6; /* 15:10 */ + picreg_t llp_maxburst : 10; /* 9:0 */ + } pic_llp_cfg_fld_s; + } pic_llp_cfg_u_t; +/* + * PCI/PCI-X Target Flush Register + * + * When read, this register will return a 0x00 after all previous transfers to + * the PCI bus subsection have completed. + */ + +/* + * Command Word Holding Register Link Side Errors + * + * The command word holding is a read-only register that holds the com- + * mand word of a Crosstalk packet when request fifo overflow or unexpect- + * ed response errors occur. Errors are indicated with error bits in the + * interrupt status register. Subsequent errors are not logged until this inter- + * rupt is cleared. + */ + typedef union pic_cmd_word_link_err_u { + picreg_t pic_cmd_word_link_err_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t didn : 4; /* 31:28 */ + picreg_t sidn : 4; /* 27:24 */ + picreg_t pactyp : 4; /* 23:20 */ + picreg_t tnum : 5; /* 19:15 */ + picreg_t coherent : 1; /* 14:14 */ + picreg_t ds : 2; /* 13:12 */ + picreg_t gbr : 1; /* 11:11 */ + picreg_t vbpm : 1; /* 10:10 */ + picreg_t error : 1; /* 9:9 */ + picreg_t barrier : 1; /* 8:8 */ + picreg_t : 8; /* 7:0 */ + } pic_cmd_word_link_err_fld_s; + } pic_cmd_word_link_err_u_t; +/* + * PCI Response Buffer Error Upper Address Holding Reg + * + * The response buffer error upper address holding register is a read only + * register which contains the upper 16-bits of the address when error asso- + * ciated with response buffer entries occur. Subsequent errors are not + * logged until the interrupt is cleared. + */ + typedef union pic_pci_rbuf_err_upper_u { + picreg_t pic_pci_rbuf_err_upper_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 9; /* 31:23 */ + picreg_t dev_num : 3; /* 22:20 */ + picreg_t buff_num : 4; /* 19:16 */ + picreg_t upp_addr : 16; /* 15:0 */ + } pic_pci_rbuf_err_upper_fld_s; + } pic_pci_rbuf_err_upper_u_t; +/* + * PCI Response Buffer Error Lower Address Holding Reg + * + * The response buffer error lower address holding register is a read only + * register which contains the address of the error associated with response + * buffer entries. Subsequent errors are not logged until the interrupt is + * cleared. + */ + typedef union pic_pci_rbuf_err_lower_u { + picreg_t pic_pci_rbuf_err_lower_regval; + struct { + picreg_t : 9; /* 63:55 */ + picreg_t dev_num : 3; /* 54:52 */ + picreg_t buff_num : 4; /* 51:48 */ + picreg_t upp_addr : 16; /* 47:32 */ + picreg_t low_addr : 32; /* 31:0 */ + } pic_pci_rbuf_err_lower_fld_s; + } pic_pci_rbuf_err_lower_u_t; +/* + * Test Pin Control Register + * + * This register selects the output function and value to the four test pins on + * the PIC . + */ + typedef union pic_test_pin_cntl_u { + picreg_t pic_test_pin_cntl_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 8; /* 31:24 */ + picreg_t tdata_out : 8; /* 23:16 */ + picreg_t sel_tpin_7 : 2; /* 15:14 */ + picreg_t sel_tpin_6 : 2; /* 13:12 */ + picreg_t sel_tpin_5 : 2; /* 11:10 */ + picreg_t sel_tpin_4 : 2; /* 9:8 */ + picreg_t sel_tpin_3 : 2; /* 7:6 */ + picreg_t sel_tpin_2 : 2; /* 5:4 */ + picreg_t sel_tpin_1 : 2; /* 3:2 */ + picreg_t sel_tpin_0 : 2; /* 1:0 */ + } pic_test_pin_cntl_fld_s; + } pic_test_pin_cntl_u_t; +/* + * Address Holding Register Link Side Errors + * + * The address holding register is a read only register which contains the ad- + * dress which either can be accessed as a word or double word. Subsequent + * errors are not logged until the error is cleared. The last logged value is + * held until the group is cleared and enabled. + */ + typedef union pic_p_addr_lkerr_u { + picreg_t pic_p_addr_lkerr_regval; + struct { + picreg_t : 16; /* 63:48 */ + picreg_t upp_addr : 16; /* 47:32 */ + picreg_t low_addr : 32; /* 31:0 */ + } pic_p_addr_lkerr_fld_s; + } pic_p_addr_lkerr_u_t; +/* + * PCI Direct Mapping Register + * + * This register is used to relocate a 2 GByte region for PCI to Crosstalk + * transfers. + */ + typedef union pic_p_dir_map_u { + picreg_t pic_p_dir_map_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 8; /* 31:24 */ + picreg_t dir_w_id : 4; /* 23:20 */ + picreg_t : 2; /* 19:18 */ + picreg_t dir_add512 : 1; /* 17:17 */ + picreg_t dir_off : 17; /* 16:0 */ + } pic_p_dir_map_fld_s; + } pic_p_dir_map_u_t; +/* + * PCI Page Map Fault Address Register + * + * This register contains the address and device number when a page map + * fault occurred. + */ + typedef union pic_p_map_fault_u { + picreg_t pic_p_map_fault_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 10; /* 31:22 */ + picreg_t pci_addr : 18; /* 21:4 */ + picreg_t : 1; /* 3:3 */ + picreg_t pci_dev_num : 3; /* 2:0 */ + } pic_p_map_fault_fld_s; + } pic_p_map_fault_u_t; +/* + * Arbitration Register + * + * This register defines the priority and bus time out timing in PCI bus arbi- + * tration. + */ + typedef union pic_p_arb_u { + picreg_t pic_p_arb_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 8; /* 31:24 */ + picreg_t dev_broke : 4; /* 23:20 */ + picreg_t : 2; /* 19:18 */ + picreg_t req_wait_tick : 2; /* 17:16 */ + picreg_t : 4; /* 15:12 */ + picreg_t req_wait_en : 4; /* 11:8 */ + picreg_t disarb : 1; /* 7:7 */ + picreg_t freeze_gnt : 1; /* 6:6 */ + picreg_t : 1; /* 5:5 */ + picreg_t en_bridge_hi : 2; /* 4:3 */ + picreg_t : 1; /* 2:2 */ + picreg_t en_bridge_lo : 2; /* 1:0 */ + } pic_p_arb_fld_s; + } pic_p_arb_u_t; +/* + * Internal Ram Parity Error Register + * + * This register logs information about parity errors on internal ram access. + */ + typedef union pic_p_ram_perr_u { + picreg_t pic_p_ram_perr_regval; + struct { + picreg_t : 6; /* 63:58 */ + picreg_t ate_err_addr : 10; /* 57:48 */ + picreg_t : 7; /* 47:41 */ + picreg_t rd_resp_err_addr : 9; /* 40:32 */ + picreg_t wrt_resp_err_addr : 8; /* 31:24 */ + picreg_t : 2; /* 23:22 */ + picreg_t ate_err : 1; /* 21:21 */ + picreg_t rd_resp_err : 1; /* 20:20 */ + picreg_t wrt_resp_err : 1; /* 19:19 */ + picreg_t dbe_ate : 3; /* 18:16 */ + picreg_t dbe_rd : 8; /* 15:8 */ + picreg_t dbe_wrt : 8; /* 7:0 */ + } pic_p_ram_perr_fld_s; + } pic_p_ram_perr_u_t; +/* + * Time-out Register + * + * This register determines retry hold off and max retries allowed for PIO + * accesses to PCI/PCI-X. + */ + typedef union pic_p_bus_timeout_u { + picreg_t pic_p_bus_timeout_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 11; /* 31:21 */ + picreg_t pci_retry_hld : 5; /* 20:16 */ + picreg_t : 6; /* 15:10 */ + picreg_t pci_retry_cnt : 10; /* 9:0 */ + } pic_p_bus_timeout_fld_s; + } pic_p_bus_timeout_u_t; +/* + * PCI/PCI-X Type 1 Configuration Register + * + * This register is use during accesses to the PCI/PCI-X type 1 configuration + * space. The bits in this register are used to supplement the address during + * the configuration cycle to select the correct secondary bus and device. + */ + typedef union pic_type1_cfg_u { + picreg_t pic_type1_cfg_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 8; /* 31:24 */ + picreg_t bus_num : 8; /* 23:16 */ + picreg_t dev_num : 5; /* 15:11 */ + picreg_t : 11; /* 10:0 */ + } pic_type1_cfg_fld_s; + } pic_type1_cfg_u_t; +/* + * PCI Bus Error Upper Address Holding Register + * + * This register holds the value of the upper address on the PCI Bus when an + * error occurs. + */ + typedef union pic_p_pci_err_upper_u { + picreg_t pic_p_pci_err_upper_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 4; /* 31:28 */ + picreg_t pci_xtalk_did : 4; /* 27:24 */ + picreg_t : 2; /* 23:22 */ + picreg_t pci_dac : 1; /* 21:21 */ + picreg_t pci_dev_master : 1; /* 20:20 */ + picreg_t pci_vdev : 1; /* 19:19 */ + picreg_t pci_dev_num : 3; /* 18:16 */ + picreg_t pci_uaddr_err : 16; /* 15:0 */ + } pic_p_pci_err_upper_fld_s; + } pic_p_pci_err_upper_u_t; +/* + * PCI Bus Error Lower Address Holding Register + * + * This register holds the value of the lower address on the PCI Bus when an + * error occurs. + */ + typedef union pic_p_pci_err_lower_u { + picreg_t pic_p_pci_err_lower_regval; + struct { + picreg_t : 4; /* 63:60 */ + picreg_t pci_xtalk_did : 4; /* 59:56 */ + picreg_t : 2; /* 55:54 */ + picreg_t pci_dac : 1; /* 53:53 */ + picreg_t pci_dev_master : 1; /* 52:52 */ + picreg_t pci_vdev : 1; /* 51:51 */ + picreg_t pci_dev_num : 3; /* 50:48 */ + picreg_t pci_uaddr_err : 16; /* 47:32 */ + picreg_t pci_laddr_err : 32; /* 31:0 */ + } pic_p_pci_err_lower_fld_s; + } pic_p_pci_err_lower_u_t; +/* + * PCI-X Error Address Register + * + * This register contains the address on the PCI-X bus when an error oc- + * curred. + */ + typedef union pic_p_pcix_err_addr_u { + picreg_t pic_p_pcix_err_addr_regval; + struct { + picreg_t pcix_err_addr : 64; /* 63:0 */ + } pic_p_pcix_err_addr_fld_s; + } pic_p_pcix_err_addr_u_t; +/* + * PCI-X Error Attribute Register + * + * This register contains the attribute data on the PCI-X bus when an error + * occurred. + */ + typedef union pic_p_pcix_err_attr_u { + picreg_t pic_p_pcix_err_attr_regval; + struct { + picreg_t : 16; /* 63:48 */ + picreg_t bus_cmd : 4; /* 47:44 */ + picreg_t byte_cnt : 12; /* 43:32 */ + picreg_t : 1; /* 31:31 */ + picreg_t ns : 1; /* 30:30 */ + picreg_t ro : 1; /* 29:29 */ + picreg_t tag : 5; /* 28:24 */ + picreg_t bus_num : 8; /* 23:16 */ + picreg_t dev_num : 5; /* 15:11 */ + picreg_t fun_num : 3; /* 10:8 */ + picreg_t l_byte_cnt : 8; /* 7:0 */ + } pic_p_pcix_err_attr_fld_s; + } pic_p_pcix_err_attr_u_t; +/* + * PCI-X Error Data Register + * + * This register contains the Data on the PCI-X bus when an error occurred. + */ + typedef union pic_p_pcix_err_data_u { + picreg_t pic_p_pcix_err_data_regval; + struct { + picreg_t pcix_err_data : 64; /* 63:0 */ + } pic_p_pcix_err_data_fld_s; + } pic_p_pcix_err_data_u_t; +/* + * PCI-X Read Request Timeout Error Register + * + * This register contains a pointer into the PCI-X read data structure. + */ + typedef union pic_p_pcix_read_req_to_u { + picreg_t pic_p_pcix_read_req_to_regval; + struct { + picreg_t : 55; /* 63:9 */ + picreg_t rd_buff_loc : 5; /* 8:4 */ + picreg_t rd_buff_struct : 4; /* 3:0 */ + } pic_p_pcix_read_req_to_fld_s; + } pic_p_pcix_read_req_to_u_t; +/* + * INT_STATUS Register + * + * This is the current interrupt status register which maintains the current + * status of all the interrupting devices which generated a n interrupt. This + * register is read only and all the bits are active high. A high bit at + * INT_STATE means the corresponding INT_N pin has been asserted + * (low). + */ + typedef union pic_p_int_status_u { + picreg_t pic_p_int_status_regval; + struct { + picreg_t : 22; /* 63:42 */ + picreg_t int_ram_perr : 1; /* 41:41 */ + picreg_t bus_arb_broke : 1; /* 40:40 */ + picreg_t pci_x_req_tout : 1; /* 39:39 */ + picreg_t pci_x_tabort : 1; /* 38:38 */ + picreg_t pci_x_perr : 1; /* 37:37 */ + picreg_t pci_x_serr : 1; /* 36:36 */ + picreg_t pci_x_mretry : 1; /* 35:35 */ + picreg_t pci_x_mtout : 1; /* 34:34 */ + picreg_t pci_x_da_parity : 1; /* 33:33 */ + picreg_t pci_x_ad_parity : 1; /* 32:32 */ + picreg_t : 1; /* 31:31 */ + picreg_t pmu_page_fault : 1; /* 30:30 */ + picreg_t unexpected_resp : 1; /* 29:29 */ + picreg_t bad_xresp_packet : 1; /* 28:28 */ + picreg_t bad_xreq_packet : 1; /* 27:27 */ + picreg_t resp_xtalk_error : 1; /* 26:26 */ + picreg_t req_xtalk_error : 1; /* 25:25 */ + picreg_t invalid_access : 1; /* 24:24 */ + picreg_t unsupported_xop : 1; /* 23:23 */ + picreg_t xreq_fifo_oflow : 1; /* 22:22 */ + picreg_t llp_rec_snerror : 1; /* 21:21 */ + picreg_t llp_rec_cberror : 1; /* 20:20 */ + picreg_t llp_rcty : 1; /* 19:19 */ + picreg_t llp_tx_retry : 1; /* 18:18 */ + picreg_t llp_tcty : 1; /* 17:17 */ + picreg_t : 1; /* 16:16 */ + picreg_t pci_abort : 1; /* 15:15 */ + picreg_t pci_parity : 1; /* 14:14 */ + picreg_t pci_serr : 1; /* 13:13 */ + picreg_t pci_perr : 1; /* 12:12 */ + picreg_t pci_master_tout : 1; /* 11:11 */ + picreg_t pci_retry_cnt : 1; /* 10:10 */ + picreg_t xread_req_tout : 1; /* 9:9 */ + picreg_t : 1; /* 8:8 */ + picreg_t int_state : 8; /* 7:0 */ + } pic_p_int_status_fld_s; + } pic_p_int_status_u_t; +/* + * Interrupt Enable Register + * + * This register enables the reporting of interrupt to the host. Each bit in this + * register corresponds to the same bit in Interrupt Status register. All bits + * are zero after reset. + */ + typedef union pic_p_int_enable_u { + picreg_t pic_p_int_enable_regval; + struct { + picreg_t : 22; /* 63:42 */ + picreg_t en_int_ram_perr : 1; /* 41:41 */ + picreg_t en_bus_arb_broke : 1; /* 40:40 */ + picreg_t en_pci_x_req_tout : 1; /* 39:39 */ + picreg_t en_pci_x_tabort : 1; /* 38:38 */ + picreg_t en_pci_x_perr : 1; /* 37:37 */ + picreg_t en_pci_x_serr : 1; /* 36:36 */ + picreg_t en_pci_x_mretry : 1; /* 35:35 */ + picreg_t en_pci_x_mtout : 1; /* 34:34 */ + picreg_t en_pci_x_da_parity : 1; /* 33:33 */ + picreg_t en_pci_x_ad_parity : 1; /* 32:32 */ + picreg_t : 1; /* 31:31 */ + picreg_t en_pmu_page_fault : 1; /* 30:30 */ + picreg_t en_unexpected_resp : 1; /* 29:29 */ + picreg_t en_bad_xresp_packet : 1; /* 28:28 */ + picreg_t en_bad_xreq_packet : 1; /* 27:27 */ + picreg_t en_resp_xtalk_error : 1; /* 26:26 */ + picreg_t en_req_xtalk_error : 1; /* 25:25 */ + picreg_t en_invalid_access : 1; /* 24:24 */ + picreg_t en_unsupported_xop : 1; /* 23:23 */ + picreg_t en_xreq_fifo_oflow : 1; /* 22:22 */ + picreg_t en_llp_rec_snerror : 1; /* 21:21 */ + picreg_t en_llp_rec_cberror : 1; /* 20:20 */ + picreg_t en_llp_rcty : 1; /* 19:19 */ + picreg_t en_llp_tx_retry : 1; /* 18:18 */ + picreg_t en_llp_tcty : 1; /* 17:17 */ + picreg_t : 1; /* 16:16 */ + picreg_t en_pci_abort : 1; /* 15:15 */ + picreg_t en_pci_parity : 1; /* 14:14 */ + picreg_t en_pci_serr : 1; /* 13:13 */ + picreg_t en_pci_perr : 1; /* 12:12 */ + picreg_t en_pci_master_tout : 1; /* 11:11 */ + picreg_t en_pci_retry_cnt : 1; /* 10:10 */ + picreg_t en_xread_req_tout : 1; /* 9:9 */ + picreg_t : 1; /* 8:8 */ + picreg_t en_int_state : 8; /* 7:0 */ + } pic_p_int_enable_fld_s; + } pic_p_int_enable_u_t; +/* + * Reset Interrupt Register + * + * A write of a "1" clears the bit and rearms the error registers. Writes also + * clear the error view register. + */ + typedef union pic_p_int_rst_u { + picreg_t pic_p_int_rst_regval; + struct { + picreg_t : 22; /* 63:42 */ + picreg_t logv_int_ram_perr : 1; /* 41:41 */ + picreg_t logv_bus_arb_broke : 1; /* 40:40 */ + picreg_t logv_pci_x_req_tout : 1; /* 39:39 */ + picreg_t logv_pci_x_tabort : 1; /* 38:38 */ + picreg_t logv_pci_x_perr : 1; /* 37:37 */ + picreg_t logv_pci_x_serr : 1; /* 36:36 */ + picreg_t logv_pci_x_mretry : 1; /* 35:35 */ + picreg_t logv_pci_x_mtout : 1; /* 34:34 */ + picreg_t logv_pci_x_da_parity : 1; /* 33:33 */ + picreg_t logv_pci_x_ad_parity : 1; /* 32:32 */ + picreg_t : 1; /* 31:31 */ + picreg_t logv_pmu_page_fault : 1; /* 30:30 */ + picreg_t logv_unexpected_resp : 1; /* 29:29 */ + picreg_t logv_bad_xresp_packet : 1; /* 28:28 */ + picreg_t logv_bad_xreq_packet : 1; /* 27:27 */ + picreg_t logv_resp_xtalk_error : 1; /* 26:26 */ + picreg_t logv_req_xtalk_error : 1; /* 25:25 */ + picreg_t logv_invalid_access : 1; /* 24:24 */ + picreg_t logv_unsupported_xop : 1; /* 23:23 */ + picreg_t logv_xreq_fifo_oflow : 1; /* 22:22 */ + picreg_t logv_llp_rec_snerror : 1; /* 21:21 */ + picreg_t logv_llp_rec_cberror : 1; /* 20:20 */ + picreg_t logv_llp_rcty : 1; /* 19:19 */ + picreg_t logv_llp_tx_retry : 1; /* 18:18 */ + picreg_t logv_llp_tcty : 1; /* 17:17 */ + picreg_t : 1; /* 16:16 */ + picreg_t logv_pci_abort : 1; /* 15:15 */ + picreg_t logv_pci_parity : 1; /* 14:14 */ + picreg_t logv_pci_serr : 1; /* 13:13 */ + picreg_t logv_pci_perr : 1; /* 12:12 */ + picreg_t logv_pci_master_tout : 1; /* 11:11 */ + picreg_t logv_pci_retry_cnt : 1; /* 10:10 */ + picreg_t logv_xread_req_tout : 1; /* 9:9 */ + picreg_t : 2; /* 8:7 */ + picreg_t multi_clr : 1; /* 6:6 */ + picreg_t : 6; /* 5:0 */ + } pic_p_int_rst_fld_s; + } pic_p_int_rst_u_t; + +/* + * Interrupt Mode Register + * + * This register defines the interrupting mode of the INT_N pins. + */ + typedef union pic_p_int_mode_u { + picreg_t pic_p_int_mode_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 24; /* 31:8 */ + picreg_t en_clr_pkt : 8; /* 7:0 */ + } pic_p_int_mode_fld_s; + } pic_p_int_mode_u_t; +/* + * Interrupt Device Select Register + * + * This register associates interrupt pins with devices thus allowing buffer + * management (flushing) when a device interrupt occurs. + */ + typedef union pic_p_int_device_u { + picreg_t pic_p_int_device_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 8; /* 31:24 */ + picreg_t int7_dev : 3; /* 23:21 */ + picreg_t int6_dev : 3; /* 20:18 */ + picreg_t int5_dev : 3; /* 17:15 */ + picreg_t int4_dev : 3; /* 14:12 */ + picreg_t int3_dev : 3; /* 11:9 */ + picreg_t int2_dev : 3; /* 8:6 */ + picreg_t int1_dev : 3; /* 5:3 */ + picreg_t int0_dev : 3; /* 2:0 */ + } pic_p_int_device_fld_s; + } pic_p_int_device_u_t; +/* + * Host Error Interrupt Field Register + * + * This register tells which bit location in the host's Interrupt Status register + * to set or reset when any error condition happens. + */ + typedef union pic_p_int_host_err_u { + picreg_t pic_p_int_host_err_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 24; /* 31:8 */ + picreg_t bridge_err_fld : 8; /* 7:0 */ + } pic_p_int_host_err_fld_s; + } pic_p_int_host_err_u_t; +/* + * Interrupt (x) Host Address Register + * + * This register allow different host address to be assigned to each interrupt + * pin and the bit in the host. + */ + typedef union pic_p_int_addr_u { + picreg_t pic_p_int_addr_regval; + struct { + picreg_t : 8; /* 63:56 */ + picreg_t int_fld : 8; /* 55:48 */ + picreg_t int_addr : 48; /* 47:0 */ + } pic_p_int_addr_fld_s; + } pic_p_int_addr_u_t; +/* + * Error Interrupt View Register + * + * This register contains the view of which interrupt occur even if they are + * not currently enabled. The group clear is used to clear these bits just like + * the interrupt status register bits. + */ + typedef union pic_p_err_int_view_u { + picreg_t pic_p_err_int_view_regval; + struct { + picreg_t : 22; /* 63:42 */ + picreg_t int_ram_perr : 1; /* 41:41 */ + picreg_t bus_arb_broke : 1; /* 40:40 */ + picreg_t pci_x_req_tout : 1; /* 39:39 */ + picreg_t pci_x_tabort : 1; /* 38:38 */ + picreg_t pci_x_perr : 1; /* 37:37 */ + picreg_t pci_x_serr : 1; /* 36:36 */ + picreg_t pci_x_mretry : 1; /* 35:35 */ + picreg_t pci_x_mtout : 1; /* 34:34 */ + picreg_t pci_x_da_parity : 1; /* 33:33 */ + picreg_t pci_x_ad_parity : 1; /* 32:32 */ + picreg_t : 1; /* 31:31 */ + picreg_t pmu_page_fault : 1; /* 30:30 */ + picreg_t unexpected_resp : 1; /* 29:29 */ + picreg_t bad_xresp_packet : 1; /* 28:28 */ + picreg_t bad_xreq_packet : 1; /* 27:27 */ + picreg_t resp_xtalk_error : 1; /* 26:26 */ + picreg_t req_xtalk_error : 1; /* 25:25 */ + picreg_t invalid_access : 1; /* 24:24 */ + picreg_t unsupported_xop : 1; /* 23:23 */ + picreg_t xreq_fifo_oflow : 1; /* 22:22 */ + picreg_t llp_rec_snerror : 1; /* 21:21 */ + picreg_t llp_rec_cberror : 1; /* 20:20 */ + picreg_t llp_rcty : 1; /* 19:19 */ + picreg_t llp_tx_retry : 1; /* 18:18 */ + picreg_t llp_tcty : 1; /* 17:17 */ + picreg_t : 1; /* 16:16 */ + picreg_t pci_abort : 1; /* 15:15 */ + picreg_t pci_parity : 1; /* 14:14 */ + picreg_t pci_serr : 1; /* 13:13 */ + picreg_t pci_perr : 1; /* 12:12 */ + picreg_t pci_master_tout : 1; /* 11:11 */ + picreg_t pci_retry_cnt : 1; /* 10:10 */ + picreg_t xread_req_tout : 1; /* 9:9 */ + picreg_t : 9; /* 8:0 */ + } pic_p_err_int_view_fld_s; + } pic_p_err_int_view_u_t; + + +/* + * Multiple Interrupt Register + * + * This register indicates if any interrupt occurs more than once without be- + * ing cleared. + */ + typedef union pic_p_mult_int_u { + picreg_t pic_p_mult_int_regval; + struct { + picreg_t : 22; /* 63:42 */ + picreg_t int_ram_perr : 1; /* 41:41 */ + picreg_t bus_arb_broke : 1; /* 40:40 */ + picreg_t pci_x_req_tout : 1; /* 39:39 */ + picreg_t pci_x_tabort : 1; /* 38:38 */ + picreg_t pci_x_perr : 1; /* 37:37 */ + picreg_t pci_x_serr : 1; /* 36:36 */ + picreg_t pci_x_mretry : 1; /* 35:35 */ + picreg_t pci_x_mtout : 1; /* 34:34 */ + picreg_t pci_x_da_parity : 1; /* 33:33 */ + picreg_t pci_x_ad_parity : 1; /* 32:32 */ + picreg_t : 1; /* 31:31 */ + picreg_t pmu_page_fault : 1; /* 30:30 */ + picreg_t unexpected_resp : 1; /* 29:29 */ + picreg_t bad_xresp_packet : 1; /* 28:28 */ + picreg_t bad_xreq_packet : 1; /* 27:27 */ + picreg_t resp_xtalk_error : 1; /* 26:26 */ + picreg_t req_xtalk_error : 1; /* 25:25 */ + picreg_t invalid_access : 1; /* 24:24 */ + picreg_t unsupported_xop : 1; /* 23:23 */ + picreg_t xreq_fifo_oflow : 1; /* 22:22 */ + picreg_t llp_rec_snerror : 1; /* 21:21 */ + picreg_t llp_rec_cberror : 1; /* 20:20 */ + picreg_t llp_rcty : 1; /* 19:19 */ + picreg_t llp_tx_retry : 1; /* 18:18 */ + picreg_t llp_tcty : 1; /* 17:17 */ + picreg_t : 1; /* 16:16 */ + picreg_t pci_abort : 1; /* 15:15 */ + picreg_t pci_parity : 1; /* 14:14 */ + picreg_t pci_serr : 1; /* 13:13 */ + picreg_t pci_perr : 1; /* 12:12 */ + picreg_t pci_master_tout : 1; /* 11:11 */ + picreg_t pci_retry_cnt : 1; /* 10:10 */ + picreg_t xread_req_tout : 1; /* 9:9 */ + picreg_t : 1; /* 8:8 */ + picreg_t int_state : 8; /* 7:0 */ + } pic_p_mult_int_fld_s; + } pic_p_mult_int_u_t; +/* + * Force Always Interrupt (x) Register + * + * A write to this data independent write only register will force a set inter- + * rupt to occur as if the interrupt line had transitioned. If the interrupt line + * is already active an addition set interrupt packet is set. All buffer flush op- + * erations also occur on this operation. + */ + + +/* + * Force Interrupt (x) Register + * + * A write to this data independent write only register in conjunction with + * the assertion of the corresponding interrupt line will force a set interrupt + * to occur as if the interrupt line had transitioned. The interrupt line must + * be active for this operation to generate a set packet, otherwise the write + * PIO is ignored. All buffer flush operations also occur when the set packet + * is sent on this operation. + */ + + +/* + * Device Registers + * + * The Device registers contain device specific and mapping information. + */ + typedef union pic_device_reg_u { + picreg_t pic_device_reg_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 2; /* 31:30 */ + picreg_t en_virtual1 : 1; /* 29:29 */ + picreg_t en_error_lock : 1; /* 28:28 */ + picreg_t en_page_chk : 1; /* 27:27 */ + picreg_t force_pci_par : 1; /* 26:26 */ + picreg_t en_virtual0 : 1; /* 25:25 */ + picreg_t : 1; /* 24:24 */ + picreg_t dir_wrt_gen : 1; /* 23:23 */ + picreg_t dev_size : 1; /* 22:22 */ + picreg_t real_time : 1; /* 21:21 */ + picreg_t : 1; /* 20:20 */ + picreg_t swap_direct : 1; /* 19:19 */ + picreg_t prefetch : 1; /* 18:18 */ + picreg_t precise : 1; /* 17:17 */ + picreg_t coherent : 1; /* 16:16 */ + picreg_t barrier : 1; /* 15:15 */ + picreg_t gbr : 1; /* 14:14 */ + picreg_t dev_swap : 1; /* 13:13 */ + picreg_t dev_io_mem : 1; /* 12:12 */ + picreg_t dev_off : 12; /* 11:0 */ + } pic_device_reg_fld_s; + } pic_device_reg_u_t; +/* + * Device (x) Write Request Buffer Flush + * + * When read, this register will return a 0x00 after the write buffer associat- + * ed with the device has been flushed. (PCI Only) + */ + + +/* + * Even Device Read Response Buffer Register (PCI Only) + * + * This register is use to allocate the read response buffers for the even num- + * bered devices. (0,2) + */ + typedef union pic_p_even_resp_u { + picreg_t pic_p_even_resp_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t buff_14_en : 1; /* 31:31 */ + picreg_t buff_14_vdev : 2; /* 30:29 */ + picreg_t buff_14_pdev : 1; /* 28:28 */ + picreg_t buff_12_en : 1; /* 27:27 */ + picreg_t buff_12_vdev : 2; /* 26:25 */ + picreg_t buff_12_pdev : 1; /* 24:24 */ + picreg_t buff_10_en : 1; /* 23:23 */ + picreg_t buff_10_vdev : 2; /* 22:21 */ + picreg_t buff_10_pdev : 1; /* 20:20 */ + picreg_t buff_8_en : 1; /* 19:19 */ + picreg_t buff_8_vdev : 2; /* 18:17 */ + picreg_t buff_8_pdev : 1; /* 16:16 */ + picreg_t buff_6_en : 1; /* 15:15 */ + picreg_t buff_6_vdev : 2; /* 14:13 */ + picreg_t buff_6_pdev : 1; /* 12:12 */ + picreg_t buff_4_en : 1; /* 11:11 */ + picreg_t buff_4_vdev : 2; /* 10:9 */ + picreg_t buff_4_pdev : 1; /* 8:8 */ + picreg_t buff_2_en : 1; /* 7:7 */ + picreg_t buff_2_vdev : 2; /* 6:5 */ + picreg_t buff_2_pdev : 1; /* 4:4 */ + picreg_t buff_0_en : 1; /* 3:3 */ + picreg_t buff_0_vdev : 2; /* 2:1 */ + picreg_t buff_0_pdev : 1; /* 0:0 */ + } pic_p_even_resp_fld_s; + } pic_p_even_resp_u_t; +/* + * Odd Device Read Response Buffer Register (PCI Only) + * + * This register is use to allocate the read response buffers for the odd num- + * bered devices. (1,3)) + */ + typedef union pic_p_odd_resp_u { + picreg_t pic_p_odd_resp_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t buff_15_en : 1; /* 31:31 */ + picreg_t buff_15_vdev : 2; /* 30:29 */ + picreg_t buff_15_pdev : 1; /* 28:28 */ + picreg_t buff_13_en : 1; /* 27:27 */ + picreg_t buff_13_vdev : 2; /* 26:25 */ + picreg_t buff_13_pdev : 1; /* 24:24 */ + picreg_t buff_11_en : 1; /* 23:23 */ + picreg_t buff_11_vdev : 2; /* 22:21 */ + picreg_t buff_11_pdev : 1; /* 20:20 */ + picreg_t buff_9_en : 1; /* 19:19 */ + picreg_t buff_9_vdev : 2; /* 18:17 */ + picreg_t buff_9_pdev : 1; /* 16:16 */ + picreg_t buff_7_en : 1; /* 15:15 */ + picreg_t buff_7_vdev : 2; /* 14:13 */ + picreg_t buff_7_pdev : 1; /* 12:12 */ + picreg_t buff_5_en : 1; /* 11:11 */ + picreg_t buff_5_vdev : 2; /* 10:9 */ + picreg_t buff_5_pdev : 1; /* 8:8 */ + picreg_t buff_3_en : 1; /* 7:7 */ + picreg_t buff_3_vdev : 2; /* 6:5 */ + picreg_t buff_3_pdev : 1; /* 4:4 */ + picreg_t buff_1_en : 1; /* 3:3 */ + picreg_t buff_1_vdev : 2; /* 2:1 */ + picreg_t buff_1_pdev : 1; /* 0:0 */ + } pic_p_odd_resp_fld_s; + } pic_p_odd_resp_u_t; +/* + * Read Response Buffer Status Register (PCI Only) + * + * This read only register contains the current response buffer status. + */ + typedef union pic_p_resp_status_u { + picreg_t pic_p_resp_status_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t rrb_valid : 16; /* 31:16 */ + picreg_t rrb_inuse : 16; /* 15:0 */ + } pic_p_resp_status_fld_s; + } pic_p_resp_status_u_t; +/* + * Read Response Buffer Clear Register (PCI Only) + * + * A write to this register clears the current contents of the buffer. + */ + typedef union pic_p_resp_clear_u { + picreg_t pic_p_resp_clear_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 16; /* 31:16 */ + picreg_t rrb_clear : 16; /* 15:0 */ + } pic_p_resp_clear_fld_s; + } pic_p_resp_clear_u_t; +/* + * PCI Read Response Buffer (x) Upper Address Match + * + * The PCI Bridge read response buffer upper address register is a read only + * register which contains the upper 16-bits of the address and status used to + * select the buffer for a PCI transaction. + */ + typedef union pic_p_buf_upper_addr_match_u { + picreg_t pic_p_buf_upper_addr_match_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t filled : 1; /* 31:31 */ + picreg_t armed : 1; /* 30:30 */ + picreg_t flush : 1; /* 29:29 */ + picreg_t xerr : 1; /* 28:28 */ + picreg_t pkterr : 1; /* 27:27 */ + picreg_t timeout : 1; /* 26:26 */ + picreg_t prefetch : 1; /* 25:25 */ + picreg_t precise : 1; /* 24:24 */ + picreg_t dw_be : 8; /* 23:16 */ + picreg_t upp_addr : 16; /* 15:0 */ + } pic_p_buf_upper_addr_match_fld_s; + } pic_p_buf_upper_addr_match_u_t; +/* + * PCI Read Response Buffer (x) Lower Address Match + * + * The PCI Bridge read response buffer lower address Match register is a + * read only register which contains the address and status used to select the + * buffer for a PCI transaction. + */ + typedef union pic_p_buf_lower_addr_match_u { + picreg_t pic_p_buf_lower_addr_match_regval; + struct { + picreg_t filled : 1; /* 63:63 */ + picreg_t armed : 1; /* 62:62 */ + picreg_t flush : 1; /* 61:61 */ + picreg_t xerr : 1; /* 60:60 */ + picreg_t pkterr : 1; /* 59:59 */ + picreg_t timeout : 1; /* 58:58 */ + picreg_t prefetch : 1; /* 57:57 */ + picreg_t precise : 1; /* 56:56 */ + picreg_t dw_be : 8; /* 55:48 */ + picreg_t upp_addr : 16; /* 47:32 */ + picreg_t low_addr : 32; /* 31:0 */ + } pic_p_buf_lower_addr_match_fld_s; + } pic_p_buf_lower_addr_match_u_t; +/* + * PCI Buffer (x) Flush Count with Data Touch Register + * + * This counter is incremented each time the corresponding response buffer + * is flushed after at least a single data element in the buffer is used. A word + * write to this address clears the count. + */ + typedef union pic_flush_w_touch_u { + picreg_t pic_flush_w_touch_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 16; /* 31:16 */ + picreg_t touch_cnt : 16; /* 15:0 */ + } pic_flush_w_touch_fld_s; + } pic_flush_w_touch_u_t; +/* + * PCI Buffer (x) Flush Count w/o Data Touch Register + * + * This counter is incremented each time the corresponding response buffer + * is flushed without any data element in the buffer being used. A word + * write to this address clears the count. + */ + typedef union pic_flush_wo_touch_u { + picreg_t pic_flush_wo_touch_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 16; /* 31:16 */ + picreg_t notouch_cnt : 16; /* 15:0 */ + } pic_flush_wo_touch_fld_s; + } pic_flush_wo_touch_u_t; +/* + * PCI Buffer (x) Request in Flight Count Register + * + * This counter is incremented on each bus clock while the request is in- + * flight. A word write to this address clears the count. ] + */ + typedef union pic_inflight_u { + picreg_t pic_inflight_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 16; /* 31:16 */ + picreg_t inflight_cnt : 16; /* 15:0 */ + } pic_inflight_fld_s; + } pic_inflight_u_t; +/* + * PCI Buffer (x) Prefetch Request Count Register + * + * This counter is incremented each time the request using this buffer was + * generated from the prefetcher. A word write to this address clears the + * count. + */ + typedef union pic_prefetch_u { + picreg_t pic_prefetch_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 16; /* 31:16 */ + picreg_t prefetch_cnt : 16; /* 15:0 */ + } pic_prefetch_fld_s; + } pic_prefetch_u_t; +/* + * PCI Buffer (x) Total PCI Retry Count Register + * + * This counter is incremented each time a PCI bus retry occurs and the ad- + * dress matches the tag for the selected buffer. The buffer must also has this + * request in-flight. A word write to this address clears the count. + */ + typedef union pic_total_pci_retry_u { + picreg_t pic_total_pci_retry_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 16; /* 31:16 */ + picreg_t retry_cnt : 16; /* 15:0 */ + } pic_total_pci_retry_fld_s; + } pic_total_pci_retry_u_t; +/* + * PCI Buffer (x) Max PCI Retry Count Register + * + * This counter is contains the maximum retry count for a single request + * which was in-flight for this buffer. A word write to this address clears the + * count. + */ + typedef union pic_max_pci_retry_u { + picreg_t pic_max_pci_retry_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 16; /* 31:16 */ + picreg_t max_retry_cnt : 16; /* 15:0 */ + } pic_max_pci_retry_fld_s; + } pic_max_pci_retry_u_t; +/* + * PCI Buffer (x) Max Latency Count Register + * + * This counter is contains the maximum count (in bus clocks) for a single + * request which was in-flight for this buffer. A word write to this address + * clears the count. + */ + typedef union pic_max_latency_u { + picreg_t pic_max_latency_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t : 16; /* 31:16 */ + picreg_t max_latency_cnt : 16; /* 15:0 */ + } pic_max_latency_fld_s; + } pic_max_latency_u_t; +/* + * PCI Buffer (x) Clear All Register + * + * Any access to this register clears all the count values for the (x) registers. + */ + + +/* + * PCI-X Registers + * + * This register contains the address in the read buffer structure. There are + * 16 read buffer structures. + */ + typedef union pic_rd_buf_addr_u { + picreg_t pic_rd_buf_addr_regval; + struct { + picreg_t pcix_err_addr : 64; /* 63:0 */ + } pic_rd_buf_addr_fld_s; + } pic_rd_buf_addr_u_t; +/* + * PCI-X Read Buffer (x) Attribute Register + * + * This register contains the attribute data in the read buffer structure. There + * are 16 read buffer structures. + */ + typedef union pic_px_read_buf_attr_u { + picreg_t pic_px_read_buf_attr_regval; + struct { + picreg_t : 16; /* 63:48 */ + picreg_t bus_cmd : 4; /* 47:44 */ + picreg_t byte_cnt : 12; /* 43:32 */ + picreg_t entry_valid : 1; /* 31:31 */ + picreg_t ns : 1; /* 30:30 */ + picreg_t ro : 1; /* 29:29 */ + picreg_t tag : 5; /* 28:24 */ + picreg_t bus_num : 8; /* 23:16 */ + picreg_t dev_num : 5; /* 15:11 */ + picreg_t fun_num : 3; /* 10:8 */ + picreg_t : 2; /* 7:6 */ + picreg_t f_buffer_index : 6; /* 5:0 */ + } pic_px_read_buf_attr_fld_s; + } pic_px_read_buf_attr_u_t; +/* + * PCI-X Write Buffer (x) Address Register + * + * This register contains the address in the write buffer structure. There are + * 8 write buffer structures. + */ + typedef union pic_px_write_buf_addr_u { + picreg_t pic_px_write_buf_addr_regval; + struct { + picreg_t pcix_err_addr : 64; /* 63:0 */ + } pic_px_write_buf_addr_fld_s; + } pic_px_write_buf_addr_u_t; +/* + * PCI-X Write Buffer (x) Attribute Register + * + * This register contains the attribute data in the write buffer structure. + * There are 8 write buffer structures. + */ + typedef union pic_px_write_buf_attr_u { + picreg_t pic_px_write_buf_attr_regval; + struct { + picreg_t : 16; /* 63:48 */ + picreg_t bus_cmd : 4; /* 47:44 */ + picreg_t byte_cnt : 12; /* 43:32 */ + picreg_t entry_valid : 1; /* 31:31 */ + picreg_t ns : 1; /* 30:30 */ + picreg_t ro : 1; /* 29:29 */ + picreg_t tag : 5; /* 28:24 */ + picreg_t bus_num : 8; /* 23:16 */ + picreg_t dev_num : 5; /* 15:11 */ + picreg_t fun_num : 3; /* 10:8 */ + picreg_t : 2; /* 7:6 */ + picreg_t f_buffer_index : 6; /* 5:0 */ + } pic_px_write_buf_attr_fld_s; + } pic_px_write_buf_attr_u_t; +/* + * PCI-X Write Buffer (x) Valid Register + * + * This register contains the valid or inuse cache lines for this buffer struc- + * ture. + */ + typedef union pic_px_write_buf_valid_u { + picreg_t pic_px_write_buf_valid_regval; + struct { + picreg_t : 32; /* 63:32 */ + picreg_t wrt_valid_buff : 32; /* 31:0 */ + } pic_px_write_buf_valid_fld_s; + } pic_px_write_buf_valid_u_t; + +#endif /* __ASSEMBLY__ */ +#endif /* _ASM_SN_PCI_PIC_H */ diff -Nru a/include/asm-ia64/sn/rw_mmr.h b/include/asm-ia64/sn/rw_mmr.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-ia64/sn/rw_mmr.h Fri Mar 7 20:40:18 2003 @@ -0,0 +1,73 @@ +/* + * 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. + */ +#ifndef _ASM_IA64_SN_RW_MMR_H +#define _ASM_IA64_SN_RW_MMR_H + + +/* + * This file contains macros used to access MMR registers via + * uncached physical addresses. + * pio_phys_read_mmr - read an MMR + * pio_phys_write_mmr - write an MMR + * pio_atomic_phys_write_mmrs - atomically write 2 MMRs with psr.ic=0 + * (interrupt collection) + * + * Addresses passed to these routines should be uncached physical addresses + * ie., 0x80000.... + */ + + +extern inline long +pio_phys_read_mmr(volatile long *mmr) +{ + long val; + asm volatile + ("mov r2=psr;;" + "rsm psr.i | psr.dt;;" + "srlz.i;;" + "ld8.acq %0=[%1];;" + "mov psr.l=r2;;" + "srlz.i;;" + : "=r"(val) + : "r"(mmr) + : "r2"); + return val; +} + + + +extern inline void +pio_phys_write_mmr(volatile long *mmr, long val) +{ + asm volatile + ("mov r2=psr;;" + "rsm psr.i | psr.dt;;" + "srlz.i;;" + "st8.rel [%0]=%1;;" + "mov psr.l=r2;;" + "srlz.i;;" + :: "r"(mmr), "r"(val) + : "r2", "memory"); +} + +extern inline void +pio_atomic_phys_write_mmrs(volatile long *mmr1, long val1, volatile long *mmr2, long val2) +{ + asm volatile + ("mov r2=psr;;" + "rsm psr.i | psr.dt | psr.ic;;" + "srlz.i;;" + "st8.rel [%0]=%1;" + "st8.rel [%2]=%3;;" + "mov psr.l=r2;;" + "srlz.i;;" + :: "r"(mmr1), "r"(val1), "r"(mmr2), "r"(val2) + : "r2", "memory"); +} + +#endif /* _ASM_IA64_SN_RW_MMR_H */ diff -Nru a/include/asm-ia64/sn/sn2/geo.h b/include/asm-ia64/sn/sn2/geo.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-ia64/sn/sn2/geo.h Fri Mar 7 20:40:18 2003 @@ -0,0 +1,109 @@ +/* $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. + */ + +#ifndef __SYS_SN_SN2_GEO_H__ +#define __SYS_SN_SN2_GEO_H__ + +/* Headers required by declarations in this file */ + +#include + + +/* The geoid_t implementation below is based loosely on the pcfg_t + implementation in sys/SN/promcfg.h. */ + +/* Type declaractions */ + +/* Size of a geoid_t structure (must be before decl. of geoid_u) */ +#define GEOID_SIZE 8 /* Would 16 be better? The size can + be different on different platforms. */ + +#define MAX_SLABS 0xe /* slabs per module */ + +typedef unsigned char geo_type_t; + +/* Fields common to all substructures */ +typedef struct geo_any_s { + moduleid_t module; /* The module (box) this h/w lives in */ + geo_type_t type; /* What type of h/w is named by this geoid_t */ + slabid_t slab; /* The logical assembly within the module */ +} geo_any_t; + +/* Additional fields for particular types of hardware */ +typedef struct geo_node_s { + geo_any_t any; /* No additional fields needed */ +} geo_node_t; + +typedef struct geo_rtr_s { + geo_any_t any; /* No additional fields needed */ +} geo_rtr_t; + +typedef struct geo_iocntl_s { + geo_any_t any; /* No additional fields needed */ +} geo_iocntl_t; + +typedef struct geo_pcicard_s { + geo_iocntl_t any; + char bus; /* Bus/widget number */ + slotid_t slot; /* PCI slot number */ +} geo_pcicard_t; + +/* Subcomponents of a node */ +typedef struct geo_cpu_s { + geo_node_t node; + char slice; /* Which CPU on the node */ +} geo_cpu_t; + +typedef struct geo_mem_s { + geo_node_t node; + char membus; /* The memory bus on the node */ + char memslot; /* The memory slot on the bus */ +} geo_mem_t; + + +typedef union geoid_u { + geo_any_t any; + geo_node_t node; + geo_iocntl_t iocntl; + geo_pcicard_t pcicard; + geo_rtr_t rtr; + geo_cpu_t cpu; + geo_mem_t mem; + char padsize[GEOID_SIZE]; +} geoid_t; + + +/* Preprocessor macros */ + +#define GEO_MAX_LEN 48 /* max. formatted length, plus some pad: + module/001c07/slab/5/node/memory/2/slot/4 */ + +/* Values for geo_type_t */ +#define GEO_TYPE_INVALID 0 +#define GEO_TYPE_MODULE 1 +#define GEO_TYPE_NODE 2 +#define GEO_TYPE_RTR 3 +#define GEO_TYPE_IOCNTL 4 +#define GEO_TYPE_IOCARD 5 +#define GEO_TYPE_CPU 6 +#define GEO_TYPE_MEM 7 +#define GEO_TYPE_MAX (GEO_TYPE_MEM+1) + +/* Parameter for hwcfg_format_geoid_compt() */ +#define GEO_COMPT_MODULE 1 +#define GEO_COMPT_SLAB 2 +#define GEO_COMPT_IOBUS 3 +#define GEO_COMPT_IOSLOT 4 +#define GEO_COMPT_CPU 5 +#define GEO_COMPT_MEMBUS 6 +#define GEO_COMPT_MEMSLOT 7 + +#define GEO_INVALID_STR "" + +#endif /* __SYS_SN_SN2_GEO_H__ */ diff -Nru a/include/asm-ia64/spinlock.h b/include/asm-ia64/spinlock.h --- a/include/asm-ia64/spinlock.h Fri Mar 7 20:40:16 2003 +++ b/include/asm-ia64/spinlock.h Fri Mar 7 20:40:16 2003 @@ -183,6 +183,19 @@ :: "r"(rw) : "ar.ccv", "p7", "r2", "r29", "memory"); \ } while(0) +#define _raw_write_trylock(rw) \ +({ \ + register long result; \ + \ + __asm__ __volatile__ ( \ + "mov ar.ccv = r0\n" \ + "dep r29 = -1, r0, 31, 1\n" \ + ";;\n" \ + "cmpxchg4.acq %0 = [%1], r29, ar.ccv\n" \ + : "=r"(result) : "r"(rw) : "ar.ccv", "r29", "memory"); \ + (result == 0); \ +}) + #define _raw_write_unlock(x) \ ({ \ smp_mb__before_clear_bit(); /* need barrier before releasing lock... */ \ diff -Nru a/include/asm-ia64/system.h b/include/asm-ia64/system.h --- a/include/asm-ia64/system.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-ia64/system.h Fri Mar 7 20:40:17 2003 @@ -206,7 +206,7 @@ #ifdef CONFIG_PERFMON DECLARE_PER_CPU(unsigned long, pfm_syst_info); -# define PERFMON_IS_SYSWIDE() (get_cpu_var(pfm_syst_info) & 0x1) +# define PERFMON_IS_SYSWIDE() (__get_cpu_var(pfm_syst_info) & 0x1) #else # define PERFMON_IS_SYSWIDE() (0) #endif diff -Nru a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h --- a/include/asm-ia64/thread_info.h Fri Mar 7 20:40:18 2003 +++ b/include/asm-ia64/thread_info.h Fri Mar 7 20:40:18 2003 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 Hewlett-Packard Co + * Copyright (C) 2002-2003 Hewlett-Packard Co * David Mosberger-Tang */ #ifndef _ASM_IA64_THREAD_INFO_H @@ -15,7 +15,8 @@ #define TI_ADDR_LIMIT 0x10 #define TI_PRE_COUNT 0x18 -#define PREEMPT_ACTIVE 0x4000000 +#define PREEMPT_ACTIVE_BIT 30 +#define PREEMPT_ACTIVE (1 << PREEMPT_ACTIVE_BIT) #ifndef __ASSEMBLY__ @@ -50,6 +51,7 @@ /* how to get the thread information struct from C */ #define current_thread_info() ((struct thread_info *) ((char *) current + IA64_TASK_SIZE)) +#define free_thread_info(ti) /* nothing */ #endif /* !__ASSEMBLY */ diff -Nru a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h --- a/include/asm-ia64/topology.h Fri Mar 7 20:40:16 2003 +++ b/include/asm-ia64/topology.h Fri Mar 7 20:40:16 2003 @@ -26,7 +26,7 @@ /* * Returns a bitmask of CPUs on Node 'node'. */ -#define node_to_cpumask(node) (node_to_cpumask[node]) +#define node_to_cpumask(node) (node_to_cpu_mask[node]) #else #define cpu_to_node(cpu) (0) diff -Nru a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h --- a/include/asm-ia64/unistd.h Fri Mar 7 20:40:16 2003 +++ b/include/asm-ia64/unistd.h Fri Mar 7 20:40:16 2003 @@ -223,7 +223,7 @@ #define __NR_sched_setaffinity 1231 #define __NR_sched_getaffinity 1232 #define __NR_set_tid_address 1233 -/* 1234 available for reuse */ +#define __NR_fadvise64 1234 /* 1235 available for reuse */ #define __NR_exit_group 1236 #define __NR_lookup_dcookie 1237 @@ -237,6 +237,15 @@ #define __NR_epoll_wait 1245 #define __NR_restart_syscall 1246 #define __NR_semtimedop 1247 +#define __NR_sys_timer_create 1248 +#define __NR_sys_timer_settime 1249 +#define __NR_sys_timer_gettime 1250 +#define __NR_sys_timer_getoverrun 1251 +#define __NR_sys_timer_delete 1252 +#define __NR_sys_clock_settime 1253 +#define __NR_sys_clock_gettime 1254 +#define __NR_sys_clock_getres 1255 +#define __NR_sys_clock_nanosleep 1256 #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER) diff -Nru a/include/asm-ia64/unwind.h b/include/asm-ia64/unwind.h --- a/include/asm-ia64/unwind.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-ia64/unwind.h Fri Mar 7 20:40:17 2003 @@ -60,6 +60,7 @@ unsigned long ip; /* instruction pointer value */ unsigned long pr; /* current predicate values */ unsigned long *cfm_loc; /* cfm save location (or NULL) */ + unsigned long pt; /* struct pt_regs location */ struct task_struct *task; struct switch_stack *sw; diff -Nru a/include/asm-m68k/sun3_pgtable.h b/include/asm-m68k/sun3_pgtable.h --- a/include/asm-m68k/sun3_pgtable.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-m68k/sun3_pgtable.h Fri Mar 7 20:40:17 2003 @@ -196,10 +196,10 @@ } /* Find an entry in the third-level pagetable. */ -#define __pte_offset(address) ((address >> PAGE_SHIFT) & (PTRS_PER_PTE-1)) -#define pte_offset_kernel(pmd, address) ((pte_t *) __pmd_page(*pmd) + __pte_offset(address)) +#define pte_index(address) ((address >> PAGE_SHIFT) & (PTRS_PER_PTE-1)) +#define pte_offset_kernel(pmd, address) ((pte_t *) __pmd_page(*pmd) + pte_index(address)) /* FIXME: should we bother with kmap() here? */ -#define pte_offset_map(pmd, address) ((pte_t *)kmap(pmd_page(*pmd)) + __pte_offset(address)) +#define pte_offset_map(pmd, address) ((pte_t *)kmap(pmd_page(*pmd)) + pte_index(address)) #define pte_offset_map_nested(pmd, address) pte_offset_map(pmd, address) #define pte_unmap(pte) kunmap(pte) #define pte_unmap_nested(pte) kunmap(pte) diff -Nru a/include/asm-parisc/bug.h b/include/asm-parisc/bug.h --- a/include/asm-parisc/bug.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-parisc/bug.h Fri Mar 7 20:40:17 2003 @@ -2,10 +2,7 @@ #define _PARISC_BUG_H /* - * Tell the user there is some problem. Beep too, so we can - * see^H^H^Hhear bugs in early bootup as well! - * - * We don't beep yet. prumpf + * Tell the user there is some problem. */ #define BUG() do { \ printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ diff -Nru a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h --- a/include/asm-parisc/pgtable.h Fri Mar 7 20:40:18 2003 +++ b/include/asm-parisc/pgtable.h Fri Mar 7 20:40:18 2003 @@ -329,9 +329,9 @@ #endif /* Find an entry in the third-level page table.. */ -#define __pte_offset(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1)) +#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1)) #define pte_offset_kernel(pmd, address) \ - ((pte_t *) pmd_page_kernel(*(pmd)) + __pte_offset(address)) + ((pte_t *) pmd_page_kernel(*(pmd)) + pte_index(address)) #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address) #define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address) #define pte_unmap(pte) do { } while (0) diff -Nru a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h --- a/include/asm-ppc/pgtable.h Fri Mar 7 20:40:16 2003 +++ b/include/asm-ppc/pgtable.h Fri Mar 7 20:40:16 2003 @@ -494,14 +494,14 @@ } /* Find an entry in the third-level page table.. */ -#define __pte_offset(address) \ +#define pte_index(address) \ (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) #define pte_offset_kernel(dir, addr) \ - ((pte_t *) pmd_page_kernel(*(dir)) + __pte_offset(addr)) + ((pte_t *) pmd_page_kernel(*(dir)) + pte_index(addr)) #define pte_offset_map(dir, addr) \ - ((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE0) + __pte_offset(addr)) + ((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE0) + pte_index(addr)) #define pte_offset_map_nested(dir, addr) \ - ((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE1) + __pte_offset(addr)) + ((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE1) + pte_index(addr)) #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0) #define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1) diff -Nru a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h --- a/include/asm-s390/pgtable.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-s390/pgtable.h Fri Mar 7 20:40:17 2003 @@ -467,9 +467,9 @@ } /* Find an entry in the third-level page table.. */ -#define __pte_offset(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1)) +#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1)) #define pte_offset_kernel(pmd, address) \ - ((pte_t *) pmd_page_kernel(*(pmd)) + __pte_offset(address)) + ((pte_t *) pmd_page_kernel(*(pmd)) + pte_index(address)) #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address) #define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address) #define pte_unmap(pte) do { } while (0) diff -Nru a/include/asm-s390x/pgtable.h b/include/asm-s390x/pgtable.h --- a/include/asm-s390x/pgtable.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-s390x/pgtable.h Fri Mar 7 20:40:17 2003 @@ -488,14 +488,14 @@ #define pgd_offset_k(address) pgd_offset(&init_mm, address) /* Find an entry in the second-level page table.. */ -#define __pmd_offset(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) +#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) #define pmd_offset(dir,addr) \ - ((pmd_t *) pgd_page_kernel(*(dir)) + __pmd_offset(addr)) + ((pmd_t *) pgd_page_kernel(*(dir)) + pmd_index(addr)) /* Find an entry in the third-level page table.. */ -#define __pte_offset(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1)) +#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE-1)) #define pte_offset_kernel(pmd, address) \ - ((pte_t *) pmd_page_kernel(*(pmd)) + __pte_offset(address)) + ((pte_t *) pmd_page_kernel(*(pmd)) + pte_index(address)) #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address) #define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address) #define pte_unmap(pte) do { } while (0) diff -Nru a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h --- a/include/asm-sh/pgtable.h Fri Mar 7 20:40:18 2003 +++ b/include/asm-sh/pgtable.h Fri Mar 7 20:40:18 2003 @@ -98,8 +98,6 @@ #endif /* !__ASSEMBLY__ */ -#define __beep() asm("") - #define PMD_SIZE (1UL << PMD_SHIFT) #define PMD_MASK (~(PMD_SIZE-1)) #define PGDIR_SIZE (1UL << PGDIR_SHIFT) @@ -274,17 +272,16 @@ /* to find an entry in a page-table-directory. */ #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) -#define __pgd_offset(address) pgd_index(address) #define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address)) /* to find an entry in a kernel page-table-directory */ #define pgd_offset_k(address) pgd_offset(&init_mm, address) /* Find an entry in the third-level page table.. */ -#define __pte_offset(address) \ +#define pte_index(address) \ ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) #define pte_offset(dir, address) ((pte_t *) pmd_page(*(dir)) + \ - __pte_offset(address)) + pte_index(address)) extern void update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t pte); diff -Nru a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h --- a/include/asm-sparc64/pgtable.h Fri Mar 7 20:40:16 2003 +++ b/include/asm-sparc64/pgtable.h Fri Mar 7 20:40:16 2003 @@ -273,11 +273,11 @@ ((address >> PMD_SHIFT) & (REAL_PTRS_PER_PMD-1))) /* Find an entry in the third-level page table.. */ -#define __pte_offset(dir, address) ((pte_t *) __pmd_page(*(dir)) + \ +#define pte_index(dir, address) ((pte_t *) __pmd_page(*(dir)) + \ ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))) -#define pte_offset_kernel __pte_offset -#define pte_offset_map __pte_offset -#define pte_offset_map_nested __pte_offset +#define pte_offset_kernel pte_index +#define pte_offset_map pte_index +#define pte_offset_map_nested pte_index #define pte_unmap(pte) do { } while (0) #define pte_unmap_nested(pte) do { } while (0) diff -Nru a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h --- a/include/asm-um/pgtable.h Fri Mar 7 20:40:18 2003 +++ b/include/asm-um/pgtable.h Fri Mar 7 20:40:18 2003 @@ -357,7 +357,6 @@ /* to find an entry in a page-table-directory. */ #define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) -#define __pgd_offset(address) pgd_index(address) /* to find an entry in a page-table-directory */ #define pgd_offset(mm, address) \ @@ -366,7 +365,7 @@ /* to find an entry in a kernel page-table-directory */ #define pgd_offset_k(address) pgd_offset(&init_mm, address) -#define __pmd_offset(address) \ +#define pmd_index(address) \ (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) /* Find an entry in the second-level page table.. */ @@ -376,13 +375,13 @@ } /* Find an entry in the third-level page table.. */ -#define __pte_offset(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) +#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) #define pte_offset_kernel(dir, address) \ - ((pte_t *) pmd_page_kernel(*(dir)) + __pte_offset(address)) + ((pte_t *) pmd_page_kernel(*(dir)) + pte_index(address)) #define pte_offset_map(dir, address) \ - ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + __pte_offset(address)) + ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + pte_index(address)) #define pte_offset_map_nested(dir, address) \ - ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + __pte_offset(address)) + ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + pte_index(address)) #define pte_unmap(pte) kunmap_atomic((pte), KM_PTE0) #define pte_unmap_nested(pte) kunmap_atomic((pte), KM_PTE1) diff -Nru a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h --- a/include/asm-x86_64/pgtable.h Fri Mar 7 20:40:17 2003 +++ b/include/asm-x86_64/pgtable.h Fri Mar 7 20:40:17 2003 @@ -321,9 +321,9 @@ #define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PTE_MASK)) #define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT)) -#define __pmd_offset(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) +#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) #define pmd_offset(dir, address) ((pmd_t *) pgd_page(*(dir)) + \ - __pmd_offset(address)) + pmd_index(address)) #define pmd_none(x) (!pmd_val(x)) #define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT) #define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0) @@ -353,10 +353,10 @@ return pte; } -#define __pte_offset(address) \ +#define pte_index(address) \ ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) #define pte_offset_kernel(dir, address) ((pte_t *) pmd_page_kernel(*(dir)) + \ - __pte_offset(address)) + pte_index(address)) /* x86-64 always has all page tables mapped. */ #define pte_offset_map(dir,address) pte_offset_kernel(dir,address) diff -Nru a/include/linux/efs_fs.h b/include/linux/efs_fs.h --- a/include/linux/efs_fs.h Fri Mar 7 20:40:16 2003 +++ b/include/linux/efs_fs.h Fri Mar 7 20:40:16 2003 @@ -15,14 +15,6 @@ #include -#ifndef LINUX_VERSION_CODE -#include -#endif - -#if LINUX_VERSION_CODE < 0x20200 -#error This code is only for linux-2.2 and later. -#endif - /* 1 block is 512 bytes */ #define EFS_BLOCKSIZE_BITS 9 #define EFS_BLOCKSIZE (1 << EFS_BLOCKSIZE_BITS) @@ -31,13 +23,6 @@ #include #include #include - -#ifndef MIN -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#endif -#ifndef MAX -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#endif static inline struct efs_inode_info *INODE_INFO(struct inode *inode) { diff -Nru a/include/linux/elf.h b/include/linux/elf.h --- a/include/linux/elf.h Fri Mar 7 20:40:16 2003 +++ b/include/linux/elf.h Fri Mar 7 20:40:16 2003 @@ -83,6 +83,8 @@ #define EM_V850 87 /* NEC v850 */ +#define EM_H8_300H 47 /* Hitachi H8/300H */ +#define EM_H8S 48 /* Hitachi H8S */ /* * This is an interim value that we will use until the committee comes diff -Nru a/include/linux/if_shaper.h b/include/linux/if_shaper.h --- a/include/linux/if_shaper.h Fri Mar 7 20:40:16 2003 +++ b/include/linux/if_shaper.h Fri Mar 7 20:40:16 2003 @@ -21,7 +21,7 @@ __u32 bitspersec; __u32 shapelatency; __u32 shapeclock; - __u32 recovery; /* Time we can next clock a packet out on + unsigned long recovery; /* Time we can next clock a packet out on an empty queue */ unsigned long locked; struct net_device_stats stats; diff -Nru a/include/linux/if_wanpipe.h b/include/linux/if_wanpipe.h --- a/include/linux/if_wanpipe.h Fri Mar 7 20:40:18 2003 +++ b/include/linux/if_wanpipe.h Fri Mar 7 20:40:18 2003 @@ -100,13 +100,9 @@ #define WAN_PACKET_MR_ALLMULTI 2 #ifdef __KERNEL__ + #ifndef netdevice_t -#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - #define netdevice_t struct net_device -#else - #define netdevice_t struct device -#endif +#define netdevice_t struct net_device #endif /* Private wanpipe socket structures. */ diff -Nru a/include/linux/if_wanpipe_common.h b/include/linux/if_wanpipe_common.h --- a/include/linux/if_wanpipe_common.h Fri Mar 7 20:40:17 2003 +++ b/include/linux/if_wanpipe_common.h Fri Mar 7 20:40:17 2003 @@ -19,11 +19,7 @@ #include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - #define netdevice_t struct net_device -#else - #define netdevice_t struct device -#endif +#define netdevice_t struct net_device typedef struct { diff -Nru a/include/linux/init.h b/include/linux/init.h --- a/include/linux/init.h Fri Mar 7 20:40:16 2003 +++ b/include/linux/init.h Fri Mar 7 20:40:16 2003 @@ -62,8 +62,10 @@ */ typedef int (*initcall_t)(void); typedef void (*exitcall_t)(void); -#endif +extern initcall_t __con_initcall_start, __con_initcall_end; +#endif + #ifndef MODULE #ifndef __ASSEMBLY__ @@ -90,6 +92,9 @@ #define __exitcall(fn) \ static exitcall_t __exitcall_##fn __exit_call = fn + +#define console_initcall(fn) \ + static initcall_t __initcall_##fn __attribute__ ((unused,__section__ (".con_initcall.init")))=fn struct obs_kernel_param { const char *str; diff -Nru a/include/linux/ipv6.h b/include/linux/ipv6.h --- a/include/linux/ipv6.h Fri Mar 7 20:40:17 2003 +++ b/include/linux/ipv6.h Fri Mar 7 20:40:17 2003 @@ -74,6 +74,21 @@ #define rt0_type rt_hdr.type; }; +struct ipv6_auth_hdr { + __u8 nexthdr; + __u8 hdrlen; /* This one is measured in 32 bit units! */ + __u16 reserved; + __u32 spi; + __u32 seq_no; /* Sequence number */ + __u8 auth_data[4]; /* Length variable but >=4. Mind the 64 bit alignment! */ +}; + +struct ipv6_esp_hdr { + __u32 spi; + __u32 seq_no; /* Sequence number */ + __u8 enc_data[8]; /* Length variable but >=8. Mind the 64 bit alignment! */ +}; + /* * IPv6 fixed header * diff -Nru a/include/linux/jiffies.h b/include/linux/jiffies.h --- a/include/linux/jiffies.h Fri Mar 7 20:40:16 2003 +++ b/include/linux/jiffies.h Fri Mar 7 20:40:16 2003 @@ -1,6 +1,7 @@ #ifndef _LINUX_JIFFIES_H #define _LINUX_JIFFIES_H +#include #include #include #include @@ -37,10 +38,16 @@ * good compiler would generate better code (and a really good compiler * wouldn't care). Gcc is currently neither. */ -#define time_after(a,b) ((long)(b) - (long)(a) < 0) +#define time_after(a,b) \ + (typecheck(unsigned long, a) && \ + typecheck(unsigned long, b) && \ + ((long)(b) - (long)(a) < 0)) #define time_before(a,b) time_after(b,a) -#define time_after_eq(a,b) ((long)(a) - (long)(b) >= 0) +#define time_after_eq(a,b) \ + (typecheck(unsigned long, a) && \ + typecheck(unsigned long, b) && \ + ((long)(a) - (long)(b) >= 0)) #define time_before_eq(a,b) time_after_eq(b,a) #endif diff -Nru a/include/linux/kernel.h b/include/linux/kernel.h --- a/include/linux/kernel.h Fri Mar 7 20:40:16 2003 +++ b/include/linux/kernel.h Fri Mar 7 20:40:16 2003 @@ -188,6 +188,17 @@ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) +/* + * Check at compile time that something is of a particular type. + * Always evaluates to 1 so you may use it easily in conparisons. + */ +#define typecheck(type,x) \ +({ type __dummy; \ + typeof(x) __dummy2; \ + (void)(&__dummy == &__dummy2); \ + 1; \ +}) + #endif /* __KERNEL__ */ #define SI_LOAD_SHIFT 16 diff -Nru a/include/linux/list.h b/include/linux/list.h --- a/include/linux/list.h Fri Mar 7 20:40:17 2003 +++ b/include/linux/list.h Fri Mar 7 20:40:17 2003 @@ -4,6 +4,7 @@ #ifdef __KERNEL__ #include +#include #include /* diff -Nru a/include/linux/netfilter_bridge/ebt_ip.h b/include/linux/netfilter_bridge/ebt_ip.h --- a/include/linux/netfilter_bridge/ebt_ip.h Fri Mar 7 20:40:17 2003 +++ b/include/linux/netfilter_bridge/ebt_ip.h Fri Mar 7 20:40:17 2003 @@ -25,7 +25,7 @@ EBT_IP_SPORT | EBT_IP_DPORT ) #define EBT_IP_MATCH "ip" -// the same values are used for the invflags +/* the same values are used for the invflags */ struct ebt_ip_info { uint32_t saddr; diff -Nru a/include/linux/netfilter_bridge/ebt_log.h b/include/linux/netfilter_bridge/ebt_log.h --- a/include/linux/netfilter_bridge/ebt_log.h Fri Mar 7 20:40:18 2003 +++ b/include/linux/netfilter_bridge/ebt_log.h Fri Mar 7 20:40:18 2003 @@ -1,7 +1,7 @@ #ifndef __LINUX_BRIDGE_EBT_LOG_H #define __LINUX_BRIDGE_EBT_LOG_H -#define EBT_LOG_IP 0x01 // if the frame is made by ip, log the ip information +#define EBT_LOG_IP 0x01 /* if the frame is made by ip, log the ip information */ #define EBT_LOG_ARP 0x02 #define EBT_LOG_MASK (EBT_LOG_IP | EBT_LOG_ARP) #define EBT_LOG_PREFIX_SIZE 30 diff -Nru a/include/linux/netfilter_bridge/ebt_mark_t.h b/include/linux/netfilter_bridge/ebt_mark_t.h --- a/include/linux/netfilter_bridge/ebt_mark_t.h Fri Mar 7 20:40:16 2003 +++ b/include/linux/netfilter_bridge/ebt_mark_t.h Fri Mar 7 20:40:16 2003 @@ -4,7 +4,7 @@ struct ebt_mark_t_info { unsigned long mark; - // EBT_ACCEPT, EBT_DROP or EBT_CONTINUE or EBT_RETURN + /* EBT_ACCEPT, EBT_DROP, EBT_CONTINUE or EBT_RETURN */ int target; }; #define EBT_MARK_TARGET "mark" diff -Nru a/include/linux/netfilter_bridge/ebt_nat.h b/include/linux/netfilter_bridge/ebt_nat.h --- a/include/linux/netfilter_bridge/ebt_nat.h Fri Mar 7 20:40:17 2003 +++ b/include/linux/netfilter_bridge/ebt_nat.h Fri Mar 7 20:40:17 2003 @@ -4,7 +4,7 @@ struct ebt_nat_info { unsigned char mac[ETH_ALEN]; - // EBT_ACCEPT, EBT_DROP, EBT_CONTINUE or EBT_RETURN + /* EBT_ACCEPT, EBT_DROP, EBT_CONTINUE or EBT_RETURN */ int target; }; #define EBT_SNAT_TARGET "snat" diff -Nru a/include/linux/netfilter_bridge/ebt_redirect.h b/include/linux/netfilter_bridge/ebt_redirect.h --- a/include/linux/netfilter_bridge/ebt_redirect.h Fri Mar 7 20:40:17 2003 +++ b/include/linux/netfilter_bridge/ebt_redirect.h Fri Mar 7 20:40:17 2003 @@ -3,7 +3,7 @@ struct ebt_redirect_info { - // EBT_ACCEPT, EBT_DROP or EBT_CONTINUE or EBT_RETURN + /* EBT_ACCEPT, EBT_DROP, EBT_CONTINUE or EBT_RETURN */ int target; }; #define EBT_REDIRECT_TARGET "redirect" diff -Nru a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h --- a/include/linux/netfilter_bridge/ebtables.h Fri Mar 7 20:40:18 2003 +++ b/include/linux/netfilter_bridge/ebtables.h Fri Mar 7 20:40:18 2003 @@ -2,7 +2,7 @@ * ebtables * * Authors: - * Bart De Schuymer + * Bart De Schuymer * * ebtables.c,v 2.0, April, 2002 * @@ -20,7 +20,7 @@ #define EBT_CHAIN_MAXNAMELEN EBT_TABLE_MAXNAMELEN #define EBT_FUNCTION_MAXNAMELEN EBT_TABLE_MAXNAMELEN -// verdicts >0 are "branches" +/* verdicts >0 are "branches" */ #define EBT_ACCEPT -1 #define EBT_DROP -2 #define EBT_CONTINUE -3 @@ -34,33 +34,34 @@ }; struct ebt_entries { - // this field is always set to zero - // See EBT_ENTRY_OR_ENTRIES. - // Must be same size as ebt_entry.bitmask + /* this field is always set to zero + * See EBT_ENTRY_OR_ENTRIES. + * Must be same size as ebt_entry.bitmask */ unsigned int distinguisher; - // the chain name + /* the chain name */ char name[EBT_CHAIN_MAXNAMELEN]; - // counter offset for this chain + /* counter offset for this chain */ unsigned int counter_offset; - // one standard (accept, drop, return) per hook + /* one standard (accept, drop, return) per hook */ int policy; - // nr. of entries + /* nr. of entries */ unsigned int nentries; - // entry list + /* entry list */ char data[0]; }; -// used for the bitmask of struct ebt_entry +/* used for the bitmask of struct ebt_entry */ -// This is a hack to make a difference between an ebt_entry struct and an -// ebt_entries struct when traversing the entries from start to end. -// Using this simplifies the code alot, while still being able to use -// ebt_entries. -// Contrary, iptables doesn't use something like ebt_entries and therefore uses -// different techniques for naming the policy and such. So, iptables doesn't -// need a hack like this. +/* This is a hack to make a difference between an ebt_entry struct and an + * ebt_entries struct when traversing the entries from start to end. + * Using this simplifies the code alot, while still being able to use + * ebt_entries. + * Contrary, iptables doesn't use something like ebt_entries and therefore uses + * different techniques for naming the policy and such. So, iptables doesn't + * need a hack like this. + */ #define EBT_ENTRY_OR_ENTRIES 0x01 -// these are the normal masks +/* these are the normal masks */ #define EBT_NOPROTO 0x02 #define EBT_802_3 0x04 #define EBT_SOURCEMAC 0x08 @@ -84,7 +85,7 @@ char name[EBT_FUNCTION_MAXNAMELEN]; struct ebt_match *match; } u; - // size of data + /* size of data */ unsigned int match_size; unsigned char data[0]; }; @@ -95,7 +96,7 @@ char name[EBT_FUNCTION_MAXNAMELEN]; struct ebt_watcher *watcher; } u; - // size of data + /* size of data */ unsigned int watcher_size; unsigned char data[0]; }; @@ -106,7 +107,7 @@ char name[EBT_FUNCTION_MAXNAMELEN]; struct ebt_target *target; } u; - // size of data + /* size of data */ unsigned int target_size; unsigned char data[0]; }; @@ -118,29 +119,29 @@ int verdict; }; -// one entry +/* one entry */ struct ebt_entry { - // this needs to be the first field + /* this needs to be the first field */ unsigned int bitmask; unsigned int invflags; uint16_t ethproto; - // the physical in-dev + /* the physical in-dev */ char in[IFNAMSIZ]; - // the logical in-dev + /* the logical in-dev */ char logical_in[IFNAMSIZ]; - // the physical out-dev + /* the physical out-dev */ char out[IFNAMSIZ]; - // the logical out-dev + /* the logical out-dev */ char logical_out[IFNAMSIZ]; unsigned char sourcemac[ETH_ALEN]; unsigned char sourcemsk[ETH_ALEN]; unsigned char destmac[ETH_ALEN]; unsigned char destmsk[ETH_ALEN]; - // sizeof ebt_entry + matches + /* sizeof ebt_entry + matches */ unsigned int watchers_offset; - // sizeof ebt_entry + matches + watchers + /* sizeof ebt_entry + matches + watchers */ unsigned int target_offset; - // sizeof ebt_entry + matches + watchers + target + /* sizeof ebt_entry + matches + watchers + target */ unsigned int next_offset; unsigned char elems[0]; }; @@ -149,20 +150,20 @@ { char name[EBT_TABLE_MAXNAMELEN]; unsigned int valid_hooks; - // nr of rules in the table + /* nr of rules in the table */ unsigned int nentries; - // total size of the entries + /* total size of the entries */ unsigned int entries_size; - // start of the chains + /* start of the chains */ struct ebt_entries *hook_entry[NF_BR_NUMHOOKS]; - // nr of counters userspace expects back + /* nr of counters userspace expects back */ unsigned int num_counters; - // where the kernel will put the old counters + /* where the kernel will put the old counters */ struct ebt_counter *counters; char *entries; }; -// [gs]etsockopt numbers +/* {g,s}etsockopt numbers */ #define EBT_BASE_CTL 128 #define EBT_SO_SET_ENTRIES (EBT_BASE_CTL) @@ -177,7 +178,7 @@ #ifdef __KERNEL__ -// return values for match() functions +/* return values for match() functions */ #define EBT_MATCH 0 #define EBT_NOMATCH 1 @@ -185,11 +186,11 @@ { struct list_head list; const char name[EBT_FUNCTION_MAXNAMELEN]; - // 0 == it matches + /* 0 == it matches */ int (*match)(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *matchdata, unsigned int datalen); - // 0 == let it in + /* 0 == let it in */ int (*check)(const char *tablename, unsigned int hookmask, const struct ebt_entry *e, void *matchdata, unsigned int datalen); void (*destroy)(void *matchdata, unsigned int datalen); @@ -203,7 +204,7 @@ void (*watcher)(const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, const void *watcherdata, unsigned int datalen); - // 0 == let it in + /* 0 == let it in */ int (*check)(const char *tablename, unsigned int hookmask, const struct ebt_entry *e, void *watcherdata, unsigned int datalen); void (*destroy)(void *watcherdata, unsigned int datalen); @@ -214,33 +215,33 @@ { struct list_head list; const char name[EBT_FUNCTION_MAXNAMELEN]; - // returns one of the standard verdicts + /* returns one of the standard verdicts */ int (*target)(struct sk_buff **pskb, unsigned int hooknr, const struct net_device *in, const struct net_device *out, const void *targetdata, unsigned int datalen); - // 0 == let it in + /* 0 == let it in */ int (*check)(const char *tablename, unsigned int hookmask, const struct ebt_entry *e, void *targetdata, unsigned int datalen); void (*destroy)(void *targetdata, unsigned int datalen); struct module *me; }; -// used for jumping from and into user defined chains (udc) +/* used for jumping from and into user defined chains (udc) */ struct ebt_chainstack { - struct ebt_entries *chaininfo; // pointer to chain data - struct ebt_entry *e; // pointer to entry data - unsigned int n; // n'th entry + struct ebt_entries *chaininfo; /* pointer to chain data */ + struct ebt_entry *e; /* pointer to entry data */ + unsigned int n; /* n'th entry */ }; struct ebt_table_info { - // total size of the entries + /* total size of the entries */ unsigned int entries_size; unsigned int nentries; - // pointers to the start of the chains + /* pointers to the start of the chains */ struct ebt_entries *hook_entry[NF_BR_NUMHOOKS]; - // room to maintain the stack used for jumping from and into udc + /* room to maintain the stack used for jumping from and into udc */ struct ebt_chainstack **chainstack; char *entries; struct ebt_counter counters[0] ____cacheline_aligned; @@ -253,11 +254,11 @@ struct ebt_replace *table; unsigned int valid_hooks; rwlock_t lock; - // e.g. could be the table explicitly only allows certain - // matches, targets, ... 0 == let it in + /* e.g. could be the table explicitly only allows certain + * matches, targets, ... 0 == let it in */ int (*check)(const struct ebt_table_info *info, unsigned int valid_hooks); - // the data used by the kernel + /* the data used by the kernel */ struct ebt_table_info *private; }; @@ -273,20 +274,20 @@ const struct net_device *in, const struct net_device *out, struct ebt_table *table); - // Used in the kernel match() functions +/* Used in the kernel match() functions */ #define FWINV(bool,invflg) ((bool) ^ !!(info->invflags & invflg)) -// True if the hook mask denotes that the rule is in a base chain, -// used in the check() functions +/* True if the hook mask denotes that the rule is in a base chain, + * used in the check() functions */ #define BASE_CHAIN (hookmask & (1 << NF_BR_NUMHOOKS)) -// Clear the bit in the hook mask that tells if the rule is on a base chain +/* Clear the bit in the hook mask that tells if the rule is on a base chain */ #define CLEAR_BASE_CHAIN_BIT (hookmask &= ~(1 << NF_BR_NUMHOOKS)) -// True if the target is not a standard target +/* True if the target is not a standard target */ #define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target >= 0) #endif /* __KERNEL__ */ -// blatently stolen from ip_tables.h -// fn returns 0 to continue iteration +/* blatently stolen from ip_tables.h + * fn returns 0 to continue iteration */ #define EBT_MATCH_ITERATE(e, fn, args...) \ ({ \ unsigned int __i; \ diff -Nru a/include/linux/netfilter_ipv4/ipchains_core.h b/include/linux/netfilter_ipv4/ipchains_core.h --- a/include/linux/netfilter_ipv4/ipchains_core.h Fri Mar 7 20:40:17 2003 +++ b/include/linux/netfilter_ipv4/ipchains_core.h Fri Mar 7 20:40:17 2003 @@ -178,12 +178,8 @@ #include #include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) #include extern void ip_fw_init(void) __init; -#else /* 2.0.x */ -extern void ip_fw_init(void); -#endif /* 2.1.x */ extern int ip_fw_ctl(int, void *, int); #ifdef CONFIG_IP_MASQUERADE extern int ip_masq_uctl(int, char *, int); diff -Nru a/include/linux/pci.h b/include/linux/pci.h --- a/include/linux/pci.h Fri Mar 7 20:40:17 2003 +++ b/include/linux/pci.h Fri Mar 7 20:40:17 2003 @@ -413,6 +413,7 @@ /* These fields are used by common fixups */ unsigned int transparent:1; /* Transparent PCI bridge */ + unsigned int multifunction:1;/* Part of multi-function device */ }; #define pci_dev_g(n) list_entry(n, struct pci_dev, global_list) @@ -548,7 +549,8 @@ { return pci_alloc_primary_bus_parented(NULL, bus); } -struct pci_dev *pci_scan_slot(struct pci_dev *temp); +int pci_scan_slot(struct pci_bus *bus, int devfn); +void pci_bus_add_devices(struct pci_bus *bus); int pci_proc_attach_device(struct pci_dev *dev); int pci_proc_detach_device(struct pci_dev *dev); int pci_proc_attach_bus(struct pci_bus *bus); @@ -641,6 +643,16 @@ int pci_request_region(struct pci_dev *, int, char *); void pci_release_region(struct pci_dev *, int); +/* drivers/pci/bus.c */ + +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); +void pci_enable_bridges(struct pci_bus *bus); + /* New-style probing supporting hot-pluggable devices */ int pci_register_driver(struct pci_driver *); void pci_unregister_driver(struct pci_driver *); @@ -844,7 +856,7 @@ #define PCIPCI_NATOMA 4 #define PCIPCI_VIAETBF 8 #define PCIPCI_VSFX 16 - +#define PCIPCI_ALIMAGIK 32 #endif /* __KERNEL__ */ #endif /* LINUX_PCI_H */ diff -Nru a/include/linux/profile.h b/include/linux/profile.h --- a/include/linux/profile.h Fri Mar 7 20:40:17 2003 +++ b/include/linux/profile.h Fri Mar 7 20:40:17 2003 @@ -2,15 +2,15 @@ #define _LINUX_PROFILE_H #ifdef __KERNEL__ - + #include #include #include #include - + /* parse command line */ int __init profile_setup(char * str); - + /* init basic kernel profiler */ void __init profile_init(void); @@ -27,14 +27,14 @@ }; #ifdef CONFIG_PROFILING - + struct notifier_block; struct task_struct; struct mm_struct; - + /* task is in do_exit() */ void profile_exit_task(struct task_struct * task); - + /* change of vma mappings */ void profile_exec_unmap(struct mm_struct * mm); @@ -44,10 +44,10 @@ int profile_event_register(enum profile_type, struct notifier_block * n); int profile_event_unregister(enum profile_type, struct notifier_block * n); - + int register_profile_notifier(struct notifier_block * nb); int unregister_profile_notifier(struct notifier_block * nb); - + /* profiling hook activated on each timer interrupt */ void profile_hook(struct pt_regs * regs); @@ -57,12 +57,12 @@ { return -ENOSYS; } - + static inline int profile_event_unregister(enum profile_type t, struct notifier_block * n) { return -ENOSYS; } - + #define profile_exit_task(a) do { } while (0) #define profile_exec_unmap(a) do { } while (0) #define profile_exit_mmap(a) do { } while (0) @@ -80,7 +80,7 @@ #define profile_hook(regs) do { } while (0) #endif /* CONFIG_PROFILING */ - + #endif /* __KERNEL__ */ - + #endif /* _LINUX_PROFILE_H */ diff -Nru a/include/linux/sched.h b/include/linux/sched.h --- a/include/linux/sched.h Fri Mar 7 20:40:16 2003 +++ b/include/linux/sched.h Fri Mar 7 20:40:16 2003 @@ -328,7 +328,7 @@ prio_array_t *array; unsigned long sleep_avg; - unsigned long sleep_timestamp; + unsigned long last_run; unsigned long policy; unsigned long cpus_allowed; diff -Nru a/include/linux/sdladrv.h b/include/linux/sdladrv.h --- a/include/linux/sdladrv.h Fri Mar 7 20:40:17 2003 +++ b/include/linux/sdladrv.h Fri Mar 7 20:40:17 2003 @@ -19,19 +19,6 @@ #ifndef _SDLADRV_H #define _SDLADRV_H -#include - -#ifndef KERNEL_VERSION - #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) -#define LINUX_2_4 -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) -#define LINUX_2_1 -#else -#define LINUX_2_0 -#endif #define SDLA_MAXIORANGE 4 /* maximum I/O port range */ #define SDLA_WINDOWSIZE 0x2000 /* default dual-port memory window size */ @@ -50,12 +37,7 @@ char S514_cpu_no[1]; /* PCI CPU Number */ unsigned char S514_slot_no; /* PCI Slot Number */ char auto_pci_cfg; /* Autodetect PCI Slot */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct pci_dev *pci_dev; /* PCI device */ -#else - unsigned char pci_bus; /* PCI bus number */ - unsigned char pci_dev_func; /* PCI device/function number */ -#endif void * dpmbase; /* dual-port memory base */ unsigned dpmsize; /* dual-port memory size */ unsigned pclk; /* CPU clock rate, kHz */ diff -Nru a/include/linux/tty.h b/include/linux/tty.h --- a/include/linux/tty.h Fri Mar 7 20:40:17 2003 +++ b/include/linux/tty.h Fri Mar 7 20:40:17 2003 @@ -294,7 +294,7 @@ unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1; unsigned char closing:1; unsigned short minimum_to_wake; - unsigned overrun_time; + unsigned long overrun_time; int num_overrun; unsigned long process_char_map[256/(8*sizeof(unsigned long))]; char *read_buf; @@ -348,7 +348,6 @@ extern int kmsg_redirect; -extern void con_init(void); extern void console_init(void); extern int lp_init(void); diff -Nru a/include/linux/usb.h b/include/linux/usb.h --- a/include/linux/usb.h Fri Mar 7 20:40:17 2003 +++ b/include/linux/usb.h Fri Mar 7 20:40:17 2003 @@ -213,7 +213,7 @@ struct usb_device { int devnum; /* Address on USB bus */ char devpath [16]; /* Use in messages: /port/port/... */ - + enum usb_device_state state; /* configured, not attached, etc */ enum usb_device_speed speed; /* high/full/low (or error) */ struct usb_tt *tt; /* low/full speed dev, highspeed hub */ @@ -240,7 +240,6 @@ int have_langid; /* whether string_langid is valid yet */ int string_langid; /* language ID for strings */ - int present; /* if device is present or not */ void *hcpriv; /* Host Controller private data */ diff -Nru a/include/linux/usb_ch9.h b/include/linux/usb_ch9.h --- a/include/linux/usb_ch9.h Fri Mar 7 20:40:17 2003 +++ b/include/linux/usb_ch9.h Fri Mar 7 20:40:17 2003 @@ -291,4 +291,25 @@ USB_SPEED_HIGH /* usb 2.0 */ }; +enum usb_device_state { + /* NOTATTACHED isn't in the USB spec, and this state acts + * the same as ATTACHED ... but it's clearer this way. + */ + USB_STATE_NOTATTACHED = 0, + + /* the chapter 9 device states */ + USB_STATE_ATTACHED, + USB_STATE_POWERED, + USB_STATE_DEFAULT, /* limited function */ + USB_STATE_ADDRESS, + USB_STATE_CONFIGURED, /* most functions */ + + USB_STATE_SUSPENDED + + /* NOTE: there are actually four different SUSPENDED + * states, returning to POWERED, DEFAULT, ADDRESS, or + * CONFIGURED respectively when SOF tokens flow again. + */ +}; + #endif /* __LINUX_USB_CH9_H */ diff -Nru a/include/linux/wanpipe.h b/include/linux/wanpipe.h --- a/include/linux/wanpipe.h Fri Mar 7 20:40:17 2003 +++ b/include/linux/wanpipe.h Fri Mar 7 20:40:17 2003 @@ -39,59 +39,7 @@ #ifndef _WANPIPE_H #define _WANPIPE_H -#include - -#ifndef KERNEL_VERSION - #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - - #define LINUX_2_4 - #define netdevice_t struct net_device - - #define FREE_READ 1 - #define FREE_WRITE 0 - - #define stop_net_queue(a) netif_stop_queue(a) - #define start_net_queue(a) netif_start_queue(a) - #define is_queue_stopped(a) netif_queue_stopped(a) - #define wake_net_dev(a) netif_wake_queue(a) - #define is_dev_running(a) netif_running(a) - #define wan_dev_kfree_skb(a,b) dev_kfree_skb_any(a) - - -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) - - #define LINUX_2_1 - #define netdevice_t struct device - #define FREE_READ 1 - #define FREE_WRITE 0 - - #define stop_net_queue(a) (set_bit(0, &##a->tbusy)) - #define start_net_queue(a) (clear_bit(0,&##a->tbusy)) - #define is_queue_stopped(a) (##a->tbusy) - #define wake_net_dev(a) {clear_bit(0,&##a->tbusy);mark_bh(NET_BH);} - #define is_dev_running(a) (test_bit(0,&##a->start)) - #define wan_dev_kfree_skb(a,b) dev_kfree_skb(a) - -#else - #define LINUX_2_0 - #define netdevice_t struct device - - #define test_and_set_bit set_bit - #define net_ratelimit() 1 - - #define stop_net_queue(a) (set_bit(0, &##a->tbusy)) - #define start_net_queue(a) (clear_bit(0,&##a->tbusy)) - #define is_queue_stopped(a) (##a->tbusy) - #define wake_net_dev(a) {clear_bit(0,&##a->tbusy);mark_bh(NET_BH);} - #define is_dev_running(a) (test_bit(0,(void*)&##a->start)) - #define wan_dev_kfree_skb(a,b) dev_kfree_skb(a,b) - #define spin_lock_init(a) - #define spin_lock(a) - #define spin_unlock(a) -#endif +#define netdevice_t struct net_device #include @@ -121,21 +69,11 @@ #define MAX_LCN_NUM 4095 /* Maximum lcn number */ #define MAX_FT1_RETRY 100 -#ifdef LINUX_2_4 - #ifndef AF_WANPIPE +#ifndef AF_WANPIPE #define AF_WANPIPE 25 #ifndef PF_WANPIPE #define PF_WANPIPE AF_WANPIPE #endif - #endif - -#else - #ifndef AF_WANPIPE - #define AF_WANPIPE 24 - #ifndef PF_WANPIPE - #define PF_WANPIPE AF_WANPIPE - #endif - #endif #endif @@ -321,12 +259,10 @@ #include /* SDLA support module API definitions */ #include /* SDLA firmware module definitions */ #include -#ifdef LINUX_2_4 - #include - #include - #include - #include -#endif +#include +#include +#include +#include #include #include #include diff -Nru a/include/linux/wanrouter.h b/include/linux/wanrouter.h --- a/include/linux/wanrouter.h Fri Mar 7 20:40:16 2003 +++ b/include/linux/wanrouter.h Fri Mar 7 20:40:16 2003 @@ -43,27 +43,10 @@ * Jan 16, 1997 Gene Kozin router_devlist made public * Jan 02, 1997 Gene Kozin Initial version (based on wanpipe.h). *****************************************************************************/ -#include -#ifndef KERNEL_VERSION - #define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - #define LINUX_2_4 - #define netdevice_t struct net_device - #include /* Support for SMP Locking */ - -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) - #define LINUX_2_1 - #define netdevice_t struct device - #include /* Support for SMP Locking */ - -#else - #define LINUX_2_0 - #define netdevice_t struct device - #define spinlock_t int -#endif +#define netdevice_t struct net_device + +#include /* Support for SMP Locking */ #ifndef _ROUTER_H #define _ROUTER_H @@ -512,11 +495,7 @@ /****** status and statistics *******/ char state; /* device state */ char api_status; /* device api status */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct net_device_stats stats; /* interface statistics */ -#else - struct enet_statistics stats; /* interface statistics */ -#endif unsigned reserved[16]; /* reserved for future use */ unsigned long critical; /* critical section flag */ spinlock_t lock; /* Support for SMP Locking */ @@ -534,11 +513,7 @@ struct wan_device* next; /* -> next device */ netdevice_t* dev; /* list of network interfaces */ unsigned ndev; /* number of interfaces */ -#ifdef LINUX_2_4 struct proc_dir_entry *dent; /* proc filesystem entry */ -#else - struct proc_dir_entry dent; /* proc filesystem entry */ -#endif } wan_device_t; /* Public functions available for device drivers */ diff -Nru a/include/net/ah.h b/include/net/ah.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/net/ah.h Fri Mar 7 20:40:18 2003 @@ -0,0 +1,35 @@ +#ifndef _NET_AH_H +#define _NET_AH_H + +#include + +struct ah_data +{ + u8 *key; + int key_len; + u8 *work_icv; + int icv_full_len; + int icv_trunc_len; + + void (*icv)(struct ah_data*, + struct sk_buff *skb, u8 *icv); + + struct crypto_tfm *tfm; +}; + +extern void skb_ah_walk(const struct sk_buff *skb, + struct crypto_tfm *tfm, icv_update_fn_t icv_update); + +static inline void +ah_hmac_digest(struct ah_data *ahp, struct sk_buff *skb, u8 *auth_data) +{ + struct crypto_tfm *tfm = ahp->tfm; + + memset(auth_data, 0, ahp->icv_trunc_len); + crypto_hmac_init(tfm, ahp->key, &ahp->key_len); + skb_ah_walk(skb, tfm, crypto_hmac_update); + crypto_hmac_final(tfm, ahp->key, &ahp->key_len, ahp->work_icv); + memcpy(auth_data, ahp->work_icv, ahp->icv_trunc_len); +} + +#endif diff -Nru a/include/net/dn_route.h b/include/net/dn_route.h --- a/include/net/dn_route.h Fri Mar 7 20:40:16 2003 +++ b/include/net/dn_route.h Fri Mar 7 20:40:16 2003 @@ -134,7 +134,7 @@ } sk->err = EHOSTUNREACH; - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->state_change(sk); } diff -Nru a/include/net/dst.h b/include/net/dst.h --- a/include/net/dst.h Fri Mar 7 20:40:18 2003 +++ b/include/net/dst.h Fri Mar 7 20:40:18 2003 @@ -247,7 +247,10 @@ struct flowi; extern int xfrm_lookup(struct dst_entry **dst_p, struct flowi *fl, struct sock *sk, int flags); +extern int xfrm6_lookup(struct dst_entry **dst_p, struct flowi *fl, + struct sock *sk, int flags); extern void xfrm_init(void); +extern void xfrm6_init(void); #endif diff -Nru a/include/net/esp.h b/include/net/esp.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/net/esp.h Fri Mar 7 20:40:18 2003 @@ -0,0 +1,56 @@ +#ifndef _NET_ESP_H +#define _NET_ESP_H + +#include + +struct esp_data +{ + /* Confidentiality */ + struct { + u8 *key; /* Key */ + int key_len; /* Key length */ + u8 *ivec; /* ivec buffer */ + /* ivlen is offset from enc_data, where encrypted data start. + * It is logically different of crypto_tfm_alg_ivsize(tfm). + * We assume that it is either zero (no ivec), or + * >= crypto_tfm_alg_ivsize(tfm). */ + int ivlen; + int padlen; /* 0..255 */ + struct crypto_tfm *tfm; /* crypto handle */ + } conf; + + /* Integrity. It is active when icv_full_len != 0 */ + struct { + u8 *key; /* Key */ + int key_len; /* Length of the key */ + u8 *work_icv; + int icv_full_len; + int icv_trunc_len; + void (*icv)(struct esp_data*, + struct sk_buff *skb, + int offset, int len, u8 *icv); + struct crypto_tfm *tfm; + } auth; +}; + +extern void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm, + int offset, int len, icv_update_fn_t icv_update); +extern int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len); +extern int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer); +extern void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len); + +static inline void +esp_hmac_digest(struct esp_data *esp, struct sk_buff *skb, int offset, + int len, u8 *auth_data) +{ + struct crypto_tfm *tfm = esp->auth.tfm; + char *icv = esp->auth.work_icv; + + memset(auth_data, 0, esp->auth.icv_trunc_len); + crypto_hmac_init(tfm, esp->auth.key, &esp->auth.key_len); + skb_icv_walk(skb, tfm, offset, len, crypto_hmac_update); + crypto_hmac_final(tfm, esp->auth.key, &esp->auth.key_len, icv); + memcpy(auth_data, icv, esp->auth.icv_trunc_len); +} + +#endif diff -Nru a/include/net/ip6_route.h b/include/net/ip6_route.h --- a/include/net/ip6_route.h Fri Mar 7 20:40:16 2003 +++ b/include/net/ip6_route.h Fri Mar 7 20:40:16 2003 @@ -57,6 +57,8 @@ struct in6_addr *saddr, int oif, int flags); +extern struct rt6_info *ndisc_get_dummy_rt(void); + /* * support functions for ND * diff -Nru a/include/net/sock.h b/include/net/sock.h --- a/include/net/sock.h Fri Mar 7 20:40:17 2003 +++ b/include/net/sock.h Fri Mar 7 20:40:17 2003 @@ -29,6 +29,8 @@ * protocol specific parts were moved to * respective headers and ipv4/v6, etc now * use private slabcaches for its socks + * Pedro Hortas : New flags field for socket options + * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -60,6 +62,18 @@ * the other protocols. */ +/* Sock flags */ +enum { + SOCK_DEAD, + SOCK_DONE, + SOCK_URGINLINE, + SOCK_KEEPOPEN, + SOCK_LINGER, + SOCK_DESTROY, + SOCK_BROADCAST, + SOCK_BSDISM, +}; + /* Define this to get the sk->debug debugging facility. */ #define SOCK_DEBUGGING #ifdef SOCK_DEBUGGING @@ -120,18 +134,8 @@ int sndbuf; /* Size of send buffer in bytes */ struct sock *prev; - /* Not all are volatile, but some are, so we might as well say they all are. - * XXX Make this a flag word -DaveM - */ - volatile char dead, - done, - urginline, - keepopen, - linger, - destroy, - no_check, - broadcast, - bsdism; + unsigned long flags; + char no_check; unsigned char debug; unsigned char rcvtstamp; unsigned char no_largesend; @@ -605,7 +609,7 @@ static inline void sock_orphan(struct sock *sk) { write_lock_bh(&sk->callback_lock); - sk->dead = 1; + __set_bit(SOCK_DEAD, &sk->flags); sk->socket = NULL; sk->sleep = NULL; write_unlock_bh(&sk->callback_lock); @@ -769,7 +773,7 @@ skb->dev = NULL; skb_set_owner_r(skb, sk); skb_queue_tail(&sk->receive_queue, skb); - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->data_ready(sk,skb->len); out: return err; @@ -784,7 +788,7 @@ return -ENOMEM; skb_set_owner_r(skb, sk); skb_queue_tail(&sk->error_queue,skb); - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->data_ready(sk,skb->len); return 0; } @@ -895,6 +899,14 @@ remove_wait_queue((sk)->sleep, &wait); \ lock_sock(sk); \ } + +static inline void sock_valbool_flag(struct sock *sk, int bit, int valbool) +{ + if (valbool) + __set_bit(bit, &sk->flags); + else + __clear_bit(bit, &sk->flags); +} extern __u32 sysctl_wmem_max; extern __u32 sysctl_rmem_max; diff -Nru a/include/net/tcp.h b/include/net/tcp.h --- a/include/net/tcp.h Fri Mar 7 20:40:16 2003 +++ b/include/net/tcp.h Fri Mar 7 20:40:16 2003 @@ -1422,7 +1422,7 @@ sk->shutdown = SHUTDOWN_MASK; - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->state_change(sk); else tcp_destroy_sock(sk); diff -Nru a/include/net/xfrm.h b/include/net/xfrm.h --- a/include/net/xfrm.h Fri Mar 7 20:40:18 2003 +++ b/include/net/xfrm.h Fri Mar 7 20:40:18 2003 @@ -12,6 +12,7 @@ #include #include +#include #define XFRM_ALIGN8(len) (((len) + 7) & ~7) @@ -223,7 +224,7 @@ char *id; int (*notify)(struct xfrm_state *x, int event); int (*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir); - struct xfrm_policy *(*compile_policy)(int opt, u8 *data, int len, int *dir); + struct xfrm_policy *(*compile_policy)(u16 family, int opt, u8 *data, int len, int *dir); }; extern int xfrm_register_km(struct xfrm_mgr *km); @@ -282,6 +283,7 @@ struct xfrm_dst *next; struct dst_entry dst; struct rtable rt; + struct rt6_info rt6; } u; }; @@ -308,26 +310,42 @@ if (sp && atomic_dec_and_test(&sp->refcnt)) __secpath_destroy(sp); } - -extern int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb); +extern int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb, unsigned short family); static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb) { if (sk && sk->policy[XFRM_POLICY_IN]) - return __xfrm_policy_check(sk, dir, skb); + return __xfrm_policy_check(sk, dir, skb, AF_INET); + + return !xfrm_policy_list[dir] || + (skb->dst->flags & DST_NOPOLICY) || + __xfrm_policy_check(sk, dir, skb, AF_INET); +} + +static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *skb) +{ + if (sk && sk->policy[XFRM_POLICY_IN]) + return __xfrm_policy_check(sk, dir, skb, AF_INET6); return !xfrm_policy_list[dir] || (skb->dst->flags & DST_NOPOLICY) || - __xfrm_policy_check(sk, dir, skb); + __xfrm_policy_check(sk, dir, skb, AF_INET6); } -extern int __xfrm_route_forward(struct sk_buff *skb); +extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family); static inline int xfrm_route_forward(struct sk_buff *skb) { return !xfrm_policy_list[XFRM_POLICY_OUT] || (skb->dst->flags & DST_NOXFRM) || - __xfrm_route_forward(skb); + __xfrm_route_forward(skb, AF_INET); +} + +static inline int xfrm6_route_forward(struct sk_buff *skb) +{ + return !xfrm_policy_list[XFRM_POLICY_OUT] || + (skb->dst->flags & DST_NOXFRM) || + __xfrm_route_forward(skb, AF_INET6); } extern int __xfrm_sk_clone_policy(struct sock *sk); @@ -380,12 +398,16 @@ extern void xfrm_input_init(void); extern int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), void *); extern struct xfrm_state *xfrm_state_alloc(void); -extern struct xfrm_state *xfrm_state_find(u32 daddr, u32 saddr, struct flowi *fl, struct xfrm_tmpl *tmpl, - struct xfrm_policy *pol, int *err); +extern struct xfrm_state *xfrm4_state_find(u32 daddr, u32 saddr, struct flowi *fl, struct xfrm_tmpl *tmpl, + struct xfrm_policy *pol, int *err); +extern struct xfrm_state *xfrm6_state_find(struct in6_addr *daddr, struct in6_addr *saddr, + struct flowi *fl, struct xfrm_tmpl *tmpl, + struct xfrm_policy *pol, int *err); extern int xfrm_state_check_expire(struct xfrm_state *x); extern void xfrm_state_insert(struct xfrm_state *x); extern int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb); -extern struct xfrm_state *xfrm_state_lookup(u32 daddr, u32 spi, u8 proto); +extern struct xfrm_state *xfrm4_state_lookup(u32 daddr, u32 spi, u8 proto); +extern struct xfrm_state *xfrm6_state_lookup(struct in6_addr *daddr, u32 spi, u8 proto); extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq); extern void xfrm_state_delete(struct xfrm_state *x); extern void xfrm_state_flush(u8 proto); @@ -393,17 +415,21 @@ extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq); extern int xfrm_check_selectors(struct xfrm_state **x, int n, struct flowi *fl); extern int xfrm4_rcv(struct sk_buff *skb); +extern int xfrm6_rcv(struct sk_buff *skb); +extern int xfrm6_clear_mutable_options(struct sk_buff *skb, u16 *nh_offset, int dir); extern int xfrm_user_policy(struct sock *sk, int optname, u8 *optval, int optlen); struct xfrm_policy *xfrm_policy_alloc(int gfp); extern int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), void *); -struct xfrm_policy *xfrm_policy_lookup(int dir, struct flowi *fl); +struct xfrm_policy *xfrm_policy_lookup(int dir, struct flowi *fl, unsigned short family); int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl); struct xfrm_policy *xfrm_policy_delete(int dir, struct xfrm_selector *sel); struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete); void xfrm_policy_flush(void); void xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi); struct xfrm_state * xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr, int create); +struct xfrm_state * xfrm6_find_acq(u8 mode, u16 reqid, u8 proto, struct in6_addr *daddr, + struct in6_addr *saddr, int create); extern void xfrm_policy_flush(void); extern void xfrm_policy_kill(struct xfrm_policy *); extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol); @@ -425,23 +451,52 @@ extern struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name); extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name); +static __inline__ int addr_match(void *token1, void *token2, int prefixlen) +{ + __u32 *a1 = token1; + __u32 *a2 = token2; + int pdw; + int pbi; + + pdw = prefixlen >> 5; /* num of whole __u32 in prefix */ + pbi = prefixlen & 0x1f; /* num of bits in incomplete u32 in prefix */ + + if (pdw) + if (memcmp(a1, a2, pdw << 2)) + return 0; + + if (pbi) { + __u32 mask; + + mask = htonl((0xffffffff) << (32 - pbi)); + + if ((a1[pdw] ^ a2[pdw]) & mask) + return 0; + } + + return 1; +} + static inline int xfrm6_selector_match(struct xfrm_selector *sel, struct flowi *fl) { - return !memcmp(fl->fl6_dst, sel->daddr.a6, sizeof(struct in6_addr)) && - !((fl->uli_u.ports.dport^sel->dport)&sel->dport_mask) && - !((fl->uli_u.ports.sport^sel->sport)&sel->sport_mask) && - (fl->proto == sel->proto || !sel->proto) && - (fl->oif == sel->ifindex || !sel->ifindex) && - !memcmp(fl->fl6_src, sel->saddr.a6, sizeof(struct in6_addr)); + return addr_match(fl->fl6_dst, &sel->daddr, sel->prefixlen_d) && + addr_match(fl->fl6_src, &sel->saddr, sel->prefixlen_s) && + !((fl->uli_u.ports.dport^sel->dport)&sel->dport_mask) && + !((fl->uli_u.ports.sport^sel->sport)&sel->sport_mask) && + (fl->proto == sel->proto || !sel->proto) && + (fl->oif == sel->ifindex || !sel->ifindex); } extern int xfrm6_register_type(struct xfrm_type *type); extern int xfrm6_unregister_type(struct xfrm_type *type); extern struct xfrm_type *xfrm6_get_type(u8 proto); -extern struct xfrm_state *xfrm6_state_lookup(struct in6_addr *daddr, u32 spi, u8 proto); -struct xfrm_state * xfrm6_find_acq(u8 mode, u16 reqid, u8 proto, struct in6_addr *daddr, struct in6_addr *saddr, int create); -void xfrm6_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi); +struct crypto_tfm; +typedef void (icv_update_fn_t)(struct crypto_tfm *, struct scatterlist *, unsigned int); + +typedef int (xfrm_dst_lookup_t)(struct xfrm_dst **dst, struct flowi *fl); +int xfrm_dst_lookup_register(xfrm_dst_lookup_t *dst_lookup, unsigned short family); +void xfrm_dst_lookup_unregister(unsigned short family); #endif /* _NET_XFRM_H */ diff -Nru a/init/do_mounts.c b/init/do_mounts.c --- a/init/do_mounts.c Fri Mar 7 20:40:16 2003 +++ b/init/do_mounts.c Fri Mar 7 20:40:16 2003 @@ -17,7 +17,7 @@ int __initdata rd_doload; /* 1 = load RAM disk, 0 = don't load */ int root_mountflags = MS_RDONLY | MS_VERBOSE; -static char * __initdata root_device_name; +char * __initdata root_device_name; static char __initdata saved_root_name[64]; /* this is initialized in init/main.c */ diff -Nru a/init/do_mounts.h b/init/do_mounts.h --- a/init/do_mounts.h Fri Mar 7 20:40:17 2003 +++ b/init/do_mounts.h Fri Mar 7 20:40:17 2003 @@ -27,6 +27,7 @@ void mount_block_root(char *name, int flags); void mount_root(void); extern int root_mountflags; +extern char *root_device_name; #ifdef CONFIG_DEVFS_FS diff -Nru a/init/do_mounts_rd.c b/init/do_mounts_rd.c --- a/init/do_mounts_rd.c Fri Mar 7 20:40:17 2003 +++ b/init/do_mounts_rd.c Fri Mar 7 20:40:17 2003 @@ -242,6 +242,7 @@ { if (rd_prompt) change_floppy("root floppy disk to be loaded into RAM disk"); + create_dev("/dev/root", ROOT_DEV, root_device_name); create_dev("/dev/ram", MKDEV(RAMDISK_MAJOR, n), NULL); return rd_load_image("/dev/root"); } diff -Nru a/kernel/cpufreq.c b/kernel/cpufreq.c --- a/kernel/cpufreq.c Fri Mar 7 20:40:16 2003 +++ b/kernel/cpufreq.c Fri Mar 7 20:40:16 2003 @@ -354,6 +354,13 @@ &cpufreq_driver->policy[cpu], sizeof(struct cpufreq_policy)); + /* 2.4-API init for this CPU */ +#ifdef CONFIG_CPU_FREQ_24_API + cpu_min_freq[cpu] = cpufreq_driver->policy[cpu].cpuinfo.min_freq; + cpu_max_freq[cpu] = cpufreq_driver->policy[cpu].cpuinfo.max_freq; + cpu_cur_freq[cpu] = cpufreq_driver->cpu_cur_freq[cpu]; +#endif + if (cpufreq_driver->target) cpufreq_governor(cpu, CPUFREQ_GOV_START); diff -Nru a/kernel/fork.c b/kernel/fork.c --- a/kernel/fork.c Fri Mar 7 20:40:16 2003 +++ b/kernel/fork.c Fri Mar 7 20:40:16 2003 @@ -916,7 +916,7 @@ */ p->first_time_slice = 1; current->time_slice >>= 1; - p->sleep_timestamp = jiffies; + p->last_run = jiffies; if (!current->time_slice) { /* * This case is rare, it happens when the parent has only diff -Nru a/kernel/sched.c b/kernel/sched.c --- a/kernel/sched.c Fri Mar 7 20:40:18 2003 +++ b/kernel/sched.c Fri Mar 7 20:40:18 2003 @@ -54,20 +54,20 @@ /* * These are the 'tuning knobs' of the scheduler: * - * Minimum timeslice is 10 msecs, default timeslice is 150 msecs, - * maximum timeslice is 300 msecs. Timeslices get refilled after + * Minimum timeslice is 10 msecs, default timeslice is 100 msecs, + * maximum timeslice is 200 msecs. Timeslices get refilled after * they expire. */ #define MIN_TIMESLICE ( 10 * HZ / 1000) -#define MAX_TIMESLICE (300 * HZ / 1000) -#define CHILD_PENALTY 95 +#define MAX_TIMESLICE (200 * HZ / 1000) +#define CHILD_PENALTY 50 #define PARENT_PENALTY 100 #define EXIT_WEIGHT 3 #define PRIO_BONUS_RATIO 25 #define INTERACTIVE_DELTA 2 -#define MAX_SLEEP_AVG (2*HZ) -#define STARVATION_LIMIT (2*HZ) -#define NODE_THRESHOLD 125 +#define MAX_SLEEP_AVG (10*HZ) +#define STARVATION_LIMIT (10*HZ) +#define NODE_THRESHOLD 125 /* * If a task is 'interactive' then we reinsert it in the active @@ -302,10 +302,13 @@ * * Both properties are important to certain workloads. */ -static inline int effective_prio(task_t *p) +static int effective_prio(task_t *p) { int bonus, prio; + if (rt_task(p)) + return p->prio; + bonus = MAX_USER_PRIO*PRIO_BONUS_RATIO*p->sleep_avg/MAX_SLEEP_AVG/100 - MAX_USER_PRIO*PRIO_BONUS_RATIO/100/2; @@ -318,31 +321,65 @@ } /* - * activate_task - move a task to the runqueue. + * __activate_task - move a task to the runqueue. + */ +static inline void __activate_task(task_t *p, runqueue_t *rq) +{ + enqueue_task(p, rq->active); + nr_running_inc(rq); +} - * Also update all the scheduling statistics stuff. (sleep average +/* + * activate_task - move a task to the runqueue and do priority recalculation + * + * Update all the scheduling statistics stuff. (sleep average * calculation, priority modifiers, etc.) */ -static inline void activate_task(task_t *p, runqueue_t *rq) +static inline int activate_task(task_t *p, runqueue_t *rq) { - unsigned long sleep_time = jiffies - p->sleep_timestamp; - prio_array_t *array = rq->active; + unsigned long sleep_time = jiffies - p->last_run; + int requeue_waker = 0; + + if (sleep_time) { + int sleep_avg; - if (!rt_task(p) && sleep_time) { /* - * This code gives a bonus to interactive tasks. We update - * an 'average sleep time' value here, based on - * sleep_timestamp. The more time a task spends sleeping, - * the higher the average gets - and the higher the priority - * boost gets as well. + * This code gives a bonus to interactive tasks. + * + * The boost works by updating the 'average sleep time' + * value here, based on ->last_run. The more time a task + * spends sleeping, the higher the average gets - and the + * higher the priority boost gets as well. */ - p->sleep_avg += sleep_time; - if (p->sleep_avg > MAX_SLEEP_AVG) - p->sleep_avg = MAX_SLEEP_AVG; - p->prio = effective_prio(p); + sleep_avg = p->sleep_avg + sleep_time; + + /* + * 'Overflow' bonus ticks go to the waker as well, so the + * ticks are not lost. This has the effect of further + * boosting tasks that are related to maximum-interactive + * tasks. + */ + if (sleep_avg > MAX_SLEEP_AVG) { + if (!in_interrupt()) { + sleep_avg += current->sleep_avg - MAX_SLEEP_AVG; + if (sleep_avg > MAX_SLEEP_AVG) + sleep_avg = MAX_SLEEP_AVG; + + if (current->sleep_avg != sleep_avg) { + current->sleep_avg = sleep_avg; + requeue_waker = 1; + } + } + sleep_avg = MAX_SLEEP_AVG; + } + if (p->sleep_avg != sleep_avg) { + p->sleep_avg = sleep_avg; + p->prio = effective_prio(p); + } } - enqueue_task(p, array); - nr_running_inc(rq); + __activate_task(p, rq); + + return requeue_waker; } /* @@ -455,8 +492,8 @@ */ static int try_to_wake_up(task_t * p, unsigned int state, int sync) { + int success = 0, requeue_waker = 0; unsigned long flags; - int success = 0; long old_state; runqueue_t *rq; @@ -479,16 +516,34 @@ } if (old_state == TASK_UNINTERRUPTIBLE) rq->nr_uninterruptible--; - activate_task(p, rq); - - if (p->prio < rq->curr->prio) - resched_task(rq->curr); + if (sync) + __activate_task(p, rq); + else { + requeue_waker = activate_task(p, rq); + if (p->prio < rq->curr->prio) + resched_task(rq->curr); + } success = 1; } p->state = TASK_RUNNING; } task_rq_unlock(rq, &flags); + /* + * We have to do this outside the other spinlock, the two + * runqueues might be different: + */ + if (requeue_waker) { + prio_array_t *array; + + rq = task_rq_lock(current, &flags); + array = current->array; + dequeue_task(current, array); + current->prio = effective_prio(current); + enqueue_task(current, array); + task_rq_unlock(rq, &flags); + } + return success; } @@ -514,19 +569,25 @@ runqueue_t *rq = task_rq_lock(current, &flags); p->state = TASK_RUNNING; - if (!rt_task(p)) { - /* - * We decrease the sleep average of forking parents - * and children as well, to keep max-interactive tasks - * from forking tasks that are max-interactive. - */ - current->sleep_avg = current->sleep_avg * PARENT_PENALTY / 100; - p->sleep_avg = p->sleep_avg * CHILD_PENALTY / 100; - p->prio = effective_prio(p); - } + /* + * We decrease the sleep average of forking parents + * and children as well, to keep max-interactive tasks + * from forking tasks that are max-interactive. + */ + current->sleep_avg = current->sleep_avg * PARENT_PENALTY / 100; + p->sleep_avg = p->sleep_avg * CHILD_PENALTY / 100; + p->prio = effective_prio(p); set_task_cpu(p, smp_processor_id()); - activate_task(p, rq); + if (unlikely(!current->array)) + __activate_task(p, rq); + else { + p->prio = current->prio; + list_add_tail(&p->run_list, ¤t->run_list); + p->array = current->array; + p->array->nr_active++; + nr_running_inc(rq); + } task_rq_unlock(rq, &flags); } @@ -953,6 +1014,11 @@ */ if (p->prio < this_rq->curr->prio) set_need_resched(); + else { + if (p->prio == this_rq->curr->prio && + p->time_slice > this_rq->curr->time_slice) + set_need_resched(); + } } /* @@ -1016,7 +1082,7 @@ */ #define CAN_MIGRATE_TASK(p,rq,this_cpu) \ - ((jiffies - (p)->sleep_timestamp > cache_decay_ticks) && \ + ((jiffies - (p)->last_run > cache_decay_ticks) && \ !task_running(rq, p) && \ ((p)->cpus_allowed & (1UL << (this_cpu)))) @@ -1076,9 +1142,9 @@ * increasing number of running tasks: */ #define EXPIRED_STARVING(rq) \ - ((rq)->expired_timestamp && \ + (STARVATION_LIMIT && ((rq)->expired_timestamp && \ (jiffies - (rq)->expired_timestamp >= \ - STARVATION_LIMIT * ((rq)->nr_running) + 1)) + STARVATION_LIMIT * ((rq)->nr_running) + 1))) /* * This function gets called by the timer code, with HZ frequency. @@ -1121,6 +1187,16 @@ return; } spin_lock(&rq->lock); + /* + * The task was running during this tick - update the + * time slice counter and the sleep average. Note: we + * do not update a thread's priority until it either + * goes to sleep or uses up its timeslice. This makes + * it possible for interactive tasks to use up their + * timeslices at their highest priority levels. + */ + if (p->sleep_avg) + p->sleep_avg--; if (unlikely(rt_task(p))) { /* * RR tasks need a special form of timeslice management. @@ -1137,16 +1213,6 @@ } goto out; } - /* - * The task was running during this tick - update the - * time slice counter and the sleep average. Note: we - * do not update a thread's priority until it either - * goes to sleep or uses up its timeslice. This makes - * it possible for interactive tasks to use up their - * timeslices at their highest priority levels. - */ - if (p->sleep_avg) - p->sleep_avg--; if (!--p->time_slice) { dequeue_task(p, rq->active); set_tsk_need_resched(p); @@ -1201,7 +1267,7 @@ rq = this_rq(); release_kernel_lock(prev); - prev->sleep_timestamp = jiffies; + prev->last_run = jiffies; spin_lock_irq(&rq->lock); /* @@ -1701,7 +1767,7 @@ else p->prio = p->static_prio; if (array) - activate_task(p, task_rq(p)); + __activate_task(p, task_rq(p)); out_unlock: task_rq_unlock(rq, &flags); @@ -2315,7 +2381,7 @@ set_task_cpu(p, cpu_dest); if (p->array) { deactivate_task(p, rq_src); - activate_task(p, rq_dest); + __activate_task(p, rq_dest); if (p->prio < rq_dest->curr->prio) resched_task(rq_dest->curr); } @@ -2442,6 +2508,7 @@ rq->idle = current; set_task_cpu(current, smp_processor_id()); wake_up_forked_process(current); + current->prio = MAX_PRIO; init_timers(); diff -Nru a/kernel/softirq.c b/kernel/softirq.c --- a/kernel/softirq.c Fri Mar 7 20:40:16 2003 +++ b/kernel/softirq.c Fri Mar 7 20:40:16 2003 @@ -92,10 +92,9 @@ mask &= ~pending; goto restart; } - __local_bh_enable(); - if (pending) wakeup_softirqd(cpu); + __local_bh_enable(); } local_irq_restore(flags); diff -Nru a/mm/fremap.c b/mm/fremap.c --- a/mm/fremap.c Fri Mar 7 20:40:16 2003 +++ b/mm/fremap.c Fri Mar 7 20:40:16 2003 @@ -1,5 +1,5 @@ /* - * linux/mm/mpopulate.c + * linux/mm/fremap.c * * Explicit pagetable population and nonlinear (random) mappings support. * diff -Nru a/mm/mremap.c b/mm/mremap.c --- a/mm/mremap.c Fri Mar 7 20:40:17 2003 +++ b/mm/mremap.c Fri Mar 7 20:40:17 2003 @@ -1,5 +1,5 @@ /* - * mm/remap.c + * mm/mremap.c * * (C) Copyright 1996 Linus Torvalds * diff -Nru a/net/appletalk/ddp.c b/net/appletalk/ddp.c --- a/net/appletalk/ddp.c Fri Mar 7 20:40:18 2003 +++ b/net/appletalk/ddp.c Fri Mar 7 20:40:18 2003 @@ -190,7 +190,7 @@ struct sock *sk = (struct sock *)data; if (!atomic_read(&sk->wmem_alloc) && - !atomic_read(&sk->rmem_alloc) && sk->dead) { + !atomic_read(&sk->rmem_alloc) && test_bit(SOCK_DEAD, &sk->flags)) { sock_put(sk); MOD_DEC_USE_COUNT; } else { @@ -205,7 +205,7 @@ skb_queue_purge(&sk->receive_queue); if (!atomic_read(&sk->wmem_alloc) && - !atomic_read(&sk->rmem_alloc) && sk->dead) { + !atomic_read(&sk->rmem_alloc) && test_bit(SOCK_DEAD, &sk->flags)) { sock_put(sk); MOD_DEC_USE_COUNT; } else { @@ -1016,9 +1016,9 @@ struct sock *sk = sock->sk; if (sk) { - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->state_change(sk); - sk->dead = 1; + __set_bit(SOCK_DEAD, &sk->flags); sock->sk = NULL; atalk_destroy_socket(sk); } @@ -1158,7 +1158,8 @@ if (addr->sat_family != AF_APPLETALK) return -EAFNOSUPPORT; - if (addr->sat_addr.s_node == ATADDR_BCAST && !sk->broadcast) { + if (addr->sat_addr.s_node == ATADDR_BCAST && + !test_bit(SOCK_BROADCAST, &sk->flags)) { #if 1 printk(KERN_WARNING "%s is broken and did not set " "SO_BROADCAST. It will break when 2.2 is " @@ -1523,7 +1524,8 @@ return -EINVAL; /* netatalk doesn't implement this check */ - if (usat->sat_addr.s_node == ATADDR_BCAST && !sk->broadcast) { + if (usat->sat_addr.s_node == ATADDR_BCAST && + !test_bit(SOCK_BROADCAST, &sk->flags)) { printk(KERN_INFO "SO_BROADCAST: Fix your netatalk as " "it will break before 2.2\n"); #if 0 diff -Nru a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c --- a/net/ax25/af_ax25.c Fri Mar 7 20:40:18 2003 +++ b/net/ax25/af_ax25.c Fri Mar 7 20:40:18 2003 @@ -330,7 +330,7 @@ ax25_cb *sax25 = ax25_sk(skb->sk); /* Queue the unaccepted socket for death */ - skb->sk->dead = 1; + __set_bit(SOCK_DEAD, &skb->sk->flags); ax25_start_heartbeat(sax25); sax25->state = AX25_STATE_0; @@ -984,8 +984,8 @@ sk->state = TCP_CLOSE; sk->shutdown |= SEND_SHUTDOWN; sk->state_change(sk); - sk->dead = 1; - sk->destroy = 1; + __set_bit(SOCK_DEAD, &sk->flags); + __set_bit(SOCK_DESTROY, &sk->flags); break; default: @@ -995,7 +995,7 @@ sk->state = TCP_CLOSE; sk->shutdown |= SEND_SHUTDOWN; sk->state_change(sk); - sk->dead = 1; + __set_bit(SOCK_DEAD, &sk->flags); ax25_destroy_socket(ax25); } diff -Nru a/net/ax25/ax25_ds_in.c b/net/ax25/ax25_ds_in.c --- a/net/ax25/ax25_ds_in.c Fri Mar 7 20:40:17 2003 +++ b/net/ax25/ax25_ds_in.c Fri Mar 7 20:40:17 2003 @@ -67,7 +67,7 @@ if (ax25->sk != NULL) { ax25->sk->state = TCP_ESTABLISHED; /* For WAIT_SABM connections we will produce an accept ready socket here */ - if (!ax25->sk->dead) + if (!test_bit(SOCK_DEAD, &ax25->sk->flags)) ax25->sk->state_change(ax25->sk); } ax25_dama_on(ax25); diff -Nru a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c --- a/net/ax25/ax25_ds_timer.c Fri Mar 7 20:40:18 2003 +++ b/net/ax25/ax25_ds_timer.c Fri Mar 7 20:40:18 2003 @@ -103,7 +103,7 @@ case AX25_STATE_0: /* Magic here: If we listen() and a new link dies before it is accepted() it isn't 'dead' so doesn't get removed. */ - if (ax25->sk == NULL || ax25->sk->destroy || (ax25->sk->state == TCP_LISTEN && ax25->sk->dead)) { + if (ax25->sk == NULL || test_bit(SOCK_DESTROY, &ax25->sk->flags) || (ax25->sk->state == TCP_LISTEN && test_bit(SOCK_DEAD, &ax25->sk->flags))) { ax25_destroy_socket(ax25); return; } @@ -157,9 +157,9 @@ ax25->sk->state = TCP_CLOSE; ax25->sk->err = 0; ax25->sk->shutdown |= SEND_SHUTDOWN; - if (!ax25->sk->dead) + if (!test_bit(SOCK_DEAD, &ax25->sk->flags)) ax25->sk->state_change(ax25->sk); - ax25->sk->dead = 1; + __set_bit(SOCK_DEAD, &ax25->sk->flags); } } diff -Nru a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c --- a/net/ax25/ax25_in.c Fri Mar 7 20:40:16 2003 +++ b/net/ax25/ax25_in.c Fri Mar 7 20:40:16 2003 @@ -434,7 +434,7 @@ ax25_start_idletimer(ax25); if (sk != NULL) { - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->data_ready(sk, skb->len); } else { kfree_skb(skb); diff -Nru a/net/ax25/ax25_std_in.c b/net/ax25/ax25_std_in.c --- a/net/ax25/ax25_std_in.c Fri Mar 7 20:40:17 2003 +++ b/net/ax25/ax25_std_in.c Fri Mar 7 20:40:17 2003 @@ -75,7 +75,7 @@ if (ax25->sk != NULL) { ax25->sk->state = TCP_ESTABLISHED; /* For WAIT_SABM connections we will produce an accept ready socket here */ - if (!ax25->sk->dead) + if (!test_bit(SOCK_DEAD, &ax25->sk->flags)) ax25->sk->state_change(ax25->sk); } } diff -Nru a/net/ax25/ax25_std_timer.c b/net/ax25/ax25_std_timer.c --- a/net/ax25/ax25_std_timer.c Fri Mar 7 20:40:16 2003 +++ b/net/ax25/ax25_std_timer.c Fri Mar 7 20:40:16 2003 @@ -37,7 +37,7 @@ case AX25_STATE_0: /* Magic here: If we listen() and a new link dies before it is accepted() it isn't 'dead' so doesn't get removed. */ - if (ax25->sk == NULL || ax25->sk->destroy || (ax25->sk->state == TCP_LISTEN && ax25->sk->dead)) { + if (ax25->sk == NULL || test_bit(SOCK_DESTROY, &ax25->sk->flags) || (ax25->sk->state == TCP_LISTEN && test_bit(SOCK_DEAD, &ax25->sk->flags))) { ax25_destroy_socket(ax25); return; } @@ -94,9 +94,9 @@ ax25->sk->state = TCP_CLOSE; ax25->sk->err = 0; ax25->sk->shutdown |= SEND_SHUTDOWN; - if (!ax25->sk->dead) + if (!test_bit(SOCK_DEAD, &ax25->sk->flags)) ax25->sk->state_change(ax25->sk); - ax25->sk->dead = 1; + __set_bit(SOCK_DEAD, &ax25->sk->flags); } } diff -Nru a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c --- a/net/ax25/ax25_subr.c Fri Mar 7 20:40:18 2003 +++ b/net/ax25/ax25_subr.c Fri Mar 7 20:40:18 2003 @@ -285,8 +285,8 @@ ax25->sk->state = TCP_CLOSE; ax25->sk->err = reason; ax25->sk->shutdown |= SEND_SHUTDOWN; - if (!ax25->sk->dead) + if (!test_bit(SOCK_DEAD, &ax25->sk->flags)) ax25->sk->state_change(ax25->sk); - ax25->sk->dead = 1; + __set_bit(SOCK_DEAD, &ax25->sk->flags); } } diff -Nru a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c --- a/net/bluetooth/l2cap.c Fri Mar 7 20:40:17 2003 +++ b/net/bluetooth/l2cap.c Fri Mar 7 20:40:17 2003 @@ -272,7 +272,7 @@ /* Kill poor orphan */ bt_sock_unlink(&l2cap_sk_list, sk); - sk->dead = 1; + __set_bit(SOCK_DEAD, &sk->flags); sock_put(sk); } diff -Nru a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c --- a/net/bluetooth/rfcomm/sock.c Fri Mar 7 20:40:17 2003 +++ b/net/bluetooth/rfcomm/sock.c Fri Mar 7 20:40:17 2003 @@ -212,7 +212,7 @@ /* Kill poor orphan */ bt_sock_unlink(&rfcomm_sk_list, sk); - sk->dead = 1; + __set_bit(SOCK_DEAD, &sk->flags); sock_put(sk); } diff -Nru a/net/bluetooth/sco.c b/net/bluetooth/sco.c --- a/net/bluetooth/sco.c Fri Mar 7 20:40:16 2003 +++ b/net/bluetooth/sco.c Fri Mar 7 20:40:16 2003 @@ -377,7 +377,7 @@ /* Kill poor orphan */ bt_sock_unlink(&sco_sk_list, sk); - sk->dead = 1; + __set_bit(SOCK_DEAD, &sk->flags); sock_put(sk); } diff -Nru a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c --- a/net/bridge/netfilter/ebt_arp.c Fri Mar 7 20:40:16 2003 +++ b/net/bridge/netfilter/ebt_arp.c Fri Mar 7 20:40:16 2003 @@ -2,7 +2,7 @@ * ebt_arp * * Authors: - * Bart De Schuymer + * Bart De Schuymer * Tim Gardner * * April, 2002 @@ -37,10 +37,10 @@ uint32_t dst; uint32_t src; - // Make sure the packet is long enough. + /* Make sure the packet is long enough */ if ((((*skb).nh.raw) + arp_len) > (*skb).tail) return EBT_NOMATCH; - // IPv4 addresses are always 4 bytes. + /* IPv4 addresses are always 4 bytes */ if (((*skb).nh.arph)->ar_pln != sizeof(uint32_t)) return EBT_NOMATCH; @@ -82,8 +82,10 @@ static struct ebt_match filter_arp = { - {NULL, NULL}, EBT_ARP_MATCH, ebt_filter_arp, ebt_arp_check, NULL, - THIS_MODULE + .name = EBT_ARP_MATCH, + .match = ebt_filter_arp, + .check = ebt_arp_check, + .me = THIS_MODULE, }; static int __init init(void) diff -Nru a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c --- a/net/bridge/netfilter/ebt_dnat.c Fri Mar 7 20:40:17 2003 +++ b/net/bridge/netfilter/ebt_dnat.c Fri Mar 7 20:40:17 2003 @@ -2,7 +2,7 @@ * ebt_dnat * * Authors: - * Bart De Schuymer + * Bart De Schuymer * * June, 2002 * @@ -45,8 +45,10 @@ static struct ebt_target dnat = { - {NULL, NULL}, EBT_DNAT_TARGET, ebt_target_dnat, ebt_target_dnat_check, - NULL, THIS_MODULE + .name = EBT_DNAT_TARGET, + .target = ebt_target_dnat, + .check = ebt_target_dnat_check, + .me = THIS_MODULE, }; static int __init init(void) diff -Nru a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c --- a/net/bridge/netfilter/ebt_ip.c Fri Mar 7 20:40:17 2003 +++ b/net/bridge/netfilter/ebt_ip.c Fri Mar 7 20:40:17 2003 @@ -2,7 +2,7 @@ * ebt_ip * * Authors: - * Bart De Schuymer + * Bart De Schuymer * * April, 2002 * @@ -86,7 +86,7 @@ if (info->bitmask & ~EBT_IP_MASK || info->invflags & ~EBT_IP_MASK) return -EINVAL; if (info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT)) { - if (!info->bitmask & EBT_IPROTO) + if (!(info->bitmask & EBT_IPROTO)) return -EINVAL; if (info->protocol != IPPROTO_TCP && info->protocol != IPPROTO_UDP) @@ -101,8 +101,10 @@ static struct ebt_match filter_ip = { - {NULL, NULL}, EBT_IP_MATCH, ebt_filter_ip, ebt_ip_check, NULL, - THIS_MODULE + .name = EBT_IP_MATCH, + .match = ebt_filter_ip, + .check = ebt_ip_check, + .me = THIS_MODULE, }; static int __init init(void) diff -Nru a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c --- a/net/bridge/netfilter/ebt_log.c Fri Mar 7 20:40:16 2003 +++ b/net/bridge/netfilter/ebt_log.c Fri Mar 7 20:40:16 2003 @@ -2,7 +2,7 @@ * ebt_log * * Authors: - * Bart De Schuymer + * Bart De Schuymer * * April, 2002 * @@ -80,8 +80,10 @@ static struct ebt_watcher log = { - {NULL, NULL}, EBT_LOG_WATCHER, ebt_log, ebt_log_check, NULL, - THIS_MODULE + .name = EBT_LOG_WATCHER, + .watcher = ebt_log, + .check = ebt_log_check, + .me = THIS_MODULE, }; static int __init init(void) diff -Nru a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c --- a/net/bridge/netfilter/ebt_mark.c Fri Mar 7 20:40:17 2003 +++ b/net/bridge/netfilter/ebt_mark.c Fri Mar 7 20:40:17 2003 @@ -2,15 +2,16 @@ * ebt_mark * * Authors: - * Bart De Schuymer + * Bart De Schuymer * * July, 2002 * */ -// The mark target can be used in any chain -// I believe adding a mangle table just for marking is total overkill -// Marking a frame doesn't really change anything in the frame anyway +/* The mark target can be used in any chain, + * I believe adding a mangle table just for marking is total overkill. + * Marking a frame doesn't really change anything in the frame anyway. + */ #include #include @@ -46,8 +47,10 @@ static struct ebt_target mark_target = { - {NULL, NULL}, EBT_MARK_TARGET, ebt_target_mark, - ebt_target_mark_check, NULL, THIS_MODULE + .name = EBT_MARK_TARGET, + .target = ebt_target_mark, + .check = ebt_target_mark_check, + .me = THIS_MODULE, }; static int __init init(void) diff -Nru a/net/bridge/netfilter/ebt_mark_m.c b/net/bridge/netfilter/ebt_mark_m.c --- a/net/bridge/netfilter/ebt_mark_m.c Fri Mar 7 20:40:16 2003 +++ b/net/bridge/netfilter/ebt_mark_m.c Fri Mar 7 20:40:16 2003 @@ -2,7 +2,7 @@ * ebt_mark_m * * Authors: - * Bart De Schuymer + * Bart De Schuymer * * July, 2002 * @@ -41,8 +41,10 @@ static struct ebt_match filter_mark = { - {NULL, NULL}, EBT_MARK_MATCH, ebt_filter_mark, ebt_mark_check, NULL, - THIS_MODULE + .name = EBT_MARK_MATCH, + .match = ebt_filter_mark, + .check = ebt_mark_check, + .me = THIS_MODULE, }; static int __init init(void) diff -Nru a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c --- a/net/bridge/netfilter/ebt_redirect.c Fri Mar 7 20:40:18 2003 +++ b/net/bridge/netfilter/ebt_redirect.c Fri Mar 7 20:40:18 2003 @@ -2,7 +2,7 @@ * ebt_redirect * * Authors: - * Bart De Schuymer + * Bart De Schuymer * * April, 2002 * @@ -51,8 +51,10 @@ static struct ebt_target redirect_target = { - {NULL, NULL}, EBT_REDIRECT_TARGET, ebt_target_redirect, - ebt_target_redirect_check, NULL, THIS_MODULE + .name = EBT_REDIRECT_TARGET, + .target = ebt_target_redirect, + .check = ebt_target_redirect_check, + .me = THIS_MODULE, }; static int __init init(void) diff -Nru a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c --- a/net/bridge/netfilter/ebt_snat.c Fri Mar 7 20:40:16 2003 +++ b/net/bridge/netfilter/ebt_snat.c Fri Mar 7 20:40:16 2003 @@ -2,7 +2,7 @@ * ebt_snat * * Authors: - * Bart De Schuymer + * Bart De Schuymer * * June, 2002 * @@ -44,8 +44,10 @@ static struct ebt_target snat = { - {NULL, NULL}, EBT_SNAT_TARGET, ebt_target_snat, ebt_target_snat_check, - NULL, THIS_MODULE + .name = EBT_SNAT_TARGET, + .target = ebt_target_snat, + .check = ebt_target_snat_check, + .me = THIS_MODULE, }; static int __init init(void) diff -Nru a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c --- a/net/bridge/netfilter/ebt_vlan.c Fri Mar 7 20:40:17 2003 +++ b/net/bridge/netfilter/ebt_vlan.c Fri Mar 7 20:40:17 2003 @@ -1,7 +1,7 @@ /* * Description: EBTables 802.1Q match extension kernelspace module. * Authors: Nick Fedchik - * Bart De Schuymer + * Bart De Schuymer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -226,12 +226,10 @@ } static struct ebt_match filter_vlan = { - {NULL, NULL}, - EBT_VLAN_MATCH, - ebt_filter_vlan, - ebt_check_vlan, - NULL, - THIS_MODULE + .name = EBT_VLAN_MATCH, + .match = ebt_filter_vlan, + .check = ebt_check_vlan, + .me = THIS_MODULE, }; /* diff -Nru a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c --- a/net/bridge/netfilter/ebtable_broute.c Fri Mar 7 20:40:16 2003 +++ b/net/bridge/netfilter/ebtable_broute.c Fri Mar 7 20:40:16 2003 @@ -2,7 +2,7 @@ * ebtable_broute * * Authors: - * Bart De Schuymer + * Bart De Schuymer * * April, 2002 * @@ -16,11 +16,12 @@ #include #include -// EBT_ACCEPT means the frame will be bridged -// EBT_DROP means the frame will be routed +/* EBT_ACCEPT means the frame will be bridged + * EBT_DROP means the frame will be routed + */ static struct ebt_entries initial_chain = { - .name = "BROUTING", - .policy = EBT_ACCEPT, + .name = "BROUTING", + .policy = EBT_ACCEPT, }; static struct ebt_replace initial_table = @@ -31,7 +32,7 @@ .hook_entry = { [NF_BR_BROUTING] = &initial_chain, }, - .entries = (char *)&initial_chain + .entries = (char *)&initial_chain, }; static int check(const struct ebt_table_info *info, unsigned int valid_hooks) @@ -57,8 +58,8 @@ ret = ebt_do_table(NF_BR_BROUTING, pskb, (*pskb)->dev, NULL, &broute_table); if (ret == NF_DROP) - return 1; // route it - return 0; // bridge it + return 1; /* route it */ + return 0; /* bridge it */ } static int __init init(void) @@ -69,7 +70,7 @@ if (ret < 0) return ret; br_write_lock_bh(BR_NETPROTO_LOCK); - // see br_input.c + /* see br_input.c */ br_should_route_hook = ebt_broute; br_write_unlock_bh(BR_NETPROTO_LOCK); return ret; diff -Nru a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c --- a/net/bridge/netfilter/ebtable_filter.c Fri Mar 7 20:40:18 2003 +++ b/net/bridge/netfilter/ebtable_filter.c Fri Mar 7 20:40:18 2003 @@ -2,7 +2,7 @@ * ebtable_filter * * Authors: - * Bart De Schuymer + * Bart De Schuymer * * April, 2002 * @@ -27,7 +27,7 @@ { .name = "OUTPUT", .policy = EBT_ACCEPT, - } + }, }; static struct ebt_replace initial_table = @@ -35,12 +35,12 @@ .name = "filter", .valid_hooks = FILTER_VALID_HOOKS, .entries_size = 3 * sizeof(struct ebt_entries), - .hook_entry = { + .hook_entry = { [NF_BR_LOCAL_IN] = &initial_chains[0], [NF_BR_FORWARD] = &initial_chains[1], - [NF_BR_LOCAL_OUT] = &initial_chains[2], + [NF_BR_LOCAL_OUT] = &initial_chains[2], }, - .entries = (char *)initial_chains + .entries = (char *)initial_chains, }; static int check(const struct ebt_table_info *info, unsigned int valid_hooks) @@ -77,14 +77,14 @@ .hook = ebt_hook, .pf = PF_BRIDGE, .hooknum = NF_BR_FORWARD, - .priority = NF_BR_PRI_FILTER_BRIDGED + .priority = NF_BR_PRI_FILTER_BRIDGED, }, { .hook = ebt_hook, .pf = PF_BRIDGE, .hooknum = NF_BR_LOCAL_OUT, - .priority = NF_BR_PRI_FILTER_OTHER - } + .priority = NF_BR_PRI_FILTER_OTHER, + }, }; static int __init init(void) diff -Nru a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c --- a/net/bridge/netfilter/ebtable_nat.c Fri Mar 7 20:40:18 2003 +++ b/net/bridge/netfilter/ebtable_nat.c Fri Mar 7 20:40:18 2003 @@ -2,7 +2,7 @@ * ebtable_nat * * Authors: - * Bart De Schuymer + * Bart De Schuymer * * April, 2002 * @@ -39,7 +39,7 @@ [NF_BR_LOCAL_OUT] = &initial_chains[1], [NF_BR_POST_ROUTING] = &initial_chains[2], }, - .entries = (char *)initial_chains + .entries = (char *)initial_chains, }; static int check(const struct ebt_table_info *info, unsigned int valid_hooks) @@ -77,19 +77,19 @@ .hook = ebt_nat_dst, .pf = PF_BRIDGE, .hooknum = NF_BR_LOCAL_OUT, - .priority = NF_BR_PRI_NAT_DST_OTHER + .priority = NF_BR_PRI_NAT_DST_OTHER, }, { .hook = ebt_nat_src, .pf = PF_BRIDGE, .hooknum = NF_BR_POST_ROUTING, - .priority = NF_BR_PRI_NAT_SRC + .priority = NF_BR_PRI_NAT_SRC, }, { .hook = ebt_nat_dst, .pf = PF_BRIDGE, .hooknum = NF_BR_PRE_ROUTING, - .priority = NF_BR_PRI_NAT_DST_BRIDGED + .priority = NF_BR_PRI_NAT_DST_BRIDGED, }, }; diff -Nru a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c --- a/net/bridge/netfilter/ebtables.c Fri Mar 7 20:40:16 2003 +++ b/net/bridge/netfilter/ebtables.c Fri Mar 7 20:40:16 2003 @@ -365,7 +365,7 @@ m->u.match = match; if (!try_module_get(match->me)) { up(&ebt_mutex); - return -EINVAL; + return -ENOENT; } up(&ebt_mutex); if (match->check && @@ -394,7 +394,7 @@ w->u.watcher = watcher; if (!try_module_get(watcher->me)) { up(&ebt_mutex); - return -EINVAL; + return -ENOENT; } up(&ebt_mutex); if (watcher->check && @@ -634,6 +634,7 @@ goto cleanup_watchers; if (!try_module_get(target->me)) { up(&ebt_mutex); + ret = -ENOENT; goto cleanup_watchers; } up(&ebt_mutex); diff -Nru a/net/core/skbuff.c b/net/core/skbuff.c --- a/net/core/skbuff.c Fri Mar 7 20:40:17 2003 +++ b/net/core/skbuff.c Fri Mar 7 20:40:17 2003 @@ -196,40 +196,6 @@ goto nodata; /* XXX: does not include slab overhead */ - skb->truesize = size + sizeof(struct sk_buff); - - /* Load the data pointers. */ - skb->head = skb->data = skb->tail = data; - skb->end = data + size; - - /* Set up other state */ - skb->len = 0; - skb->cloned = 0; - skb->data_len = 0; - - atomic_set(&skb->users, 1); - atomic_set(&(skb_shinfo(skb)->dataref), 1); - skb_shinfo(skb)->nr_frags = 0; - skb_shinfo(skb)->tso_size = 0; - skb_shinfo(skb)->tso_segs = 0; - skb_shinfo(skb)->frag_list = NULL; -out: - return skb; -nodata: - skb_head_to_pool(skb); - skb = NULL; - goto out; -} - - -/* - * Slab constructor for a skb head. - */ -static void skb_headerinit(void *p, kmem_cache_t *cache, - unsigned long flags) -{ - struct sk_buff *skb = p; - skb->next = skb->prev = NULL; skb->list = NULL; skb->sk = NULL; @@ -238,27 +204,50 @@ skb->dst = NULL; skb->sp = NULL; memset(skb->cb, 0, sizeof(skb->cb)); + /* Set up other state */ + skb->len = 0; + skb->data_len = 0; + skb->csum = 0; + skb->cloned = 0; skb->pkt_type = PACKET_HOST; /* Default type */ skb->ip_summed = 0; skb->priority = 0; + atomic_set(&skb->users, 1); skb->security = 0; /* By default packets are insecure */ - skb->destructor = NULL; + skb->truesize = size + sizeof(struct sk_buff); + + /* Load the data pointers. */ + skb->head = skb->data = skb->tail = data; + skb->end = data + size; + skb->destructor = NULL; #ifdef CONFIG_NETFILTER - skb->nfmark = skb->nfcache = 0; - skb->nfct = NULL; + skb->nfmark = skb->nfcache = 0; + skb->nfct = NULL; #ifdef CONFIG_NETFILTER_DEBUG - skb->nf_debug = 0; + skb->nf_debug = 0; #endif #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) - skb->nf_bridge = NULL; + skb->nf_bridge = NULL; #endif #endif #ifdef CONFIG_NET_SCHED - skb->tc_index = 0; -#endif + skb->tc_index = 0; +#endif + atomic_set(&(skb_shinfo(skb)->dataref), 1); + skb_shinfo(skb)->nr_frags = 0; + skb_shinfo(skb)->tso_size = 0; + skb_shinfo(skb)->tso_segs = 0; + skb_shinfo(skb)->frag_list = NULL; +out: + return skb; +nodata: + skb_head_to_pool(skb); + skb = NULL; + goto out; } + static void skb_drop_fraglist(struct sk_buff *skb) { struct sk_buff *list = skb_shinfo(skb)->frag_list; @@ -339,7 +328,6 @@ nf_bridge_put(skb->nf_bridge); #endif #endif - skb_headerinit(skb, NULL, 0); /* clean state */ kfree_skbmem(skb); } @@ -1261,7 +1249,7 @@ sizeof(struct sk_buff), 0, SLAB_HWCACHE_ALIGN, - skb_headerinit, NULL); + NULL, NULL); if (!skbuff_head_cache) panic("cannot create skbuff cache"); diff -Nru a/net/core/sock.c b/net/core/sock.c --- a/net/core/sock.c Fri Mar 7 20:40:17 2003 +++ b/net/core/sock.c Fri Mar 7 20:40:17 2003 @@ -178,7 +178,7 @@ switch(optname) { case SO_DONTLINGER: - sk->linger=0; + __clear_bit(SOCK_LINGER, &sk->flags); return 0; } #endif @@ -214,7 +214,7 @@ sk->localroute=valbool; break; case SO_BROADCAST: - sk->broadcast=valbool; + sock_valbool_flag(sk, SOCK_BROADCAST, valbool); break; case SO_SNDBUF: /* Don't error on this BSD doesn't and if you think @@ -262,11 +262,11 @@ tcp_set_keepalive(sk, valbool); } #endif - sk->keepopen = valbool; + sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool); break; case SO_OOBINLINE: - sk->urginline = valbool; + sock_valbool_flag(sk, SOCK_URGINLINE, valbool); break; case SO_NO_CHECK: @@ -290,7 +290,7 @@ break; } if(ling.l_onoff==0) { - sk->linger=0; + __clear_bit(SOCK_LINGER, &sk->flags); } else { #if (BITS_PER_LONG == 32) if (ling.l_linger >= MAX_SCHEDULE_TIMEOUT/HZ) @@ -298,12 +298,12 @@ else #endif sk->lingertime=ling.l_linger*HZ; - sk->linger=1; + __set_bit(SOCK_LINGER, &sk->flags); } break; case SO_BSDCOMPAT: - sk->bsdism = valbool; + sock_valbool_flag(sk, SOCK_BSDISM, valbool); break; case SO_PASSCRED: @@ -443,7 +443,7 @@ break; case SO_BROADCAST: - v.val= sk->broadcast; + v.val= test_bit(SOCK_BROADCAST, &sk->flags); break; case SO_SNDBUF: @@ -459,7 +459,7 @@ break; case SO_KEEPALIVE: - v.val = sk->keepopen; + v.val = test_bit(SOCK_KEEPOPEN, &sk->flags); break; case SO_TYPE: @@ -473,7 +473,7 @@ break; case SO_OOBINLINE: - v.val = sk->urginline; + v.val = test_bit(SOCK_URGINLINE, &sk->flags); break; case SO_NO_CHECK: @@ -486,12 +486,12 @@ case SO_LINGER: lv=sizeof(v.ling); - v.ling.l_onoff=sk->linger; + v.ling.l_onoff = test_bit(SOCK_LINGER, &sk->flags); v.ling.l_linger=sk->lingertime/HZ; break; case SO_BSDCOMPAT: - v.val = sk->bsdism; + v.val = test_bit(SOCK_BSDISM, &sk->flags); break; case SO_TIMESTAMP: @@ -806,6 +806,7 @@ page = alloc_pages(sk->allocation, 0); if (!page) { err = -ENOBUFS; + skb_shinfo(skb)->nr_frags = i; kfree_skb(skb); goto failure; } diff -Nru a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c --- a/net/decnet/dn_nsp_in.c Fri Mar 7 20:40:16 2003 +++ b/net/decnet/dn_nsp_in.c Fri Mar 7 20:40:16 2003 @@ -118,7 +118,7 @@ break; } - if (wakeup && !sk->dead) + if (wakeup && !test_bit(SOCK_DEAD, &sk->flags)) sk->state_change(sk); } @@ -367,7 +367,7 @@ } } dn_nsp_send_link(sk, DN_NOCHANGE, 0); - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->state_change(sk); } @@ -428,7 +428,7 @@ break; } - if (!sk->dead) { + if (!test_bit(SOCK_DEAD, &sk->flags)) { if (sk->socket->state != SS_UNCONNECTED) sk->socket->state = SS_DISCONNECTING; sk->state_change(sk); @@ -477,7 +477,7 @@ scp->state = DN_CN; } - if (!sk->dead) { + if (!test_bit(SOCK_DEAD, &sk->flags)) { if (sk->socket->state != SS_UNCONNECTED) sk->socket->state = SS_DISCONNECTING; sk->state_change(sk); @@ -549,7 +549,7 @@ } break; } - if (wake_up && !sk->dead) + if (wake_up && !test_bit(SOCK_DEAD, &sk->flags)) sk->state_change(sk); } @@ -587,7 +587,7 @@ * Therefore the plain read_lock is ok here. -DaveM */ read_lock(&sk->callback_lock); - if (!sk->dead) { + if (!test_bit(SOCK_DEAD, &sk->flags)) { struct socket *sock = sk->socket; wake_up_interruptible(sk->sleep); if (sock && sock->fasync_list && @@ -671,7 +671,7 @@ if (scp->state == DN_CI) { scp->state = DN_NC; sk->state = TCP_CLOSE; - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->state_change(sk); } @@ -861,7 +861,7 @@ int other = 1; /* both data and ack frames can kick a CC socket into RUN */ - if ((scp->state == DN_CC) && !sk->dead) { + if ((scp->state == DN_CC) && !test_bit(SOCK_DEAD, &sk->flags)) { scp->state = DN_RUN; sk->state = TCP_ESTABLISHED; sk->state_change(sk); diff -Nru a/net/econet/af_econet.c b/net/econet/af_econet.c --- a/net/econet/af_econet.c Fri Mar 7 20:40:17 2003 +++ b/net/econet/af_econet.c Fri Mar 7 20:40:17 2003 @@ -533,7 +533,7 @@ sock->sk = NULL; sk->socket = NULL; - sk->dead = 1; + __set_bit(SOCK_DEAD, &sk->flags); /* Purge queues */ diff -Nru a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c --- a/net/ipv4/af_inet.c Fri Mar 7 20:40:16 2003 +++ b/net/ipv4/af_inet.c Fri Mar 7 20:40:16 2003 @@ -146,7 +146,7 @@ sk); return; } - if (!sk->dead) { + if (!test_bit(SOCK_DEAD, &sk->flags)) { printk("Attempt to release alive inet socket %p\n", sk); return; } @@ -454,7 +454,8 @@ * linger.. */ timeout = 0; - if (sk->linger && !(current->flags & PF_EXITING)) + if (test_bit(SOCK_LINGER, &sk->flags) && + !(current->flags & PF_EXITING)) timeout = sk->lingertime; sock->sk = NULL; sk->prot->close(sk, timeout); diff -Nru a/net/ipv4/ah.c b/net/ipv4/ah.c --- a/net/ipv4/ah.c Fri Mar 7 20:40:18 2003 +++ b/net/ipv4/ah.c Fri Mar 7 20:40:18 2003 @@ -2,30 +2,14 @@ #include #include #include +#include #include #include #include #include -#define AH_HLEN_NOICV 12 - -typedef void (icv_update_fn_t)(struct crypto_tfm *, - struct scatterlist *, unsigned int); - -struct ah_data -{ - u8 *key; - int key_len; - u8 *work_icv; - int icv_full_len; - int icv_trunc_len; - - void (*icv)(struct ah_data*, - struct sk_buff *skb, u8 *icv); - - struct crypto_tfm *tfm; -}; +#define AH_HLEN_NOICV 12 /* Clear mutable options and find final destination to substitute * into IP header for icv calculation. Options are already checked @@ -71,92 +55,6 @@ return 0; } -static void skb_ah_walk(const struct sk_buff *skb, - struct crypto_tfm *tfm, icv_update_fn_t icv_update) -{ - int offset = 0; - int len = skb->len; - int start = skb->len - skb->data_len; - int i, copy = start - offset; - struct scatterlist sg; - - /* Checksum header. */ - if (copy > 0) { - if (copy > len) - copy = len; - - sg.page = virt_to_page(skb->data + offset); - sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; - sg.length = copy; - - icv_update(tfm, &sg, 1); - - if ((len -= copy) == 0) - return; - offset += copy; - } - - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - int end; - - BUG_TRAP(start <= offset + len); - - end = start + skb_shinfo(skb)->frags[i].size; - if ((copy = end - offset) > 0) { - skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - - if (copy > len) - copy = len; - - sg.page = frag->page; - sg.offset = frag->page_offset + offset-start; - sg.length = copy; - - icv_update(tfm, &sg, 1); - - if (!(len -= copy)) - return; - offset += copy; - } - start = end; - } - - if (skb_shinfo(skb)->frag_list) { - struct sk_buff *list = skb_shinfo(skb)->frag_list; - - for (; list; list = list->next) { - int end; - - BUG_TRAP(start <= offset + len); - - end = start + list->len; - if ((copy = end - offset) > 0) { - if (copy > len) - copy = len; - skb_ah_walk(list, tfm, icv_update); - if ((len -= copy) == 0) - return; - offset += copy; - } - start = end; - } - } - if (len) - BUG(); -} - -static void -ah_hmac_digest(struct ah_data *ahp, struct sk_buff *skb, u8 *auth_data) -{ - struct crypto_tfm *tfm = ahp->tfm; - - memset(auth_data, 0, ahp->icv_trunc_len); - crypto_hmac_init(tfm, ahp->key, &ahp->key_len); - skb_ah_walk(skb, tfm, crypto_hmac_update); - crypto_hmac_final(tfm, ahp->key, &ahp->key_len, ahp->work_icv); - memcpy(auth_data, ahp->work_icv, ahp->icv_trunc_len); -} - static int ah_output(struct sk_buff *skb) { int err; @@ -330,7 +228,7 @@ skb->h.icmph->code != ICMP_FRAG_NEEDED) return; - x = xfrm_state_lookup(iph->daddr, ah->spi, IPPROTO_AH); + x = xfrm4_state_lookup(iph->daddr, ah->spi, IPPROTO_AH); if (!x) return; printk(KERN_DEBUG "pmtu discvovery on SA AH/%08x/%08x\n", diff -Nru a/net/ipv4/esp.c b/net/ipv4/esp.c --- a/net/ipv4/esp.c Fri Mar 7 20:40:17 2003 +++ b/net/ipv4/esp.c Fri Mar 7 20:40:17 2003 @@ -2,318 +2,15 @@ #include #include #include +#include #include #include #include #include #include -#define MAX_SG_ONSTACK 4 - -typedef void (icv_update_fn_t)(struct crypto_tfm *, - struct scatterlist *, unsigned int); - -/* BUGS: - * - we assume replay seqno is always present. - */ - -struct esp_data -{ - /* Confidentiality */ - struct { - u8 *key; /* Key */ - int key_len; /* Key length */ - u8 *ivec; /* ivec buffer */ - /* ivlen is offset from enc_data, where encrypted data start. - * It is logically different of crypto_tfm_alg_ivsize(tfm). - * We assume that it is either zero (no ivec), or - * >= crypto_tfm_alg_ivsize(tfm). */ - int ivlen; - int padlen; /* 0..255 */ - struct crypto_tfm *tfm; /* crypto handle */ - } conf; - - /* Integrity. It is active when icv_full_len != 0 */ - struct { - u8 *key; /* Key */ - int key_len; /* Length of the key */ - u8 *work_icv; - int icv_full_len; - int icv_trunc_len; - void (*icv)(struct esp_data*, - struct sk_buff *skb, - int offset, int len, u8 *icv); - struct crypto_tfm *tfm; - } auth; -}; - -/* Move to common area: it is shared with AH. */ - -void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm, - int offset, int len, icv_update_fn_t icv_update) -{ - int start = skb->len - skb->data_len; - int i, copy = start - offset; - struct scatterlist sg; - - /* Checksum header. */ - if (copy > 0) { - if (copy > len) - copy = len; - - sg.page = virt_to_page(skb->data + offset); - sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; - sg.length = copy; - - icv_update(tfm, &sg, 1); - - if ((len -= copy) == 0) - return; - offset += copy; - } - - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - int end; - - BUG_TRAP(start <= offset + len); - - end = start + skb_shinfo(skb)->frags[i].size; - if ((copy = end - offset) > 0) { - skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - - if (copy > len) - copy = len; - - sg.page = frag->page; - sg.offset = frag->page_offset + offset-start; - sg.length = copy; - - icv_update(tfm, &sg, 1); - - if (!(len -= copy)) - return; - offset += copy; - } - start = end; - } - - if (skb_shinfo(skb)->frag_list) { - struct sk_buff *list = skb_shinfo(skb)->frag_list; - - for (; list; list = list->next) { - int end; - - BUG_TRAP(start <= offset + len); - - end = start + list->len; - if ((copy = end - offset) > 0) { - if (copy > len) - copy = len; - skb_icv_walk(list, tfm, offset-start, copy, icv_update); - if ((len -= copy) == 0) - return; - offset += copy; - } - start = end; - } - } - if (len) - BUG(); -} - - -/* Looking generic it is not used in another places. */ - -int -skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) -{ - int start = skb->len - skb->data_len; - int i, copy = start - offset; - int elt = 0; - - if (copy > 0) { - if (copy > len) - copy = len; - sg[elt].page = virt_to_page(skb->data + offset); - sg[elt].offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; - sg[elt].length = copy; - elt++; - if ((len -= copy) == 0) - return elt; - offset += copy; - } - - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - int end; - - BUG_TRAP(start <= offset + len); - - end = start + skb_shinfo(skb)->frags[i].size; - if ((copy = end - offset) > 0) { - skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - - if (copy > len) - copy = len; - sg[elt].page = frag->page; - sg[elt].offset = frag->page_offset+offset-start; - sg[elt].length = copy; - elt++; - if (!(len -= copy)) - return elt; - offset += copy; - } - start = end; - } - if (skb_shinfo(skb)->frag_list) { - struct sk_buff *list = skb_shinfo(skb)->frag_list; - - for (; list; list = list->next) { - int end; - - BUG_TRAP(start <= offset + len); - - end = start + list->len; - if ((copy = end - offset) > 0) { - if (copy > len) - copy = len; - elt += skb_to_sgvec(list, sg+elt, offset - start, copy); - if ((len -= copy) == 0) - return elt; - offset += copy; - } - start = end; - } - } - if (len) - BUG(); - return elt; -} - -/* Common with AH after some work on arguments. */ - -static void -esp_hmac_digest(struct esp_data *esp, struct sk_buff *skb, int offset, - int len, u8 *auth_data) -{ - struct crypto_tfm *tfm = esp->auth.tfm; - char *icv = esp->auth.work_icv; - - memset(auth_data, 0, esp->auth.icv_trunc_len); - crypto_hmac_init(tfm, esp->auth.key, &esp->auth.key_len); - skb_icv_walk(skb, tfm, offset, len, crypto_hmac_update); - crypto_hmac_final(tfm, esp->auth.key, &esp->auth.key_len, icv); - memcpy(auth_data, icv, esp->auth.icv_trunc_len); -} - -/* Check that skb data bits are writable. If they are not, copy data - * to newly created private area. If "tailbits" is given, make sure that - * tailbits bytes beyond current end of skb are writable. - * - * Returns amount of elements of scatterlist to load for subsequent - * transformations and pointer to writable trailer skb. - */ - -int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer) -{ - int copyflag; - int elt; - struct sk_buff *skb1, **skb_p; - - /* If skb is cloned or its head is paged, reallocate - * head pulling out all the pages (pages are considered not writable - * at the moment even if they are anonymous). - */ - if ((skb_cloned(skb) || skb_shinfo(skb)->nr_frags) && - __pskb_pull_tail(skb, skb_pagelen(skb)-skb_headlen(skb)) == NULL) - return -ENOMEM; - - /* Easy case. Most of packets will go this way. */ - if (!skb_shinfo(skb)->frag_list) { - /* A little of trouble, not enough of space for trailer. - * This should not happen, when stack is tuned to generate - * good frames. OK, on miss we reallocate and reserve even more - * space, 128 bytes is fair. */ - - if (skb_tailroom(skb) < tailbits && - pskb_expand_head(skb, 0, tailbits-skb_tailroom(skb)+128, GFP_ATOMIC)) - return -ENOMEM; - - /* Voila! */ - *trailer = skb; - return 1; - } - - /* Misery. We are in troubles, going to mincer fragments... */ - - elt = 1; - skb_p = &skb_shinfo(skb)->frag_list; - copyflag = 0; - - while ((skb1 = *skb_p) != NULL) { - int ntail = 0; - - /* The fragment is partially pulled by someone, - * this can happen on input. Copy it and everything - * after it. */ - - if (skb_shared(skb1)) - copyflag = 1; - - /* If the skb is the last, worry about trailer. */ - - if (skb1->next == NULL && tailbits) { - if (skb_shinfo(skb1)->nr_frags || - skb_shinfo(skb1)->frag_list || - skb_tailroom(skb1) < tailbits) - ntail = tailbits + 128; - } - - if (copyflag || - skb_cloned(skb1) || - ntail || - skb_shinfo(skb1)->nr_frags || - skb_shinfo(skb1)->frag_list) { - struct sk_buff *skb2; - - /* Fuck, we are miserable poor guys... */ - if (ntail == 0) - skb2 = skb_copy(skb1, GFP_ATOMIC); - else - skb2 = skb_copy_expand(skb1, - skb_headroom(skb1), - ntail, - GFP_ATOMIC); - if (unlikely(skb2 == NULL)) - return -ENOMEM; - - if (skb1->sk) - skb_set_owner_w(skb, skb1->sk); - - /* Looking around. Are we still alive? - * OK, link new skb, drop old one */ - - skb2->next = skb1->next; - *skb_p = skb2; - kfree_skb(skb1); - skb1 = skb2; - } - elt++; - *trailer = skb1; - skb_p = &skb1->next; - } - - return elt; -} - -void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len) -{ - if (tail != skb) { - skb->data_len += len; - skb->len += len; - } - return skb_put(tail, len); -} +#define MAX_SG_ONSTACK 4 int esp_output(struct sk_buff *skb) { @@ -575,7 +272,7 @@ skb->h.icmph->code != ICMP_FRAG_NEEDED) return; - x = xfrm_state_lookup(iph->daddr, esph->spi, IPPROTO_ESP); + x = xfrm4_state_lookup(iph->daddr, esph->spi, IPPROTO_ESP); if (!x) return; printk(KERN_DEBUG "pmtu discvovery on SA ESP/%08x/%08x\n", diff -Nru a/net/ipv4/igmp.c b/net/ipv4/igmp.c --- a/net/ipv4/igmp.c Fri Mar 7 20:40:18 2003 +++ b/net/ipv4/igmp.c Fri Mar 7 20:40:18 2003 @@ -606,7 +606,7 @@ static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr) { struct flowi fl = { .nl_u = { .ip4_u = - { .daddr = imr->imr_address.s_addr } } }; + { .daddr = imr->imr_multiaddr.s_addr } } }; struct rtable *rt; struct net_device *dev = NULL; struct in_device *idev = NULL; diff -Nru a/net/ipv4/raw.c b/net/ipv4/raw.c --- a/net/ipv4/raw.c Fri Mar 7 20:40:17 2003 +++ b/net/ipv4/raw.c Fri Mar 7 20:40:17 2003 @@ -450,7 +450,8 @@ goto done; err = -EACCES; - if (rt->rt_flags & RTCF_BROADCAST && !sk->broadcast) + if (rt->rt_flags & RTCF_BROADCAST && + !test_bit(SOCK_BROADCAST, &sk->flags)) goto done; if (msg->msg_flags & MSG_CONFIRM) diff -Nru a/net/ipv4/route.c b/net/ipv4/route.c --- a/net/ipv4/route.c Fri Mar 7 20:40:18 2003 +++ b/net/ipv4/route.c Fri Mar 7 20:40:18 2003 @@ -96,6 +96,7 @@ #include #include #include +#include #ifdef CONFIG_SYSCTL #include #endif @@ -930,7 +931,7 @@ rth->u.dst.dev != dev) break; - dst_clone(&rth->u.dst); + dst_hold(&rth->u.dst); rcu_read_unlock(); rt = dst_alloc(&ipv4_dst_ops); @@ -2599,6 +2600,13 @@ #endif /* CONFIG_PROC_FS */ #endif /* CONFIG_NET_CLS_ROUTE */ +int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl) +{ + int err = 0; + err = __ip_route_output_key((struct rtable**)dst, fl); + return err; +} + int __init ip_rt_init(void) { int i, order, goal, rc = 0; @@ -2680,6 +2688,7 @@ ip_rt_gc_interval; add_timer(&rt_periodic_timer); + xfrm_dst_lookup_register(xfrm_dst_lookup, AF_INET); #ifdef CONFIG_PROC_FS if (rt_cache_proc_init()) goto out_enomem; diff -Nru a/net/ipv4/tcp.c b/net/ipv4/tcp.c --- a/net/ipv4/tcp.c Fri Mar 7 20:40:16 2003 +++ b/net/ipv4/tcp.c Fri Mar 7 20:40:16 2003 @@ -441,7 +441,7 @@ if ((tp->rcv_nxt != tp->copied_seq) && (tp->urg_seq != tp->copied_seq || tp->rcv_nxt != tp->copied_seq + 1 || - sk->urginline || !tp->urg_data)) + test_bit(SOCK_URGINLINE, &sk->flags) || !tp->urg_data)) mask |= POLLIN | POLLRDNORM; if (!(sk->shutdown & SEND_SHUTDOWN)) { @@ -497,7 +497,8 @@ lock_sock(sk); if ((1 << sk->state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) answ = 0; - else if (sk->urginline || !tp->urg_data || + else if (test_bit(SOCK_URGINLINE, &sk->flags) || + !tp->urg_data || before(tp->urg_seq, tp->copied_seq) || !before(tp->urg_seq, tp->rcv_nxt)) { answ = tp->rcv_nxt - tp->copied_seq; @@ -1254,10 +1255,11 @@ struct tcp_opt *tp = tcp_sk(sk); /* No URG data to read. */ - if (sk->urginline || !tp->urg_data || tp->urg_data == TCP_URG_READ) + if (test_bit(SOCK_URGINLINE, &sk->flags) || !tp->urg_data || + tp->urg_data == TCP_URG_READ) return -EINVAL; /* Yes this is right ! */ - if (sk->state == TCP_CLOSE && !sk->done) + if (sk->state == TCP_CLOSE && !test_bit(SOCK_DONE, &sk->flags)) return -ENOTCONN; if (tp->urg_data & TCP_URG_VALID) { @@ -1588,7 +1590,7 @@ (flags & MSG_PEEK)) break; } else { - if (sk->done) + if (test_bit(SOCK_DONE, &sk->flags)) break; if (sk->err) { @@ -1600,7 +1602,7 @@ break; if (sk->state == TCP_CLOSE) { - if (!sk->done) { + if (!test_bit(SOCK_DONE, &sk->flags)) { /* This occurs when user tries to read * from never connected socket. */ @@ -1713,7 +1715,8 @@ u32 urg_offset = tp->urg_seq - *seq; if (urg_offset < used) { if (!urg_offset) { - if (!sk->urginline) { + if (!test_bit(SOCK_URGINLINE, + &sk->flags)) { ++*seq; offset++; used--; @@ -1837,7 +1840,7 @@ /* * Shutdown the sending side of a connection. Much like close except - * that we don't receive shut down or set sk->dead. + * that we don't receive shut down or set SOCK_DEAD in sk->flags. */ void tcp_shutdown(struct sock *sk, int how) @@ -1902,7 +1905,7 @@ void tcp_destroy_sock(struct sock *sk) { BUG_TRAP(sk->state == TCP_CLOSE); - BUG_TRAP(sk->dead); + BUG_TRAP(test_bit(SOCK_DEAD, &sk->flags)); /* It cannot be in hash table! */ BUG_TRAP(!sk->pprev); @@ -1979,7 +1982,7 @@ NET_INC_STATS_USER(TCPAbortOnClose); tcp_set_state(sk, TCP_CLOSE); tcp_send_active_reset(sk, GFP_KERNEL); - } else if (sk->linger && !sk->lingertime) { + } else if (test_bit(SOCK_LINGER, &sk->flags) && !sk->lingertime) { /* Check zero linger _after_ checking for unread data. */ sk->prot->disconnect(sk, 0); NET_INC_STATS_USER(TCPAbortOnData); @@ -2157,7 +2160,7 @@ } sk->shutdown = 0; - sk->done = 0; + __clear_bit(SOCK_DONE, &sk->flags); tp->srtt = 0; if ((tp->write_seq += tp->max_window + 2) == 0) tp->write_seq = 1; @@ -2358,7 +2361,7 @@ err = -EINVAL; else { tp->keepalive_time = val * HZ; - if (sk->keepopen && + if (test_bit(SOCK_KEEPOPEN, &sk->flags) && !((1 << sk->state) & (TCPF_CLOSE | TCPF_LISTEN))) { __u32 elapsed = tcp_time_stamp - tp->rcv_tstamp; if (tp->keepalive_time > elapsed) diff -Nru a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c --- a/net/ipv4/tcp_input.c Fri Mar 7 20:40:17 2003 +++ b/net/ipv4/tcp_input.c Fri Mar 7 20:40:17 2003 @@ -2352,7 +2352,7 @@ sk->err = ECONNRESET; } - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->error_report(sk); tcp_done(sk); @@ -2379,7 +2379,7 @@ tcp_schedule_ack(tp); sk->shutdown |= RCV_SHUTDOWN; - sk->done = 1; + __clear_bit(SOCK_DONE, &sk->flags); switch(sk->state) { case TCP_SYN_RECV: @@ -2428,7 +2428,7 @@ tcp_sack_reset(tp); tcp_mem_reclaim(sk); - if (!sk->dead) { + if (!test_bit(SOCK_DEAD, &sk->flags)) { sk->state_change(sk); /* Do not send POLL_HUP for half duplex close. */ @@ -2745,7 +2745,7 @@ if (eaten > 0) { __kfree_skb(skb); - } else if (!sk->dead) + } else if (!test_bit(SOCK_DEAD, &sk->flags)) sk->data_ready(sk, 0); return; } @@ -3247,7 +3247,7 @@ * buggy users. */ if (tp->urg_seq == tp->copied_seq && tp->urg_data && - !sk->urginline && + !test_bit(SOCK_URGINLINE, &sk->flags) && tp->copied_seq != tp->rcv_nxt) { struct sk_buff *skb = skb_peek(&sk->receive_queue); tp->copied_seq++; @@ -3284,7 +3284,7 @@ if (skb_copy_bits(skb, ptr, &tmp, 1)) BUG(); tp->urg_data = TCP_URG_VALID | tmp; - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->data_ready(sk,0); } } @@ -3699,7 +3699,7 @@ tcp_init_metrics(sk); tcp_init_buffer_space(sk); - if (sk->keepopen) + if (test_bit(SOCK_KEEPOPEN, &sk->flags)) tcp_reset_keepalive_timer(sk, keepalive_time_when(tp)); if (!tp->snd_wscale) @@ -3714,7 +3714,7 @@ mb(); tcp_set_state(sk, TCP_ESTABLISHED); - if(!sk->dead) { + if(!test_bit(SOCK_DEAD, &sk->flags)) { sk->state_change(sk); sk_wake_async(sk, 0, POLL_OUT); } @@ -3977,7 +3977,7 @@ sk->shutdown |= SEND_SHUTDOWN; dst_confirm(sk->dst_cache); - if (!sk->dead) { + if (!test_bit(SOCK_DEAD, &sk->flags)) { /* Wake up lingering close() */ sk->state_change(sk); } else { diff -Nru a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c --- a/net/ipv4/tcp_minisocks.c Fri Mar 7 20:40:17 2003 +++ b/net/ipv4/tcp_minisocks.c Fri Mar 7 20:40:17 2003 @@ -676,7 +676,7 @@ newsk->wmem_queued = 0; newsk->forward_alloc = 0; - newsk->done = 0; + __clear_bit(SOCK_DONE, &newsk->flags); newsk->userlocks = sk->userlocks & ~SOCK_BINDPORT_LOCK; newsk->backlog.head = newsk->backlog.tail = NULL; newsk->callback_lock = RW_LOCK_UNLOCKED; @@ -761,7 +761,7 @@ #endif atomic_inc(&tcp_sockets_allocated); - if (newsk->keepopen) + if (test_bit(SOCK_KEEPOPEN, &newsk->flags)) tcp_reset_keepalive_timer(newsk, keepalive_time_when(newtp)); newsk->socket = NULL; newsk->sleep = NULL; diff -Nru a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c --- a/net/ipv4/tcp_output.c Fri Mar 7 20:40:17 2003 +++ b/net/ipv4/tcp_output.c Fri Mar 7 20:40:17 2003 @@ -1276,7 +1276,7 @@ tp->rcv_ssthresh = tp->rcv_wnd; sk->err = 0; - sk->done = 0; + __clear_bit(SOCK_DONE, &sk->flags); tp->snd_wnd = 0; tcp_init_wl(tp, tp->write_seq, 0); tp->snd_una = tp->write_seq; diff -Nru a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c --- a/net/ipv4/tcp_timer.c Fri Mar 7 20:40:18 2003 +++ b/net/ipv4/tcp_timer.c Fri Mar 7 20:40:18 2003 @@ -189,7 +189,7 @@ } retry_until = sysctl_tcp_retries2; - if (sk->dead) { + if (test_bit(SOCK_DEAD, &sk->flags)) { int alive = (tp->rto < TCP_RTO_MAX); retry_until = tcp_orphan_retries(sk, alive); @@ -297,7 +297,7 @@ */ max_probes = sysctl_tcp_retries2; - if (sk->dead) { + if (test_bit(SOCK_DEAD, &sk->flags)) { int alive = ((tp->rto<backoff) < TCP_RTO_MAX); max_probes = tcp_orphan_retries(sk, alive); @@ -327,7 +327,7 @@ BUG_TRAP(!skb_queue_empty(&sk->write_queue)); - if (tp->snd_wnd == 0 && !sk->dead && + if (tp->snd_wnd == 0 && !test_bit(SOCK_DEAD, &sk->flags) && !((1<state)&(TCPF_SYN_SENT|TCPF_SYN_RECV))) { /* Receiver dastardly shrinks window. Our retransmits * become zero probes, but we should not timeout this @@ -571,7 +571,7 @@ if ((1<state)&(TCPF_CLOSE|TCPF_LISTEN)) return; - if (val && !sk->keepopen) + if (val && !test_bit(SOCK_KEEPOPEN, &sk->flags)) tcp_reset_keepalive_timer(sk, keepalive_time_when(tcp_sk(sk))); else if (!val) tcp_delete_keepalive_timer(sk); @@ -597,7 +597,7 @@ goto out; } - if (sk->state == TCP_FIN_WAIT2 && sk->dead) { + if (sk->state == TCP_FIN_WAIT2 && test_bit(SOCK_DEAD, &sk->flags)) { if (tp->linger2 >= 0) { int tmo = tcp_fin_time(tp) - TCP_TIMEWAIT_LEN; @@ -610,7 +610,7 @@ goto death; } - if (!sk->keepopen || sk->state == TCP_CLOSE) + if (!test_bit(SOCK_KEEPOPEN, &sk->flags) || sk->state == TCP_CLOSE) goto out; elapsed = keepalive_time_when(tp); diff -Nru a/net/ipv4/udp.c b/net/ipv4/udp.c --- a/net/ipv4/udp.c Fri Mar 7 20:40:16 2003 +++ b/net/ipv4/udp.c Fri Mar 7 20:40:16 2003 @@ -606,7 +606,8 @@ goto out; err = -EACCES; - if (rt->rt_flags&RTCF_BROADCAST && !sk->broadcast) + if (rt->rt_flags&RTCF_BROADCAST && + !test_bit(SOCK_BROADCAST, &sk->flags)) goto out; if (connected) sk_dst_set(sk, dst_clone(&rt->u.dst)); @@ -887,7 +888,8 @@ inet->sport, usin->sin_port, sk); if (err) return err; - if ((rt->rt_flags&RTCF_BROADCAST) && !sk->broadcast) { + if ((rt->rt_flags&RTCF_BROADCAST) && + !test_bit(SOCK_BROADCAST, &sk->flags)) { ip_rt_put(rt); return -EACCES; } diff -Nru a/net/ipv4/xfrm_algo.c b/net/ipv4/xfrm_algo.c --- a/net/ipv4/xfrm_algo.c Fri Mar 7 20:40:16 2003 +++ b/net/ipv4/xfrm_algo.c Fri Mar 7 20:40:16 2003 @@ -8,9 +8,17 @@ * Software Foundation; either version 2 of the License, or (at your option) * any later version. */ +#include #include #include #include +#if defined(CONFIG_INET_AH) || defined(CONFIG_INET_AH_MODULE) || defined(CONFIG_INET6_AH) || defined(CONFIG_INET6_AH_MODULE) +#include +#endif +#if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE) +#include +#endif +#include /* * Algorithms supported by IPsec. These entries contain properties which @@ -348,3 +356,333 @@ n++; return n; } + +#if defined(CONFIG_INET_AH) || defined(CONFIG_INET_AH_MODULE) || defined(CONFIG_INET6_AH) || defined(CONFIG_INET6_AH_MODULE) +void skb_ah_walk(const struct sk_buff *skb, + struct crypto_tfm *tfm, icv_update_fn_t icv_update) +{ + int offset = 0; + int len = skb->len; + int start = skb->len - skb->data_len; + int i, copy = start - offset; + struct scatterlist sg; + + /* Checksum header. */ + if (copy > 0) { + if (copy > len) + copy = len; + + sg.page = virt_to_page(skb->data + offset); + sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; + sg.length = copy; + + icv_update(tfm, &sg, 1); + + if ((len -= copy) == 0) + return; + offset += copy; + } + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + int end; + + BUG_TRAP(start <= offset + len); + + end = start + skb_shinfo(skb)->frags[i].size; + if ((copy = end - offset) > 0) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + if (copy > len) + copy = len; + + sg.page = frag->page; + sg.offset = frag->page_offset + offset-start; + sg.length = copy; + + icv_update(tfm, &sg, 1); + + if (!(len -= copy)) + return; + offset += copy; + } + start = end; + } + + if (skb_shinfo(skb)->frag_list) { + struct sk_buff *list = skb_shinfo(skb)->frag_list; + + for (; list; list = list->next) { + int end; + + BUG_TRAP(start <= offset + len); + + end = start + list->len; + if ((copy = end - offset) > 0) { + if (copy > len) + copy = len; + skb_ah_walk(list, tfm, icv_update); + if ((len -= copy) == 0) + return; + offset += copy; + } + start = end; + } + } + if (len) + BUG(); +} +#endif + +#if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE) +/* Move to common area: it is shared with AH. */ + +void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm, + int offset, int len, icv_update_fn_t icv_update) +{ + int start = skb->len - skb->data_len; + int i, copy = start - offset; + struct scatterlist sg; + + /* Checksum header. */ + if (copy > 0) { + if (copy > len) + copy = len; + + sg.page = virt_to_page(skb->data + offset); + sg.offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; + sg.length = copy; + + icv_update(tfm, &sg, 1); + + if ((len -= copy) == 0) + return; + offset += copy; + } + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + int end; + + BUG_TRAP(start <= offset + len); + + end = start + skb_shinfo(skb)->frags[i].size; + if ((copy = end - offset) > 0) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + if (copy > len) + copy = len; + + sg.page = frag->page; + sg.offset = frag->page_offset + offset-start; + sg.length = copy; + + icv_update(tfm, &sg, 1); + + if (!(len -= copy)) + return; + offset += copy; + } + start = end; + } + + if (skb_shinfo(skb)->frag_list) { + struct sk_buff *list = skb_shinfo(skb)->frag_list; + + for (; list; list = list->next) { + int end; + + BUG_TRAP(start <= offset + len); + + end = start + list->len; + if ((copy = end - offset) > 0) { + if (copy > len) + copy = len; + skb_icv_walk(list, tfm, offset-start, copy, icv_update); + if ((len -= copy) == 0) + return; + offset += copy; + } + start = end; + } + } + if (len) + BUG(); +} + + +/* Looking generic it is not used in another places. */ + +int +skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) +{ + int start = skb->len - skb->data_len; + int i, copy = start - offset; + int elt = 0; + + if (copy > 0) { + if (copy > len) + copy = len; + sg[elt].page = virt_to_page(skb->data + offset); + sg[elt].offset = (unsigned long)(skb->data + offset) % PAGE_SIZE; + sg[elt].length = copy; + elt++; + if ((len -= copy) == 0) + return elt; + offset += copy; + } + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + int end; + + BUG_TRAP(start <= offset + len); + + end = start + skb_shinfo(skb)->frags[i].size; + if ((copy = end - offset) > 0) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + if (copy > len) + copy = len; + sg[elt].page = frag->page; + sg[elt].offset = frag->page_offset+offset-start; + sg[elt].length = copy; + elt++; + if (!(len -= copy)) + return elt; + offset += copy; + } + start = end; + } + + if (skb_shinfo(skb)->frag_list) { + struct sk_buff *list = skb_shinfo(skb)->frag_list; + + for (; list; list = list->next) { + int end; + + BUG_TRAP(start <= offset + len); + + end = start + list->len; + if ((copy = end - offset) > 0) { + if (copy > len) + copy = len; + elt += skb_to_sgvec(list, sg+elt, offset - start, copy); + if ((len -= copy) == 0) + return elt; + offset += copy; + } + start = end; + } + } + if (len) + BUG(); + return elt; +} + +/* Check that skb data bits are writable. If they are not, copy data + * to newly created private area. If "tailbits" is given, make sure that + * tailbits bytes beyond current end of skb are writable. + * + * Returns amount of elements of scatterlist to load for subsequent + * transformations and pointer to writable trailer skb. + */ + +int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer) +{ + int copyflag; + int elt; + struct sk_buff *skb1, **skb_p; + + /* If skb is cloned or its head is paged, reallocate + * head pulling out all the pages (pages are considered not writable + * at the moment even if they are anonymous). + */ + if ((skb_cloned(skb) || skb_shinfo(skb)->nr_frags) && + __pskb_pull_tail(skb, skb_pagelen(skb)-skb_headlen(skb)) == NULL) + return -ENOMEM; + + /* Easy case. Most of packets will go this way. */ + if (!skb_shinfo(skb)->frag_list) { + /* A little of trouble, not enough of space for trailer. + * This should not happen, when stack is tuned to generate + * good frames. OK, on miss we reallocate and reserve even more + * space, 128 bytes is fair. */ + + if (skb_tailroom(skb) < tailbits && + pskb_expand_head(skb, 0, tailbits-skb_tailroom(skb)+128, GFP_ATOMIC)) + return -ENOMEM; + + /* Voila! */ + *trailer = skb; + return 1; + } + + /* Misery. We are in troubles, going to mincer fragments... */ + + elt = 1; + skb_p = &skb_shinfo(skb)->frag_list; + copyflag = 0; + + while ((skb1 = *skb_p) != NULL) { + int ntail = 0; + + /* The fragment is partially pulled by someone, + * this can happen on input. Copy it and everything + * after it. */ + + if (skb_shared(skb1)) + copyflag = 1; + + /* If the skb is the last, worry about trailer. */ + + if (skb1->next == NULL && tailbits) { + if (skb_shinfo(skb1)->nr_frags || + skb_shinfo(skb1)->frag_list || + skb_tailroom(skb1) < tailbits) + ntail = tailbits + 128; + } + + if (copyflag || + skb_cloned(skb1) || + ntail || + skb_shinfo(skb1)->nr_frags || + skb_shinfo(skb1)->frag_list) { + struct sk_buff *skb2; + + /* Fuck, we are miserable poor guys... */ + if (ntail == 0) + skb2 = skb_copy(skb1, GFP_ATOMIC); + else + skb2 = skb_copy_expand(skb1, + skb_headroom(skb1), + ntail, + GFP_ATOMIC); + if (unlikely(skb2 == NULL)) + return -ENOMEM; + + if (skb1->sk) + skb_set_owner_w(skb, skb1->sk); + + /* Looking around. Are we still alive? + * OK, link new skb, drop old one */ + + skb2->next = skb1->next; + *skb_p = skb2; + kfree_skb(skb1); + skb1 = skb2; + } + elt++; + *trailer = skb1; + skb_p = &skb1->next; + } + + return elt; +} + +void *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len) +{ + if (tail != skb) { + skb->data_len += len; + skb->len += len; + } + return skb_put(tail, len); +} +#endif diff -Nru a/net/ipv4/xfrm_input.c b/net/ipv4/xfrm_input.c --- a/net/ipv4/xfrm_input.c Fri Mar 7 20:40:16 2003 +++ b/net/ipv4/xfrm_input.c Fri Mar 7 20:40:16 2003 @@ -1,4 +1,14 @@ +/* Changes + * + * Mitsuru KANDA @USAGI : IPv6 Support + * Kazunori MIYAZAWA @USAGI : + * YOSHIFUJI Hideaki @USAGI : + * Kunihiro Ishiguro : + * + */ + #include +#include #include static kmem_cache_t *secpath_cachep; @@ -64,7 +74,7 @@ if (xfrm_nr == XFRM_MAX_DEPTH) goto drop; - x = xfrm_state_lookup(iph->daddr, spi, iph->protocol); + x = xfrm4_state_lookup(iph->daddr, spi, iph->protocol); if (x == NULL) goto drop; @@ -157,3 +167,288 @@ if (!secpath_cachep) panic("IP: failed to allocate secpath_cache\n"); } + +#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + +/* Fetch spi and seq frpm ipsec header */ + +static int xfrm6_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq) +{ + int offset, offset_seq; + + switch (nexthdr) { + case IPPROTO_AH: + offset = offsetof(struct ip_auth_hdr, spi); + offset_seq = offsetof(struct ip_auth_hdr, seq_no); + break; + case IPPROTO_ESP: + offset = offsetof(struct ip_esp_hdr, spi); + offset_seq = offsetof(struct ip_esp_hdr, seq_no); + break; + case IPPROTO_COMP: + if (!pskb_may_pull(skb, 4)) + return -EINVAL; + *spi = *(u16*)(skb->h.raw + 2); + *seq = 0; + return 0; + default: + return 1; + } + + if (!pskb_may_pull(skb, 16)) + return -EINVAL; + + *spi = *(u32*)(skb->h.raw + offset); + *seq = *(u32*)(skb->h.raw + offset_seq); + return 0; +} + +static int zero_out_mutable_opts(struct ipv6_opt_hdr *opthdr) +{ + u8 *opt = (u8 *)opthdr; + int len = ipv6_optlen(opthdr); + int off = 0; + int optlen = 0; + + off += 2; + len -= 2; + + while (len > 0) { + + switch (opt[off]) { + + case IPV6_TLV_PAD0: + optlen = 1; + break; + default: + if (len < 2) + goto bad; + optlen = opt[off+1]+2; + if (len < optlen) + goto bad; + if (opt[off] & 0x20) + memset(&opt[off+2], 0, opt[off+1]); + break; + } + + off += optlen; + len -= optlen; + } + if (len == 0) + return 1; + +bad: + return 0; +} + +int xfrm6_clear_mutable_options(struct sk_buff *skb, u16 *nh_offset, int dir) +{ + u16 offset = sizeof(struct ipv6hdr); + struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); + unsigned int packet_len = skb->tail - skb->nh.raw; + u8 nexthdr = skb->nh.ipv6h->nexthdr; + u8 nextnexthdr = 0; + + *nh_offset = ((unsigned char *)&skb->nh.ipv6h->nexthdr) - skb->nh.raw; + + while (offset + 1 <= packet_len) { + + switch (nexthdr) { + + case NEXTHDR_HOP: + *nh_offset = offset; + offset += ipv6_optlen(exthdr); + if (!zero_out_mutable_opts(exthdr)) { + if (net_ratelimit()) + printk(KERN_WARNING "overrun hopopts\n"); + return 0; + } + nexthdr = exthdr->nexthdr; + exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); + break; + + case NEXTHDR_ROUTING: + *nh_offset = offset; + offset += ipv6_optlen(exthdr); + ((struct ipv6_rt_hdr*)exthdr)->segments_left = 0; + nexthdr = exthdr->nexthdr; + exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); + break; + + case NEXTHDR_DEST: + *nh_offset = offset; + offset += ipv6_optlen(exthdr); + if (!zero_out_mutable_opts(exthdr)) { + if (net_ratelimit()) + printk(KERN_WARNING "overrun destopt\n"); + return 0; + } + nexthdr = exthdr->nexthdr; + exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); + break; + + case NEXTHDR_AUTH: + if (dir == XFRM_POLICY_OUT) { + memset(((struct ipv6_auth_hdr*)exthdr)->auth_data, 0, + (((struct ipv6_auth_hdr*)exthdr)->hdrlen - 1) << 2); + } + if (exthdr->nexthdr == NEXTHDR_DEST) { + offset += (((struct ipv6_auth_hdr*)exthdr)->hdrlen + 2) << 2; + exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); + nextnexthdr = exthdr->nexthdr; + if (!zero_out_mutable_opts(exthdr)) { + if (net_ratelimit()) + printk(KERN_WARNING "overrun destopt\n"); + return 0; + } + } + return nexthdr; + default : + return nexthdr; + } + } + + return nexthdr; +} + +int xfrm6_rcv(struct sk_buff *skb) +{ + int err; + u32 spi, seq; + struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH]; + struct xfrm_state *x; + int xfrm_nr = 0; + int decaps = 0; + struct ipv6hdr *hdr = skb->nh.ipv6h; + unsigned char *tmp_hdr = NULL; + int hdr_len = 0; + u16 nh_offset = 0; + u8 nexthdr = 0; + + if (hdr->nexthdr == IPPROTO_AH || hdr->nexthdr == IPPROTO_ESP) { + nh_offset = ((unsigned char*)&skb->nh.ipv6h->nexthdr) - skb->nh.raw; + hdr_len = sizeof(struct ipv6hdr); + } else { + hdr_len = skb->h.raw - skb->nh.raw; + } + + tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC); + if (!tmp_hdr) + goto drop; + memcpy(tmp_hdr, skb->nh.raw, hdr_len); + + nexthdr = xfrm6_clear_mutable_options(skb, &nh_offset, XFRM_POLICY_IN); + hdr->priority = 0; + hdr->flow_lbl[0] = 0; + hdr->flow_lbl[1] = 0; + hdr->flow_lbl[2] = 0; + hdr->hop_limit = 0; + + if ((err = xfrm6_parse_spi(skb, nexthdr, &spi, &seq)) != 0) + goto drop; + + do { + struct ipv6hdr *iph = skb->nh.ipv6h; + + if (xfrm_nr == XFRM_MAX_DEPTH) + goto drop; + + x = xfrm6_state_lookup(&iph->daddr, spi, nexthdr); + if (x == NULL) + goto drop; + spin_lock(&x->lock); + if (unlikely(x->km.state != XFRM_STATE_VALID)) + goto drop_unlock; + + if (x->props.replay_window && xfrm_replay_check(x, seq)) + goto drop_unlock; + + nexthdr = x->type->input(x, skb); + if (nexthdr <= 0) + goto drop_unlock; + + if (x->props.replay_window) + xfrm_replay_advance(x, seq); + + x->curlft.bytes += skb->len; + x->curlft.packets++; + + spin_unlock(&x->lock); + + xfrm_vec[xfrm_nr++] = x; + + iph = skb->nh.ipv6h; /* ??? */ + + if (nexthdr == NEXTHDR_DEST) { + if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+8) || + !pskb_may_pull(skb, (skb->h.raw-skb->data)+((skb->h.raw[1]+1)<<3))) { + err = -EINVAL; + goto drop; + } + nexthdr = skb->h.raw[0]; + nh_offset = skb->h.raw - skb->nh.raw; + skb_pull(skb, (skb->h.raw[1]+1)<<3); + skb->h.raw = skb->data; + } + + if (x->props.mode) { /* XXX */ + if (iph->nexthdr != IPPROTO_IPV6) + goto drop; + skb->nh.raw = skb->data; + iph = skb->nh.ipv6h; + decaps = 1; + break; + } + + if ((err = xfrm6_parse_spi(skb, nexthdr, &spi, &seq)) < 0) + goto drop; + } while (!err); + + memcpy(skb->nh.raw, tmp_hdr, hdr_len); + skb->nh.raw[nh_offset] = nexthdr; + skb->nh.ipv6h->payload_len = htons(hdr_len + skb->len - sizeof(struct ipv6hdr)); + + /* Allocate new secpath or COW existing one. */ + if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) { + struct sec_path *sp; + sp = kmem_cache_alloc(secpath_cachep, SLAB_ATOMIC); + if (!sp) + goto drop; + if (skb->sp) { + memcpy(sp, skb->sp, sizeof(struct sec_path)); + secpath_put(skb->sp); + } else + sp->len = 0; + atomic_set(&sp->refcnt, 1); + skb->sp = sp; + } + + if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH) + goto drop; + + memcpy(skb->sp->xvec+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(void*)); + skb->sp->len += xfrm_nr; + + if (decaps) { + if (!(skb->dev->flags&IFF_LOOPBACK)) { + dst_release(skb->dst); + skb->dst = NULL; + } + netif_rx(skb); + return 0; + } else { + return -nexthdr; + } + +drop_unlock: + spin_unlock(&x->lock); + xfrm_state_put(x); +drop: + if (tmp_hdr) kfree(tmp_hdr); + while (--xfrm_nr >= 0) + xfrm_state_put(xfrm_vec[xfrm_nr]); + kfree_skb(skb); + return 0; +} + +#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */ diff -Nru a/net/ipv4/xfrm_policy.c b/net/ipv4/xfrm_policy.c --- a/net/ipv4/xfrm_policy.c Fri Mar 7 20:40:17 2003 +++ b/net/ipv4/xfrm_policy.c Fri Mar 7 20:40:17 2003 @@ -1,6 +1,16 @@ +/* Changes + * + * Mitsuru KANDA @USAGI : IPv6 Support + * Kazunori MIYAZAWA @USAGI : + * Kunihiro Ishiguro : + * + */ + #include #include #include +#include +#include DECLARE_MUTEX(xfrm_cfg_sem); @@ -10,6 +20,11 @@ struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2]; extern struct dst_ops xfrm4_dst_ops; +#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) +extern struct dst_ops xfrm6_dst_ops; +#endif + +static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family); /* Limited flow cache. Its function now is to accelerate search for * policy rules. @@ -48,6 +63,24 @@ return hash & (FLOWCACHE_HASH_SIZE-1); } +#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) +static inline u32 flow_hash6(struct flowi *fl) +{ + u32 hash = fl->fl6_src->s6_addr32[2] ^ + fl->fl6_src->s6_addr32[3] ^ + fl->uli_u.ports.sport; + + hash = ((hash & 0xF0F0F0F0) >> 4) | ((hash & 0x0F0F0F0F) << 4); + + hash ^= fl->fl6_dst->s6_addr32[2] ^ + fl->fl6_dst->s6_addr32[3] ^ + fl->uli_u.ports.dport; + hash ^= (hash >> 10); + hash ^= (hash >> 20); + return hash & (FLOWCACHE_HASH_SIZE-1); +} +#endif + static int flow_lwm = 2*FLOWCACHE_HASH_SIZE; static int flow_hwm = 4*FLOWCACHE_HASH_SIZE; @@ -77,13 +110,27 @@ } } -struct xfrm_policy *flow_lookup(int dir, struct flowi *fl) +struct xfrm_policy *flow_lookup(int dir, struct flowi *fl, + unsigned short family) { - struct xfrm_policy *pol; + struct xfrm_policy *pol = NULL; struct flow_entry *fle; - u32 hash = flow_hash(fl); + u32 hash; int cpu; + switch (family) { + case AF_INET: + hash = flow_hash(fl); + break; +#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + case AF_INET6: + hash = flow_hash6(fl); + break; +#endif + default: + return NULL; + } + local_bh_disable(); cpu = smp_processor_id(); @@ -101,7 +148,7 @@ } } - pol = xfrm_policy_lookup(dir, fl); + pol = xfrm_policy_lookup(dir, fl, family); if (fle) { /* Stale flow entry found. Update it. */ @@ -199,6 +246,46 @@ return type; } +static xfrm_dst_lookup_t *__xfrm_dst_lookup[AF_MAX]; +rwlock_t xdl_lock = RW_LOCK_UNLOCKED; + +int xfrm_dst_lookup_register(xfrm_dst_lookup_t *dst_lookup, + unsigned short family) +{ + int err = 0; + + write_lock(&xdl_lock); + if (__xfrm_dst_lookup[family]) + err = -ENOBUFS; + else { + __xfrm_dst_lookup[family] = dst_lookup; + } + write_unlock(&xdl_lock); + + return err; +} + +void xfrm_dst_lookup_unregister(unsigned short family) +{ + write_lock(&xdl_lock); + if (__xfrm_dst_lookup[family]) + __xfrm_dst_lookup[family] = 0; + write_unlock(&xdl_lock); +} + +static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, + unsigned short family) +{ + int err = 0; + read_lock(&xdl_lock); + if (__xfrm_dst_lookup[family]) + err = __xfrm_dst_lookup[family](dst, fl); + else + err = -EINVAL; + read_unlock(&xdl_lock); + return err; +} + #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) static struct xfrm_type *xfrm6_type_map[256]; static rwlock_t xfrm6_type_lock = RW_LOCK_UNLOCKED; @@ -506,15 +593,32 @@ /* Find policy to apply to this flow. */ -struct xfrm_policy *xfrm_policy_lookup(int dir, struct flowi *fl) +struct xfrm_policy *xfrm_policy_lookup(int dir, struct flowi *fl, + unsigned short family) { struct xfrm_policy *pol; read_lock_bh(&xfrm_policy_lock); for (pol = xfrm_policy_list[dir]; pol; pol = pol->next) { struct xfrm_selector *sel = &pol->selector; + int match; + + if (pol->family != family) + continue; - if (xfrm4_selector_match(sel, fl)) { + switch (family) { + case AF_INET: + match = xfrm4_selector_match(sel, fl); + break; +#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + case AF_INET6: + match = xfrm6_selector_match(sel, fl); + break; +#endif + default: + match = 0; + } + if (match) { atomic_inc(&pol->refcnt); break; } @@ -529,7 +633,21 @@ read_lock_bh(&xfrm_policy_lock); if ((pol = sk->policy[dir]) != NULL) { - if (xfrm4_selector_match(&pol->selector, fl)) + int match; + + switch (sk->family) { + case AF_INET: + match = xfrm4_selector_match(&pol->selector, fl); + break; +#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + case AF_INET6: + match = xfrm6_selector_match(&pol->selector, fl); + break; +#endif + default: + match = 0; + } + if (match) atomic_inc(&pol->refcnt); else pol = NULL; @@ -630,8 +748,8 @@ /* Resolve list of templates for the flow, given policy. */ static int -xfrm_tmpl_resolve(struct xfrm_policy *policy, struct flowi *fl, - struct xfrm_state **xfrm) +xfrm4_tmpl_resolve(struct xfrm_policy *policy, struct flowi *fl, + struct xfrm_state **xfrm) { int nx; int i, error; @@ -649,7 +767,7 @@ local = tmpl->saddr.xfrm4_addr; } - x = xfrm_state_find(remote, local, fl, tmpl, policy, &error); + x = xfrm4_state_find(remote, local, fl, tmpl, policy, &error); if (x && x->km.state == XFRM_STATE_VALID) { xfrm[nx++] = x; @@ -674,6 +792,53 @@ return error; } +#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) +static int +xfrm6_tmpl_resolve(struct xfrm_policy *policy, struct flowi *fl, + struct xfrm_state **xfrm) +{ + int nx; + int i, error; + struct in6_addr *daddr = fl->fl6_dst; + struct in6_addr *saddr = fl->fl6_src; + + for (nx=0, i = 0; i < policy->xfrm_nr; i++) { + struct xfrm_state *x=NULL; + struct in6_addr *remote = daddr; + struct in6_addr *local = saddr; + struct xfrm_tmpl *tmpl = &policy->xfrm_vec[i]; + + if (tmpl->mode) { + remote = (struct in6_addr*)&tmpl->id.daddr; + local = (struct in6_addr*)&tmpl->saddr; + } + + x = xfrm6_state_find(remote, local, fl, tmpl, policy, &error); + + if (x && x->km.state == XFRM_STATE_VALID) { + xfrm[nx++] = x; + daddr = remote; + saddr = local; + continue; + } + if (x) { + error = (x->km.state == XFRM_STATE_ERROR ? + -EINVAL : -EAGAIN); + xfrm_state_put(x); + } + + if (!tmpl->optional) + goto fail; + } + return nx; + +fail: + for (nx--; nx>=0; nx--) + xfrm_state_put(xfrm[nx]); + return error; +} +#endif + /* Check that the bundle accepts the flow and its components are * still valid. */ @@ -694,6 +859,24 @@ return 0; } +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +static int xfrm6_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl) +{ + do { + if (xdst->u.dst.ops != &xfrm6_dst_ops) + return 1; + + if (!xfrm6_selector_match(&xdst->u.dst.xfrm->sel, fl)) + return 0; + if (xdst->u.dst.xfrm->km.state != XFRM_STATE_VALID || + xdst->u.dst.path->obsolete > 0) + return 0; + xdst = (struct xfrm_dst*)xdst->u.dst.child; + } while (xdst); + return 0; +} +#endif + /* Allocate chain of dst_entry's, attach known xfrm's, calculate * all the metrics... Shortly, bundle a bundle. @@ -728,7 +911,7 @@ else { dst_prev->child = dst1; dst1->flags |= DST_NOHASH; - dst_clone(dst1); + dst_hold(dst1); } dst_prev = dst1; if (xfrm[i]->props.mode) { @@ -744,11 +927,11 @@ .saddr = local } } }; - err = __ip_route_output_key(&rt, &fl_tunnel); + err = xfrm_dst_lookup((struct xfrm_dst**)&rt, &fl_tunnel, AF_INET); if (err) goto error; } else { - dst_clone(&rt->u.dst); + dst_hold(&rt->u.dst); } dst_prev->child = &rt->u.dst; for (dst_prev = dst; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) { @@ -791,6 +974,97 @@ return err; } +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +static int +xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int nx, + struct flowi *fl, struct dst_entry **dst_p) +{ + struct dst_entry *dst, *dst_prev; + struct rt6_info *rt0 = (struct rt6_info*)(*dst_p); + struct rt6_info *rt = rt0; + struct in6_addr *remote = fl->fl6_dst; + struct in6_addr *local = fl->fl6_src; + int i; + int err = 0; + int header_len = 0; + + dst = dst_prev = NULL; + + for (i = 0; i < nx; i++) { + struct dst_entry *dst1 = dst_alloc(&xfrm6_dst_ops); + + if (unlikely(dst1 == NULL)) { + err = -ENOBUFS; + goto error; + } + + dst1->xfrm = xfrm[i]; + if (!dst) + dst = dst1; + else { + dst_prev->child = dst1; + dst1->flags |= DST_NOHASH; + dst_clone(dst1); + } + dst_prev = dst1; + if (xfrm[i]->props.mode) { + remote = (struct in6_addr*)&xfrm[i]->id.daddr; + local = (struct in6_addr*)&xfrm[i]->props.saddr; + } + header_len += xfrm[i]->props.header_len; + } + + if (ipv6_addr_cmp(remote, fl->fl6_dst)) { + struct flowi fl_tunnel = { .nl_u = { .ip6_u = + { .daddr = remote, + .saddr = local } + } + }; + err = xfrm_dst_lookup((struct xfrm_dst**)&dst, &fl_tunnel, AF_INET6); + if (err) + goto error; + } else { + dst_clone(&rt->u.dst); + } + dst_prev->child = &rt->u.dst; + for (dst_prev = dst; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) { + struct xfrm_dst *x = (struct xfrm_dst*)dst_prev; + x->u.rt.fl = *fl; + + dst_prev->dev = rt->u.dst.dev; + if (rt->u.dst.dev) + dev_hold(rt->u.dst.dev); + dst_prev->obsolete = -1; + dst_prev->flags |= DST_HOST; + dst_prev->lastuse = jiffies; + dst_prev->header_len = header_len; + memcpy(&dst_prev->metrics, &rt->u.dst.metrics, sizeof(dst_prev->metrics)); + dst_prev->path = &rt->u.dst; + + /* Copy neighbout for reachability confirmation */ + dst_prev->neighbour = neigh_clone(rt->u.dst.neighbour); + dst_prev->input = rt->u.dst.input; + dst_prev->output = dst_prev->xfrm->type->output; + /* Sheit... I remember I did this right. Apparently, + * it was magically lost, so this code needs audit */ + x->u.rt6.rt6i_flags = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL); + x->u.rt6.rt6i_metric = rt0->rt6i_metric; + x->u.rt6.rt6i_node = rt0->rt6i_node; + x->u.rt6.rt6i_hoplimit = rt0->rt6i_hoplimit; + x->u.rt6.rt6i_gateway = rt0->rt6i_gateway; + memcpy(&x->u.rt6.rt6i_gateway, &rt0->rt6i_gateway, sizeof(x->u.rt6.rt6i_gateway)); + header_len -= x->u.dst.xfrm->props.header_len; + } + *dst_p = dst; + return 0; + +error: + if (dst) + dst_free(dst); + return err; +} +#endif + /* Main function: finds/creates a bundle for given flow. * * At the moment we eat a raw IP route. Mostly to speed up lookups @@ -806,9 +1080,7 @@ int nx = 0; int err; u32 genid; - - fl->oif = rt->u.dst.dev->ifindex; - fl->fl4_src = rt->rt_src; + u16 family = (*dst_p)->ops->family; restart: genid = xfrm_policy_genid; @@ -821,11 +1093,12 @@ if ((rt->u.dst.flags & DST_NOXFRM) || !xfrm_policy_list[XFRM_POLICY_OUT]) return 0; - policy = flow_lookup(XFRM_POLICY_OUT, fl); - if (!policy) - return 0; + policy = flow_lookup(XFRM_POLICY_OUT, fl, family); } + if (!policy) + return 0; + policy->curlft.use_time = (unsigned long)xtime.tv_sec; switch (policy->action) { @@ -846,23 +1119,48 @@ * LATER: help from flow cache. It is optional, this * is required only for output policy. */ - read_lock_bh(&policy->lock); - for (dst = policy->bundles; dst; dst = dst->next) { - struct xfrm_dst *xdst = (struct xfrm_dst*)dst; - if (xdst->u.rt.fl.fl4_dst == fl->fl4_dst && - xdst->u.rt.fl.fl4_src == fl->fl4_src && - xdst->u.rt.fl.oif == fl->oif && - xfrm_bundle_ok(xdst, fl)) { - dst_clone(dst); + if (family == AF_INET) { + fl->oif = rt->u.dst.dev->ifindex; + fl->fl4_src = rt->rt_src; + read_lock_bh(&policy->lock); + for (dst = policy->bundles; dst; dst = dst->next) { + struct xfrm_dst *xdst = (struct xfrm_dst*)dst; + if (xdst->u.rt.fl.fl4_dst == fl->fl4_dst && + xdst->u.rt.fl.fl4_src == fl->fl4_src && + xdst->u.rt.fl.oif == fl->oif && + xfrm_bundle_ok(xdst, fl)) { + dst_clone(dst); + break; + } + } + read_unlock_bh(&policy->lock); + if (dst) break; + nx = xfrm4_tmpl_resolve(policy, fl, xfrm); +#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + } else if (family == AF_INET6) { + read_lock_bh(&policy->lock); + for (dst = policy->bundles; dst; dst = dst->next) { + struct xfrm_dst *xdst = (struct xfrm_dst*)dst; + if (!ipv6_addr_cmp(&xdst->u.rt6.rt6i_dst.addr, fl->fl6_dst) && + !ipv6_addr_cmp(&xdst->u.rt6.rt6i_src.addr, fl->fl6_src) && + xfrm6_bundle_ok(xdst, fl)) { + dst_clone(dst); + break; + } } + read_unlock_bh(&policy->lock); + if (dst) + break; + nx = xfrm6_tmpl_resolve(policy, fl, xfrm); +#endif + } else { + return -EINVAL; } - read_unlock_bh(&policy->lock); if (dst) break; - nx = xfrm_tmpl_resolve(policy, fl, xfrm); if (unlikely(nx<0)) { err = nx; if (err == -EAGAIN) { @@ -873,7 +1171,18 @@ __set_task_state(tsk, TASK_INTERRUPTIBLE); add_wait_queue(&km_waitq, &wait); - err = xfrm_tmpl_resolve(policy, fl, xfrm); + switch (family) { + case AF_INET: + err = xfrm4_tmpl_resolve(policy, fl, xfrm); + break; +#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + case AF_INET6: + err = xfrm6_tmpl_resolve(policy, fl, xfrm); + break; +#endif + default: + err = -EINVAL; + } if (err == -EAGAIN) schedule(); __set_task_state(tsk, TASK_RUNNING); @@ -896,7 +1205,19 @@ } dst = &rt->u.dst; - err = xfrm_bundle_create(policy, xfrm, nx, fl, &dst); + switch (family) { + case AF_INET: + err = xfrm_bundle_create(policy, xfrm, nx, fl, &dst); + break; +#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + case AF_INET6: + err = xfrm6_bundle_create(policy, xfrm, nx, fl, &dst); + break; +#endif + default: + err = -EINVAL; + } + if (unlikely(err)) { int i; for (i=0; inext = policy->bundles; policy->bundles = dst; - dst_clone(dst); + dst_hold(dst); write_unlock_bh(&policy->lock); } *dst_p = dst; @@ -962,7 +1283,7 @@ } static void -_decode_session(struct sk_buff *skb, struct flowi *fl) +_decode_session4(struct sk_buff *skb, struct flowi *fl) { struct iphdr *iph = skb->nh.iph; u8 *xprth = skb->nh.raw + iph->ihl*4; @@ -1008,18 +1329,109 @@ fl->fl4_src = iph->saddr; } -int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb) +#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) +static inline int +xfrm6_state_ok(struct xfrm_tmpl *tmpl, struct xfrm_state *x) +{ + return x->id.proto == tmpl->id.proto && + (x->id.spi == tmpl->id.spi || !tmpl->id.spi) && + x->props.mode == tmpl->mode && + (tmpl->aalgos & (1<props.aalgo)) && + (!x->props.mode || !ipv6_addr_any((struct in6_addr*)&x->props.saddr) || + !ipv6_addr_cmp((struct in6_addr *)&tmpl->saddr, (struct in6_addr*)&x->props.saddr)); +} + +static inline int +xfrm6_policy_ok(struct xfrm_tmpl *tmpl, struct sec_path *sp, int idx) +{ + for (; idx < sp->len; idx++) { + if (xfrm6_state_ok(tmpl, sp->xvec[idx])) + return ++idx; + } + return -1; +} + +static inline void +_decode_session6(struct sk_buff *skb, struct flowi *fl) +{ + u16 offset = sizeof(struct ipv6hdr); + struct ipv6hdr *hdr = skb->nh.ipv6h; + struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); + u8 nexthdr = skb->nh.ipv6h->nexthdr; + + fl->fl6_dst = &hdr->daddr; + fl->fl6_src = &hdr->saddr; + + while (pskb_may_pull(skb, skb->nh.raw + offset + 1 - skb->data)) { + switch (nexthdr) { + case NEXTHDR_ROUTING: + case NEXTHDR_HOP: + case NEXTHDR_DEST: + offset += ipv6_optlen(exthdr); + nexthdr = exthdr->nexthdr; + exthdr = (struct ipv6_opt_hdr*)(skb->nh.raw + offset); + break; + + case IPPROTO_UDP: + case IPPROTO_TCP: + case IPPROTO_SCTP: + if (pskb_may_pull(skb, skb->nh.raw + offset + 4 - skb->data)) { + u16 *ports = (u16 *)exthdr; + + fl->uli_u.ports.sport = ports[0]; + fl->uli_u.ports.dport = ports[1]; + } + return; + + /* XXX Why are there these headers? */ + case IPPROTO_AH: + case IPPROTO_ESP: + default: + fl->uli_u.spi = 0; + return; + }; + } +} +#endif + +int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, + unsigned short family) { struct xfrm_policy *pol; struct flowi fl; - _decode_session(skb, &fl); + switch (family) { + case AF_INET: + _decode_session4(skb, &fl); + break; +#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + case AF_INET6: + _decode_session6(skb, &fl); + break; +#endif + default : + return 0; + } /* First, check used SA against their selectors. */ if (skb->sp) { int i; + for (i=skb->sp->len-1; i>=0; i--) { - if (!xfrm4_selector_match(&skb->sp->xvec[i]->sel, &fl)) + int match; + switch (family) { + case AF_INET: + match = xfrm4_selector_match(&skb->sp->xvec[i]->sel, &fl); + break; +#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + case AF_INET6: + match = xfrm6_selector_match(&skb->sp->xvec[i]->sel, &fl); + break; +#endif + default: + match = 0; + } + if (!match) return 0; } } @@ -1029,7 +1441,7 @@ pol = xfrm_sk_policy_lookup(sk, dir, &fl); if (!pol) - pol = flow_lookup(dir, &fl); + pol = flow_lookup(dir, &fl, family); if (!pol) return 1; @@ -1050,7 +1462,18 @@ * are implied between each two transformations. */ for (i = pol->xfrm_nr-1, k = 0; i >= 0; i--) { - k = xfrm_policy_ok(pol->xfrm_vec+i, sp, k); + switch (family) { + case AF_INET: + k = xfrm_policy_ok(pol->xfrm_vec+i, sp, k); + break; +#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + case AF_INET6: + k = xfrm6_policy_ok(pol->xfrm_vec+i, sp, k); + break; +#endif + default: + k = -1; + } if (k < 0) goto reject; } @@ -1064,18 +1487,29 @@ return 0; } -int __xfrm_route_forward(struct sk_buff *skb) +int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) { struct flowi fl; - _decode_session(skb, &fl); + switch (family) { + case AF_INET: + _decode_session4(skb, &fl); + break; +#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + case AF_INET6: + _decode_session6(skb, &fl); + break; +#endif + default: + return 0; + } return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0; } /* Optimize later using cookies and generation ids. */ -static struct dst_entry *xfrm4_dst_check(struct dst_entry *dst, u32 cookie) +static struct dst_entry *xfrm_dst_check(struct dst_entry *dst, u32 cookie) { struct dst_entry *child = dst; @@ -1091,19 +1525,19 @@ return dst; } -static void xfrm4_dst_destroy(struct dst_entry *dst) +static void xfrm_dst_destroy(struct dst_entry *dst) { xfrm_state_put(dst->xfrm); dst->xfrm = NULL; } -static void xfrm4_link_failure(struct sk_buff *skb) +static void xfrm_link_failure(struct sk_buff *skb) { /* Impossible. Such dst must be popped before reaches point of failure. */ return; } -static struct dst_entry *xfrm4_negative_advice(struct dst_entry *dst) +static struct dst_entry *xfrm_negative_advice(struct dst_entry *dst) { if (dst) { if (dst->obsolete) { @@ -1114,8 +1548,7 @@ return dst; } - -static int xfrm4_garbage_collect(void) +static void __xfrm_garbage_collect(void) { int i; struct xfrm_policy *pol; @@ -1145,10 +1578,22 @@ gc_list = dst->next; dst_free(dst); } +} +static inline int xfrm4_garbage_collect(void) +{ + __xfrm_garbage_collect(); return (atomic_read(&xfrm4_dst_ops.entries) > xfrm4_dst_ops.gc_thresh*2); } +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +static inline int xfrm6_garbage_collect(void) +{ + __xfrm_garbage_collect(); + return (atomic_read(&xfrm6_dst_ops.entries) > xfrm6_dst_ops.gc_thresh*2); +} +#endif + static int bundle_depends_on(struct dst_entry *dst, struct xfrm_state *x) { do { @@ -1192,7 +1637,7 @@ return 0; } - + static void xfrm4_update_pmtu(struct dst_entry *dst, u32 mtu) { struct dst_entry *path = dst->path; @@ -1203,6 +1648,18 @@ path->ops->update_pmtu(path, mtu); } +#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) +static void xfrm6_update_pmtu(struct dst_entry *dst, u32 mtu) +{ + struct dst_entry *path = dst->path; + + if (mtu >= 1280 && mtu < dst_pmtu(dst)) + return; + + path->ops->update_pmtu(path, mtu); +} +#endif + /* Well... that's _TASK_. We need to scan through transformation * list and figure out what mss tcp should generate in order to * final datagram fit to mtu. Mama mia... :-) @@ -1212,7 +1669,7 @@ * * Consider this function as something like dark humour. :-) */ -static int xfrm4_get_mss(struct dst_entry *dst, u32 mtu) +static int xfrm_get_mss(struct dst_entry *dst, u32 mtu) { int res = mtu - dst->header_len; @@ -1247,16 +1704,32 @@ .family = AF_INET, .protocol = __constant_htons(ETH_P_IP), .gc = xfrm4_garbage_collect, - .check = xfrm4_dst_check, - .destroy = xfrm4_dst_destroy, - .negative_advice = xfrm4_negative_advice, - .link_failure = xfrm4_link_failure, + .check = xfrm_dst_check, + .destroy = xfrm_dst_destroy, + .negative_advice = xfrm_negative_advice, + .link_failure = xfrm_link_failure, .update_pmtu = xfrm4_update_pmtu, - .get_mss = xfrm4_get_mss, + .get_mss = xfrm_get_mss, .gc_thresh = 1024, .entry_size = sizeof(struct xfrm_dst), }; +#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) +struct dst_ops xfrm6_dst_ops = { + .family = AF_INET6, + .protocol = __constant_htons(ETH_P_IPV6), + .gc = xfrm6_garbage_collect, + .check = xfrm_dst_check, + .destroy = xfrm_dst_destroy, + .negative_advice = xfrm_negative_advice, + .link_failure = xfrm_link_failure, + .update_pmtu = xfrm6_update_pmtu, + .get_mss = xfrm_get_mss, + .gc_thresh = 1024, + .entry_size = sizeof(struct xfrm_dst), +}; +#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */ + void __init xfrm_init(void) { xfrm4_dst_ops.kmem_cachep = kmem_cache_create("xfrm4_dst_cache", @@ -1267,8 +1740,12 @@ if (!xfrm4_dst_ops.kmem_cachep) panic("IP: failed to allocate xfrm4_dst_cache\n"); - flow_cache_init(); +#if defined (CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) + xfrm6_dst_ops.kmem_cachep = xfrm4_dst_ops.kmem_cachep; +#endif + flow_cache_init(); xfrm_state_init(); xfrm_input_init(); } + diff -Nru a/net/ipv4/xfrm_state.c b/net/ipv4/xfrm_state.c --- a/net/ipv4/xfrm_state.c Fri Mar 7 20:40:17 2003 +++ b/net/ipv4/xfrm_state.c Fri Mar 7 20:40:17 2003 @@ -1,3 +1,11 @@ +/* Changes + * + * Mitsuru KANDA @USAGI : IPv6 Support + * Kazunori MIYAZAWA @USAGI : + * Kunihiro Ishiguro : + * + */ + #include #include #include @@ -207,8 +215,8 @@ } struct xfrm_state * -xfrm_state_find(u32 daddr, u32 saddr, struct flowi *fl, struct xfrm_tmpl *tmpl, - struct xfrm_policy *pol, int *err) +xfrm4_state_find(u32 daddr, u32 saddr, struct flowi *fl, struct xfrm_tmpl *tmpl, + struct xfrm_policy *pol, int *err) { unsigned h = ntohl(daddr); struct xfrm_state *x; @@ -290,6 +298,7 @@ x->props.saddr.xfrm4_addr = saddr; x->props.mode = tmpl->mode; x->props.reqid = tmpl->reqid; + x->props.family = AF_INET; if (km_query(x, tmpl, pol) == 0) { x->km.state = XFRM_STATE_ACQ; @@ -318,14 +327,133 @@ return x; } +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +struct xfrm_state * +xfrm6_state_find(struct in6_addr *daddr, struct in6_addr *saddr, struct flowi *fl, struct xfrm_tmpl *tmpl, + struct xfrm_policy *pol, int *err) +{ + unsigned h = ntohl(daddr->s6_addr32[2]^daddr->s6_addr32[3]); + struct xfrm_state *x; + int acquire_in_progress = 0; + int error = 0; + struct xfrm_state *best = NULL; + + h = (h ^ (h>>16)) % XFRM_DST_HSIZE; + + spin_lock_bh(&xfrm_state_lock); + list_for_each_entry(x, xfrm_state_bydst+h, bydst) { + if (x->props.family == AF_INET6&& + !ipv6_addr_cmp(daddr, (struct in6_addr *)&x->id.daddr) && + x->props.reqid == tmpl->reqid && + (!ipv6_addr_cmp(saddr, (struct in6_addr *)&x->props.saddr)|| ipv6_addr_any(saddr)) && + tmpl->mode == x->props.mode && + tmpl->id.proto == x->id.proto) { + /* Resolution logic: + 1. There is a valid state with matching selector. + Done. + 2. Valid state with inappropriate selector. Skip. + + Entering area of "sysdeps". + + 3. If state is not valid, selector is temporary, + it selects only session which triggered + previous resolution. Key manager will do + something to install a state with proper + selector. + */ + if (x->km.state == XFRM_STATE_VALID) { + if (!xfrm6_selector_match(&x->sel, fl)) + continue; + if (!best || + best->km.dying > x->km.dying || + (best->km.dying == x->km.dying && + best->curlft.add_time < x->curlft.add_time)) + best = x; + } else if (x->km.state == XFRM_STATE_ACQ) { + acquire_in_progress = 1; + } else if (x->km.state == XFRM_STATE_ERROR || + x->km.state == XFRM_STATE_EXPIRED) { + if (xfrm6_selector_match(&x->sel, fl)) + error = 1; + } + } + } + + if (best) { + atomic_inc(&best->refcnt); + spin_unlock_bh(&xfrm_state_lock); + return best; + } + x = NULL; + if (!error && !acquire_in_progress && + ((x = xfrm_state_alloc()) != NULL)) { + /* Initialize temporary selector matching only + * to current session. */ + memcpy(&x->sel.daddr, fl->fl6_dst, sizeof(struct in6_addr)); + memcpy(&x->sel.saddr, fl->fl6_src, sizeof(struct in6_addr)); + x->sel.dport = fl->uli_u.ports.dport; + x->sel.dport_mask = ~0; + x->sel.sport = fl->uli_u.ports.sport; + x->sel.sport_mask = ~0; + x->sel.prefixlen_d = 128; + x->sel.prefixlen_s = 128; + x->sel.proto = fl->proto; + x->sel.ifindex = fl->oif; + x->id = tmpl->id; + if (ipv6_addr_any((struct in6_addr*)&x->id.daddr)) + memcpy(&x->id.daddr, daddr, sizeof(x->sel.daddr)); + memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr)); + if (ipv6_addr_any((struct in6_addr*)&x->props.saddr)) + memcpy(&x->props.saddr, &saddr, sizeof(x->sel.saddr)); + x->props.mode = tmpl->mode; + x->props.reqid = tmpl->reqid; + x->props.family = AF_INET6; + + if (km_query(x, tmpl, pol) == 0) { + x->km.state = XFRM_STATE_ACQ; + list_add_tail(&x->bydst, xfrm_state_bydst+h); + atomic_inc(&x->refcnt); + if (x->id.spi) { + struct in6_addr *addr = (struct in6_addr*)&x->id.daddr; + h = ntohl((addr->s6_addr32[2]^addr->s6_addr32[3])^x->id.spi^x->id.proto); + h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE; + list_add(&x->byspi, xfrm_state_byspi+h); + atomic_inc(&x->refcnt); + } + x->lft.hard_add_expires_seconds = ACQ_EXPIRES; + atomic_inc(&x->refcnt); + mod_timer(&x->timer, ACQ_EXPIRES*HZ); + } else { + x->km.state = XFRM_STATE_DEAD; + xfrm_state_put(x); + x = NULL; + error = 1; + } + } + spin_unlock_bh(&xfrm_state_lock); + if (!x) + *err = acquire_in_progress ? -EAGAIN : + (error ? -ESRCH : -ENOMEM); + return x; +} +#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */ + void xfrm_state_insert(struct xfrm_state *x) { unsigned h = 0; - if (x->props.family == AF_INET) + switch (x->props.family) { + case AF_INET: h = ntohl(x->id.daddr.xfrm4_addr); - else if (x->props.family == AF_INET6) + break; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + case AF_INET6: h = ntohl(x->id.daddr.a6[2]^x->id.daddr.a6[3]); + break; +#endif + default: + return; + } h = (h ^ (h>>16)) % XFRM_DST_HSIZE; @@ -384,7 +512,7 @@ } struct xfrm_state * -xfrm_state_lookup(u32 daddr, u32 spi, u8 proto) +xfrm4_state_lookup(u32 daddr, u32 spi, u8 proto) { unsigned h = ntohl(daddr^spi^proto); struct xfrm_state *x; @@ -406,6 +534,31 @@ return NULL; } +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +struct xfrm_state * +xfrm6_state_lookup(struct in6_addr *daddr, u32 spi, u8 proto) +{ + unsigned h = ntohl(daddr->s6_addr32[2]^daddr->s6_addr32[3]^spi^proto); + struct xfrm_state *x; + + h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE; + + spin_lock_bh(&xfrm_state_lock); + list_for_each_entry(x, xfrm_state_byspi+h, byspi) { + if (x->props.family == AF_INET6 && + spi == x->id.spi && + !ipv6_addr_cmp(daddr, (struct in6_addr *)x->id.daddr.a6) && + proto == x->id.proto) { + atomic_inc(&x->refcnt); + spin_unlock_bh(&xfrm_state_lock); + return x; + } + } + spin_unlock_bh(&xfrm_state_lock); + return NULL; +} +#endif + struct xfrm_state * xfrm_find_acq(u8 mode, u16 reqid, u8 proto, u32 daddr, u32 saddr, int create) { @@ -445,7 +598,59 @@ x0->km.state = XFRM_STATE_ACQ; x0->id.daddr.xfrm4_addr = daddr; x0->id.proto = proto; + x0->props.mode = mode; + x0->props.reqid = reqid; x0->props.family = AF_INET; + x0->lft.hard_add_expires_seconds = ACQ_EXPIRES; + atomic_inc(&x0->refcnt); + mod_timer(&x0->timer, jiffies + ACQ_EXPIRES*HZ); + atomic_inc(&x0->refcnt); + list_add_tail(&x0->bydst, xfrm_state_bydst+h); + wake_up(&km_waitq); + } + spin_unlock_bh(&xfrm_state_lock); + return x0; +} + +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +struct xfrm_state * +xfrm6_find_acq(u8 mode, u16 reqid, u8 proto, struct in6_addr *daddr, struct in6_addr *saddr, int create) +{ + struct xfrm_state *x, *x0; + unsigned h = ntohl(daddr->s6_addr32[2]^daddr->s6_addr32[3]); + + h = (h ^ (h>>16)) % XFRM_DST_HSIZE; + x0 = NULL; + + spin_lock_bh(&xfrm_state_lock); + list_for_each_entry(x, xfrm_state_bydst+h, bydst) { + if (x->props.family == AF_INET6 && + !ipv6_addr_cmp(daddr, (struct in6_addr *)x->id.daddr.a6) && + mode == x->props.mode && + proto == x->id.proto && + !ipv6_addr_cmp(saddr, (struct in6_addr *)x->props.saddr.a6) && + reqid == x->props.reqid && + x->km.state == XFRM_STATE_ACQ) { + if (!x0) + x0 = x; + if (x->id.spi) + continue; + x0 = x; + break; + } + } + if (x0) { + atomic_inc(&x0->refcnt); + } else if (create && (x0 = xfrm_state_alloc()) != NULL) { + memcpy(x0->sel.daddr.a6, daddr, sizeof(struct in6_addr)); + memcpy(x0->sel.saddr.a6, saddr, sizeof(struct in6_addr)); + x0->sel.prefixlen_d = 128; + x0->sel.prefixlen_s = 128; + memcpy(x0->props.saddr.a6, saddr, sizeof(struct in6_addr)); + x0->km.state = XFRM_STATE_ACQ; + memcpy(x0->id.daddr.a6, daddr, sizeof(struct in6_addr)); + x0->id.proto = proto; + x0->props.family = AF_INET6; x0->props.mode = mode; x0->props.reqid = reqid; x0->lft.hard_add_expires_seconds = ACQ_EXPIRES; @@ -458,6 +663,7 @@ spin_unlock_bh(&xfrm_state_lock); return x0; } +#endif /* Silly enough, but I'm lazy to build resolution list */ @@ -491,7 +697,18 @@ return; if (minspi == maxspi) { - x0 = xfrm_state_lookup(x->id.daddr.xfrm4_addr, minspi, x->id.proto); + switch(x->props.family) { + case AF_INET: + x0 = xfrm4_state_lookup(x->id.daddr.xfrm4_addr, minspi, x->id.proto); + break; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + case AF_INET6: + x0 = xfrm6_state_lookup((struct in6_addr*)x->id.daddr.a6, minspi, x->id.proto); + break; +#endif + default: + x0 = NULL; + } if (x0) { xfrm_state_put(x0); return; @@ -503,7 +720,18 @@ maxspi = ntohl(maxspi); for (h=0; hid.daddr.xfrm4_addr, htonl(spi), x->id.proto); + switch(x->props.family) { + case AF_INET: + x0 = xfrm4_state_lookup(x->id.daddr.xfrm4_addr, minspi, x->id.proto); + break; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + case AF_INET6: + x0 = xfrm6_state_lookup((struct in6_addr*)x->id.daddr.a6, minspi, x->id.proto); + break; +#endif + default: + x0 = NULL; + } if (x0 == NULL) break; xfrm_state_put(x0); @@ -512,7 +740,18 @@ } if (x->id.spi) { spin_lock_bh(&xfrm_state_lock); - h = ntohl(x->id.daddr.xfrm4_addr^x->id.spi^x->id.proto); + switch(x->props.family) { + case AF_INET: + h = ntohl(x->id.daddr.xfrm4_addr^x->id.spi^x->id.proto); + break; +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + case AF_INET6: + h = ntohl(x->id.daddr.a6[2]^x->id.daddr.a6[3]^x->id.spi^x->id.proto); + break; +#endif + default: + h = 0; /* XXX */ + } h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE; list_add(&x->byspi, xfrm_state_byspi+h); atomic_inc(&x->refcnt); @@ -605,14 +844,21 @@ int i; for (i=0; iprops.family == AF_INET && - !xfrm4_selector_match(&x[i]->sel, fl)) - return -EINVAL; + int match; + switch(x[i]->props.family) { + case AF_INET: + match = xfrm4_selector_match(&x[i]->sel, fl); + break; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) - if (x[i]->props.family == AF_INET6 && - !xfrm6_selector_match(&x[i]->sel, fl)) - return -EINVAL; + case AF_INET6: + match = xfrm6_selector_match(&x[i]->sel, fl); + break; #endif + default: + match = 0; + } + if (!match) + return -EINVAL; } return 0; } @@ -680,7 +926,7 @@ err = -EINVAL; read_lock(&xfrm_km_lock); list_for_each_entry(km, &xfrm_km_list, list) { - pol = km->compile_policy(optname, data, optlen, &err); + pol = km->compile_policy(sk->family, optname, data, optlen, &err); if (err >= 0) break; } @@ -722,118 +968,3 @@ } } -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -struct xfrm_state * -xfrm6_state_lookup(struct in6_addr *daddr, u32 spi, u8 proto) -{ - unsigned h = ntohl(daddr->s6_addr32[2]^daddr->s6_addr32[3]^spi^proto); - struct xfrm_state *x; - - h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE; - - spin_lock_bh(&xfrm_state_lock); - list_for_each_entry(x, xfrm_state_byspi+h, byspi) { - if (x->props.family == AF_INET6 && - spi == x->id.spi && - !ipv6_addr_cmp(daddr, (struct in6_addr *)x->id.daddr.a6) && - proto == x->id.proto) { - atomic_inc(&x->refcnt); - spin_unlock_bh(&xfrm_state_lock); - return x; - } - } - spin_unlock_bh(&xfrm_state_lock); - return NULL; -} - -struct xfrm_state * -xfrm6_find_acq(u8 mode, u16 reqid, u8 proto, struct in6_addr *daddr, struct in6_addr *saddr, int create) -{ - struct xfrm_state *x, *x0; - unsigned h = ntohl(daddr->s6_addr32[2]^daddr->s6_addr32[3]); - - h = (h ^ (h>>16)) % XFRM_DST_HSIZE; - x0 = NULL; - - spin_lock_bh(&xfrm_state_lock); - list_for_each_entry(x, xfrm_state_bydst+h, bydst) { - if (x->props.family == AF_INET6 && - !memcmp(daddr, x->id.daddr.a6, sizeof(struct in6_addr)) && - mode == x->props.mode && - proto == x->id.proto && - !memcmp(saddr, x->props.saddr.a6, sizeof(struct in6_addr)) && - reqid == x->props.reqid && - x->km.state == XFRM_STATE_ACQ) { - if (!x0) - x0 = x; - if (x->id.spi) - continue; - x0 = x; - break; - } - } - if (x0) { - atomic_inc(&x0->refcnt); - } else if (create && (x0 = xfrm_state_alloc()) != NULL) { - memcpy(x0->sel.daddr.a6, daddr, sizeof(struct in6_addr)); - memcpy(x0->sel.saddr.a6, saddr, sizeof(struct in6_addr)); - x0->sel.prefixlen_d = 128; - x0->sel.prefixlen_s = 128; - memcpy(x0->props.saddr.a6, saddr, sizeof(struct in6_addr)); - x0->km.state = XFRM_STATE_ACQ; - memcpy(x0->id.daddr.a6, daddr, sizeof(struct in6_addr)); - x0->id.proto = proto; - x0->props.family = AF_INET6; - x0->props.mode = mode; - x0->props.reqid = reqid; - x0->lft.hard_add_expires_seconds = ACQ_EXPIRES; - atomic_inc(&x0->refcnt); - mod_timer(&x0->timer, jiffies + ACQ_EXPIRES*HZ); - atomic_inc(&x0->refcnt); - list_add_tail(&x0->bydst, xfrm_state_bydst+h); - wake_up(&km_waitq); - } - spin_unlock_bh(&xfrm_state_lock); - return x0; -} - -void -xfrm6_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi) -{ - u32 h; - struct xfrm_state *x0; - - if (x->id.spi) - return; - - if (minspi == maxspi) { - x0 = xfrm6_state_lookup((struct in6_addr*)x->id.daddr.a6, minspi, x->id.proto); - if (x0) { - xfrm_state_put(x0); - return; - } - x->id.spi = minspi; - } else { - u32 spi = 0; - minspi = ntohl(minspi); - maxspi = ntohl(maxspi); - for (h=0; hid.daddr.a6, htonl(spi), x->id.proto); - if (x0 == NULL) - break; - xfrm_state_put(x0); - } - x->id.spi = htonl(spi); - } - if (x->id.spi) { - spin_lock_bh(&xfrm_state_lock); - h = ntohl(x->id.daddr.a6[2]^x->id.daddr.a6[3]^x->id.spi^x->id.proto); - h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE; - list_add(&x->byspi, xfrm_state_byspi+h); - atomic_inc(&x->refcnt); - spin_unlock_bh(&xfrm_state_lock); - wake_up(&km_waitq); - } -} -#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */ diff -Nru a/net/ipv4/xfrm_user.c b/net/ipv4/xfrm_user.c --- a/net/ipv4/xfrm_user.c Fri Mar 7 20:40:17 2003 +++ b/net/ipv4/xfrm_user.c Fri Mar 7 20:40:17 2003 @@ -234,8 +234,8 @@ switch (x->props.family) { case AF_INET: - x1 = xfrm_state_lookup(x->props.saddr.xfrm4_addr, - x->id.spi, x->id.proto); + x1 = xfrm4_state_lookup(x->props.saddr.xfrm4_addr, + x->id.spi, x->id.proto); break; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: @@ -265,7 +265,7 @@ switch (p->family) { case AF_INET: - x = xfrm_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto); + x = xfrm4_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto); break; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: @@ -395,7 +395,7 @@ switch (p->family) { case AF_INET: - x = xfrm_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto); + x = xfrm4_state_lookup(p->saddr.xfrm4_addr, p->spi, p->proto); break; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: @@ -538,6 +538,21 @@ return -EINVAL; }; + switch (p->family) { + case AF_INET: + break; + + case AF_INET6: +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) + break; +#else + return -EAFNOSUPPORT; +#endif + + default: + return -EINVAL; + }; + return verify_policy_dir(p->dir); } @@ -1057,7 +1072,8 @@ /* User gives us xfrm_user_policy_info followed by an array of 0 * or more templates. */ -struct xfrm_policy *xfrm_compile_policy(int opt, u8 *data, int len, int *dir) +struct xfrm_policy *xfrm_compile_policy(u16 family, int opt, + u8 *data, int len, int *dir) { struct xfrm_userpolicy_info *p = (struct xfrm_userpolicy_info *)data; struct xfrm_user_tmpl *ut = (struct xfrm_user_tmpl *) (p + 1); diff -Nru a/net/ipv6/Kconfig b/net/ipv6/Kconfig --- a/net/ipv6/Kconfig Fri Mar 7 20:40:17 2003 +++ b/net/ipv6/Kconfig Fri Mar 7 20:40:17 2003 @@ -17,5 +17,20 @@ See for details. -source "net/ipv6/netfilter/Kconfig" +config INET6_AH + tristate "IPv6: AH transformation" + depends on IPV6 + ---help--- + Support for IPsec AH. + + If unsure, say Y. + +config INET6_ESP + tristate "IPv6: ESP transformation" + depends on IPV6 + ---help--- + Support for IPsec ESP. + If unsure, say Y. + +source "net/ipv6/netfilter/Kconfig" diff -Nru a/net/ipv6/Makefile b/net/ipv6/Makefile --- a/net/ipv6/Makefile Fri Mar 7 20:40:17 2003 +++ b/net/ipv6/Makefile Fri Mar 7 20:40:17 2003 @@ -10,4 +10,6 @@ exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \ ip6_flowlabel.o ipv6_syms.o +obj-$(CONFIG_INET6_AH) += ah6.o +obj-$(CONFIG_INET6_ESP) += esp6.o obj-$(CONFIG_NETFILTER) += netfilter/ diff -Nru a/net/ipv6/ah6.c b/net/ipv6/ah6.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/net/ipv6/ah6.c Fri Mar 7 20:40:18 2003 @@ -0,0 +1,362 @@ +/* + * Copyright (C)2002 USAGI/WIDE Project + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors + * + * Mitsuru KANDA @USAGI : IPv6 Support + * Kazunori MIYAZAWA @USAGI : + * Kunihiro Ishiguro : + * + * This file is derived from net/ipv4/ah.c. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AH_HLEN_NOICV 12 + +/* XXX no ipv6 ah specific */ +#define NIP6(addr) \ + ntohs((addr).s6_addr16[0]),\ + ntohs((addr).s6_addr16[1]),\ + ntohs((addr).s6_addr16[2]),\ + ntohs((addr).s6_addr16[3]),\ + ntohs((addr).s6_addr16[4]),\ + ntohs((addr).s6_addr16[5]),\ + ntohs((addr).s6_addr16[6]),\ + ntohs((addr).s6_addr16[7]) + +int ah6_output(struct sk_buff *skb) +{ + int err; + int hdr_len = sizeof(struct ipv6hdr); + struct dst_entry *dst = skb->dst; + struct xfrm_state *x = dst->xfrm; + struct ipv6hdr *iph = NULL; + struct ip_auth_hdr *ah; + struct ah_data *ahp; + u16 nh_offset = 0; + u8 nexthdr; +printk(KERN_DEBUG "%s\n", __FUNCTION__); + if (skb->ip_summed == CHECKSUM_HW && skb_checksum_help(skb) == NULL) + return -EINVAL; + + spin_lock_bh(&x->lock); + if ((err = xfrm_state_check_expire(x)) != 0) + goto error; + if ((err = xfrm_state_check_space(x, skb)) != 0) + goto error; + + if (x->props.mode) { + iph = skb->nh.ipv6h; + skb->nh.ipv6h = (struct ipv6hdr*)skb_push(skb, x->props.header_len); + skb->nh.ipv6h->version = 6; + skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); + skb->nh.ipv6h->nexthdr = IPPROTO_AH; + memcpy(&skb->nh.ipv6h->saddr, &x->props.saddr, sizeof(struct in6_addr)); + memcpy(&skb->nh.ipv6h->daddr, &x->id.daddr, sizeof(struct in6_addr)); + ah = (struct ip_auth_hdr*)(skb->nh.ipv6h+1); + ah->nexthdr = IPPROTO_IPV6; + } else { + hdr_len = skb->h.raw - skb->nh.raw; + iph = kmalloc(hdr_len, GFP_ATOMIC); + if (!iph) { + err = -ENOMEM; + goto error; + } + memcpy(iph, skb->data, hdr_len); + skb->nh.ipv6h = (struct ipv6hdr*)skb_push(skb, x->props.header_len); + memcpy(skb->nh.ipv6h, iph, hdr_len); + nexthdr = xfrm6_clear_mutable_options(skb, &nh_offset, XFRM_POLICY_OUT); + if (nexthdr == 0) + goto error; + + skb->nh.raw[nh_offset] = IPPROTO_AH; + skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); + ah = (struct ip_auth_hdr*)(skb->nh.raw+hdr_len); + skb->h.raw = (unsigned char*) ah; + ah->nexthdr = nexthdr; + } + + skb->nh.ipv6h->priority = 0; + skb->nh.ipv6h->flow_lbl[0] = 0; + skb->nh.ipv6h->flow_lbl[1] = 0; + skb->nh.ipv6h->flow_lbl[2] = 0; + skb->nh.ipv6h->hop_limit = 0; + + ahp = x->data; + ah->hdrlen = (XFRM_ALIGN8(ahp->icv_trunc_len + + AH_HLEN_NOICV) >> 2) - 2; + + ah->reserved = 0; + ah->spi = x->id.spi; + ah->seq_no = htonl(++x->replay.oseq); + ahp->icv(ahp, skb, ah->auth_data); + + if (x->props.mode) { + skb->nh.ipv6h->hop_limit = iph->hop_limit; + skb->nh.ipv6h->priority = iph->priority; + skb->nh.ipv6h->flow_lbl[0] = iph->flow_lbl[0]; + skb->nh.ipv6h->flow_lbl[1] = iph->flow_lbl[1]; + skb->nh.ipv6h->flow_lbl[2] = iph->flow_lbl[2]; + } else { + memcpy(skb->nh.ipv6h, iph, hdr_len); + skb->nh.raw[nh_offset] = IPPROTO_AH; + skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); + kfree (iph); + } + + skb->nh.raw = skb->data; + + x->curlft.bytes += skb->len; + x->curlft.packets++; + spin_unlock_bh(&x->lock); + if ((skb->dst = dst_pop(dst)) == NULL) + goto error_nolock; + return NET_XMIT_BYPASS; +error: + spin_unlock_bh(&x->lock); +error_nolock: + kfree_skb(skb); + return err; +} + +int ah6_input(struct xfrm_state *x, struct sk_buff *skb) +{ + int ah_hlen; + struct ipv6hdr *iph; + struct ipv6_auth_hdr *ah; + struct ah_data *ahp; + unsigned char *tmp_hdr = NULL; + int hdr_len = skb->h.raw - skb->nh.raw; + u8 nexthdr = 0; + + if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr))) + goto out; + + ah = (struct ipv6_auth_hdr*)skb->data; + ahp = x->data; + ah_hlen = (ah->hdrlen + 2) << 2; + + if (ah_hlen != XFRM_ALIGN8(ahp->icv_full_len + AH_HLEN_NOICV) && + ah_hlen != XFRM_ALIGN8(ahp->icv_trunc_len + AH_HLEN_NOICV)) + goto out; + + if (!pskb_may_pull(skb, ah_hlen)) + goto out; + + /* We are going to _remove_ AH header to keep sockets happy, + * so... Later this can change. */ + if (skb_cloned(skb) && + pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) + goto out; + + tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC); + if (!tmp_hdr) + goto out; + memcpy(tmp_hdr, skb->nh.raw, hdr_len); + ah = (struct ipv6_auth_hdr*)skb->data; + iph = skb->nh.ipv6h; + + { + u8 auth_data[ahp->icv_trunc_len]; + + memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); + skb_push(skb, skb->data - skb->nh.raw); + ahp->icv(ahp, skb, ah->auth_data); + if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) { + if (net_ratelimit()) + printk(KERN_WARNING "ipsec ah authentication error\n"); + x->stats.integrity_failed++; + goto free_out; + } + } + + nexthdr = ah->nexthdr; + skb->nh.raw = skb_pull(skb, (ah->hdrlen+2)<<2); + memcpy(skb->nh.raw, tmp_hdr, hdr_len); + skb->nh.ipv6h->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); + skb_pull(skb, hdr_len); + skb->h.raw = skb->data; + + + kfree(tmp_hdr); + + return nexthdr; + +free_out: + kfree(tmp_hdr); +out: + return -EINVAL; +} + +void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + int type, int code, int offset, __u32 info) +{ + struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; + struct ip_auth_hdr *ah = (struct ip_auth_hdr*)(skb->data+offset); + struct xfrm_state *x; + + if (type != ICMPV6_DEST_UNREACH || + type != ICMPV6_PKT_TOOBIG) + return; + + x = xfrm6_state_lookup(&iph->daddr, ah->spi, IPPROTO_AH); + if (!x) + return; + + printk(KERN_DEBUG "pmtu discvovery on SA AH/%08x/" + "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + ntohl(ah->spi), NIP6(iph->daddr)); + + xfrm_state_put(x); +} + +static int ah6_init_state(struct xfrm_state *x, void *args) +{ + struct ah_data *ahp = NULL; + struct xfrm_algo_desc *aalg_desc; + + /* null auth can use a zero length key */ + if (x->aalg->alg_key_len > 512) + goto error; + + ahp = kmalloc(sizeof(*ahp), GFP_KERNEL); + if (ahp == NULL) + return -ENOMEM; + + memset(ahp, 0, sizeof(*ahp)); + + ahp->key = x->aalg->alg_key; + ahp->key_len = (x->aalg->alg_key_len+7)/8; + ahp->tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); + if (!ahp->tfm) + goto error; + ahp->icv = ah_hmac_digest; + + /* + * Lookup the algorithm description maintained by xfrm_algo, + * verify crypto transform properties, and store information + * we need for AH processing. This lookup cannot fail here + * after a successful crypto_alloc_tfm(). + */ + aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name); + BUG_ON(!aalg_desc); + + if (aalg_desc->uinfo.auth.icv_fullbits/8 != + crypto_tfm_alg_digestsize(ahp->tfm)) { + printk(KERN_INFO "AH: %s digestsize %u != %hu\n", + x->aalg->alg_name, crypto_tfm_alg_digestsize(ahp->tfm), + aalg_desc->uinfo.auth.icv_fullbits/8); + goto error; + } + + ahp->icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8; + ahp->icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8; + + ahp->work_icv = kmalloc(ahp->icv_full_len, GFP_KERNEL); + if (!ahp->work_icv) + goto error; + + x->props.header_len = XFRM_ALIGN8(ahp->icv_trunc_len + AH_HLEN_NOICV); + if (x->props.mode) + x->props.header_len += 20; + x->data = ahp; + + return 0; + +error: + if (ahp) { + if (ahp->work_icv) + kfree(ahp->work_icv); + if (ahp->tfm) + crypto_free_tfm(ahp->tfm); + kfree(ahp); + } + return -EINVAL; +} + +static void ah6_destroy(struct xfrm_state *x) +{ + struct ah_data *ahp = x->data; + + if (ahp->work_icv) { + kfree(ahp->work_icv); + ahp->work_icv = NULL; + } + if (ahp->tfm) { + crypto_free_tfm(ahp->tfm); + ahp->tfm = NULL; + } +} + +static struct xfrm_type ah6_type = +{ + .description = "AH6", + .proto = IPPROTO_AH, + .init_state = ah6_init_state, + .destructor = ah6_destroy, + .input = ah6_input, + .output = ah6_output +}; + +static struct inet6_protocol ah6_protocol = { + .handler = xfrm6_rcv, + .err_handler = ah6_err, +}; + +int __init ah6_init(void) +{ + SET_MODULE_OWNER(&ah6_type); + + if (xfrm6_register_type(&ah6_type) < 0) { + printk(KERN_INFO "ipv6 ah init: can't add xfrm type\n"); + return -EAGAIN; + } + + if (inet6_add_protocol(&ah6_protocol, IPPROTO_AH) < 0) { + printk(KERN_INFO "ipv6 ah init: can't add protocol\n"); + xfrm6_unregister_type(&ah6_type); + return -EAGAIN; + } + + return 0; +} + +static void __exit ah6_fini(void) +{ + if (inet6_del_protocol(&ah6_protocol, IPPROTO_AH) < 0) + printk(KERN_INFO "ipv6 ah close: can't remove protocol\n"); + + if (xfrm6_unregister_type(&ah6_type) < 0) + printk(KERN_INFO "ipv6 ah close: can't remove xfrm type\n"); + +} + +module_init(ah6_init); +module_exit(ah6_fini); + +MODULE_LICENSE("GPL"); diff -Nru a/net/ipv6/esp6.c b/net/ipv6/esp6.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/net/ipv6/esp6.c Fri Mar 7 20:40:18 2003 @@ -0,0 +1,527 @@ +/* + * Copyright (C)2002 USAGI/WIDE Project + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors + * + * Mitsuru KANDA @USAGI : IPv6 Support + * Kazunori MIYAZAWA @USAGI : + * Kunihiro Ishiguro : + * + * This file is derived from net/ipv4/esp.c + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_SG_ONSTACK 4 + +/* BUGS: + * - we assume replay seqno is always present. + */ + +/* Move to common area: it is shared with AH. */ +/* Common with AH after some work on arguments. */ + +/* XXX no ipv6 esp specific */ +#define NIP6(addr) \ + ntohs((addr).s6_addr16[0]),\ + ntohs((addr).s6_addr16[1]),\ + ntohs((addr).s6_addr16[2]),\ + ntohs((addr).s6_addr16[3]),\ + ntohs((addr).s6_addr16[4]),\ + ntohs((addr).s6_addr16[5]),\ + ntohs((addr).s6_addr16[6]),\ + ntohs((addr).s6_addr16[7]) + +static int get_offset(u8 *packet, u32 packet_len, u8 *nexthdr, struct ipv6_opt_hdr **prevhdr) +{ + u16 offset = sizeof(struct ipv6hdr); + struct ipv6_opt_hdr *exthdr = (struct ipv6_opt_hdr*)(packet + offset); + u8 nextnexthdr; + + *nexthdr = ((struct ipv6hdr*)packet)->nexthdr; + + while (offset + 1 < packet_len) { + + switch (*nexthdr) { + + case NEXTHDR_HOP: + case NEXTHDR_ROUTING: + offset += ipv6_optlen(exthdr); + *nexthdr = exthdr->nexthdr; + *prevhdr = exthdr; + exthdr = (struct ipv6_opt_hdr*)(packet + offset); + break; + + case NEXTHDR_DEST: + nextnexthdr = + ((struct ipv6_opt_hdr*)(packet + offset + ipv6_optlen(exthdr)))->nexthdr; + /* XXX We know the option is inner dest opt + with next next header check. */ + if (nextnexthdr != NEXTHDR_HOP && + nextnexthdr != NEXTHDR_ROUTING && + nextnexthdr != NEXTHDR_DEST) { + return offset; + } + offset += ipv6_optlen(exthdr); + *nexthdr = exthdr->nexthdr; + *prevhdr = exthdr; + exthdr = (struct ipv6_opt_hdr*)(packet + offset); + break; + + default : + return offset; + } + } + + return offset; +} + +int esp6_output(struct sk_buff *skb) +{ + int err; + int hdr_len = 0; + struct dst_entry *dst = skb->dst; + struct xfrm_state *x = dst->xfrm; + struct ipv6hdr *iph = NULL, *top_iph; + struct ip_esp_hdr *esph; + struct crypto_tfm *tfm; + struct esp_data *esp; + struct sk_buff *trailer; + struct ipv6_opt_hdr *prevhdr = NULL; + int blksize; + int clen; + int alen; + int nfrags; + u8 nexthdr; +printk(KERN_DEBUG "%s\n", __FUNCTION__); + /* First, if the skb is not checksummed, complete checksum. */ + if (skb->ip_summed == CHECKSUM_HW && skb_checksum_help(skb) == NULL) + return -EINVAL; + + spin_lock_bh(&x->lock); + if ((err = xfrm_state_check_expire(x)) != 0) + goto error; + if ((err = xfrm_state_check_space(x, skb)) != 0) + goto error; + + err = -ENOMEM; + + /* Strip IP header in transport mode. Save it. */ + + if (!x->props.mode) { + hdr_len = get_offset(skb->nh.raw, skb->len, &nexthdr, &prevhdr); + iph = kmalloc(hdr_len, GFP_ATOMIC); + if (!iph) { + err = -ENOMEM; + goto error; + } + memcpy(iph, skb->nh.raw, hdr_len); + __skb_pull(skb, hdr_len); + } + + /* Now skb is pure payload to encrypt */ + + /* Round to block size */ + clen = skb->len; + + esp = x->data; + alen = esp->auth.icv_trunc_len; + tfm = esp->conf.tfm; + blksize = crypto_tfm_alg_blocksize(tfm); + clen = (clen + 2 + blksize-1)&~(blksize-1); + if (esp->conf.padlen) + clen = (clen + esp->conf.padlen-1)&~(esp->conf.padlen-1); + + if ((nfrags = skb_cow_data(skb, clen-skb->len+alen, &trailer)) < 0) { + if (!x->props.mode && iph) kfree(iph); + goto error; + } + + /* Fill padding... */ + do { + int i; + for (i=0; ilen - 2; i++) + *(u8*)(trailer->tail + i) = i+1; + } while (0); + *(u8*)(trailer->tail + clen-skb->len - 2) = (clen - skb->len)-2; + pskb_put(skb, trailer, clen - skb->len); + + if (x->props.mode) { + iph = skb->nh.ipv6h; + top_iph = (struct ipv6hdr*)skb_push(skb, x->props.header_len); + esph = (struct ip_esp_hdr*)(top_iph+1); + *(u8*)(trailer->tail - 1) = IPPROTO_IPV6; + top_iph->version = 6; + top_iph->priority = iph->priority; + top_iph->flow_lbl[0] = iph->flow_lbl[0]; + top_iph->flow_lbl[1] = iph->flow_lbl[1]; + top_iph->flow_lbl[2] = iph->flow_lbl[2]; + top_iph->nexthdr = IPPROTO_ESP; + top_iph->payload_len = htons(skb->len + alen); + top_iph->hop_limit = iph->hop_limit; + memcpy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr, sizeof(struct ipv6hdr)); + memcpy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr, sizeof(struct ipv6hdr)); + } else { + /* XXX exthdr */ + esph = (struct ip_esp_hdr*)skb_push(skb, x->props.header_len); + skb->h.raw = (unsigned char*)esph; + top_iph = (struct ipv6hdr*)skb_push(skb, hdr_len); + memcpy(top_iph, iph, hdr_len); + kfree(iph); + top_iph->payload_len = htons(skb->len + alen - sizeof(struct ipv6hdr)); + if (prevhdr) { + prevhdr->nexthdr = IPPROTO_ESP; + } else { + top_iph->nexthdr = IPPROTO_ESP; + } + *(u8*)(trailer->tail - 1) = nexthdr; + } + + esph->spi = x->id.spi; + esph->seq_no = htonl(++x->replay.oseq); + + if (esp->conf.ivlen) + crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); + + do { + struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags]; + struct scatterlist *sg = sgbuf; + + if (unlikely(nfrags > MAX_SG_ONSTACK)) { + sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); + if (!sg) + goto error; + } + skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen); + crypto_cipher_encrypt(tfm, sg, sg, clen); + if (unlikely(sg != sgbuf)) + kfree(sg); + } while (0); + + if (esp->conf.ivlen) { + memcpy(esph->enc_data, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); + crypto_cipher_get_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); + } + + if (esp->auth.icv_full_len) { + esp->auth.icv(esp, skb, (u8*)esph-skb->data, + 8+esp->conf.ivlen+clen, trailer->tail); + pskb_put(skb, trailer, alen); + } + + skb->nh.raw = skb->data; + + x->curlft.bytes += skb->len; + x->curlft.packets++; + spin_unlock_bh(&x->lock); + if ((skb->dst = dst_pop(dst)) == NULL) + goto error_nolock; + return NET_XMIT_BYPASS; + +error: + spin_unlock_bh(&x->lock); +error_nolock: + kfree_skb(skb); + return err; +} + +int esp6_input(struct xfrm_state *x, struct sk_buff *skb) +{ + struct ipv6hdr *iph; + struct ip_esp_hdr *esph; + struct esp_data *esp = x->data; + struct sk_buff *trailer; + int blksize = crypto_tfm_alg_blocksize(esp->conf.tfm); + int alen = esp->auth.icv_trunc_len; + int elen = skb->len - 8 - esp->conf.ivlen - alen; + + int hdr_len = skb->h.raw - skb->nh.raw; + int nfrags; + u8 ret_nexthdr = 0; + unsigned char *tmp_hdr = NULL; + + if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr))) + goto out; + + if (elen <= 0 || (elen & (blksize-1))) + goto out; + + tmp_hdr = kmalloc(hdr_len, GFP_ATOMIC); + if (!tmp_hdr) + goto out; + memcpy(tmp_hdr, skb->nh.raw, hdr_len); + + /* If integrity check is required, do this. */ + if (esp->auth.icv_full_len) { + u8 sum[esp->auth.icv_full_len]; + u8 sum1[alen]; + + esp->auth.icv(esp, skb, 0, skb->len-alen, sum); + + if (skb_copy_bits(skb, skb->len-alen, sum1, alen)) + BUG(); + + if (unlikely(memcmp(sum, sum1, alen))) { + x->stats.integrity_failed++; + goto out; + } + } + + if ((nfrags = skb_cow_data(skb, 0, &trailer)) < 0) + goto out; + + skb->ip_summed = CHECKSUM_NONE; + + esph = (struct ip_esp_hdr*)skb->data; + iph = skb->nh.ipv6h; + + /* Get ivec. This can be wrong, check against another impls. */ + if (esp->conf.ivlen) + crypto_cipher_set_iv(esp->conf.tfm, esph->enc_data, crypto_tfm_alg_ivsize(esp->conf.tfm)); + + { + u8 nexthdr[2]; + struct scatterlist sgbuf[nfrags>MAX_SG_ONSTACK ? 0 : nfrags]; + struct scatterlist *sg = sgbuf; + u8 padlen; + + if (unlikely(nfrags > MAX_SG_ONSTACK)) { + sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); + if (!sg) + goto out; + } + skb_to_sgvec(skb, sg, 8+esp->conf.ivlen, elen); + crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen); + if (unlikely(sg != sgbuf)) + kfree(sg); + + if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) + BUG(); + + padlen = nexthdr[0]; + if (padlen+2 >= elen) { + if (net_ratelimit()) { + printk(KERN_WARNING "ipsec esp packet is garbage padlen=%d, elen=%d\n", padlen+2, elen); + } + goto out; + } + /* ... check padding bits here. Silly. :-) */ + + ret_nexthdr = nexthdr[1]; + pskb_trim(skb, skb->len - alen - padlen - 2); + skb->h.raw = skb_pull(skb, 8 + esp->conf.ivlen); + skb->nh.raw += 8 + esp->conf.ivlen; + memcpy(skb->nh.raw, tmp_hdr, hdr_len); + } + kfree(tmp_hdr); + return ret_nexthdr; + +out: + return -EINVAL; +} + +static u32 esp6_get_max_size(struct xfrm_state *x, int mtu) +{ + struct esp_data *esp = x->data; + u32 blksize = crypto_tfm_alg_blocksize(esp->conf.tfm); + + if (x->props.mode) { + mtu = (mtu + 2 + blksize-1)&~(blksize-1); + } else { + /* The worst case. */ + mtu += 2 + blksize; + } + if (esp->conf.padlen) + mtu = (mtu + esp->conf.padlen-1)&~(esp->conf.padlen-1); + + return mtu + x->props.header_len + esp->auth.icv_full_len; +} + +void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + int type, int code, int offset, __u32 info) +{ + struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; + struct ip_esp_hdr *esph = (struct ip_esp_hdr*)(skb->data+offset); + struct xfrm_state *x; + + if (type != ICMPV6_DEST_UNREACH || + type != ICMPV6_PKT_TOOBIG) + return; + + x = xfrm6_state_lookup(&iph->daddr, esph->spi, IPPROTO_ESP); + if (!x) + return; + printk(KERN_DEBUG "pmtu discvovery on SA ESP/%08x/" + "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", + ntohl(esph->spi), NIP6(iph->daddr)); + xfrm_state_put(x); +} + +void esp6_destroy(struct xfrm_state *x) +{ + struct esp_data *esp = x->data; + + if (esp->conf.tfm) { + crypto_free_tfm(esp->conf.tfm); + esp->conf.tfm = NULL; + } + if (esp->conf.ivec) { + kfree(esp->conf.ivec); + esp->conf.ivec = NULL; + } + if (esp->auth.tfm) { + crypto_free_tfm(esp->auth.tfm); + esp->auth.tfm = NULL; + } + if (esp->auth.work_icv) { + kfree(esp->auth.work_icv); + esp->auth.work_icv = NULL; + } +} + +int esp6_init_state(struct xfrm_state *x, void *args) +{ + struct esp_data *esp = NULL; + + if (x->aalg) { + if (x->aalg->alg_key_len == 0 || x->aalg->alg_key_len > 512) + goto error; + } + if (x->ealg == NULL || x->ealg->alg_key_len == 0) + goto error; + + esp = kmalloc(sizeof(*esp), GFP_KERNEL); + if (esp == NULL) + return -ENOMEM; + + memset(esp, 0, sizeof(*esp)); + + if (x->aalg) { + struct xfrm_algo_desc *aalg_desc; + + esp->auth.key = x->aalg->alg_key; + esp->auth.key_len = (x->aalg->alg_key_len+7)/8; + esp->auth.tfm = crypto_alloc_tfm(x->aalg->alg_name, 0); + if (esp->auth.tfm == NULL) + goto error; + esp->auth.icv = esp_hmac_digest; + + aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name); + BUG_ON(!aalg_desc); + + if (aalg_desc->uinfo.auth.icv_fullbits/8 != + crypto_tfm_alg_digestsize(esp->auth.tfm)) { + printk(KERN_INFO "ESP: %s digestsize %u != %hu\n", + x->aalg->alg_name, + crypto_tfm_alg_digestsize(esp->auth.tfm), + aalg_desc->uinfo.auth.icv_fullbits/8); + goto error; + } + + esp->auth.icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8; + esp->auth.icv_trunc_len = aalg_desc->uinfo.auth.icv_truncbits/8; + + esp->auth.work_icv = kmalloc(esp->auth.icv_full_len, GFP_KERNEL); + if (!esp->auth.work_icv) + goto error; + } + esp->conf.key = x->ealg->alg_key; + esp->conf.key_len = (x->ealg->alg_key_len+7)/8; + esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_CBC); + if (esp->conf.tfm == NULL) + goto error; + esp->conf.ivlen = crypto_tfm_alg_ivsize(esp->conf.tfm); + esp->conf.padlen = 0; + if (esp->conf.ivlen) { + esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL); + get_random_bytes(esp->conf.ivec, esp->conf.ivlen); + } + crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len); + x->props.header_len = 8 + esp->conf.ivlen; + if (x->props.mode) + x->props.header_len += 40; /* XXX ext hdr */ + x->data = esp; + return 0; + +error: + if (esp) { + if (esp->auth.tfm) + crypto_free_tfm(esp->auth.tfm); + if (esp->auth.work_icv) + kfree(esp->auth.work_icv); + if (esp->conf.tfm) + crypto_free_tfm(esp->conf.tfm); + kfree(esp); + } + return -EINVAL; +} + +static struct xfrm_type esp6_type = +{ + .description = "ESP6", + .proto = IPPROTO_ESP, + .init_state = esp6_init_state, + .destructor = esp6_destroy, + .get_max_size = esp6_get_max_size, + .input = esp6_input, + .output = esp6_output +}; + +static struct inet6_protocol esp6_protocol = { + .handler = xfrm6_rcv, + .err_handler = esp6_err, +}; + +int __init esp6_init(void) +{ + SET_MODULE_OWNER(&esp6_type); + if (xfrm6_register_type(&esp6_type) < 0) { + printk(KERN_INFO "ipv6 esp init: can't add xfrm type\n"); + return -EAGAIN; + } + if (inet6_add_protocol(&esp6_protocol, IPPROTO_ESP) < 0) { + printk(KERN_INFO "ipv6 esp init: can't add protocol\n"); + xfrm6_unregister_type(&esp6_type); + return -EAGAIN; + } + + return 0; +} + +static void __exit esp6_fini(void) +{ + if (inet6_del_protocol(&esp6_protocol, IPPROTO_ESP) < 0) + printk(KERN_INFO "ipv6 esp close: can't remove protocol\n"); + if (xfrm6_unregister_type(&esp6_type) < 0) + printk(KERN_INFO "ipv6 esp close: can't remove xfrm type\n"); +} + +module_init(esp6_init); +module_exit(esp6_fini); + +MODULE_LICENSE("GPL"); diff -Nru a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c --- a/net/ipv6/ip6_input.c Fri Mar 7 20:40:17 2003 +++ b/net/ipv6/ip6_input.c Fri Mar 7 20:40:17 2003 @@ -150,7 +150,8 @@ It would be stupid to detect for optional headers, which are missing with probability of 200% */ - if (nexthdr != IPPROTO_TCP && nexthdr != IPPROTO_UDP) { + if (nexthdr != IPPROTO_TCP && nexthdr != IPPROTO_UDP && + nexthdr != NEXTHDR_AUTH && nexthdr != NEXTHDR_ESP) { nhoff = ipv6_parse_exthdrs(&skb, nhoff); if (nhoff < 0) return 0; diff -Nru a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c --- a/net/ipv6/ip6_output.c Fri Mar 7 20:40:16 2003 +++ b/net/ipv6/ip6_output.c Fri Mar 7 20:40:16 2003 @@ -192,6 +192,11 @@ int seg_len = skb->len; int hlimit; u32 mtu; + int err = 0; + + if ((err = xfrm_lookup(&skb->dst, fl, sk, 0)) < 0) { + return err; + } if (opt) { int head_room; @@ -550,7 +555,7 @@ || (fl->oif && fl->oif != dst->dev->ifindex)) { dst = NULL; } else - dst_clone(dst); + dst_hold(dst); } if (dst == NULL) @@ -576,6 +581,13 @@ } pktlength = length; + if (dst) { + if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) { + dst_release(dst); + return -ENETUNREACH; + } + } + if (hlimit < 0) { if (ipv6_addr_is_multicast(fl->fl6_dst)) hlimit = np->mcast_hops; @@ -630,10 +642,8 @@ err = 0; if (flags&MSG_PROBE) goto out; - - skb = sock_alloc_send_skb(sk, pktlength + 15 + - dev->hard_header_len, - flags & MSG_DONTWAIT, &err); + /* alloc skb with mtu as we do in the IPv4 stack for IPsec */ + skb = sock_alloc_send_skb(sk, mtu, flags & MSG_DONTWAIT, &err); if (skb == NULL) { IP6_INC_STATS(Ip6OutDiscards); @@ -663,6 +673,8 @@ err = getfrag(data, &hdr->saddr, ((char *) hdr) + (pktlength - length), 0, length); + if (!opt || !opt->dst1opt) + skb->h.raw = ((char *) hdr) + (pktlength - length); if (!err) { IP6_INC_STATS(Ip6OutRequests); diff -Nru a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c --- a/net/ipv6/ndisc.c Fri Mar 7 20:40:17 2003 +++ b/net/ipv6/ndisc.c Fri Mar 7 20:40:17 2003 @@ -71,6 +71,7 @@ #include #include +#include #include #include @@ -335,8 +336,6 @@ unsigned char ha[MAX_ADDR_LEN]; unsigned char *h_dest = NULL; - skb_reserve(skb, (dev->hard_header_len + 15) & ~15); - if (dev->hard_header) { if (ipv6_addr_type(daddr) & IPV6_ADDR_MULTICAST) { ndisc_mc_map(daddr, ha, dev, 1); @@ -373,10 +372,50 @@ * Send a Neighbour Advertisement */ +int ndisc_output(struct sk_buff *skb) +{ + if (skb) { + struct neighbour *neigh = (skb->dst ? skb->dst->neighbour : NULL); + if (ndisc_build_ll_hdr(skb, skb->dev, &skb->nh.ipv6h->daddr, neigh, skb->len) == 0) { + kfree_skb(skb); + return -EINVAL; + } + dev_queue_xmit(skb); + return 0; + } + return -EINVAL; +} + +static inline void ndisc_rt_init(struct rt6_info *rt, struct net_device *dev, + struct neighbour *neigh) +{ + rt->rt6i_dev = dev; + rt->rt6i_nexthop = neigh; + rt->rt6i_expires = 0; + rt->rt6i_flags = RTF_LOCAL; + rt->rt6i_metric = 0; + rt->rt6i_hoplimit = 255; + rt->u.dst.output = ndisc_output; +} + +static inline void ndisc_flow_init(struct flowi *fl, u8 type, + struct in6_addr *saddr, struct in6_addr *daddr) +{ + memset(fl, 0, sizeof(*fl)); + fl->fl6_src = saddr; + fl->fl6_dst = daddr; + fl->proto = IPPROTO_ICMPV6; + fl->uli_u.icmpt.type = type; + fl->uli_u.icmpt.code = 0; +} + static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, struct in6_addr *daddr, struct in6_addr *solicited_addr, - int router, int solicited, int override, int inc_opt) + int router, int solicited, int override, int inc_opt) { + struct flowi fl; + struct rt6_info *rt = NULL; + struct dst_entry* dst; struct sock *sk = ndisc_socket->sk; struct nd_msg *msg; int len; @@ -385,6 +424,22 @@ len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr); + rt = ndisc_get_dummy_rt(); + if (!rt) + return; + + ndisc_flow_init(&fl, NDISC_NEIGHBOUR_ADVERTISEMENT, solicited_addr, daddr); + ndisc_rt_init(rt, dev, neigh); + + dst = (struct dst_entry*)rt; + dst_clone(dst); + + err = xfrm_lookup(&dst, &fl, NULL, 0); + if (err < 0) { + dst_release(dst); + return; + } + if (inc_opt) { if (dev->addr_len) len += NDISC_OPT_SPACE(dev->addr_len); @@ -400,14 +455,10 @@ return; } - if (ndisc_build_ll_hdr(skb, dev, daddr, neigh, len) == 0) { - kfree_skb(skb); - return; - } - + skb_reserve(skb, (dev->hard_header_len + 15) & ~15); ip6_nd_hdr(sk, skb, dev, solicited_addr, daddr, IPPROTO_ICMPV6, len); - msg = (struct nd_msg *) skb_put(skb, len); + skb->h.raw = (unsigned char*) msg = (struct nd_msg *) skb_put(skb, len); msg->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT; msg->icmph.icmp6_code = 0; @@ -430,7 +481,9 @@ csum_partial((__u8 *) msg, len, 0)); - dev_queue_xmit(skb); + dst_clone(dst); + skb->dst = dst; + dst_output(skb); ICMP6_INC_STATS(Icmp6OutNeighborAdvertisements); ICMP6_INC_STATS(Icmp6OutMsgs); @@ -440,6 +493,9 @@ struct in6_addr *solicit, struct in6_addr *daddr, struct in6_addr *saddr) { + struct flowi fl; + struct rt6_info *rt = NULL; + struct dst_entry* dst; struct sock *sk = ndisc_socket->sk; struct sk_buff *skb; struct nd_msg *msg; @@ -454,6 +510,22 @@ saddr = &addr_buf; } + rt = ndisc_get_dummy_rt(); + if (!rt) + return; + + ndisc_flow_init(&fl, NDISC_NEIGHBOUR_SOLICITATION, saddr, daddr); + ndisc_rt_init(rt, dev, neigh); + + dst = (struct dst_entry*)rt; + dst_clone(dst); + + err = xfrm_lookup(&dst, &fl, NULL, 0); + if (err < 0) { + dst_release(dst); + return; + } + len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr); send_llinfo = dev->addr_len && ipv6_addr_type(saddr) != IPV6_ADDR_ANY; if (send_llinfo) @@ -466,14 +538,10 @@ return; } - if (ndisc_build_ll_hdr(skb, dev, daddr, neigh, len) == 0) { - kfree_skb(skb); - return; - } - + skb_reserve(skb, (dev->hard_header_len + 15) & ~15); ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len); - msg = (struct nd_msg *)skb_put(skb, len); + skb->h.raw = (unsigned char*) msg = (struct nd_msg *)skb_put(skb, len); msg->icmph.icmp6_type = NDISC_NEIGHBOUR_SOLICITATION; msg->icmph.icmp6_code = 0; msg->icmph.icmp6_cksum = 0; @@ -492,7 +560,9 @@ csum_partial((__u8 *) msg, len, 0)); /* send it! */ - dev_queue_xmit(skb); + dst_clone(dst); + skb->dst = dst; + dst_output(skb); ICMP6_INC_STATS(Icmp6OutNeighborSolicits); ICMP6_INC_STATS(Icmp6OutMsgs); @@ -501,6 +571,9 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, struct in6_addr *daddr) { + struct flowi fl; + struct rt6_info *rt = NULL; + struct dst_entry* dst; struct sock *sk = ndisc_socket->sk; struct sk_buff *skb; struct icmp6hdr *hdr; @@ -508,6 +581,22 @@ int len; int err; + rt = ndisc_get_dummy_rt(); + if (!rt) + return; + + ndisc_flow_init(&fl, NDISC_ROUTER_SOLICITATION, saddr, daddr); + ndisc_rt_init(rt, dev, NULL); + + dst = (struct dst_entry*)rt; + dst_clone(dst); + + err = xfrm_lookup(&dst, &fl, NULL, 0); + if (err < 0) { + dst_release(dst); + return; + } + len = sizeof(struct icmp6hdr); if (dev->addr_len) len += NDISC_OPT_SPACE(dev->addr_len); @@ -519,14 +608,10 @@ return; } - if (ndisc_build_ll_hdr(skb, dev, daddr, NULL, len) == 0) { - kfree_skb(skb); - return; - } - + skb_reserve(skb, (dev->hard_header_len + 15) & ~15); ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len); - hdr = (struct icmp6hdr *) skb_put(skb, len); + skb->h.raw = (unsigned char*) hdr = (struct icmp6hdr *) skb_put(skb, len); hdr->icmp6_type = NDISC_ROUTER_SOLICITATION; hdr->icmp6_code = 0; hdr->icmp6_cksum = 0; @@ -543,7 +628,9 @@ csum_partial((__u8 *) hdr, len, 0)); /* send it! */ - dev_queue_xmit(skb); + dst_clone(dst); + skb->dst = dst; + dst_output(skb); ICMP6_INC_STATS(Icmp6OutRouterSolicits); ICMP6_INC_STATS(Icmp6OutMsgs); @@ -1125,6 +1212,8 @@ struct in6_addr *addrp; struct net_device *dev; struct rt6_info *rt; + struct dst_entry *dst; + struct flowi fl; u8 *opt; int rd_len; int err; @@ -1136,6 +1225,22 @@ if (rt == NULL) return; + dst = (struct dst_entry*)rt; + + if (ipv6_get_lladdr(dev, &saddr_buf)) { + ND_PRINTK1("redirect: no link_local addr for dev\n"); + return; + } + + ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr); + + dst_clone(dst); + err = xfrm_lookup(&dst, &fl, NULL, 0); + if (err) { + dst_release(dst); + return; + } + if (rt->rt6i_flags & RTF_GATEWAY) { ND_PRINTK1("ndisc_send_redirect: not a neighbour\n"); dst_release(&rt->u.dst); @@ -1164,11 +1269,6 @@ rd_len &= ~0x7; len += rd_len; - if (ipv6_get_lladdr(dev, &saddr_buf)) { - ND_PRINTK1("redirect: no link_local addr for dev\n"); - return; - } - buff = sock_alloc_send_skb(sk, MAX_HEADER + len + dev->hard_header_len + 15, 0, &err); if (buff == NULL) { @@ -1178,15 +1278,11 @@ hlen = 0; - if (ndisc_build_ll_hdr(buff, dev, &skb->nh.ipv6h->saddr, NULL, len) == 0) { - kfree_skb(buff); - return; - } - + skb_reserve(skb, (dev->hard_header_len + 15) & ~15); ip6_nd_hdr(sk, buff, dev, &saddr_buf, &skb->nh.ipv6h->saddr, IPPROTO_ICMPV6, len); - icmph = (struct icmp6hdr *) skb_put(buff, len); + skb->h.raw = (unsigned char*) icmph = (struct icmp6hdr *) skb_put(buff, len); memset(icmph, 0, sizeof(struct icmp6hdr)); icmph->icmp6_type = NDISC_REDIRECT; @@ -1224,7 +1320,8 @@ len, IPPROTO_ICMPV6, csum_partial((u8 *) icmph, len, 0)); - dev_queue_xmit(buff); + skb->dst = dst; + dst_output(skb); ICMP6_INC_STATS(Icmp6OutRedirects); ICMP6_INC_STATS(Icmp6OutMsgs); diff -Nru a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c --- a/net/ipv6/netfilter/ip6t_ah.c Fri Mar 7 20:40:16 2003 +++ b/net/ipv6/netfilter/ip6t_ah.c Fri Mar 7 20:40:16 2003 @@ -9,7 +9,6 @@ #include #include -EXPORT_NO_SYMBOLS; MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("IPv6 AH match"); MODULE_AUTHOR("Andras Kis-Szabo "); diff -Nru a/net/ipv6/netfilter/ip6t_dst.c b/net/ipv6/netfilter/ip6t_dst.c --- a/net/ipv6/netfilter/ip6t_dst.c Fri Mar 7 20:40:16 2003 +++ b/net/ipv6/netfilter/ip6t_dst.c Fri Mar 7 20:40:16 2003 @@ -15,7 +15,6 @@ #define HOPBYHOP 0 -EXPORT_NO_SYMBOLS; MODULE_LICENSE("GPL"); #if HOPBYHOP MODULE_DESCRIPTION("IPv6 HbH match"); diff -Nru a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c --- a/net/ipv6/netfilter/ip6t_esp.c Fri Mar 7 20:40:17 2003 +++ b/net/ipv6/netfilter/ip6t_esp.c Fri Mar 7 20:40:17 2003 @@ -9,7 +9,6 @@ #include #include -EXPORT_NO_SYMBOLS; MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("IPv6 ESP match"); MODULE_AUTHOR("Andras Kis-Szabo "); diff -Nru a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c --- a/net/ipv6/netfilter/ip6t_frag.c Fri Mar 7 20:40:16 2003 +++ b/net/ipv6/netfilter/ip6t_frag.c Fri Mar 7 20:40:16 2003 @@ -11,7 +11,6 @@ #include #include -EXPORT_NO_SYMBOLS; MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("IPv6 FRAG match"); MODULE_AUTHOR("Andras Kis-Szabo "); diff -Nru a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c --- a/net/ipv6/netfilter/ip6t_hbh.c Fri Mar 7 20:40:18 2003 +++ b/net/ipv6/netfilter/ip6t_hbh.c Fri Mar 7 20:40:18 2003 @@ -15,7 +15,6 @@ #define HOPBYHOP 1 -EXPORT_NO_SYMBOLS; MODULE_LICENSE("GPL"); #if HOPBYHOP MODULE_DESCRIPTION("IPv6 HbH match"); diff -Nru a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c --- a/net/ipv6/netfilter/ip6t_ipv6header.c Fri Mar 7 20:40:18 2003 +++ b/net/ipv6/netfilter/ip6t_ipv6header.c Fri Mar 7 20:40:18 2003 @@ -14,7 +14,6 @@ #include #include -EXPORT_NO_SYMBOLS; MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("IPv6 headers match"); MODULE_AUTHOR("Andras Kis-Szabo "); diff -Nru a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c --- a/net/ipv6/netfilter/ip6t_rt.c Fri Mar 7 20:40:16 2003 +++ b/net/ipv6/netfilter/ip6t_rt.c Fri Mar 7 20:40:16 2003 @@ -11,7 +11,6 @@ #include #include -EXPORT_NO_SYMBOLS; MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("IPv6 RT match"); MODULE_AUTHOR("Andras Kis-Szabo "); diff -Nru a/net/ipv6/raw.c b/net/ipv6/raw.c --- a/net/ipv6/raw.c Fri Mar 7 20:40:16 2003 +++ b/net/ipv6/raw.c Fri Mar 7 20:40:16 2003 @@ -45,6 +45,7 @@ #include #include +#include struct sock *raw_v6_htable[RAWV6_HTABLE_SIZE]; rwlock_t raw_v6_lock = RW_LOCK_UNLOCKED; @@ -303,6 +304,11 @@ { struct inet_opt *inet = inet_sk(sk); struct raw6_opt *raw_opt = raw6_sk(sk); + + if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) { + kfree_skb(skb); + return NET_RX_DROP; + } if (!raw_opt->checksum) skb->ip_summed = CHECKSUM_UNNECESSARY; diff -Nru a/net/ipv6/route.c b/net/ipv6/route.c --- a/net/ipv6/route.c Fri Mar 7 20:40:17 2003 +++ b/net/ipv6/route.c Fri Mar 7 20:40:17 2003 @@ -49,6 +49,8 @@ #include #include #include +#include +#include #include @@ -128,6 +130,12 @@ rwlock_t rt6_lock = RW_LOCK_UNLOCKED; +/* Dummy rt for ndisc */ +struct rt6_info *ndisc_get_dummy_rt() +{ + return dst_alloc(&ip6_dst_ops); +} + /* * Route lookup. Any rt6_lock is implied. */ @@ -356,7 +364,7 @@ rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); - dst_clone(&rt->u.dst); + dst_hold(&rt->u.dst); err = rt6_ins(rt); if (err == 0) @@ -366,7 +374,7 @@ return rt; } - dst_clone(&ip6_null_entry.u.dst); + dst_hold(&ip6_null_entry.u.dst); return &ip6_null_entry; } @@ -374,7 +382,7 @@ if (rt == &ip6_null_entry && strict) { \ while ((fn = fn->parent) != NULL) { \ if (fn->fn_flags & RTN_ROOT) { \ - dst_clone(&rt->u.dst); \ + dst_hold(&rt->u.dst); \ goto out; \ } \ if (fn->fn_flags & RTN_RTINFO) \ @@ -404,7 +412,7 @@ if ((rt->rt6i_flags & RTF_CACHE)) { rt = rt6_device_match(rt, skb->dev->ifindex, strict); BACKTRACK(); - dst_clone(&rt->u.dst); + dst_hold(&rt->u.dst); goto out; } @@ -424,7 +432,7 @@ */ goto relookup; } - dst_clone(&rt->u.dst); + dst_hold(&rt->u.dst); out: read_unlock_bh(&rt6_lock); @@ -455,7 +463,7 @@ if ((rt->rt6i_flags & RTF_CACHE)) { rt = rt6_device_match(rt, fl->oif, strict); BACKTRACK(); - dst_clone(&rt->u.dst); + dst_hold(&rt->u.dst); goto out; } if (rt->rt6i_flags & RTF_DEFAULT) { @@ -480,7 +488,7 @@ */ goto relookup; } - dst_clone(&rt->u.dst); + dst_hold(&rt->u.dst); out: read_unlock_bh(&rt6_lock); @@ -815,7 +823,7 @@ if (rtmsg->rtmsg_metric && rtmsg->rtmsg_metric != rt->rt6i_metric) continue; - dst_clone(&rt->u.dst); + dst_hold(&rt->u.dst); read_unlock_bh(&rt6_lock); return ip6_del_rt(rt); @@ -878,7 +886,7 @@ read_lock(&rt6_lock); for (rt1 = ip6_routing_table.leaf; rt1; rt1 = rt1->u.next) { if (!ipv6_addr_cmp(saddr, &rt1->rt6i_gateway)) { - dst_clone(&rt1->u.dst); + dst_hold(&rt1->u.dst); dst_release(&rt->u.dst); read_unlock(&rt6_lock); rt = rt1; @@ -1065,7 +1073,7 @@ break; } if (rt) - dst_clone(&rt->u.dst); + dst_hold(&rt->u.dst); write_unlock_bh(&rt6_lock); return rt; } @@ -1859,6 +1867,14 @@ #endif +int xfrm6_dst_lookup(struct xfrm_dst **dst, struct flowi *fl) +{ + int err = 0; + *dst = (struct xfrm_dst*)ip6_route_output(NULL, fl); + if (!*dst) + err = -ENETUNREACH; + return err; +} void __init ip6_route_init(void) { @@ -1867,6 +1883,7 @@ 0, SLAB_HWCACHE_ALIGN, NULL, NULL); fib6_init(); + xfrm_dst_lookup_register(xfrm6_dst_lookup, AF_INET6); #ifdef CONFIG_PROC_FS proc_net_create("ipv6_route", 0, rt6_proc_info); proc_net_create("rt6_stats", 0, rt6_proc_stats); @@ -1880,7 +1897,7 @@ proc_net_remove("ipv6_route"); proc_net_remove("rt6_stats"); #endif - + xfrm_dst_lookup_unregister(AF_INET6); rt6_ifdown(NULL); fib6_gc_cleanup(); } diff -Nru a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c --- a/net/ipv6/tcp_ipv6.c Fri Mar 7 20:40:17 2003 +++ b/net/ipv6/tcp_ipv6.c Fri Mar 7 20:40:17 2003 @@ -50,6 +50,7 @@ #include #include #include +#include #include @@ -677,6 +678,9 @@ fl.nl_u.ip6_u.daddr = rt0->addr; } + if (!fl.fl6_src) + fl.fl6_src = &np->saddr; + dst = ip6_route_output(sk, &fl); if ((err = dst->error) != 0) { @@ -800,7 +804,7 @@ dst = ip6_route_output(sk, &fl); } else - dst_clone(dst); + dst_hold(dst); if (dst->error) { sk->err_soft = -dst->error; @@ -1637,6 +1641,9 @@ if (sk_filter(sk, skb, 0)) goto discard_and_relse; + if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) + goto discard_it; + skb->dev = NULL; bh_lock_sock(sk); @@ -1652,6 +1659,9 @@ return ret; no_tcp_socket: + if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) + goto discard_and_relse; + if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { bad_packet: TCP_INC_STATS_BH(TcpInErrs); @@ -1671,8 +1681,11 @@ discard_and_relse: sock_put(sk); goto discard_it; - + do_time_wait: + if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) + goto discard_and_relse; + if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { TCP_INC_STATS_BH(TcpInErrs); sock_put(sk); diff -Nru a/net/ipv6/udp.c b/net/ipv6/udp.c --- a/net/ipv6/udp.c Fri Mar 7 20:40:18 2003 +++ b/net/ipv6/udp.c Fri Mar 7 20:40:18 2003 @@ -50,6 +50,7 @@ #include #include +#include DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6); @@ -541,6 +542,11 @@ static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) { + if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) { + kfree_skb(skb); + return -1; + } + #if defined(CONFIG_FILTER) if (sk->filter && skb->ip_summed != CHECKSUM_UNNECESSARY) { if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) { @@ -645,6 +651,9 @@ if (!pskb_may_pull(skb, sizeof(struct udphdr))) goto short_packet; + + if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) + goto discard; saddr = &skb->nh.ipv6h->saddr; daddr = &skb->nh.ipv6h->daddr; diff -Nru a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c --- a/net/ipx/af_ipx.c Fri Mar 7 20:40:16 2003 +++ b/net/ipx/af_ipx.c Fri Mar 7 20:40:16 2003 @@ -1719,10 +1719,10 @@ if (!sk) goto out; - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->state_change(sk); - sk->dead = 1; + __set_bit(SOCK_DEAD, &sk->flags); sock->sk = NULL; ipx_destroy_socket(sk); diff -Nru a/net/irda/af_irda.c b/net/irda/af_irda.c --- a/net/irda/af_irda.c Fri Mar 7 20:40:16 2003 +++ b/net/irda/af_irda.c Fri Mar 7 20:40:16 2003 @@ -133,13 +133,13 @@ } /* Prevent race conditions with irda_release() and irda_shutdown() */ - if ((!sk->dead) && (sk->state != TCP_CLOSE)) { + if ((!test_bit(SOCK_DEAD, &sk->flags)) && (sk->state != TCP_CLOSE)) { sk->state = TCP_CLOSE; sk->err = ECONNRESET; sk->shutdown |= SEND_SHUTDOWN; sk->state_change(sk); - sk->dead = 1; /* Uh-oh... Should use sock_orphan ? */ + __set_bit(SOCK_DEAD, &sk->flags); /* Uh-oh... Should use sock_orphan ? */ /* Close our TSAP. * If we leave it open, IrLMP put it back into the list of @@ -163,7 +163,7 @@ /* Note : once we are there, there is not much you want to do * with the socket anymore, apart from closing it. * For example, bind() and connect() won't reset sk->err, - * sk->shutdown and sk->dead to valid values... + * sk->shutdown and sk->flags to valid values... * Jean II */ } diff -Nru a/net/key/af_key.c b/net/key/af_key.c --- a/net/key/af_key.c Fri Mar 7 20:40:16 2003 +++ b/net/key/af_key.c Fri Mar 7 20:40:16 2003 @@ -51,7 +51,7 @@ { skb_queue_purge(&sk->receive_queue); - if (!sk->dead) { + if (!test_bit(SOCK_DEAD, &sk->flags)) { printk("Attempt to release alive pfkey socket: %p\n", sk); return; } @@ -550,8 +550,8 @@ switch (((struct sockaddr *)(addr + 1))->sa_family) { case AF_INET: - x = xfrm_state_lookup(((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr, - sa->sadb_sa_spi, proto); + x = xfrm4_state_lookup(((struct sockaddr_in *)(addr + 1))->sin_addr.s_addr, + sa->sadb_sa_spi, proto); break; #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case AF_INET6: @@ -1097,18 +1097,7 @@ min_spi = htonl(0x100); max_spi = htonl(0x0fffffff); } - switch (x->props.family) { - case AF_INET: - xfrm_alloc_spi(x, min_spi, max_spi); - break; -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) - case AF_INET6: - xfrm6_alloc_spi(x, min_spi, max_spi); - break; -#endif - default: - break; - } + xfrm_alloc_spi(x, min_spi, max_spi); if (x->id.spi) resp_skb = pfkey_xfrm_state2msg(x, 0, 3); } @@ -2420,7 +2409,8 @@ return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL); } -static struct xfrm_policy *pfkey_compile_policy(int opt, u8 *data, int len, int *dir) +static struct xfrm_policy *pfkey_compile_policy(u16 family, int opt, + u8 *data, int len, int *dir) { struct xfrm_policy *xp; struct sadb_x_policy *pol = (struct sadb_x_policy*)data; @@ -2451,6 +2441,7 @@ xp->lft.hard_byte_limit = XFRM_INF; xp->lft.soft_packet_limit = XFRM_INF; xp->lft.hard_packet_limit = XFRM_INF; + xp->family = family; xp->xfrm_nr = 0; if (pol->sadb_x_policy_type == IPSEC_POLICY_IPSEC && diff -Nru a/net/llc/llc_conn.c b/net/llc/llc_conn.c --- a/net/llc/llc_conn.c Fri Mar 7 20:40:16 2003 +++ b/net/llc/llc_conn.c Fri Mar 7 20:40:16 2003 @@ -119,9 +119,9 @@ sk->shutdown = SHUTDOWN_MASK; sk->socket->state = SS_UNCONNECTED; sk->state = TCP_CLOSE; - if (!sk->dead) { + if (!test_bit(SOCK_DEAD, &sk->flags)) { sk->state_change(sk); - sk->dead = 1; + __set_bit(SOCK_DEAD, &sk->flags); } } kfree_skb(skb); diff -Nru a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c --- a/net/netlink/af_netlink.c Fri Mar 7 20:40:17 2003 +++ b/net/netlink/af_netlink.c Fri Mar 7 20:40:17 2003 @@ -90,7 +90,7 @@ { skb_queue_purge(&sk->receive_queue); - if (!sk->dead) { + if (!test_bit(SOCK_DEAD, &sk->flags)) { printk("Freeing alive netlink socket %p\n", sk); return; } @@ -457,7 +457,7 @@ if ((atomic_read(&sk->rmem_alloc) > sk->rcvbuf || test_bit(0, &nlk->state)) && - !sk->dead) + !test_bit(SOCK_DEAD, &sk->flags)) timeo = schedule_timeout(timeo); __set_current_state(TASK_RUNNING); diff -Nru a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c --- a/net/netrom/af_netrom.c Fri Mar 7 20:40:17 2003 +++ b/net/netrom/af_netrom.c Fri Mar 7 20:40:17 2003 @@ -285,7 +285,7 @@ while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) { if (skb->sk != sk) { /* A pending connection */ - skb->sk->dead = 1; /* Queue the unaccepted socket for death */ + __set_bit(SOCK_DEAD, &skb->sk->flags); /* Queue the unaccepted socket for death */ nr_start_heartbeat(skb->sk); nr_sk(skb->sk)->state = NR_STATE_0; } @@ -545,8 +545,8 @@ sk->state = TCP_CLOSE; sk->shutdown |= SEND_SHUTDOWN; sk->state_change(sk); - sk->dead = 1; - sk->destroy = 1; + __set_bit(SOCK_DEAD, &sk->flags); + __set_bit(SOCK_DESTROY, &sk->flags); sk->socket = NULL; break; @@ -960,7 +960,7 @@ nr_start_heartbeat(make); nr_start_idletimer(make); - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->data_ready(sk, skb->len); return 1; diff -Nru a/net/netrom/nr_in.c b/net/netrom/nr_in.c --- a/net/netrom/nr_in.c Fri Mar 7 20:40:16 2003 +++ b/net/netrom/nr_in.c Fri Mar 7 20:40:16 2003 @@ -90,7 +90,7 @@ nr->n2count = 0; nr->window = skb->data[20]; sk->state = TCP_ESTABLISHED; - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->state_change(sk); break; } diff -Nru a/net/netrom/nr_subr.c b/net/netrom/nr_subr.c --- a/net/netrom/nr_subr.c Fri Mar 7 20:40:18 2003 +++ b/net/netrom/nr_subr.c Fri Mar 7 20:40:18 2003 @@ -276,8 +276,8 @@ sk->err = reason; sk->shutdown |= SEND_SHUTDOWN; - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->state_change(sk); - sk->dead = 1; + __set_bit(SOCK_DEAD, &sk->flags); } diff -Nru a/net/netrom/nr_timer.c b/net/netrom/nr_timer.c --- a/net/netrom/nr_timer.c Fri Mar 7 20:40:17 2003 +++ b/net/netrom/nr_timer.c Fri Mar 7 20:40:17 2003 @@ -141,7 +141,9 @@ case NR_STATE_0: /* Magic here: If we listen() and a new link dies before it is accepted() it isn't 'dead' so doesn't get removed. */ - if (sk->destroy || (sk->state == TCP_LISTEN && sk->dead)) { + if (test_bit(SOCK_DESTROY, &sk->flags) || + (sk->state == TCP_LISTEN && + test_bit(SOCK_DEAD, &sk->flags))) { nr_destroy_socket(sk); return; } @@ -209,10 +211,10 @@ sk->err = 0; sk->shutdown |= SEND_SHUTDOWN; - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->state_change(sk); - sk->dead = 1; + __set_bit(SOCK_DEAD, &sk->flags); bh_unlock_sock(sk); } diff -Nru a/net/netsyms.c b/net/netsyms.c --- a/net/netsyms.c Fri Mar 7 20:40:16 2003 +++ b/net/netsyms.c Fri Mar 7 20:40:16 2003 @@ -54,6 +54,12 @@ #include #include #include +#if defined(CONFIG_INET_AH) || defined(CONFIG_INET_AH_MODULE) || defined(CONFIG_INET6_AH) || defined(CONFIG_INET6_AH_MODULE) +#include +#endif +#if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE) +#include +#endif extern struct net_proto_family inet_family_ops; @@ -296,11 +302,11 @@ EXPORT_SYMBOL(__xfrm_route_forward); EXPORT_SYMBOL(xfrm_state_alloc); EXPORT_SYMBOL(__xfrm_state_destroy); -EXPORT_SYMBOL(xfrm_state_find); +EXPORT_SYMBOL(xfrm4_state_find); EXPORT_SYMBOL(xfrm_state_insert); EXPORT_SYMBOL(xfrm_state_check_expire); EXPORT_SYMBOL(xfrm_state_check_space); -EXPORT_SYMBOL(xfrm_state_lookup); +EXPORT_SYMBOL(xfrm4_state_lookup); EXPORT_SYMBOL(xfrm_replay_check); EXPORT_SYMBOL(xfrm_replay_advance); EXPORT_SYMBOL(xfrm_check_selectors); @@ -324,13 +330,17 @@ EXPORT_SYMBOL(xfrm_policy_flush); EXPORT_SYMBOL(xfrm_policy_byid); EXPORT_SYMBOL(xfrm_policy_list); +EXPORT_SYMBOL(xfrm_dst_lookup_register); +EXPORT_SYMBOL(xfrm_dst_lookup_unregister); #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +EXPORT_SYMBOL(xfrm6_state_find); +EXPORT_SYMBOL(xfrm6_rcv); EXPORT_SYMBOL(xfrm6_state_lookup); EXPORT_SYMBOL(xfrm6_find_acq); -EXPORT_SYMBOL(xfrm6_alloc_spi); EXPORT_SYMBOL(xfrm6_register_type); EXPORT_SYMBOL(xfrm6_unregister_type); EXPORT_SYMBOL(xfrm6_get_type); +EXPORT_SYMBOL(xfrm6_clear_mutable_options); #endif EXPORT_SYMBOL_GPL(xfrm_probe_algs); @@ -342,6 +352,15 @@ EXPORT_SYMBOL_GPL(xfrm_ealg_get_byid); EXPORT_SYMBOL_GPL(xfrm_aalg_get_byname); EXPORT_SYMBOL_GPL(xfrm_ealg_get_byname); +#if defined(CONFIG_INET_AH) || defined(CONFIG_INET_AH_MODULE) || defined(CONFIG_INET6_AH) || defined(CONFIG_INET6_AH_MODULE) +EXPORT_SYMBOL_GPL(skb_ah_walk); +#endif +#if defined(CONFIG_INET_ESP) || defined(CONFIG_INET_ESP_MODULE) || defined(CONFIG_INET6_ESP) || defined(CONFIG_INET6_ESP_MODULE) +EXPORT_SYMBOL_GPL(skb_cow_data); +EXPORT_SYMBOL_GPL(pskb_put); +EXPORT_SYMBOL_GPL(skb_icv_walk); +EXPORT_SYMBOL_GPL(skb_to_sgvec); +#endif #if defined (CONFIG_IPV6_MODULE) || defined (CONFIG_IP_SCTP_MODULE) /* inet functions common to v4 and v6 */ diff -Nru a/net/packet/af_packet.c b/net/packet/af_packet.c --- a/net/packet/af_packet.c Fri Mar 7 20:40:17 2003 +++ b/net/packet/af_packet.c Fri Mar 7 20:40:17 2003 @@ -198,7 +198,7 @@ BUG_TRAP(atomic_read(&sk->rmem_alloc)==0); BUG_TRAP(atomic_read(&sk->wmem_alloc)==0); - if (!sk->dead) { + if (!test_bit(SOCK_DEAD, &sk->flags)) { printk("Attempt to release alive packet socket: %p\n", sk); return; } @@ -852,7 +852,7 @@ po->running = 1; } else { sk->err = ENETDOWN; - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->error_report(sk); } } else { @@ -1392,7 +1392,7 @@ __sock_put(sk); po->running = 0; sk->err = ENETDOWN; - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->error_report(sk); } if (msg == NETDEV_UNREGISTER) { diff -Nru a/net/rose/af_rose.c b/net/rose/af_rose.c --- a/net/rose/af_rose.c Fri Mar 7 20:40:17 2003 +++ b/net/rose/af_rose.c Fri Mar 7 20:40:17 2003 @@ -365,7 +365,7 @@ while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) { if (skb->sk != sk) { /* A pending connection */ - skb->sk->dead = 1; /* Queue the unaccepted socket for death */ + __set_bit(SOCK_DEAD, &skb->sk->flags); /* Queue the unaccepted socket for death */ rose_start_heartbeat(skb->sk); rose_sk(skb->sk)->state = ROSE_STATE_0; } @@ -646,8 +646,8 @@ sk->state = TCP_CLOSE; sk->shutdown |= SEND_SHUTDOWN; sk->state_change(sk); - sk->dead = 1; - sk->destroy = 1; + __set_bit(SOCK_DEAD, &sk->flags); + __set_bit(SOCK_DESTROY, &sk->flags); break; default: @@ -1019,7 +1019,7 @@ rose_start_heartbeat(make); - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->data_ready(sk, skb->len); return 1; diff -Nru a/net/rose/rose_in.c b/net/rose/rose_in.c --- a/net/rose/rose_in.c Fri Mar 7 20:40:17 2003 +++ b/net/rose/rose_in.c Fri Mar 7 20:40:17 2003 @@ -54,7 +54,7 @@ rose->vl = 0; rose->state = ROSE_STATE_3; sk->state = TCP_ESTABLISHED; - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->state_change(sk); break; diff -Nru a/net/rose/rose_route.c b/net/rose/rose_route.c --- a/net/rose/rose_route.c Fri Mar 7 20:40:18 2003 +++ b/net/rose/rose_route.c Fri Mar 7 20:40:18 2003 @@ -910,9 +910,9 @@ sk->state = TCP_CLOSE; sk->err = 0; sk->shutdown |= SEND_SHUTDOWN; - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->state_change(sk); - sk->dead = 1; + __set_bit(SOCK_DEAD, &sk->flags); } else { skb->h.raw = skb->data; diff -Nru a/net/rose/rose_subr.c b/net/rose/rose_subr.c --- a/net/rose/rose_subr.c Fri Mar 7 20:40:18 2003 +++ b/net/rose/rose_subr.c Fri Mar 7 20:40:18 2003 @@ -510,8 +510,8 @@ sk->err = reason; sk->shutdown |= SEND_SHUTDOWN; - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->state_change(sk); - sk->dead = 1; + __set_bit(SOCK_DEAD, &sk->flags); } diff -Nru a/net/rose/rose_timer.c b/net/rose/rose_timer.c --- a/net/rose/rose_timer.c Fri Mar 7 20:40:17 2003 +++ b/net/rose/rose_timer.c Fri Mar 7 20:40:17 2003 @@ -136,7 +136,9 @@ case ROSE_STATE_0: /* Magic here: If we listen() and a new link dies before it is accepted() it isn't 'dead' so doesn't get removed. */ - if (sk->destroy || (sk->state == TCP_LISTEN && sk->dead)) { + if (test_bit(SOCK_DESTROY, &sk->flags) || + (sk->state == TCP_LISTEN && + test_bit(SOCK_DEAD, &sk->flags))) { rose_destroy_socket(sk); return; } @@ -207,9 +209,9 @@ sk->err = 0; sk->shutdown |= SEND_SHUTDOWN; - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->state_change(sk); - sk->dead = 1; + __set_bit(SOCK_DEAD, &sk->flags); bh_unlock_sock(sk); } diff -Nru a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c --- a/net/sctp/ulpqueue.c Fri Mar 7 20:40:18 2003 +++ b/net/sctp/ulpqueue.c Fri Mar 7 20:40:18 2003 @@ -189,7 +189,7 @@ /* If the socket is just going to throw this away, do not * even try to deliver it. */ - if (sk->dead || (sk->shutdown & RCV_SHUTDOWN)) + if (test_bit(SOCK_DEAD, &sk->flags) || (sk->shutdown & RCV_SHUTDOWN)) goto out_free; /* Check if the user wishes to receive this event. */ diff -Nru a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c --- a/net/sunrpc/clnt.c Fri Mar 7 20:40:16 2003 +++ b/net/sunrpc/clnt.c Fri Mar 7 20:40:16 2003 @@ -208,7 +208,8 @@ rpcauth_destroy(clnt->cl_auth); clnt->cl_auth = NULL; } - rpc_rmdir(clnt->cl_pathname); + if (clnt->cl_pathname[0]) + rpc_rmdir(clnt->cl_pathname); if (clnt->cl_xprt) { xprt_destroy(clnt->cl_xprt); clnt->cl_xprt = NULL; diff -Nru a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c --- a/net/sunrpc/xprt.c Fri Mar 7 20:40:17 2003 +++ b/net/sunrpc/xprt.c Fri Mar 7 20:40:17 2003 @@ -967,7 +967,7 @@ dprintk("RPC: tcp_state_change client %p...\n", xprt); dprintk("RPC: state %x conn %d dead %d zapped %d\n", sk->state, xprt_connected(xprt), - sk->dead, sk->zapped); + test_bit(SOCK_DEAD, &sk->flags), sk->zapped); switch (sk->state) { case TCP_ESTABLISHED: diff -Nru a/net/unix/af_unix.c b/net/unix/af_unix.c --- a/net/unix/af_unix.c Fri Mar 7 20:40:17 2003 +++ b/net/unix/af_unix.c Fri Mar 7 20:40:17 2003 @@ -331,7 +331,8 @@ * we signal error. Messages are lost. Do not make this, * when peer was not connected to us. */ - if (!other->dead && unix_peer(other) == sk) { + if (!test_bit(SOCK_DEAD, &other->flags) && + unix_peer(other) == sk) { other->err = ECONNRESET; other->error_report(other); } @@ -347,7 +348,7 @@ BUG_TRAP(atomic_read(&sk->wmem_alloc) == 0); BUG_TRAP(!u->list); BUG_TRAP(sk->socket==NULL); - if (sk->dead==0) { + if (!test_bit(SOCK_DEAD, &sk->flags)) { printk("Attempt to release alive unix socket: %p\n", sk); return; } @@ -863,7 +864,7 @@ __set_current_state(TASK_INTERRUPTIBLE); add_wait_queue_exclusive(&u->peer_wait, &wait); - sched = (!other->dead && + sched = (!test_bit(SOCK_DEAD, &other->flags) && !(other->shutdown&RCV_SHUTDOWN) && skb_queue_len(&other->receive_queue) > other->max_ack_backlog); @@ -928,7 +929,7 @@ unix_state_rlock(other); /* Apparently VFS overslept socket death. Retry. */ - if (other->dead) { + if (test_bit(SOCK_DEAD, &other->flags)) { unix_state_runlock(other); sock_put(other); goto restart; @@ -1261,7 +1262,7 @@ if (!unix_may_send(sk, other)) goto out_unlock; - if (other->dead) { + if (test_bit(SOCK_DEAD, &other->flags)) { /* * Check with 1003.1g - what should * datagram error @@ -1403,7 +1404,8 @@ unix_state_rlock(other); - if (other->dead || (other->shutdown & RCV_SHUTDOWN)) + if (test_bit(SOCK_DEAD, &other->flags) || + (other->shutdown & RCV_SHUTDOWN)) goto pipe_err_free; skb_queue_tail(&other->receive_queue, skb); diff -Nru a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c --- a/net/wanrouter/af_wanpipe.c Fri Mar 7 20:40:18 2003 +++ b/net/wanrouter/af_wanpipe.c Fri Mar 7 20:40:18 2003 @@ -76,14 +76,7 @@ #define DBG_PRINTK(format, a...) #endif -#if defined(LINUX_2_1) - #define dev_put(a) - #define __sock_put(a) - #define sock_hold(a) - #define DECLARE_WAITQUEUE(a,b) \ - struct wait_queue a = { b, NULL } -#endif - + /* SECURE SOCKET IMPLEMENTATION * * TRANSMIT: @@ -599,17 +592,8 @@ return -EMSGSIZE; } - #ifndef LINUX_2_4 - dev_lock_list(); - #endif - - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3) skb = sock_alloc_send_skb(sk, len+dev->hard_header_len+15, msg->msg_flags & MSG_DONTWAIT, &err); - #else - skb = sock_alloc_send_skb(sk, len+dev->hard_header_len+15, 0, - msg->msg_flags & MSG_DONTWAIT, &err); - #endif if (skb==NULL){ goto out_unlock; @@ -642,10 +626,6 @@ if (!(dev->flags & IFF_UP)) goto out_free; - #ifndef LINUX_2_4 - dev_unlock_list(); - #endif - if (atomic_read(&sk->wmem_alloc) + skb->truesize > (unsigned int)sk->sndbuf){ kfree_skb(skb); return -ENOBUFS; @@ -665,9 +645,6 @@ out_free: kfree_skb(skb); out_unlock: -#ifndef LINUX_2_4 - dev_unlock_list(); -#endif return err; } @@ -862,16 +839,12 @@ kfree(wp); wp_sk(sk) = NULL; - #ifdef LINUX_2_4 if (atomic_read(&sk->refcnt) != 1){ atomic_set(&sk->refcnt,1); DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i ! :delay.\n", atomic_read(&sk->refcnt)); } sock_put(sk); - #else - sk_free(sk); - #endif atomic_dec(&wanpipe_socks_nr); MOD_DEC_USE_COUNT; return; @@ -970,16 +943,8 @@ * protocol entry in the device list. *===========================================================*/ -#ifdef LINUX_2_4 static int wanpipe_release(struct socket *sock) -#else -static int wanpipe_release(struct socket *sock, struct socket *peersock) -#endif { - -#ifndef LINUX_2_4 - struct sk_buff *skb; -#endif wanpipe_opt *wp; struct sock *sk = sock->sk; struct sock **skp; @@ -1039,25 +1004,13 @@ sock->sk = NULL; sk->socket = NULL; - sk->dead = 1; + __set_bit(SOCK_DEAD, &sk->flags); /* Purge queues */ -#ifdef LINUX_2_4 skb_queue_purge(&sk->receive_queue); skb_queue_purge(&sk->write_queue); skb_queue_purge(&sk->error_queue); -#else - while ((skb=skb_dequeue(&sk->receive_queue))!=NULL){ - kfree_skb(skb); - } - while ((skb=skb_dequeue(&sk->error_queue))!=NULL){ - kfree_skb(skb); - } - while ((skb=skb_dequeue(&sk->write_queue))!=NULL){ - kfree_skb(skb); - } -#endif if (atomic_read(&sk->rmem_alloc) || atomic_read(&sk->wmem_alloc)) { del_timer(&sk->timer); printk(KERN_INFO "wansock: Killing in Timer R %i , W %i\n", @@ -1072,16 +1025,12 @@ kfree(wp); wp_sk(sk) = NULL; - #ifdef LINUX_2_4 if (atomic_read(&sk->refcnt) != 1){ DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i !:release.\n", atomic_read(&sk->refcnt)); atomic_set(&sk->refcnt,1); } sock_put(sk); - #else - sk_free(sk); - #endif atomic_dec(&wanpipe_socks_nr); MOD_DEC_USE_COUNT; return 0; @@ -1128,7 +1077,7 @@ while ((skb=skb_dequeue(&sk->receive_queue))!=NULL){ if ((deadsk = get_newsk_from_skb(skb))){ DBG_PRINTK (KERN_INFO "wansock: RELEASE: FOUND DEAD SOCK\n"); - deadsk->dead=1; + __set_bit(SOCK_DEAD, &deadsk->flags); start_cleanup_timer(deadsk); } kfree_skb(skb); @@ -1181,10 +1130,6 @@ { struct sock *sk = (struct sock *)data; -#ifndef LINUX_2_4 - struct sk_buff *skb; -#endif - struct sock **skp; if (!sk) @@ -1226,21 +1171,9 @@ sk->socket = NULL; /* Purge queues */ -#ifdef LINUX_2_4 skb_queue_purge(&sk->receive_queue); skb_queue_purge(&sk->write_queue); skb_queue_purge(&sk->error_queue); -#else - while ((skb=skb_dequeue(&sk->receive_queue)) != NULL){ - kfree_skb(skb); - } - while ((skb=skb_dequeue(&sk->write_queue)) != NULL) { - kfree_skb(skb); - } - while ((skb=skb_dequeue(&sk->error_queue)) != NULL){ - kfree_skb(skb); - } -#endif if (atomic_read(&sk->rmem_alloc) || atomic_read(&sk->wmem_alloc)) { del_timer(&sk->timer); @@ -1257,16 +1190,12 @@ wp_sk(sk) = NULL; } - #ifdef LINUX_2_4 if (atomic_read(&sk->refcnt) != 1){ atomic_set(&sk->refcnt,1); DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i ! :timer.\n", atomic_read(&sk->refcnt)); } sock_put(sk); - #else - sk_free(sk); - #endif atomic_dec(&wanpipe_socks_nr); MOD_DEC_USE_COUNT; return; @@ -1301,16 +1230,12 @@ wp_sk(sk) = NULL; } - #ifdef LINUX_2_4 if (atomic_read(&sk->refcnt) != 1){ atomic_set(&sk->refcnt,1); DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i ! :timer.\n", atomic_read(&sk->refcnt)); } sock_put(sk); - #else - sk_free(sk); - #endif atomic_dec(&wanpipe_socks_nr); MOD_DEC_USE_COUNT; return; @@ -1330,16 +1255,12 @@ wp_sk(sk) = NULL; } - #ifdef LINUX_2_4 if (atomic_read(&sk->refcnt) != 1){ atomic_set(&sk->refcnt,1); DBG_PRINTK(KERN_INFO "wansock: Error, wrong reference count: %i !:listen.\n", atomic_read(&sk->refcnt)); } sock_put(sk); - #else - sk_free(sk); - #endif atomic_dec(&wanpipe_socks_nr); MOD_DEC_USE_COUNT; return; @@ -1494,11 +1415,7 @@ */ strncpy(name,sll->sll_device,14); name[14]=0; -#ifdef LINUX_2_4 dev = dev_get_by_name(name); -#else - dev = dev_get(name); -#endif if (dev == NULL){ printk(KERN_INFO "wansock: Failed to get Dev from name: %s,\n", name); @@ -1706,11 +1623,7 @@ if (err) goto out_free; -#ifdef LINUX_2_1 - sk->stamp=skb->stamp; -#else sock_recv_timestamp(msg, sk, skb); -#endif if (msg->msg_name) memcpy(msg->msg_name, skb->cb, msg->msg_namelen); @@ -2212,11 +2125,7 @@ if (sock_writeable(sk)){ mask |= POLLOUT | POLLWRNORM | POLLWRBAND; }else{ - #ifdef LINUX_2_4 set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags); - #else - sk->socket->flags |= SO_NOSPACE; - #endif } return mask; @@ -2649,7 +2558,6 @@ return 0; } -#ifdef LINUX_2_4 struct proto_ops wanpipe_ops = { .family = PF_WANPIPE, @@ -2668,29 +2576,6 @@ .sendmsg = wanpipe_sendmsg, .recvmsg = wanpipe_recvmsg }; -#else -struct proto_ops wanpipe_ops = { - PF_WANPIPE, - - sock_no_dup, - wanpipe_release, - wanpipe_bind, - wanpipe_connect, - sock_no_socketpair, - wanpipe_accept, - wanpipe_getname, - wanpipe_poll, - wanpipe_ioctl, - wanpipe_listen, - sock_no_shutdown, - sock_no_setsockopt, - sock_no_getsockopt, - sock_no_fcntl, - wanpipe_sendmsg, - wanpipe_recvmsg -}; -#endif - static struct net_proto_family wanpipe_family_ops = { .family =PF_WANPIPE, diff -Nru a/net/x25/af_x25.c b/net/x25/af_x25.c --- a/net/x25/af_x25.c Fri Mar 7 20:40:18 2003 +++ b/net/x25/af_x25.c Fri Mar 7 20:40:18 2003 @@ -344,7 +344,7 @@ /* * Queue the unaccepted socket for death */ - skb->sk->dead = 1; + __set_bit(SOCK_DEAD, &skb->sk->flags); x25_start_heartbeat(skb->sk); x25_sk(skb->sk)->state = X25_STATE_0; } @@ -580,8 +580,8 @@ sk->state = TCP_CLOSE; sk->shutdown |= SEND_SHUTDOWN; sk->state_change(sk); - sk->dead = 1; - sk->destroy = 1; + __set_bit(SOCK_DEAD, &sk->flags); + __set_bit(SOCK_DESTROY, &sk->flags); break; } @@ -902,7 +902,7 @@ x25_start_heartbeat(make); - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->data_ready(sk, skb->len); rc = 1; sock_put(sk); @@ -1112,7 +1112,8 @@ if (flags & MSG_OOB) { rc = -EINVAL; - if (sk->urginline || !skb_peek(&x25->interrupt_in_queue)) + if (test_bit(SOCK_URGINLINE, &sk->flags) || + !skb_peek(&x25->interrupt_in_queue)) goto out; skb = skb_dequeue(&x25->interrupt_in_queue); diff -Nru a/net/x25/x25_in.c b/net/x25/x25_in.c --- a/net/x25/x25_in.c Fri Mar 7 20:40:18 2003 +++ b/net/x25/x25_in.c Fri Mar 7 20:40:18 2003 @@ -86,7 +86,7 @@ skb_set_owner_r(skbn, sk); skb_queue_tail(&sk->receive_queue, skbn); - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->data_ready(sk, skbn->len); return 0; @@ -129,7 +129,7 @@ skb->len); x25->calluserdata.cudlength = skb->len; } - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->state_change(sk); break; } @@ -277,7 +277,7 @@ break; case X25_INTERRUPT: - if (sk->urginline) { + if (test_bit(SOCK_URGINLINE, &sk->flags)) { queued = (sock_queue_rcv_skb(sk, skb) == 0); } else { skb_set_owner_r(skb, sk); diff -Nru a/net/x25/x25_subr.c b/net/x25/x25_subr.c --- a/net/x25/x25_subr.c Fri Mar 7 20:40:16 2003 +++ b/net/x25/x25_subr.c Fri Mar 7 20:40:16 2003 @@ -344,10 +344,10 @@ sk->err = reason; sk->shutdown |= SEND_SHUTDOWN; - if (!sk->dead) + if (!test_bit(SOCK_DEAD, &sk->flags)) sk->state_change(sk); - sk->dead = 1; + __set_bit(SOCK_DEAD, &sk->flags); } /* diff -Nru a/net/x25/x25_timer.c b/net/x25/x25_timer.c --- a/net/x25/x25_timer.c Fri Mar 7 20:40:16 2003 +++ b/net/x25/x25_timer.c Fri Mar 7 20:40:16 2003 @@ -139,7 +139,7 @@ case X25_STATE_0: /* Magic here: If we listen() and a new link dies before it is accepted() it isn't 'dead' so doesn't get removed. */ - if (sk->destroy || (sk->state == TCP_LISTEN && sk->dead)) { + if (test_bit(SOCK_DESTROY, &sk->flags) || (sk->state == TCP_LISTEN && test_bit(SOCK_DEAD, &sk->flags))) { x25_destroy_socket(sk); goto unlock; } diff -Nru a/scripts/Makefile.build b/scripts/Makefile.build --- a/scripts/Makefile.build Fri Mar 7 20:40:18 2003 +++ b/scripts/Makefile.build Fri Mar 7 20:40:18 2003 @@ -163,12 +163,12 @@ # Single-part modules are special since we need to mark them in $(MODVERDIR) $(single-used-m): %.o: %.c FORCE - $(touch-module) ifdef CONFIG_MODVERSIONS $(call if_changed_rule,vcc_o_c) else $(call if_changed_dep,cc_o_c) endif + $(touch-module) quiet_cmd_cc_lst_c = MKLST $@ cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \ @@ -262,8 +262,8 @@ $(call if_changed,link_multi-y) $(multi-used-m) : %.o: $(multi-objs-m) FORCE - $(touch-module) $(call if_changed,link_multi-m) + $(touch-module) targets += $(multi-used-y) $(multi-used-m) diff -Nru a/scripts/Makefile.modpost b/scripts/Makefile.modpost --- a/scripts/Makefile.modpost Fri Mar 7 20:40:17 2003 +++ b/scripts/Makefile.modpost Fri Mar 7 20:40:17 2003 @@ -37,7 +37,7 @@ quiet_cmd_cc_o_c = CC $@ cmd_cc_o_c = $(CC) $(CFLAGS) $(CFLAGS_MODULE) -c -o $@ $< -$(modules:.ko=.mod.o): %.mod.o: %.mod.c +$(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE $(call if_changed,cc_o_c) targets += $(modules:.ko=.mod.o) @@ -51,9 +51,9 @@ # Extract all checksums for all exported symbols quiet_cmd_modpost = MODPOST - cmd_modpost = scripts/modpost $^ + cmd_modpost = scripts/modpost $(filter-out FORCE,$^) -__modpost: $(wildcard vmlinux) $(modules:.ko=.o) +__modpost: $(wildcard vmlinux) $(modules:.ko=.o) FORCE $(call if_changed,modpost) targets += __modpost diff -Nru a/scripts/modpost.c b/scripts/modpost.c --- a/scripts/modpost.c Fri Mar 7 20:40:16 2003 +++ b/scripts/modpost.c Fri Mar 7 20:40:16 2003 @@ -293,6 +293,9 @@ /* undefined symbol */ if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL) break; + /* ignore global offset table */ + if (strcmp(symname, "_GLOBAL_OFFSET_TABLE_") == 0) + break; if (memcmp(symname, MODULE_SYMBOL_PREFIX, strlen(MODULE_SYMBOL_PREFIX)) == 0) { diff -Nru a/scripts/per-cpu-check.awk b/scripts/per-cpu-check.awk --- a/scripts/per-cpu-check.awk Fri Mar 7 20:40:18 2003 +++ b/scripts/per-cpu-check.awk Fri Mar 7 20:40:18 2003 @@ -6,7 +6,7 @@ IN_PER_CPU=0 } -/__per_cpu$$/ && ! ( / __ksymtab_/ || / __kstrtab_/ || / __kcrctab_/ ) { +/__per_cpu$$/ && ! ( / __ksymtab_/ || / __kstrtab_/ || / __kcrctab_/ || / __crc_/ ) { if (!IN_PER_CPU) { print $$3 " not in per-cpu section" > "/dev/stderr"; FOUND=1; diff -Nru a/sound/oss/trident.c b/sound/oss/trident.c --- a/sound/oss/trident.c Fri Mar 7 20:40:17 2003 +++ b/sound/oss/trident.c Fri Mar 7 20:40:17 2003 @@ -221,7 +221,7 @@ #define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */ #define TRIDENT_DMA_MASK 0x3fffffff /* DMA buffer mask for pci_alloc_consist */ -#define ALI_DMA_MASK 0xffffffff /* ALI Tridents lack the 30-bit limitation */ +#define ALI_DMA_MASK 0x7fffffff /* ALI Tridents have 31-bit DMA. Wow. */ #define NR_HW_CH 32 diff -Nru a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c --- a/sound/pci/ac97/ac97_codec.c Fri Mar 7 20:40:16 2003 +++ b/sound/pci/ac97/ac97_codec.c Fri Mar 7 20:40:16 2003 @@ -1808,7 +1808,7 @@ */ static int ac97_reset_wait(ac97_t *ac97, int timeout, int with_modem) { - signed long end_time; + unsigned long end_time; end_time = jiffies + timeout; do { unsigned short ext_mid; @@ -1866,7 +1866,7 @@ int err; ac97_t *ac97; char name[64]; - signed long end_time; + unsigned long end_time; static snd_device_ops_t ops = { .dev_free = snd_ac97_dev_free, }; diff -Nru a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c --- a/sound/pci/intel8x0.c Fri Mar 7 20:40:17 2003 +++ b/sound/pci/intel8x0.c Fri Mar 7 20:40:17 2003 @@ -1741,7 +1741,7 @@ static int snd_intel8x0_ich_chip_init(intel8x0_t *chip) { - signed long end_time; + unsigned long end_time; unsigned int cnt, status, nstatus; /* put logic to right state */ diff -Nru a/usr/Makefile b/usr/Makefile --- a/usr/Makefile Fri Mar 7 20:40:17 2003 +++ b/usr/Makefile Fri Mar 7 20:40:17 2003 @@ -1,16 +1,34 @@ obj-y := initramfs_data.o -host-progs := gen_init_cpio +host-progs := gen_init_cpio clean-files := initramfs_data.cpio.gz LDFLAGS_initramfs_data.o := $(LDFLAGS_BLOB) -r -T -$(obj)/initramfs_data.o: $(src)/initramfs_data.scr $(obj)/initramfs_data.cpio.gz FORCE +$(obj)/initramfs_data.o: $(src)/initramfs_data.scr \ + $(obj)/initramfs_data.cpio.gz FORCE $(call if_changed,ld) -$(obj)/initramfs_data.cpio.gz: $(obj)/gen_init_cpio - ./$< | gzip -9c > $@ +# initramfs-y are the programs which will be copied into the CPIO +# archive. Currently, the filenames are hardcoded in gen_init_cpio, +# but we need the information for the build as well, so it's duplicated +# here. +# Commented out for now +# initramfs-y := $(obj)/root/hello + +quiet_cmd_cpio = CPIO $@ + cmd_cpio = ./$< > $@ + +$(obj)/initramfs_data.cpio: $(obj)/gen_init_cpio $(initramfs-y) FORCE + $(call if_changed,cpio) + +targets += $(obj)/initramfs_data.cpio + +$(obj)/initramfs_data.cpio.gz: $(obj)/initramfs_data.cpio FORCE + $(call if_changed,gzip) + +targets += $(obj)/initramfs_data.cpio.gz diff -Nru a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c --- a/usr/gen_init_cpio.c Fri Mar 7 20:40:17 2003 +++ b/usr/gen_init_cpio.c Fri Mar 7 20:40:17 2003 @@ -5,10 +5,28 @@ #include #include #include +#include static unsigned int offset; static unsigned int ino = 721; +static void push_string(const char *name) +{ + unsigned int name_len = strlen(name) + 1; + + fputs(name, stdout); + putchar(0); + offset += name_len; +} + +static void push_pad (void) +{ + while (offset & 3) { + putchar(0); + offset++; + } +} + static void push_rest(const char *name) { unsigned int name_len = strlen(name) + 1; @@ -118,6 +136,78 @@ 0); /* chksum */ push_hdr(s); push_rest(name); +} + +/* Not marked static to keep the compiler quiet, as no one uses this yet... */ +void cpio_mkfile(const char *filename, const char *location, + unsigned int mode, uid_t uid, gid_t gid) +{ + char s[256]; + char *filebuf; + struct stat buf; + int file; + int retval; + int i; + + mode |= S_IFREG; + + retval = stat (filename, &buf); + if (retval) { + fprintf (stderr, "Filename %s could not be located\n", filename); + goto error; + } + + file = open (filename, O_RDONLY); + if (file < 0) { + fprintf (stderr, "Filename %s could not be opened for reading\n", filename); + goto error; + } + + filebuf = malloc(buf.st_size); + if (!filebuf) { + fprintf (stderr, "out of memory\n"); + goto error_close; + } + + retval = read (file, filebuf, buf.st_size); + if (retval < 0) { + fprintf (stderr, "Can not read %s file\n", filename); + goto error_free; + } + + sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX" + "%08X%08X%08X%08X%08X%08X%08X", + "070701", /* magic */ + ino++, /* ino */ + mode, /* mode */ + (long) uid, /* uid */ + (long) gid, /* gid */ + 1, /* nlink */ + (long) buf.st_mtime, /* mtime */ + (int) buf.st_size, /* filesize */ + 3, /* major */ + 1, /* minor */ + 0, /* rmajor */ + 0, /* rminor */ + strlen(location) + 1, /* namesize */ + 0); /* chksum */ + push_hdr(s); + push_string(location); + push_pad(); + + for (i = 0; i < buf.st_size; ++i) + fputc(filebuf[i], stdout); + close(file); + free(filebuf); + push_pad(); + return; + +error_free: + free(filebuf); +error_close: + close(file); +error: + exit(-1); } int main (int argc, char *argv[])