# 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.69 -> 1.1115 # drivers/video/fbmem.c 1.74 -> 1.75 # drivers/i2c/chips/w83781d.c 1.5 -> 1.6 # drivers/hotplug/cpqphp_core.c 1.15.1.1 -> 1.17 # include/asm-i386/mpspec.h 1.11 -> 1.12 # Documentation/DocBook/kernel-api.tmpl 1.23.1.2 -> 1.25 # include/linux/file.h 1.9 -> 1.10 # arch/ppc64/kernel/signal.c 1.26 -> 1.27 # include/linux/proc_fs.h 1.15 -> 1.16 # drivers/i2c/chips/lm75.c 1.14 -> 1.15 # arch/i386/kernel/timers/Makefile 1.6 -> 1.7 # drivers/media/video/tda9887.c 1.5 -> 1.6 # include/linux/netfilter_ipv4/ip_nat_core.h 1.1 -> 1.2 # drivers/block/acsi_slm.c 1.11 -> 1.12 # arch/i386/mm/fault.c 1.24 -> 1.26 # drivers/char/esp.c 1.18 -> 1.19 # sound/oss/opl3sa2.c 1.20 -> 1.21 # arch/i386/lib/usercopy.c 1.11 -> 1.12 # include/net/dn_dev.h 1.4 -> 1.5 # drivers/usb/misc/usblcd.c 1.7 -> 1.8 # net/ipx/ipx_proc.c 1.2 -> 1.4 # drivers/char/vme_scc.c 1.16 -> 1.17 # drivers/usb/misc/tiglusb.c 1.17 -> 1.18 # include/asm-ppc64/page.h 1.18 -> 1.19 # drivers/ieee1394/raw1394.c 1.24 -> 1.25 # drivers/char/lp.c 1.25 -> 1.26 # net/ipv4/netfilter/ip_nat_proto_tcp.c 1.3 -> 1.4 # kernel/ksyms.c 1.195 -> 1.197 # include/asm-ppc64/unistd.h 1.19 -> 1.20 # arch/ppc64/kernel/entry.S 1.24 -> 1.26 # drivers/i2c/chips/adm1021.c 1.15 -> 1.16 # include/linux/sysrq.h 1.4 -> 1.5 # drivers/net/wan/cosa.c 1.20 -> 1.21 # fs/select.c 1.19 -> 1.20 # drivers/sbus/char/bpp.c 1.13 -> 1.14 # drivers/usb/media/dabusb.h 1.5 -> 1.6 # drivers/char/isicom.c 1.17 -> 1.18 # include/linux/swap.h 1.76 -> 1.77 # include/asm-i386/edd.h 1.4 -> 1.5 # include/net/dn_route.h 1.6 -> 1.7 # drivers/atm/Makefile 1.17 -> 1.18 # include/asm-i386/processor.h 1.48 -> 1.49 # net/ipv6/exthdrs.c 1.9 -> 1.10 # fs/file_table.c 1.23 -> 1.24 # net/core/neighbour.c 1.11 -> 1.13 # include/asm-i386/fixmap.h 1.11 -> 1.12 # net/Kconfig 1.11 -> 1.12 # arch/ppc64/kernel/udbg.c 1.7 -> 1.8 # drivers/media/video/mxb.c 1.3 -> 1.4 # include/linux/raid/md.h 1.26 -> 1.27 # mm/page_alloc.c 1.154 -> 1.155 # include/asm-ppc64/processor.h 1.27 -> 1.29 # drivers/char/random.c 1.32 -> 1.33 # drivers/char/dz.c 1.18 -> 1.20 # drivers/input/serio/i8042.c 1.26 -> 1.27 # arch/i386/kernel/smp.c 1.30 -> 1.31 # fs/ext3/Makefile 1.9 -> 1.10 # include/net/ipx.h 1.6 -> 1.9 # drivers/net/pcmcia/nmclan_cs.c 1.13 -> 1.14 # include/linux/sched.h 1.142 -> 1.143 # include/asm-ppc64/module.h 1.2 -> 1.3 # drivers/atm/ambassador.c 1.11 -> 1.12 # drivers/i2c/chips/via686a.c 1.6 -> 1.7 # drivers/media/video/bttv-if.c 1.11 -> 1.13 # drivers/media/video/bttv.h 1.9 -> 1.10 # include/asm-ppc64/ucontext.h 1.2 -> 1.3 # arch/ppc64/kernel/chrp_setup.c 1.21.2.2 -> 1.27 # drivers/media/video/videodev.c 1.19 -> 1.20 # fs/dcache.c 1.51 -> 1.52 # net/ipv4/af_inet.c 1.44 -> 1.45 # mm/vmscan.c 1.156 -> 1.157 # drivers/isdn/hardware/eicon/divasmain.c 1.8 -> 1.9 # arch/um/drivers/mmapper_kern.c 1.4 -> 1.5 # net/ipv6/netfilter/ip6t_ah.c 1.4 -> 1.5 # net/atm/Makefile 1.7 -> 1.8 # drivers/i2c/i2c-core.c 1.32 -> 1.35 # arch/ppc64/kernel/rtas.c 1.9 -> 1.11 # drivers/ieee1394/video1394.c 1.34 -> 1.35 # arch/i386/Kconfig 1.56 -> 1.57 # net/ipv4/netfilter/ip_nat_core.c 1.22 -> 1.23 # include/asm-i386/uaccess.h 1.23 -> 1.24 # drivers/media/video/saa7134/saa7134-i2c.c 1.7 -> 1.9 # net/ipv4/netfilter/ip_nat_helper.c 1.12 -> 1.13 # net/ipx/af_ipx.c 1.29 -> 1.31 # fs/devfs/base.c 1.87 -> 1.88 # init/main.c 1.98 -> 1.99 # include/asm-i386/numnodes.h 1.3 -> 1.4 # net/ipv4/fib_semantics.c 1.10 -> 1.11 # include/linux/i2c.h 1.25 -> 1.28 # net/ipv4/netfilter/ip_nat_proto_udp.c 1.1 -> 1.3 # drivers/usb/class/usblp.c 1.42 -> 1.44 # fs/stat.c 1.18 -> 1.19 # include/asm-i386/mach-summit/mach_ipi.h 1.2 -> 1.3 # drivers/char/drm/radeon_cp.c 1.18 -> 1.19 # arch/i386/vmlinux.lds.S 1.29 -> 1.30 # drivers/media/dvb/dvb-core/dvbdev.c 1.8 -> 1.10 # mm/swapfile.c 1.77 -> 1.78 # include/asm-ppc64/sigcontext.h 1.3 -> 1.4 # drivers/char/cyclades.c 1.21 -> 1.22 # security/dummy.c 1.19 -> 1.20 # net/ipv6/netfilter/ip6t_frag.c 1.4 -> 1.5 # net/decnet/Makefile 1.5 -> 1.6 # drivers/serial/core.c 1.59 -> 1.60 # include/linux/major.h 1.8 -> 1.9 # arch/ppc64/kernel/LparData.c 1.8 -> 1.9 # net/bridge/br_input.c 1.10 -> 1.11 # include/linux/fs.h 1.238 -> 1.240 # net/decnet/dn_table.c 1.5 -> 1.6 # include/linux/netfilter_ipv4/ip_nat_helper.h 1.4 -> 1.5 # drivers/block/paride/pt.c 1.15 -> 1.16 # drivers/sgi/char/sgiserial.c 1.12 -> 1.13 # drivers/usb/image/scanner.c 1.57 -> 1.59 # net/ipv6/netfilter/ip6t_rt.c 1.4 -> 1.5 # fs/sysv/dir.c 1.14 -> 1.15 # drivers/char/ser_a2232.c 1.8 -> 1.9 # drivers/char/n_hdlc.c 1.14 -> 1.15 # fs/udf/dir.c 1.12 -> 1.13 # include/asm-ppc64/types.h 1.2 -> 1.3 # drivers/char/vc_screen.c 1.9 -> 1.10 # drivers/md/md.c 1.166 -> 1.167 # drivers/i2c/busses/i2c-piix4.c 1.8 -> 1.9 # arch/ppc64/kernel/ras.c 1.3 -> 1.4 # arch/mips/au1000/common/serial.c 1.15 -> 1.16 # net/ipv4/netfilter/ip_nat_tftp.c 1.2 -> 1.3 # arch/i386/kernel/mpparse.c 1.39 -> 1.40 # include/asm-ppc64/machdep.h 1.14 -> 1.16 # net/ipv4/netfilter/ip_nat_proto_icmp.c 1.1 -> 1.3 # include/linux/brlvger.h 1.3 -> 1.4 # drivers/media/video/tvaudio.c 1.17 -> 1.18 # arch/i386/kernel/io_apic.c 1.64 -> 1.65 # drivers/ide/ide-tape.c 1.22 -> 1.23 # drivers/hotplug/acpiphp_glue.c 1.8 -> 1.9 # drivers/usb/media/vicam.c 1.34 -> 1.35 # net/decnet/dn_dev.c 1.10 -> 1.11 # mm/filemap.c 1.191 -> 1.192 # drivers/acpi/acpi_ksyms.c 1.23 -> 1.24 # net/decnet/dn_nsp_in.c 1.9 -> 1.10 # fs/namei.c 1.71 -> 1.72 # arch/sparc64/solaris/socksys.c 1.11 -> 1.12 # drivers/hotplug/cpqphp_ctrl.c 1.9.1.1 -> 1.11 # drivers/isdn/i4l/isdn_common.c 1.73 -> 1.74 # arch/i386/Makefile 1.50 -> 1.51 # net/socket.c 1.56 -> 1.57 # drivers/char/synclink.c 1.34 -> 1.35 # drivers/isdn/hardware/eicon/divasi.c 1.5 -> 1.6 # drivers/media/video/bttvp.h 1.10 -> 1.11 # drivers/char/rio/riotty.c 1.8 -> 1.9 # include/asm-ppc64/proc_fs.h 1.1 -> 1.2 # drivers/net/pcmcia/xirc2ps_cs.c 1.17 -> 1.18 # drivers/char/ftape/zftape/zftape-init.c 1.17 -> 1.18 # net/netlink/netlink_dev.c 1.15 -> 1.16 # fs/nfsd/vfs.c 1.60 -> 1.61 # drivers/usb/image/scanner.h 1.33 -> 1.35 # drivers/char/keyboard.c 1.30 -> 1.31 # drivers/usb/misc/auerswald.c 1.29 -> 1.30 # net/ipv4/netfilter/ipfwadm_core.c 1.14 -> 1.15 # drivers/media/video/dpc7146.c 1.1 -> 1.2 # include/asm-i386/mach-bigsmp/mach_ipi.h 1.1 -> 1.2 # fs/xattr.c 1.13 -> 1.14 # drivers/hotplug/Kconfig 1.6 -> 1.7 # include/asm-i386/mach-numaq/mach_apic.h 1.14 -> 1.15 # drivers/char/dtlk.c 1.11 -> 1.12 # drivers/usb/input/hiddev.c 1.31 -> 1.32 # mm/shmem.c 1.117 -> 1.118 # include/linux/usb.h 1.75 -> 1.77 # drivers/char/serial167.c 1.21 -> 1.22 # drivers/media/video/tda9875.c 1.12 -> 1.13 # include/asm-i386/mach-summit/mach_mpparse.h 1.5 -> 1.6 # arch/ppc64/kernel/irq.c 1.23 -> 1.25 # include/linux/input.h 1.29 -> 1.30 # fs/super.c 1.100 -> 1.101 # drivers/atm/Kconfig 1.3 -> 1.4 # fs/binfmt_elf.c 1.44 -> 1.45 # drivers/scsi/sg.c 1.52 -> 1.53 # drivers/char/riscom8.c 1.14 -> 1.15 # include/linux/blkpg.h 1.4 -> 1.5 # lib/inflate.c 1.2 -> 1.3 # drivers/usb/usb-skeleton.c 1.32 -> 1.34 # arch/ppc64/kernel/rtas-proc.c 1.4 -> 1.6 # arch/ppc64/kernel/setup.c 1.21.1.1 -> 1.24 # arch/i386/kernel/setup.c 1.79 -> 1.80 # drivers/scsi/osst.c 1.42 -> 1.43 # drivers/char/tpqic02.c 1.22 -> 1.23 # include/asm-ppc64/naca.h 1.5 -> 1.6 # drivers/input/joydev.c 1.17 -> 1.18 # sound/oss/soundcard.c 1.15 -> 1.16 # drivers/i2c/busses/i2c-i801.c 1.8 -> 1.9 # include/net/dn_fib.h 1.3 -> 1.4 # include/linux/tty.h 1.15 -> 1.16 # drivers/usb/input/xpad.c 1.13 -> 1.14 # ipc/shm.c 1.25 -> 1.26 # include/asm-i386/mmzone.h 1.11 -> 1.12 # drivers/char/mem.c 1.35 -> 1.36 # drivers/usb/core/usb.c 1.122 -> 1.123 # drivers/usb/misc/brlvger.c 1.16 -> 1.17 # drivers/i2c/busses/i2c-ali15x3.c 1.7 -> 1.8 # arch/ppc64/kernel/traps.c 1.14 -> 1.16 # drivers/char/dsp56k.c 1.12 -> 1.13 # arch/ppc64/kernel/head.S 1.26 -> 1.31 # drivers/isdn/hardware/eicon/divamnt.c 1.5 -> 1.6 # include/asm-ppc64/xics.h 1.4 -> 1.5 # drivers/s390/char/tubio.h 1.11 -> 1.12 # net/ipv4/netfilter/ip_nat_proto_unknown.c 1.2 -> 1.3 # net/decnet/af_decnet.c 1.24 -> 1.25 # drivers/char/serial_tx3912.c 1.12 -> 1.13 # drivers/net/pcmcia/ibmtr_cs.c 1.12 -> 1.13 # fs/ext3/dir.c 1.10 -> 1.11 # drivers/usb/image/mdc800.c 1.29 -> 1.30 # fs/ext2/dir.c 1.21 -> 1.22 # fs/pipe.c 1.24 -> 1.25 # include/linux/sunrpc/svc.h 1.19 -> 1.20 # include/asm-i386/apicdef.h 1.7 -> 1.8 # drivers/input/input.c 1.30 -> 1.31 # include/linux/netfilter_ipv4/ip_nat_protocol.h 1.1 -> 1.2 # arch/ppc64/kernel/xics.c 1.19 -> 1.22 # fs/reiserfs/dir.c 1.18 -> 1.19 # include/linux/list.h 1.28 -> 1.29 # drivers/i2c/busses/i2c-isa.c 1.2 -> 1.3 # net/ipv6/af_inet6.c 1.32 -> 1.34 # drivers/sbus/char/vfc_dev.c 1.10 -> 1.11 # fs/ext3/xattr.c 1.14 -> 1.15 # drivers/char/mwave/mwavedd.h 1.3 -> 1.4 # fs/Kconfig 1.23 -> 1.25 # drivers/usb/media/dabusb.c 1.27 -> 1.28 # fs/buffer.c 1.198 -> 1.199 # mm/vmalloc.c 1.24 -> 1.25 # arch/ppc64/kernel/htab.c 1.32 -> 1.33 # arch/ppc64/mm/init.c 1.40 -> 1.42 # arch/ppc64/kernel/open_pic.c 1.11 -> 1.13 # include/asm-i386/smp.h 1.23 -> 1.24 # drivers/char/tty_io.c 1.90 -> 1.92 # drivers/char/pcxx.c 1.10 -> 1.11 # arch/ppc64/kernel/process.c 1.30 -> 1.31 # drivers/ieee1394/amdtp.c 1.12 -> 1.13 # MAINTAINERS 1.136 -> 1.138 # drivers/s390/char/tubfs.c 1.16 -> 1.17 # drivers/usb/net/rtl8150.c 1.22 -> 1.24 # net/ipv6/netfilter/ip6t_esp.c 1.4 -> 1.5 # arch/ppc64/kernel/pci_dma.c 1.11 -> 1.14 # drivers/char/rio/rio_linux.c 1.19 -> 1.20 # drivers/media/video/msp3400.c 1.17 -> 1.18 # drivers/char/istallion.c 1.20 -> 1.22 # net/atm/lec.c 1.17 -> 1.18 # drivers/char/raw.c 1.31 -> 1.32 # fs/ext2/xattr.c 1.12 -> 1.13 # net/unix/af_unix.c 1.42 -> 1.43 # fs/read_write.c 1.30 -> 1.31 # fs/coda/psdev.c 1.16 -> 1.17 # drivers/usb/class/cdc-acm.c 1.38 -> 1.39 # drivers/usb/misc/rio500.c 1.20 -> 1.21 # include/asm-i386/mach-summit/mach_apic.h 1.22 -> 1.23 # drivers/scsi/st.c 1.60 -> 1.61 # fs/qnx4/dir.c 1.6 -> 1.7 # arch/ppc64/kernel/open_pic_defs.h 1.1 -> 1.2 # include/asm-i386/unistd.h 1.24 -> 1.25 # fs/namespace.c 1.39 -> 1.40 # net/atm/svc.c 1.5 -> 1.7 # drivers/usb/host/ehci-hcd.c 1.47 -> 1.48 # arch/ppc64/kernel/asm-offsets.c 1.12 -> 1.13 # Makefile 1.405 -> 1.406 # fs/ext2/xattr.h 1.5 -> 1.6 # drivers/net/pcmcia/fmvj18x_cs.c 1.19 -> 1.20 # drivers/net/pcmcia/smc91c92_cs.c 1.17 -> 1.18 # sound/core/sound.c 1.25 -> 1.26 # mm/page-writeback.c 1.62 -> 1.63 # include/asm-ppc64/mmu.h 1.6 -> 1.7 # drivers/char/mxser.c 1.21 -> 1.22 # net/decnet/dn_neigh.c 1.5 -> 1.6 # drivers/i2c/i2c-keywest.c 1.1 -> 1.2 # arch/ppc64/mm/numa.c 1.2 -> 1.4 # drivers/mtd/mtdchar.c 1.12 -> 1.13 # drivers/char/rocket.c 1.19 -> 1.20 # arch/ppc64/kernel/syscalls.c 1.9 -> 1.10 # include/asm-ppc64/ptrace.h 1.1 -> 1.2 # drivers/char/rio/rio_linux.h 1.3 -> 1.4 # drivers/media/video/cpia.c 1.24 -> 1.25 # arch/ppc64/kernel/sys_ppc32.c 1.53.1.5 -> 1.59 # net/decnet/TODO 1.4 -> 1.5 # CREDITS 1.81 -> 1.82 # drivers/media/video/tda7432.c 1.10 -> 1.11 # fs/seq_file.c 1.9 -> 1.10 # arch/ppc64/kernel/prom.c 1.22 -> 1.25 # drivers/char/tipar.c 1.6 -> 1.7 # include/asm-i386/kmap_types.h 1.13 -> 1.14 # net/core/skbuff.c 1.25 -> 1.26 # include/linux/security.h 1.16 -> 1.17 # drivers/ieee1394/dv1394.c 1.30 -> 1.31 # drivers/input/evdev.c 1.24 -> 1.25 # drivers/i2c/busses/i2c-viapro.c 1.2 -> 1.3 # arch/ppc64/kernel/iSeries_setup.c 1.10.1.1 -> 1.12 # include/linux/devfs_fs_kernel.h 1.44 -> 1.45 # arch/ppc64/kernel/smp.c 1.31.2.1 -> 1.34 # drivers/media/video/bt832.c 1.2 -> 1.3 # fs/ext2/Makefile 1.8 -> 1.9 # drivers/char/stallion.c 1.21 -> 1.23 # drivers/media/video/saa5249.c 1.14 -> 1.15 # drivers/usb/class/bluetty.c 1.40 -> 1.41 # net/ipv6/route.c 1.26 -> 1.29 # arch/ppc64/mm/fault.c 1.9 -> 1.10 # net/ipv4/tcp_minisocks.c 1.27 -> 1.28 # fs/minix/dir.c 1.13 -> 1.14 # drivers/sgi/char/shmiq.c 1.9 -> 1.10 # arch/ppc64/kernel/pacaData.c 1.5 -> 1.6 # drivers/usb/storage/unusual_devs.h 1.33 -> 1.37 # drivers/i2c/chips/it87.c 1.3 -> 1.6 # drivers/i2c/i2c-dev.c 1.27 -> 1.29 # net/atm/signaling.c 1.5 -> 1.6 # mm/slab.c 1.75 -> 1.78 # fs/nfs/inode.c 1.76 -> 1.77 # net/ipv4/netfilter/ip_nat_standalone.c 1.22 -> 1.23 # include/linux/rtnetlink.h 1.10 -> 1.11 # net/ipv6/ip6_fib.c 1.11 -> 1.14 # drivers/usb/host/ehci-q.c 1.45 -> 1.46 # drivers/s390/char/tubtty.c 1.10 -> 1.11 # scripts/Makefile.build 1.34 -> 1.35 # net/atm/mpc.c 1.10 -> 1.11 # drivers/s390/char/tuball.c 1.11 -> 1.12 # fs/ufs/dir.c 1.13 -> 1.14 # drivers/char/drm/drm_drv.h 1.17 -> 1.18 # drivers/hotplug/cpqphp.h 1.6.1.1 -> 1.9 # drivers/i2c/busses/i2c-amd8111.c 1.7 -> 1.8 # include/linux/atmdev.h 1.8 -> 1.10 # drivers/usb/serial/console.c 1.2 -> 1.3 # drivers/media/video/tuner.c 1.17 -> 1.18 # drivers/tc/zs.c 1.14 -> 1.16 # drivers/char/ipmi/ipmi_devintf.c 1.7 -> 1.8 # drivers/block/paride/pg.c 1.15 -> 1.16 # include/linux/pfkeyv2.h 1.5 -> 1.6 # include/asm-i386/mach-default/mach_mpparse.h 1.3 -> 1.4 # net/ipv4/netfilter/ipchains_core.c 1.13 -> 1.14 # drivers/char/hvc_console.c 1.13.1.4 -> 1.17 # drivers/char/vt.c 1.43 -> 1.45 # drivers/i2c/busses/i2c-amd756.c 1.6 -> 1.7 # drivers/usb/host/ehci.h 1.19 -> 1.20 # arch/ppc64/kernel/pci.c 1.29 -> 1.30 # arch/ppc64/xmon/xmon.c 1.24 -> 1.26 # drivers/char/sysrq.c 1.26 -> 1.27 # arch/ppc64/kernel/misc.S 1.52.2.3 -> 1.57 # drivers/char/specialix.c 1.14 -> 1.15 # arch/sparc64/kernel/power.c 1.12 -> 1.13 # include/asm-i386/mach-default/mach_ipi.h 1.1 -> 1.2 # fs/bfs/dir.c 1.18 -> 1.19 # drivers/media/video/tvmixer.c 1.13 -> 1.15 # fs/hugetlbfs/inode.c 1.22 -> 1.23 # fs/ntfs/inode.c 1.104 -> 1.105 # arch/ppc64/kernel/signal32.c 1.38 -> 1.39 # include/linux/ipx.h 1.2 -> 1.3 # fs/partitions/check.c 1.109 -> 1.111 # drivers/net/ppp_deflate.c 1.9 -> 1.10 # drivers/input/mousedev.c 1.24 -> 1.25 # Documentation/Changes 1.33 -> 1.34 # arch/ppc64/kernel/rtas_flash.c 1.4 -> 1.5 # drivers/char/misc.c 1.18 -> 1.19 # drivers/bluetooth/hci_usb.c 1.26 -> 1.27 # drivers/char/moxa.c 1.17 -> 1.18 # drivers/hotplug/cpqphp_pci.c 1.16 -> 1.18 # drivers/net/ppp_generic.c 1.24 -> 1.25 # include/asm-i386/mach-bigsmp/mach_apic.h 1.8 -> 1.9 # fs/ext3/xattr.h 1.6 -> 1.7 # drivers/net/pcmcia/3c589_cs.c 1.16 -> 1.17 # kernel/panic.c 1.10 -> 1.11 # include/asm-ppc64/mmzone.h 1.9 -> 1.10 # net/decnet/dn_route.c 1.15 -> 1.16 # drivers/atm/iphase.c 1.18 -> 1.19 # drivers/isdn/capi/capi.c 1.40 -> 1.42 # include/asm-ppc64/io.h 1.7 -> 1.8 # drivers/input/tsdev.c 1.10 -> 1.11 # drivers/char/sh-sci.c 1.18 -> 1.19 # sound/core/info.c 1.24 -> 1.25 # arch/i386/kernel/timers/timer.c 1.6 -> 1.7 # drivers/macintosh/macserial.c 1.20 -> 1.21 # sound/sound_core.c 1.17 -> 1.18 # drivers/char/ppdev.c 1.20 -> 1.21 # include/asm-ppc64/topology.h 1.6 -> 1.7 # net/atm/clip.c 1.7 -> 1.8 # net/decnet/dn_nsp_out.c 1.7 -> 1.8 # fs/ext3/fsync.c 1.7 -> 1.8 # arch/ppc64/kernel/Makefile 1.22 -> 1.23 # arch/ppc64/kernel/module.c 1.2 -> 1.4 # include/asm-ppc64/rtas.h 1.5 -> 1.6 # net/decnet/Kconfig 1.1 -> 1.2 # include/linux/slab.h 1.20 -> 1.21 # arch/ppc64/kernel/align.c 1.6 -> 1.8 # net/ipv4/fib_frontend.c 1.10 -> 1.11 # include/linux/seq_file.h 1.4 -> 1.5 # arch/ppc64/kernel/ioctl32.c 1.25.1.2 -> 1.30 # drivers/char/amiserial.c 1.19 -> 1.20 # drivers/usb/core/file.c 1.7 -> 1.8 # arch/ppc64/kernel/pSeries_lpar.c 1.20 -> 1.21 # drivers/usb/misc/speedtch.c 1.80 -> 1.81 # include/asm-i386/mach-default/mach_apic.h 1.22 -> 1.23 # drivers/macintosh/adb.c 1.18 -> 1.19 # net/ipv6/netfilter/ip6t_ipv6header.c 1.4 -> 1.5 # drivers/usb/serial/bus.c 1.7 -> 1.8 # net/decnet/dn_fib.c 1.4 -> 1.5 # drivers/hotplug/ibmphp_core.c 1.24 -> 1.26 # drivers/char/ip2main.c 1.28 -> 1.31 # drivers/usb/serial/usb-serial.h 1.29 -> 1.30 # net/atm/common.c 1.15 -> 1.17 # (new) -> 1.1 include/asm-i386/mach-generic/mach_mpparse.h # (new) -> 1.1 arch/i386/mach-generic/probe.c # (new) -> 1.1 arch/i386/mach-generic/default.c # (new) -> 1.1 include/linux/atm_he.h # (new) -> 1.2 drivers/atm/he.c # (new) -> 1.1 arch/i386/mach-generic/bigsmp.c # (new) -> 1.1 include/asm-i386/mach-generic/mach_apic.h # (new) -> 1.1 include/linux/atmbr2684.h # (new) -> 1.1 net/atm/br2684.c # (new) -> 1.1 drivers/atm/he.h # (new) -> 1.1 fs/ext3/xattr_security.c # (new) -> 1.1 fs/ext2/xattr_security.c # (new) -> 1.1 net/decnet/netfilter/dn_rtmsg.c # (new) -> 1.1 include/asm-ppc64/systemcfg.h # (new) -> 1.1 arch/i386/mach-generic/Makefile # (new) -> 1.1 net/decnet/netfilter/Makefile # (new) -> 1.1 include/asm-i386/genapic.h # (new) -> 1.1 arch/ppc64/kernel/proc_ppc64.c # (new) -> 1.1 include/asm-i386/mach-generic/mach_ipi.h # (new) -> 1.1 net/decnet/netfilter/Kconfig # (new) -> 1.1 arch/i386/mach-generic/summit.c # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/05/04 torvalds@home.transmeta.com 1.1042.94.10 # Linux 2.5.69 # -------------------------------------------- # 03/05/05 anton@samba.org 1.1057.2.13 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/tmp3 # -------------------------------------------- # 03/05/04 davem@nuts.ninka.net 1.1042.1.183 # [ATM]: mpc.c warning fixes. # -------------------------------------------- # 03/05/04 davem@nuts.ninka.net 1.1042.1.184 # [NETFILTER IPV6]: Fix warnings. # -------------------------------------------- # 03/05/04 davem@nuts.ninka.net 1.1042.1.185 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/05 anton@samba.org 1.1062 # Merge samba.org:/scratch/anton/tmp3 # into samba.org:/scratch/anton/linux-2.5_ppc64 # -------------------------------------------- # 03/05/05 anton@samba.org 1.1057.2.14 # Merge samba.org:/scratch/anton/tmp3 # into samba.org:/scratch/anton/linux-2.5_ppc64drivers # -------------------------------------------- # 03/05/04 torvalds@home.transmeta.com 1.1063 # Merge http://ppc.bkbits.net/for-linus-ppc64drivers # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/05 acme@conectiva.com.br 1.1042.91.2 # o list.h: implement list_for_each_entry_safe # -------------------------------------------- # 03/05/05 acme@conectiva.com.br 1.1042.91.3 # o ipx: convert ipx_interface handling to use list_head # -------------------------------------------- # 03/05/05 bunk@fs.tum.de 1.1042.81.3 # [PATCH] USB: kill the last occurances of usb_serial_get_by_minor # # I got an error at the final linking of 2.5.68-bk11. It seems the patch # below is needed. # -------------------------------------------- # 03/05/05 geert@linux-m68k.org 1.1042.81.4 # [PATCH] USB: Big endian RTL8150 # # The RTL8150 USB Ethernet driver doesn't work on big endian machines. Here are # patches (for both 2.4.x and 2.5.x) to fix that. The fix was tested on the # 2.4.20 and 2.4.21-rc1 version of the driver on big endian MIPS. # # Changes: # - Fix endianness of rx_creg (from Dimitri Torfs ) # - Kill unused last parameter of async_set_registers() # -------------------------------------------- # 03/05/05 davem@redhat.com 1.1042.81.5 # [PATCH] USB speedtouch fix # # Missing header file. Please apply. # -------------------------------------------- # 03/05/05 philipp@void.at 1.1042.81.6 # [PATCH] USB: unusual_devs.h patch # -------------------------------------------- # 03/05/05 greg@kroah.com 1.1064 # Merge kroah.com:/home/greg/linux/BK/bleed-2.5 # into kroah.com:/home/greg/linux/BK/gregkh-2.5 # -------------------------------------------- # 03/05/05 nicolas@dupeux.net 1.1065 # [PATCH] USB: UNUSUAL_DEV for aiptek pocketcam # # Here is the unusual_dev entry i'm using to get my digital camera. # # # diff -cr linux/drivers/usb/storage/unusual_devs.h linux_vaxvms/drivers/usb/storage/unusual_devs.h # *** linux/drivers/usb/storage/unusual_devs.h 2003-03-14 21:32:46.000000000 +0100 # -------------------------------------------- # 03/05/05 acme@conectiva.com.br 1.1042.91.4 # o ipx: convert ipx_route to use list_head # -------------------------------------------- # 03/05/05 davem@nuts.ninka.net 1.1063.1.1 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.1.2 # [IPSEC]: Fix SADB_EALG_{3,}DESCBC values. # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.1.3 # Merge bk://kernel.bkbits.net/acme/ipx-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.1.4 # [ATM]: Fix some CPP pasting in ambassador driver. # -------------------------------------------- # 03/05/06 chas@locutus.cmf.nrl.navy.mil 1.1063.1.5 # [ATM]: Fix excessive stack usage in iphase driver. # -------------------------------------------- # 03/05/06 chas@locutus.cmf.nrl.navy.mil 1.1063.1.6 # [ATM]: svcs possible race with sigd. # -------------------------------------------- # 03/05/06 steve@gw.chygwyn.com 1.1063.1.7 # [FS]: Add seq_release_private and proc_net_fops_create helpers. # -------------------------------------------- # 03/05/06 steve@gw.chygwyn.com 1.1063.1.8 # [DECNET]: seq file conversions and fixes. # o Removed blksize from decnet device parameters - use the device mtu like we # ought to. # o Removed /proc/net/decnet_route file - I don't think anybody ever used it # and it was lacking a full enough description of the routes to be useful. # ip -D route list is much better :-) # o Added rt_local_src entry to decnet routes so that we get the local source # address right when forwarding. # o Added correct proto argument to struct flowi for routing # o MSG_MORE in sendmsg (ignored, but accepted whereas before we'd error) # o /proc/net/decnet converted to seq_file # o /proc/net/decnet_dev converted to seq_file # o /proc/net/decnet_cache converted to seq_file # o Use pskb_may_pull() and add code to linearize skbs on the input path # except for those containing data. # o Fixed returned packet code (mostly - some left to do) # o update_pmtu() method for decnet dst entries (ip_gre device assumes this # method exists - well I think it does :-) # o Fixed bug in forwarding to get IE bit set correctly # o Fixed compile bugs with CONFIG_DECNET_ROUTE_FWMARK pointed out by Adrian # Bunk # o Fixed zero dest code to grab an address from loopback # o Fixed local routes in dn_route_output_slow() # o Fixed error case in dn_route_input/output_slow() pointed out by Rusty # -------------------------------------------- # 03/05/06 rusty@rustcorp.com.au 1.1063.1.9 # [NETFILTER]: Fix Module Usage in ipchains and ipfwadm. # Gets rid of some warnings. Manipulating our own module count inside the # sockopt is safe, because unregistering that sockopt will block. # -------------------------------------------- # 03/05/06 rusty@rustcorp.com.au 1.1063.1.10 # [NETFILTER]: Make NAT code handle non-linear skbs. # Makes the NAT code and all NAT helpers handle non-linear skbs. # Main trick is to introduce skb_ip_make_writable which handles all # the decloning, linearizing, etc. # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.1.11 # [NETFILTER]: ip_nat_proto_{icmp,udp}.c need ip_nat_core.h # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.1.12 # [IPV6]: Kill spurious module_{get,put}(). # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.1.13 # [BLUETOOTH]: Fix hci_usb build. # -------------------------------------------- # 03/05/06 yoshfuji@linux-ipv6.org 1.1063.1.14 # [IPV6]: Fix offset in ICMPV6_HDR_FIELD messages. # -------------------------------------------- # 03/05/06 yoshfuji@linux-ipv6.org 1.1063.1.15 # [IPV^]: Use correct icmp6 type in ip6_pkt_discard. # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.2.1 # [SPARC64]: Only use power interrupt when button property exists. # -------------------------------------------- # 03/05/06 chas@cmf.nrl.navy.mil 1.1063.1.16 # [ATM]: Fix foul up in lec driver. # -------------------------------------------- # 03/05/06 torvalds@home.transmeta.com 1.1063.3.1 # Merge bk://kernel.bkbits.net/davem/sparc-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.1.17 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.1.18 # [IPV6]: Remove illogical bug check in fib6_del. # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.3.2 # Merge gregkh@kernel.bkbits.net:/home/gregkh/linux/i2c-2.5 # into kroah.com:/home/greg/linux/BK/i2c-2.5 # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.4.1 # Merge gregkh@kernel.bkbits.net:/home/gregkh/linux/pci-2.5 # into kroah.com:/home/greg/linux/BK/pci-2.5 # -------------------------------------------- # 03/05/06 roland@frob.com 1.1063.5.1 # [PATCH] core dump psinfo.pr_sname letter fix # # This patch makes the state letter in the pr_sname field in core dumps # correct for stopped and zombie threads. The order needed to be changed when # the TASK_* values changed. This matches the letters used in sched.c:show_task. # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.4.2 # [PATCH] PCI Hotplug: fix up the compaq driver to work properly again. # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.4.3 # [PATCH] PCI Hotplug: fix up the ibm driver to work properly again. # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.4.4 # [PATCH] PCI Hotplug: fix compiler warning in ibm driver. # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.4.5 # [PATCH] PCI Hotplug: fix up the acpi driver to work properly again. # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.4.6 # [PATCH] PCI Hotplug: fix dependancies for CONFIG_HOTPLUG_PCI_ACPI # # Thanks to Adrian Bunk for pointing this out. # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.4.7 # PCI Hotplug: export the acpi_resource_to_address64 function, as the acpi pci hotplug driver needs it. # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.3.3 # Merge kroah.com:/home/greg/linux/BK/bleed-2.5 # into kroah.com:/home/greg/linux/BK/i2c-2.5 # -------------------------------------------- # 03/05/06 kraxel@bytesex.org 1.1063.3.4 # [PATCH] i2c #1/3: listify i2c core # # This is the first of tree patches for i2c. Trying to get the i2c # cleanups finshed before 2.6.x, so we (hopefully) don't have a # ever-changing i2c subsystem in 2.7.x again (which is very annonying for # driver maintainance). # # Changes: # # * listify i2c-core, i.e. make it use instead of # statically-sized arrays, removed lots of ugly code :) # * added i2c_(get|put)_adapter, changed i2c-dev.c to use these # functions instead maintaining is own adapter list. # * killed the I2C_DF_DUMMY flag which had the strange semantics to # make the i2c subsystem call driver->attach_adapter on detaches. # Added a detach_adapter() callback instead. # * some other minor cleanups along the way ... # -------------------------------------------- # 03/05/06 kraxel@bytesex.org 1.1063.3.5 # [PATCH] i2c #2/3: add i2c_clients_command # # Changes: # # * adds a i2c_clients_command() function to i2c-core which calls # the ->command() callback of all clients attached to a adapter. # * make bttv + saa7134 drivers use that function instead of mucking # with the i2c_adapter struct themself. # -------------------------------------------- # 03/05/06 kraxel@bytesex.org 1.1063.3.6 # [PATCH] i2c #3/3: add class field to i2c_adapter # # This is the last of three patches for i2c. It introduces a new field # to i2c_adapter which classifies the kind of hardware a i2c adapter # belongs to (analog tv card / dvb card / smbus / gfx card ...). i2c chip # drivers can use this infomation to decide whenever they want to look for # hardware on that adapter or not. It doesn't make sense to probe for a # tv tuner on a smbus for example ... # -------------------------------------------- # 03/05/06 torvalds@home.transmeta.com 1.1063.4.8 # Merge bk://kernel.bkbits.net/gregkh/linux/pci-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.3.7 # [PATCH] i2c: fix compile error due to previous patches. # -------------------------------------------- # 03/05/06 warp@mercury.d2dc.net 1.1063.3.8 # [PATCH] i2c: it87 patch. # # More or less straight forward patch. # # Fix a typo in the comments at the top. # Show all 9 voltage inputs. # Show all 3 fan inputs. # Allow you to select the temp sensor type from the sysfs interface, # instead of just with the temp_type module option. # (1 = diode, 2 = thermistor, 0 = disabled). # # I'm still trying to figure out the registers for PWM fan controller # support. # -------------------------------------------- # 03/05/06 sri@us.ibm.com 1.1063.5.2 # o net/socket: fix bug in sys_accept # # module_put() gets called twice on error. Once via the explicit module_put and # the second via sock_release(). Also i think we should do a __module_get() with # newsock's owner(although same as the original listening sock). # -------------------------------------------- # 03/05/06 torvalds@home.transmeta.com 1.1063.3.9 # Merge bk://kernel.bkbits.net/gregkh/linux/i2c-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/06 paulkf@microgate.com 1.1063.3.10 # [PATCH] synclink update # # - Add support for hardware version 2 (universal PCI) of synclink adapter # - Use mod_timer() function # -------------------------------------------- # 03/05/06 paulkf@microgate.com 1.1063.3.11 # [PATCH] n_hdlc update # # - Use C99 initializers # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.1.19 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.1.20 # Merge bk://kernel.bkbits.net/acme/unix-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.1.21 # [IPV4/IPV6]: Set owner field in family ops. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1066 # [PATCH] USB: add usb class support for usb drivers that use the USB major # # This also consolodates the devfs calls for the USB drivers. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1067 # [PATCH] USB: converted usblp over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1068 # [PATCH] USB: converted mdc800 over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1069 # [PATCH] USB: converted scanner over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1070 # [PATCH] USB: converted dabusb over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1071 # [PATCH] USB: converted auerswald over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1072 # [PATCH] USB: converted brlvger over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1073 # [PATCH] USB: converted rio500 over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1074 # [PATCH] USB: converted usblcd over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1075 # [PATCH] USB: converted usb-skeleton over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1076 # [PATCH] USB: remove #include from some drivers that do not need it. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1077 # USB: converted hiddev over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 rddunlap@osdl.org 1.1063.1.22 # [NET]: Spelling/typo fixes in rtnetlink.h # -------------------------------------------- # 03/05/07 rddunlap@osdl.org 1.1063.1.23 # [IPV6]: Convert /proc/net/rt6_stats to seq_file. # -------------------------------------------- # 03/05/07 bdschuym@pandora.be 1.1063.1.24 # [BRIDGE]: Change pkt_type to PACKET_HOST earlier. # -------------------------------------------- # 03/05/07 shemminger@osdl.org 1.1063.1.25 # [IPV4]: Replace explicit dev->refcount bumps with dev_hold. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.1.26 # [NET]: Remove duplicated alloc_skb debug check. # -------------------------------------------- # 03/05/07 chas@cmf.nrl.navy.mil 1.1063.1.27 # [ATM]: Add Forerunner HE support. # -------------------------------------------- # 03/05/07 chas@cmf.nrl.navy.mil 1.1063.1.28 # [ATM]: Forward port br2864 to 2.5.x # -------------------------------------------- # 03/05/07 chas@cmf.nrl.navy.mil 1.1063.1.29 # [ATM]: Clip locking and more atmvcc cleanup. # -------------------------------------------- # 03/05/07 rddunlap@osdl.org 1.1063.1.30 # [IPV6]: Fix typos in ip6_fib.c # -------------------------------------------- # 03/05/07 rddunlap@osdl.org 1.1063.1.31 # [IPV6]: Use time_after() etc. for comparing jiffies. # -------------------------------------------- # 03/05/07 olof@austin.ibm.com 1.1063.1.32 # [TCP]: tcp_twkill leaves death row list in inconsistent state over tcp_timewait_kill. # -------------------------------------------- # 03/05/07 davem@nuts.ninka.net 1.1063.1.33 # [ATM]: Fix build of HE driver. # -------------------------------------------- # 03/05/07 torvalds@penguin.transmeta.com 1.1063.3.12 # Whee. Fix ancient mailing address. # -------------------------------------------- # 03/05/07 torvalds@penguin.transmeta.com 1.1063.1.34 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into penguin.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/07 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/05/07 torvalds@penguin.transmeta.com 1.1079 # Merge bk://kernel.bkbits.net/gregkh/linux/linus-2.5 # into penguin.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.1 # [PATCH] tc_zs tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.2 # [PATCH] specialix tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.3 # [PATCH] stallion tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.4 # [PATCH] serial_tx3912 tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.5 # [PATCH] sh-sci tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.6 # [PATCH] ser_a2232 tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.7 # [PATCH] serial167 tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.8 # [PATCH] rocket tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.9 # [PATCH] sgi/char/sgiserial tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.10 # [PATCH] rio tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.11 # [PATCH] riscom8 tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.12 # [PATCH] pcxx tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.13 # [PATCH] mxser tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.14 # [PATCH] istallion tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.15 # [PATCH] moxa tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.16 # [PATCH] ip2main tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.17 # [PATCH] isicom tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.18 # [PATCH] esp tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.19 # [PATCH] hvc_console tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.20 # [PATCH] dz tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.21 # [PATCH] cyclades tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.22 # [PATCH] amiserial tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.23 # [PATCH] macintosh/macserial tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.24 # [PATCH] isdn/capi tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.6.25 # [PATCH] vme_scc tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.6.26 # TTY: add tty class support for all tty devices. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.6.27 # TTY: changes based on tty_register_device() paramater change. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.6.28 # TTY: remove usb-serial sysfs dev file as it is now redundant. # -------------------------------------------- # 03/05/07 torvalds@home.transmeta.com 1.1080 # Make lib/inflate.c look remotely like ANSI C, so that it can be # properly checked with the rest of the kernel. # -------------------------------------------- # 03/05/07 torvalds@home.transmeta.com 1.1081 # Avoid using undefined preprocessor symbols: check CONFIG_MK7 with # "defined()" rather than using it as a value. # -------------------------------------------- # 03/05/07 torvalds@home.transmeta.com 1.1082 # Use "__attribute__" consistently. # -------------------------------------------- # 03/05/07 torvalds@home.transmeta.com 1.1083 # Allow external checkers to overrid the "cond_syscall()" macro. # -------------------------------------------- # 03/05/07 torvalds@home.transmeta.com 1.1084 # Support a "checking" mode for kernel builds, that runs a # user-supplied source checker on all C files before compiling # them. # # I'll release the actual checker once I've cleaned it up a # bit more (yay, all the copyright paperwork completed!) # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1085 # [PATCH] generic subarchitecture for ia32 # # From: Andi Kleen # # This patch adds an generic x86 subarchitecture. It is intended to provide # an dynamic interface for APIC drivers. There are already three subarchitectures # (bigsmp, summit, default) that only differ in how they drive the local APIC. # A fourth - Unisys ES7000 - is scheduled to be merged soon. # # The subarchitecture concept separated this nicely, but it has the big # drawback that they are compile time options. A Linux vendor cannot # ship own binary kernel rpms for all of these machines. Runtime probing # is needed instead. # # This patch adds a new "generic" subarchitecture that just acts as a # dynamic switching layer for APIC drivers. It only tries to virtualize # the APICs, no attempt is made to cover further incompatiblities. # This means machines like the Visual Workstation, pc9800 or # Voyager are not covered; but these are unlikely to be supported by # binary distributions anyways. # # The generic arch reuses the existing interface in mach_ipi / mach_mpparse.h / # mach_apic.h and just pulls it using some macros into an "struct genapic" # object. The main APIC code does not recognize it, it is all hidden # in the mach-generic include files. # # Auto detection of APIC types is supported in the usual way used by # existing ports like Summit - checking ACPI or mptables for specific # signatures - or it can be specified by the user using a new "apic=" # boot option. I also moved the DMI scan to before the generic # subarchitecture probe, so DMI could be used in future too to probe # specific machines. # # Some minor hacks were needed to avoid circular declaration of a few # symbols, but overall it's fairly clean. # # The patch has been tested on a Summit machine, an generic 4 virtual CPUs # Xeon and on an ES7000. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1086 # [PATCH] Fix .altinstructions linking failures # # From: Andi Kleen # # Some configs didn't link anymore because they got references from # .altinstructions to __exit functions. Fixing it at the linker level is not # easily possible. This patch just discards .text.exit at runtime instead of # link time to avoid this. # # It will also fix a related problem with .eh_frame in modern gcc (so far only # observed on x86-64, but could happen on i386 too) # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1087 # [PATCH] cpia driver __exit fix # # From: Andi Kleen # # This driver was bogusly relying on the dropping of the __exit section at link # time. cpia_exit() is calling proc_cpia_destroy(), which doesn't even exist # if !CONFIG_MODULE. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1088 # [PATCH] fix OSS opl3sa2 compilation # # From: Zwane Mwaikambo # # There was a 2.4 merge from Alan Cox, but a few #ifdef's got shuffled around # in the process, resulting in a broken build for !CONFIG_PM # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1089 # [PATCH] misc fixes # # - ifdef fix in kmap_types.h (Oleg Drokin) # # - remove redundant ext3 inclusions (Burton Windle) # # - Fix misidentified warning printk in vmalloc.c # # - radeon_cp printk warning fix (Randy Dunlap) # # - Update minimum binutils version for the ".incbin" thing in vsyscall.S # # - update raw driver to recent module API. # # - update my email address # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1090 # [PATCH] mwave build fix # # From: Michael Buesch and Paul Schroeder. # # mwavedd.h needs and smapi.h # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1091 # [PATCH] drm timer initialisation fix # # The timer is being initialised too late (in ->open()). If modprobe fails we # get an uninitialised timer warning. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1092 # [PATCH] slab: initialisation cleanup and oops fix # # From: Manfred Spraul # # attached is the promised cleanup/bugfix patch for the slab bootstrap: # # - kmem_cache_init & kmem_cache_sizes_init merged into one function, # called after mem_init(). It's impossible to bring slab to an operational # state without working gfp, thus the early partial initialization is not # necessary. # # - g_cpucache_up set to FULL at the end of kmem_cache_init instead of the # module init call. This is a bugfix: slab was completely initialized, # just the update of the state was missing. # # - some documentation for the bootstrap added. # # The minimal fix for the bug is a two-liner: move g_cpucache_up=FULL from # cpucache_init to kmem_cache_sizes_init, but I want to get rid of # kmem_cache_sizes_init, too. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1093 # [PATCH] sysrq-S, sysrq-U cleanups # # From: Christoph Hellwig # # Change sysrq sync/remount from a magic bdflush hook to proper pdflush # operations. The sync operation reuses most of the regular sys_sync path now # instead of implementing it's own superblock walking and (broken) local disk # detection, the remount implementation has been moved to super.c, cleaned up # and updated for the last two years locking changes. It also shares some code # with the regular remount path now. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1094 # [PATCH] s/UPDATE_ATIME/update_atime/ cleanup # # From: Stewart Smith # # Remove the UPDATE_ATIME() macro, use update_atime() directly. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1095 # [PATCH] irqreturn_t for drivers/net/pcmcia # # From: Zwane Mwaikambo # # update pcmcia drivers for new IRQ API # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1096 # [PATCH] keyboard.c Fix CONFIG_MAGIC_SYSRQ+PrintScreen # # From: Chris Heath # # This patch fixes the PrintScreen key when CONFIG_MAGIC_SYSRQ is enabled. It # allows you to use that key normally when Alt is not being pressed. Patch is # against kernel 2.5.68. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1097 # [PATCH] Don't use devfs names in disk_name() # # From: Christoph Hellwig # # disk_name() (and hence bdevname()) are now returning devfs-style device names # when devfs is enabled. # # This is nice, but these names are very long, and they overflow the 32-char # buffers which these functions use. # # The choices are: # # a) Use a bigger buffer (increase BDEVNAME_SIZE). # # This might be practical. But how big? # # b) return the name in kmalloced memory, make caller free it up. Yuk. # # c) Add a print_bdevname() thing and intersperse that amongst the printk's. # This would work. # # d) Just print the non-devfs device name. That's what this patch does. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1098 # [PATCH] devfs: API changes # # From: Christoph Hellwig # # Some people may already have noticed that I've been revamping the devfs API # recently. The worst offender still left is devfs_register, it's prototype # is: # # devfs_handle_t devfs_register(devfs_handle_t dir, # const char *name, unsigned int flags, # unsigned int major, unsigned int minor, # umode_t mode, void *ops, void *info) # # Of these: # # - dir and flags are always zero # - the return value is never used # - info is only used in one driver which doesn't even need it for # operation # - umode_t always describes a character device # - name very often comes from a stack buffer we sprintf'ed into # # so obviously we really want a much simpler API instead. My first draft for # this was: # # int devfs_mk_cdev(dev_t dev, umode_t mode, # struct file_operations *fops, void *info, # const char *fmt, ...) # # this removes the unused argumens, switches to a proper dev_t for the device # number and allows to directly use a printf-like expression as name, getting # rid of the temporary buffers. # # Now Al has reappeared and put the first steps of his CIDR for charater device # on public ftp and we'll soon have a similar lookup object + fops mechanism in # generic code as we already habe for blockdevices, i.e. the devfs code to # assign fops from an entry will become superflous as generic code already does # it. That means the fops and info arguments are obsolete before they were # introduced, so I'd like to propose the following API instead: # # int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...) # # which is much nicer anyway. The educated reader will notice that this is # exactly the same prototype devfs_mk_bdev has so I'll probably get suggestions # to merge those two into some kind of devfs_mk_node soon. Personally I don't # like that as character and blockdevices are two really separate entinities # and I'll like to keep them as separate as possible. # # Example patch that introduces the API and converts drivers/input attached. # # Every driver which calls devfs_mk_cdev (about 50) needs conversion. Note # that the transition can happen in pieces - devfs_register continues to work # after this patch, it's just the plan to get rid of it in the end. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1099 # [PATCH] remove partition_name() # # From: Christoph Hellwig # # partition_name() is a variant of __bdevname() that caches results and # returns a pointrer to kmalloc()ed data instead of printing into a buffer. # Due to it's caching it gets utterly confused when the name for a dev_t # changes (can happen easily now with device mapper and probably in the # future with dynamic dev_t users). # # It's only used by the raid code and most calls are through a wrapper, # bdev_partition_name() which takes a struct block_device * that maybe be # NULL. # # The patch below changes the bdev_partition_name() to call bdevname() if # possible and the other calls where we really have nothing more than a dev_t # to __bdevname. # # Btw, it would be nice if someone who knows the md code a bit better than me # could remove bdev_partition_name() in favour of direct calls to bdevname() # where possible - that would also get rid of the returns pointer to string # on stack issue that this patch can't fix yet. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1100 # [PATCH] switch most remaining drivers over to devfs_mk_bdev # # From: Christoph Hellwig # # This is a pretty huge patch, but splitting it doesn't make a lot # of sense.. # # (USB may still need work) # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1101 # [PATCH] dvbdev fixes # # From: Monchi Abbad # # I found a mistake in the dvbdev.c file when creating the dvb /devfs files, # it created /dev/dvb/adapter0device0 instead of /dev/dvb/adapter0/device0. # But here is a simple fix. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1102 # [PATCH] access_ok() race fix for 80386. # # From: Manfred Spraul # # Real 80386 cpus ignore the write protected bit in the page tables when # running in supervisory mode. Thus the write protected bit must be checked by # software. The current implementation does that check during access_ok(). # This can result in data corruptions, if kswapd starts a swap-out between the # access_ok and the actual write operation. # # To fix this, the patch moves the check from access_ok() into # __copy_to_user_ll(), and redirects all user space writes into # __copy_to_user_ll(). The patch only affects kernels build for 80386 cpus. # Additionally, the patch removes the dead prototypes for __put_user_{1,2,4,8}. # # Due to the uninlining of access_ok, the .text segment is now ~ 8 kB shorter. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1103 # [PATCH] hold i_sem on swapfiles # # If a swapfile is ftruncated while in use, subsequent swapout will scribble on # the filesystem. # # This is a case of root-shoot-foot, but wrecking the fs is a fairly rude # response. And it's easy to fix: hold i_sem across the life of the swapon. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1104 # [PATCH] remove unnecessary PAE pgd set # # From: Dave Hansen , Bill Irwin # # With PAE on, there are only 4 PGD entries. The kernel ones never change, # so there is no need to copy them when a vmalloc fault occurs. This was # this was causing problems with the split pmd patches, but it is still # correct for mainline. # # Tested with and without PAE. I ran it in a loop turning on and off 10 swap # partitions, which is what excited the original bug. # http://bugme.osdl.org/show_bug.cgi?id=640 # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1105 # [PATCH] account for slab reclaim in try_to_free_pages() # # try_to_free_pages() currently fails to notice that it successfully freed slab # pages via shrink_slab(). So it can keep looping and eventually call # out_of_memory(), even though there's a lot of memory now free. # # And even if it doesn't do that, it can free too much memory. # # The patch changes try_to_free_pages() so that it will notice freed slab pages # and will return when enough memory has been freed via shrink_slab(). # # Many options were considered, but must of them were unacceptably inaccurate, # intrusive or sleazy. I ended up putting the accounting into a stack-local # structure which is pointed to by current->reclaim_state. # # One reason for this is that we can cleanly resurrect the current->local_pages # pool by putting it into struct reclaim_state. # # (current->local_pages was removed because the per-cpu page pools in the page # allocator largely duplicate its function. But it is still possible for # interrupt-time allocations to steal just-freed pages, so we might want to put # it back some time.) # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1106 # [PATCH] slab: additional debug checks # # From: Manfred Spraul # # below is the promised patch for better slab debugging, against 2.5.68-mm4: # # Changes: # # - enable redzoning and last user accounting even for large objects, if # that doesn't waste too much memory # # - document why FORCED_DEBUG doesn't enable redzoning&last user accounting # for some caches. # # - check the validity of the bufctl chains in a slab in __free_blocks. # This detects double-free error for the caches without redzoning. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1107 # [PATCH] reduced overheads in fget/fput # # From: Dipankar Sarma # # # fget() shows up on profiles, especially on SMP. Dipankar's patch # special-cases the situation wherein there are no sharers of current->files. # # In this situation we know that no other process can close this file, so it # is not necessary to increment the file's refcount. # # It's ugly as sin, but makes a substantial difference. # # The test is # # dd if=/dev/zero of=foo bs=1 count=1M # # On 4CPU P3 xeon with 1MB L2 cache and 512MB ram: # # kernel sys time std-dev # ------------ -------- ------- # # UP - vanilla 2.104 0.028 # UP - file 1.867 0.019 # # SMP - vanilla 2.976 0.023 # SMP - file 2.719 0.026 # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1108 # [PATCH] allow i8042 interrupt sharing # # Ed Tomlinson has a machine on which some other device grabs IRQ12 first, and # the 8042 doesn't work. Enabling shared iRQs in the 8042 driver fixes it up. # Alan has confirmed that this is OK. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1109 # [PATCH] select() speedup # # From: Christoph Hellwig # # Originally by David Mosberger, testing by Roger Luethi. From the ia64 tree. # # Basically, it avoids going to memory all the time. What this does is make # life a lot easier for gcc, so it can actually do a decent amount of # optimization. The restructuring clearly is less important for out-of-order # CPUs, but even there it gives some benefits. # # More specifically, the loop is now structured to operate one "unsigned long" # at a time, rather than one bit at a time. Of course, you still need to # process all the bits, but most of the relevant state in the inner loop can be # kept in registers. # # Roger Luethi measured the routine on a bunch of different machines (mostly # x86, IIRC: P5, P6, Crusoe, Athlons) and performance improved there, too (and # it should definitely improve performance on any RISC-like architecture). # # # Roger's benchmarking results (vs number of fd's): # # File TCP # Numbfer of fd's: 10 250 500 10 250 500 # # UP, Pentium MMX 233MHz original 8.2 108.5 212.8 11.0 180.0 356.5 # UP, Pentium MMX 233MHz w/patch 7.4 87.6 171.1 10.4 163.6 323.4 # # MP, Pentium MMX 233MHz original 15.7 283.8 562.8 18.9 354.4 705.5 # MP, Pentium MMX 233MHz w/patch 14.6 255.6 506.5 17.8 332.8 664.1 # # UP, Athlon 1394 MHz original 1.3 13.4 26.1 1.9 24.7 48.6 # UP, Athlon 1394 MHz w/patch 1.2 11.0 21.5 1.6 22.3 43.8 # # MP, Athlon 1394 MHz original 1.6 22.4 44.6 1.9 30.9 60.5 # MP, Athlon 1394 MHz w/patch 1.5 21.2 41.7 1.9 30.2 59.6 # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1110 # [PATCH] Move security_d_instantiate hook calls # # From: Stephen Smalley # # This patch moves the security_d_instantiate hook calls in d_instantiate and # d_splice_alias after the inode has been attached to the dentry. This # change is necessary so that security modules can internally call the # getxattr inode operation (which takes a dentry parameter) from this hook to # obtain the inode security label. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1111 # [PATCH] ext3 xattr handler for security modules # # From: Stephen Smalley # # This patch against 2.5.68 implements an xattr handler for ext3 to support the # use of extended attributes by security modules for storing file security # labels. As per the earlier discussion of extended attributes for security # modules, this handler uses a "security." prefix and allows for per-module # attribute names. Security checking for userspace access to these attributes # can be performed by the security module using the LSM hooks in fs/xattr.c, # and the security module is free to internally use the inode operations # without restriction for managing its security labels. Unlike the trusted # namespace, these labels are used internally for access control purposes by # the security modules, and controls over userspace access to them require # finer granularity than capable() supports. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1112 # [PATCH] ext2 xattr handler for security modules # # From: Stephen Smalley # # This patch against 2.5.68 implements an xattr handler for ext2 to support the # use of extended attributes by security modules for storing file security # labels. As per the earlier discussion of extended attributes for security # modules, this handler uses a "security." prefix and allows for per-module # attribute names. Security checking on userspace access to these attributes # can be performed by the security module using the LSM hooks in fs/xattr.c, # and the security module is free to internally use the inode operations # without restriction for managing its security labels. Unlike the trusted # namespace, these labels are used internally for access control purposes by # the security module, and controls over userspace access to them require finer # granularity than capable() supports. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1113 # [PATCH] Change LSM hooks in setxattr # # From: Stephen Smalley # # This patch against 2.5.69 adds a security_inode_post_setxattr hook so that # security modules can update the inode security structure after a successful # setxattr, and it moves the existing security_inode_setxattr hook call after # the taking the inode semaphore so that atomicity is provided for the # security check and the update to the inode security structure. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1114 # [PATCH] Work around include/linux/sunrpc/svc.h compilation # # From: Grzegorz Jaskiewicz # # gcc-2.94 fails to compile this code, alleging an invalid lvalue. # An equivalent transformation fixes it up. # -------------------------------------------- # 03/05/07 torvalds@home.transmeta.com 1.1115 # Merge conflicting tty devfs cleanups # -------------------------------------------- # diff -Nru a/CREDITS b/CREDITS --- a/CREDITS Thu May 8 00:24:29 2003 +++ b/CREDITS Thu May 8 00:24:29 2003 @@ -3027,8 +3027,8 @@ W: http://www.cs.helsinki.fi/Linus.Torvalds P: 1024/A86B35C5 96 54 50 29 EC 11 44 7A BE 67 3C 24 03 13 62 C8 D: Original kernel hacker -S: 1050 Woodduck Avenue -S: Santa Clara, California 95051 +S: 3990 Freedom Circle +S: Santa Clara, California 95054 S: USA N: Marcelo W. Tosatti diff -Nru a/Documentation/Changes b/Documentation/Changes --- a/Documentation/Changes Thu May 8 00:24:30 2003 +++ b/Documentation/Changes Thu May 8 00:24:30 2003 @@ -50,7 +50,7 @@ o Gnu C 2.95.3 # gcc --version o Gnu make 3.78 # make --version -o binutils 2.9.5.0.25 # ld -v +o binutils 2.12 # ld -v o util-linux 2.10o # fdformat --version o module-init-tools 0.9.9 # depmod -V o e2fsprogs 1.29 # tune2fs diff -Nru a/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS Thu May 8 00:24:29 2003 +++ b/MAINTAINERS Thu May 8 00:24:29 2003 @@ -679,7 +679,7 @@ EXT3 FILE SYSTEM P: Stephen Tweedie, Andrew Morton -M: sct@redhat.com, akpm@zip.com.au, adilger@clusterfs.com +M: sct@redhat.com, akpm@digeo.com, adilger@clusterfs.com L: ext3-users@redhat.com S: Maintained @@ -801,20 +801,13 @@ M: drivers@neukum.org S: Maintained -I2C DRIVERS -P: Simon Vogl -M: simon@tk.uni-linz.ac.at -P: Frodo Looijaard -M: frodol@dds.nl -L: linux-i2c@pelican.tk.uni-linz.ac.at -W: http://www.tk.uni-linz.ac.at/~simon/private/i2c -S: Maintained - -SENSORS DRIVERS +I2C AND SENSORS DRIVERS P: Frodo Looijaard M: frodol@dds.nl P: Philip Edelbrock M: phil@netroedge.com +P: Greg Kroah-Hartman +M: greg@kroah.com L: sensors@stimpy.netroedge.com W: http://www.lm-sensors.nu/ S: Maintained @@ -1264,7 +1257,7 @@ NETWORK DEVICE DRIVERS P: Andrew Morton -M: akpm@zip.com.au +M: akpm@digeo.com P: Jeff Garzik M: jgarzik@pobox.com L: linux-net@vger.kernel.org diff -Nru a/Makefile b/Makefile --- a/Makefile Thu May 8 00:24:29 2003 +++ b/Makefile Thu May 8 00:24:29 2003 @@ -90,7 +90,7 @@ KBUILD_MODULES := 1 endif -export KBUILD_MODULES KBUILD_BUILTIN KBUILD_VERBOSE +export KBUILD_MODULES KBUILD_BUILTIN KBUILD_VERBOSE KBUILD_CHECKSRC # Beautify output # --------------------------------------------------------------------------- @@ -118,6 +118,16 @@ KBUILD_VERBOSE = 1 endif +ifdef C + ifeq ("$(origin C)", "command line") + KBUILD_CHECKSRC = $(C) + endif +endif +ifndef KBUILD_CHECKSRC + KBUILD_CHECKSRC = 0 +endif + + MAKEFLAGS += --no-print-directory # For maximum performance (+ possibly random breakage, uncomment @@ -172,6 +182,7 @@ DEPMOD = /sbin/depmod KALLSYMS = scripts/kallsyms PERL = perl +CHECK = /home/torvalds/parser/check MODFLAGS = -DMODULE CFLAGS_MODULE = $(MODFLAGS) AFLAGS_MODULE = $(MODFLAGS) @@ -189,7 +200,7 @@ export VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION KERNELRELEASE ARCH \ CONFIG_SHELL TOPDIR HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \ CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE \ - HOSTCXX HOSTCXXFLAGS LDFLAGS_BLOB LDFLAGS_MODULE + HOSTCXX HOSTCXXFLAGS LDFLAGS_BLOB LDFLAGS_MODULE CHECK export CPPFLAGS NOSTDINC_FLAGS OBJCOPYFLAGS LDFLAGS export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig --- a/arch/i386/Kconfig Thu May 8 00:24:27 2003 +++ b/arch/i386/Kconfig Thu May 8 00:24:27 2003 @@ -65,19 +65,16 @@ config X86_SUMMIT bool "Summit/EXA (IBM x440)" + depends on SMP help This option is needed for IBM systems that use the Summit/EXA chipset. In particular, it is needed for the x440. If you don't have one of these computers, you should say N here. -config ACPI_SRAT - bool - default y - depends on NUMA && X86_SUMMIT - config X86_BIGSMP bool "Support for other sub-arch SMP systems with more than 8 CPUs" + depends on SMP help This option is needed for the systems that have more than 8 CPUs and if the system is not of any sub-arch type above. @@ -95,8 +92,24 @@ A kernel compiled for the Visual Workstation will not run on PCs and vice versa. See for details. +config X86_GENERICARCH + bool "Generic architecture (Summit, bigsmp, default)" + depends on SMP + help + This option compiles in the Summit, bigsmp, default subarchitectures. + It is intended for a generic binary kernel. + endchoice +config ACPI_SRAT + bool + default y + depends on NUMA && (X86_SUMMIT || X86_GENERICARCH) + +config X86_CYCLONE_TIMER + bool + default y + depends on X86_SUMMIT || X86_GENERICARCH choice prompt "Processor family" @@ -666,7 +679,7 @@ # Common NUMA Features config NUMA bool "Numa Memory Allocation Support" - depends on SMP && HIGHMEM64G && (X86_PC || X86_NUMAQ || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY)) + depends on SMP && HIGHMEM64G && (X86_PC || X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY)) default n if X86_PC default y if (X86_NUMAQ || X86_SUMMIT) @@ -764,7 +777,7 @@ # Summit needs it only when NUMA is on config BOOT_IOREMAP bool - depends on (X86_SUMMIT && NUMA) + depends on ((X86_SUMMIT || X86_GENERICARCH) && NUMA) default y endmenu diff -Nru a/arch/i386/Makefile b/arch/i386/Makefile --- a/arch/i386/Makefile Thu May 8 00:24:28 2003 +++ b/arch/i386/Makefile Thu May 8 00:24:28 2003 @@ -73,6 +73,11 @@ mflags-$(CONFIG_X86_SUMMIT) := -Iinclude/asm-i386/mach-summit mcore-$(CONFIG_X86_SUMMIT) := mach-default +# generic subarchitecture +mflags-$(CONFIG_X86_GENERICARCH) := -Iinclude/asm-i386/mach-generic +mcore-$(CONFIG_X86_GENERICARCH) := mach-default +core-$(CONFIG_X86_GENERICARCH) += arch/i386/mach-generic/ + # default subarch .h files mflags-y += -Iinclude/asm-i386/mach-default diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c --- a/arch/i386/kernel/io_apic.c Thu May 8 00:24:28 2003 +++ b/arch/i386/kernel/io_apic.c Thu May 8 00:24:28 2003 @@ -280,7 +280,9 @@ extern unsigned long irq_affinity[NR_IRQS]; static int __cacheline_aligned pending_irq_balance_apicid[NR_IRQS]; -static int irqbalance_disabled = NO_BALANCE_IRQ; + +#define IRQBALANCE_CHECK_ARCH -999 +static int irqbalance_disabled = IRQBALANCE_CHECK_ARCH; static int physical_balance = 0; struct irq_cpu_info { @@ -342,8 +344,10 @@ unsigned long allowed_mask; unsigned int new_cpu; - if (irqbalance_disabled) + if (irqbalance_disabled == IRQBALANCE_CHECK_ARCH && NO_BALANCE_IRQ) return; + else if (irqbalance_disabled) + return; allowed_mask = cpu_online_map & irq_affinity[irq]; new_cpu = move(cpu, allowed_mask, now, 1); diff -Nru a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c --- a/arch/i386/kernel/mpparse.c Thu May 8 00:24:28 2003 +++ b/arch/i386/kernel/mpparse.c Thu May 8 00:24:28 2003 @@ -73,7 +73,9 @@ /* Bitmask of physically existing CPUs */ unsigned long phys_cpu_present_map; +#ifndef CONFIG_X86_GENERICARCH int x86_summit = 0; +#endif u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; /* diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c --- a/arch/i386/kernel/setup.c Thu May 8 00:24:28 2003 +++ b/arch/i386/kernel/setup.c Thu May 8 00:24:28 2003 @@ -91,6 +91,7 @@ extern void early_cpu_init(void); extern void dmi_scan_machine(void); +extern void generic_apic_probe(char *); extern int root_mountflags; extern char _text, _etext, _edata, _end; extern int blk_nohighio; @@ -959,6 +960,13 @@ smp_alloc_memory(); /* AP processor realmode stacks in low memory*/ #endif paging_init(); + + dmi_scan_machine(); + +#ifdef CONFIG_X86_GENERICARCH + generic_apic_probe(*cmdline_p); +#endif + #ifdef CONFIG_ACPI_BOOT /* * Parse the ACPI tables for possible boot-time SMP configuration. @@ -980,7 +988,6 @@ conswitchp = &dummy_con; #endif #endif - dmi_scan_machine(); } static int __init highio_setup(char *str) diff -Nru a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c --- a/arch/i386/kernel/smp.c Thu May 8 00:24:27 2003 +++ b/arch/i386/kernel/smp.c Thu May 8 00:24:27 2003 @@ -123,7 +123,7 @@ return SET_APIC_DEST_FIELD(mask); } -static inline void __send_IPI_shortcut(unsigned int shortcut, int vector) +inline void __send_IPI_shortcut(unsigned int shortcut, int vector) { /* * Subtle. In the case of the 'never do double writes' workaround @@ -155,7 +155,7 @@ __send_IPI_shortcut(APIC_DEST_SELF, vector); } -static inline void send_IPI_mask_bitmask(int mask, int vector) +inline void send_IPI_mask_bitmask(int mask, int vector) { unsigned long cfg; unsigned long flags; @@ -186,7 +186,7 @@ local_irq_restore(flags); } -static inline void send_IPI_mask_sequence(int mask, int vector) +inline void send_IPI_mask_sequence(int mask, int vector) { unsigned long cfg, flags; unsigned int query_cpu, query_mask; diff -Nru a/arch/i386/kernel/timers/Makefile b/arch/i386/kernel/timers/Makefile --- a/arch/i386/kernel/timers/Makefile Thu May 8 00:24:27 2003 +++ b/arch/i386/kernel/timers/Makefile Thu May 8 00:24:27 2003 @@ -4,4 +4,4 @@ obj-y := timer.o timer_none.o timer_tsc.o timer_pit.o -obj-$(CONFIG_X86_SUMMIT) += timer_cyclone.o +obj-$(CONFIG_X86_CYCLONE_TIMER) += timer_cyclone.o diff -Nru a/arch/i386/kernel/timers/timer.c b/arch/i386/kernel/timers/timer.c --- a/arch/i386/kernel/timers/timer.c Thu May 8 00:24:30 2003 +++ b/arch/i386/kernel/timers/timer.c Thu May 8 00:24:30 2003 @@ -6,12 +6,12 @@ /* list of externed timers */ extern struct timer_opts timer_pit; extern struct timer_opts timer_tsc; -#ifdef CONFIG_X86_SUMMIT +#ifdef CONFIG_X86_CYCLONE_TIMER extern struct timer_opts timer_cyclone; #endif /* list of timers, ordered by preference, NULL terminated */ static struct timer_opts* timers[] = { -#ifdef CONFIG_X86_SUMMIT +#ifdef CONFIG_X86_CYCLONE_TIMER &timer_cyclone, #endif &timer_tsc, diff -Nru a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c --- a/arch/i386/lib/usercopy.c Thu May 8 00:24:27 2003 +++ b/arch/i386/lib/usercopy.c Thu May 8 00:24:27 2003 @@ -6,6 +6,9 @@ * Copyright 1997 Linus Torvalds */ #include +#include +#include +#include #include #include @@ -483,6 +486,53 @@ unsigned long __copy_to_user_ll(void *to, const void *from, unsigned long n) { +#ifndef CONFIG_X86_WP_WORKS_OK + if (unlikely(boot_cpu_data.wp_works_ok == 0) && + ((unsigned long )to) < TASK_SIZE) { + /* + * CPU does not honor the WP bit when writing + * from supervisory mode, and due to preemption or SMP, + * the page tables can change at any time. + * Do it manually. Manfred + */ + while (n) { + unsigned long offset = ((unsigned long)to)%PAGE_SIZE; + unsigned long len = PAGE_SIZE - offset; + int retval; + struct page *pg; + void *maddr; + + if (len > n) + len = n; + +survive: + down_read(¤t->mm->mmap_sem); + retval = get_user_pages(current, current->mm, + (unsigned long )to, 1, 1, 0, &pg, NULL); + + if (retval == -ENOMEM && current->pid == 1) { + up_read(¤t->mm->mmap_sem); + blk_congestion_wait(WRITE, HZ/50); + goto survive; + } + + if (retval != 1) + break; + + maddr = kmap_atomic(pg, KM_USER0); + memcpy(maddr + offset, from, len); + kunmap_atomic(maddr, KM_USER0); + set_page_dirty_lock(pg); + put_page(pg); + up_read(¤t->mm->mmap_sem); + + from += len; + to += len; + n -= len; + } + return n; + } +#endif if (movsl_is_ok(to, from, n)) __copy_user(to, from, n); else diff -Nru a/arch/i386/mach-generic/Makefile b/arch/i386/mach-generic/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/mach-generic/Makefile Thu May 8 00:24:30 2003 @@ -0,0 +1,18 @@ +# +# Makefile for the generic architecture +# + +EXTRA_CFLAGS += -I../kernel + +obj-y := probe.o summit.o bigsmp.o default.o + + +# +# Makefile for the generic architecture +# + +EXTRA_CFLAGS += -I../kernel + +obj-y := probe.o summit.o bigsmp.o default.o + + diff -Nru a/arch/i386/mach-generic/bigsmp.c b/arch/i386/mach-generic/bigsmp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/mach-generic/bigsmp.c Thu May 8 00:24:30 2003 @@ -0,0 +1,23 @@ +/* + * APIC driver for "bigsmp" XAPIC machines with more than 8 virtual CPUs. + * Drives the local APIC in "clustered mode". + */ +#define APIC_DEFINITION 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int dmi_bigsmp; /* can be set by dmi scanners */ + +static __init int probe_bigsmp(void) +{ + return dmi_bigsmp; +} + +struct genapic apic_bigsmp = APIC_INIT("bigsmp", probe_bigsmp); diff -Nru a/arch/i386/mach-generic/default.c b/arch/i386/mach-generic/default.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/mach-generic/default.c Thu May 8 00:24:30 2003 @@ -0,0 +1,22 @@ +/* + * Default generic APIC driver. This handles upto 8 CPUs. + */ +#define APIC_DEFINITION 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* should be called last. */ +static __init int probe_default(void) +{ + return 1; +} + +struct genapic apic_default = APIC_INIT("default", probe_default); diff -Nru a/arch/i386/mach-generic/probe.c b/arch/i386/mach-generic/probe.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/mach-generic/probe.c Thu May 8 00:24:30 2003 @@ -0,0 +1,96 @@ +/* Copyright 2003 Andi Kleen, SuSE Labs. + * Subject to the GNU Public License, v.2 + * + * Generic x86 APIC driver probe layer. + */ +#include +#include +#include +#include +#include +#include +#include + +extern struct genapic apic_summit; +extern struct genapic apic_bigsmp; +extern struct genapic apic_default; + +struct genapic *genapic = &apic_default; + +struct genapic *apic_probe[] __initdata = { + &apic_summit, + &apic_bigsmp, + &apic_default, /* must be last */ + NULL, +}; + +void __init generic_apic_probe(char *command_line) +{ + char *s; + int i; + int changed = 0; + + s = strstr(command_line, "apic="); + if (s && (s == command_line || isspace(s[-1]))) { + char *p = strchr(s, ' '), old; + if (!p) + p = strchr(s, '\0'); + old = *p; + *p = 0; + for (i = 0; !changed && apic_probe[i]; i++) { + if (!strcmp(apic_probe[i]->name, s+5)) { + changed = 1; + genapic = apic_probe[i]; + } + } + if (!changed) + printk(KERN_ERR "Unknown genapic `%s' specified.\n", s); + *p = old; + } + for (i = 0; !changed && apic_probe[i]; i++) { + if (apic_probe[i]->probe()) { + changed = 1; + genapic = apic_probe[i]; + } + } + /* Not visible without early console */ + if (!changed) + panic("Didn't find an APIC driver"); + + printk(KERN_INFO "Using APIC driver %s\n", genapic->name); +} + +/* These functions can switch the APIC even after the initial ->probe() */ + +int __init mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid) +{ + int i; + for (i = 0; apic_probe[i]; ++i) { + if (apic_probe[i]->mps_oem_check(mpc,oem,productid)) { + genapic = apic_probe[i]; + printk(KERN_INFO "Switched to APIC driver `%s'.\n", + genapic->name); + return 1; + } + } + return 0; +} + +int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + int i; + for (i = 0; apic_probe[i]; ++i) { + if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) { + genapic = apic_probe[i]; + printk(KERN_INFO "Switched to APIC driver `%s'.\n", + genapic->name); + return 1; + } + } + return 0; +} + +int hard_smp_processor_id(void) +{ + return genapic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID)); +} diff -Nru a/arch/i386/mach-generic/summit.c b/arch/i386/mach-generic/summit.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/mach-generic/summit.c Thu May 8 00:24:30 2003 @@ -0,0 +1,22 @@ +/* + * APIC driver for the IBM "Summit" chipset. + */ +#define APIC_DEFINITION 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static __init int probe_summit(void) +{ + /* probed later in mptable/ACPI hooks */ + return 0; +} + +struct genapic apic_summit = APIC_INIT("summit", probe_summit); diff -Nru a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c --- a/arch/i386/mm/fault.c Thu May 8 00:24:27 2003 +++ b/arch/i386/mm/fault.c Thu May 8 00:24:27 2003 @@ -29,87 +29,6 @@ extern void die(const char *,struct pt_regs *,long); -#ifndef CONFIG_X86_WP_WORKS_OK -/* - * Ugly, ugly, but the goto's result in better assembly.. - */ -int __verify_write(const void * addr, unsigned long size) -{ - struct mm_struct *mm = current->mm; - struct vm_area_struct * vma; - unsigned long start = (unsigned long) addr; - - if (!size || segment_eq(get_fs(),KERNEL_DS)) - return 1; - - down_read(&mm->mmap_sem); - vma = find_vma(current->mm, start); - if (!vma) - goto bad_area; - if (vma->vm_start > start) - goto check_stack; - -good_area: - if (!(vma->vm_flags & VM_WRITE)) - goto bad_area; - size--; - size += start & ~PAGE_MASK; - size >>= PAGE_SHIFT; - start &= PAGE_MASK; - - for (;;) { - survive: - switch (handle_mm_fault(current->mm, vma, start, 1)) { - case VM_FAULT_SIGBUS: - goto bad_area; - case VM_FAULT_OOM: - goto out_of_memory; - case VM_FAULT_MINOR: - case VM_FAULT_MAJOR: - break; - default: - BUG(); - } - if (!size) - break; - size--; - start += PAGE_SIZE; - if (start < vma->vm_end) - continue; - vma = vma->vm_next; - if (!vma || vma->vm_start != start) - goto bad_area; - if (!(vma->vm_flags & VM_WRITE)) - goto bad_area;; - } - /* - * We really need to hold mmap_sem over the whole access to - * userspace, else another thread could change permissions. - * This is unfixable, so don't use i386-class machines for - * critical servers. - */ - up_read(&mm->mmap_sem); - return 1; - -check_stack: - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; - if (expand_stack(vma, start) == 0) - goto good_area; - -bad_area: - up_read(&mm->mmap_sem); - return 0; - -out_of_memory: - if (current->pid == 1) { - yield(); - goto survive; - } - goto bad_area; -} -#endif - /* * Unlock any spinlocks which will prevent us from getting the * message out @@ -405,8 +324,12 @@ if (!pgd_present(*pgd_k)) goto no_context; - set_pgd(pgd, *pgd_k); - + + /* + * set_pgd(pgd, *pgd_k); here would be useless on PAE + * and redundant with the set_pmd() on non-PAE. + */ + pmd = pmd_offset(pgd, address); pmd_k = pmd_offset(pgd_k, address); if (!pmd_present(*pmd_k)) diff -Nru a/arch/i386/vmlinux.lds.S b/arch/i386/vmlinux.lds.S --- a/arch/i386/vmlinux.lds.S Thu May 8 00:24:28 2003 +++ b/arch/i386/vmlinux.lds.S Thu May 8 00:24:28 2003 @@ -85,7 +85,11 @@ __alt_instructions = .; .altinstructions : { *(.altinstructions) } __alt_instructions_end = .; - .altinstr_replacement : { *(.altinstr_replacement) } + .altinstr_replacement : { *(.altinstr_replacement) } + /* .exit.text is discard at runtime, not link time, to deal with references + from .altinstructions and .eh_frame */ + .exit.text : { *(.exit.text) } + .exit.data : { *(.exit.data) } . = ALIGN(4096); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } @@ -106,8 +110,6 @@ /* Sections to be discarded */ /DISCARD/ : { - *(.exit.text) - *(.exit.data) *(.exitcall.exit) } diff -Nru a/arch/mips/au1000/common/serial.c b/arch/mips/au1000/common/serial.c --- a/arch/mips/au1000/common/serial.c Thu May 8 00:24:28 2003 +++ b/arch/mips/au1000/common/serial.c Thu May 8 00:24:28 2003 @@ -2681,8 +2681,8 @@ (state->flags & ASYNC_FOURPORT) ? " FourPort" : "", state->port, state->irq, uart_config[state->type].name); - tty_register_device(&serial_driver, state->line); - tty_register_device(&callout_driver, state->line); + tty_register_device(&serial_driver, state->line, NULL); + tty_register_device(&callout_driver, state->line, NULL); } return 0; } @@ -2769,8 +2769,8 @@ state->iomem_base ? "iomem" : "port", state->iomem_base ? (unsigned long)state->iomem_base : state->port, state->irq, uart_config[state->type].name); - tty_register_device(&serial_driver, state->line); - tty_register_device(&callout_driver, state->line); + tty_register_device(&serial_driver, state->line, NULL); + tty_register_device(&callout_driver, state->line, NULL); return state->line + SERIAL_DEV_OFFSET; } diff -Nru a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c --- a/arch/ppc64/kernel/LparData.c Thu May 8 00:24:28 2003 +++ b/arch/ppc64/kernel/LparData.c Thu May 8 00:24:28 2003 @@ -61,7 +61,7 @@ 0xc8a5d9c4, /* desc = "HvRD" ebcdic */ sizeof(struct HvReleaseData), offsetof(struct naca_struct, xItVpdAreas), - (struct naca_struct *)(KERNELBASE+0x4000), /* 64-bit Naca address */ + (struct naca_struct *)(NACA_VIRT_ADDR), /* 64-bit Naca address */ 0x6000, /* offset of LparMap within loadarea (see head.S) */ 0, 1, /* tags inactive */ diff -Nru a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile Thu May 8 00:24:30 2003 +++ b/arch/ppc64/kernel/Makefile Thu May 8 00:24:30 2003 @@ -15,7 +15,7 @@ iSeries_IoMmTable.o iSeries_irq.o \ iSeries_VpdInfo.o XmPciLpEvent.o \ HvCall.o HvLpConfig.o LparData.o mf_proc.o \ - proc_pmc.o iSeries_setup.o ItLpQueue.o hvCall.o \ + iSeries_setup.o ItLpQueue.o hvCall.o \ mf.o HvLpEvent.o iSeries_proc.o obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \ @@ -25,6 +25,7 @@ obj-y += open_pic.o xics.o pSeries_htab.o rtas.o \ chrp_setup.o i8259.o ras.o prom.o +obj-$(CONFIG_PROC_FS) += proc_ppc64.o obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o diff -Nru a/arch/ppc64/kernel/align.c b/arch/ppc64/kernel/align.c --- a/arch/ppc64/kernel/align.c Thu May 8 00:24:30 2003 +++ b/arch/ppc64/kernel/align.c Thu May 8 00:24:30 2003 @@ -237,7 +237,7 @@ dsisr = regs->dsisr; /* Power4 doesn't set DSISR for an alignment interrupt */ - if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) { + if (!cpu_alignexc_sets_dsisr()) { unsigned int real_instr; if (__get_user(real_instr, (unsigned int *)regs->nip)) return 0; @@ -309,6 +309,7 @@ /* Doing stfs, have to convert to single */ enable_kernel_fp(); cvt_df(¤t->thread.fpr[reg], (float *)&data.v[4], ¤t->thread.fpscr); + disable_kernel_fp(); } else data.dd = current->thread.fpr[reg]; @@ -342,6 +343,7 @@ /* Doing lfs, have to convert to double */ enable_kernel_fp(); cvt_fd((float *)&data.v[4], ¤t->thread.fpr[reg], ¤t->thread.fpscr); + disable_kernel_fp(); } else current->thread.fpr[reg] = data.dd; diff -Nru a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c --- a/arch/ppc64/kernel/asm-offsets.c Thu May 8 00:24:29 2003 +++ b/arch/ppc64/kernel/asm-offsets.c Thu May 8 00:24:29 2003 @@ -59,14 +59,14 @@ /* naca */ DEFINE(PACA, offsetof(struct naca_struct, paca)); - DEFINE(DCACHEL1LINESIZE, offsetof(struct naca_struct, dCacheL1LineSize)); + DEFINE(DCACHEL1LINESIZE, offsetof(struct systemcfg, dCacheL1LineSize)); DEFINE(DCACHEL1LOGLINESIZE, offsetof(struct naca_struct, dCacheL1LogLineSize)); DEFINE(DCACHEL1LINESPERPAGE, offsetof(struct naca_struct, dCacheL1LinesPerPage)); - DEFINE(ICACHEL1LINESIZE, offsetof(struct naca_struct, iCacheL1LineSize)); + DEFINE(ICACHEL1LINESIZE, offsetof(struct systemcfg, iCacheL1LineSize)); DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct naca_struct, iCacheL1LogLineSize)); DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct naca_struct, iCacheL1LinesPerPage)); DEFINE(SLBSIZE, offsetof(struct naca_struct, slb_size)); - DEFINE(PLATFORM, offsetof(struct naca_struct, platform)); + DEFINE(PLATFORM, offsetof(struct systemcfg, platform)); /* paca */ DEFINE(PACA_SIZE, sizeof(struct paca_struct)); diff -Nru a/arch/ppc64/kernel/chrp_setup.c b/arch/ppc64/kernel/chrp_setup.c --- a/arch/ppc64/kernel/chrp_setup.c Thu May 8 00:24:27 2003 +++ b/arch/ppc64/kernel/chrp_setup.c Thu May 8 00:24:27 2003 @@ -263,6 +263,8 @@ char *os; static int display_character, set_indicator; static int max_width; + static spinlock_t progress_lock = SPIN_LOCK_UNLOCKED; + static int pending_newline = 0; /* did last write end with unprinted newline? */ if (!rtas.base) return; @@ -278,34 +280,79 @@ display_character = rtas_token("display-character"); set_indicator = rtas_token("set-indicator"); } - if (display_character == RTAS_UNKNOWN_SERVICE) { - /* use hex display */ - if (set_indicator == RTAS_UNKNOWN_SERVICE) - return; - rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex); + + if(display_character == RTAS_UNKNOWN_SERVICE) { + /* use hex display if available */ + if(set_indicator != RTAS_UNKNOWN_SERVICE) + rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex); return; } - rtas_call(display_character, 1, 1, NULL, '\r'); + spin_lock(&progress_lock); + /* Last write ended with newline, but we didn't print it since + * it would just clear the bottom line of output. Print it now + * instead. + * + * If no newline is pending, print a CR to start output at the + * beginning of the line. + */ + if(pending_newline) { + rtas_call(display_character, 1, 1, NULL, '\r'); + rtas_call(display_character, 1, 1, NULL, '\n'); + pending_newline = 0; + } else + rtas_call(display_character, 1, 1, NULL, '\r'); + width = max_width; os = s; - while ( *os ) - { - if ( (*os == '\n') || (*os == '\r') ) + while (*os) { + if(*os == '\n' || *os == '\r') { + /* Blank to end of line. */ + while(width-- > 0) + rtas_call(display_character, 1, 1, NULL, ' '); + + /* If newline is the last character, save it + * until next call to avoid bumping up the + * display output. + */ + if(*os == '\n' && !os[1]) { + pending_newline = 1; + spin_unlock(&progress_lock); + return; + } + + /* RTAS wants CR-LF, not just LF */ + + if(*os == '\n') { + rtas_call(display_character, 1, 1, NULL, '\r'); + rtas_call(display_character, 1, 1, NULL, '\n'); + } else { + /* CR might be used to re-draw a line, so we'll + * leave it alone and not add LF. + */ + rtas_call(display_character, 1, 1, NULL, *os); + } + width = max_width; - else + } else { width--; - rtas_call(display_character, 1, 1, NULL, *os++ ); + rtas_call(display_character, 1, 1, NULL, *os); + } + + os++; + /* if we overwrite the screen length */ - if ( width == 0 ) + if ( width <= 0 ) while ( (*os != 0) && (*os != '\n') && (*os != '\r') ) os++; } - + /* Blank to end of line. */ while ( width-- > 0 ) rtas_call(display_character, 1, 1, NULL, ' ' ); + + spin_unlock(&progress_lock); } extern void setup_default_decr(void); diff -Nru a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S --- a/arch/ppc64/kernel/entry.S Thu May 8 00:24:27 2003 +++ b/arch/ppc64/kernel/entry.S Thu May 8 00:24:27 2003 @@ -225,10 +225,6 @@ bl .sys32_rt_sigreturn b 80f -_GLOBAL(ppc64_sigreturn) - bl .sys_sigreturn - b 80f - _GLOBAL(ppc64_rt_sigreturn) bl .sys_rt_sigreturn @@ -412,11 +408,6 @@ ld r4,GPR4(r1) ld r1,GPR1(r1) - /* - * What if we took an exception and stole this segment, we may - * fault on the above addresses and globber SRR0/1. Should check RI - * bit and repeat - Anton - */ rfid /* Note: this must change if we start using the TIF_NOTIFY_RESUME bit */ diff -Nru a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S --- a/arch/ppc64/kernel/head.S Thu May 8 00:24:29 2003 +++ b/arch/ppc64/kernel/head.S Thu May 8 00:24:29 2003 @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include #include @@ -49,8 +51,9 @@ * 0x0100 - 0x2fff : pSeries Interrupt prologs * 0x3000 - 0x3fff : Interrupt support * 0x4000 - 0x4fff : NACA - * 0x5000 - 0x5fff : Initial segment table + * 0x5000 - 0x5fff : SystemCfg * 0x6000 : iSeries and common interrupt prologs + * 0x9000 - 0x9fff : Initial segment table */ /* @@ -123,6 +126,10 @@ * All of it must fit below the first exception vector at 0x100. */ _GLOBAL(__secondary_hold) + mfmsr r24 + ori r24,r24,MSR_RI + mtmsrd r24 /* RI on */ + /* Grab our linux cpu number */ mr r24,r3 @@ -362,11 +369,11 @@ STD_EXCEPTION_PSERIES( 0x1300, InstructionBreakpoint ) /* Space for the naca. Architected to be located at real address - * 0x4000. Various tools rely on this location being fixed. + * NACA_PHYS_ADDR. Various tools rely on this location being fixed. * The first dword of the naca is required by iSeries LPAR to * point to itVpdAreas. On pSeries native, this value is not used. */ - . = 0x4000 + . = NACA_PHYS_ADDR .globl __end_interrupts .globl __start_naca __end_interrupts: @@ -380,21 +387,14 @@ .llong 0x0 .llong paca - /* - * Space for the initial segment table - * For LPAR, the hypervisor must fill in at least one entry - * before we get control (with relocate on) - */ - . = 0x5000 + . = SYSTEMCFG_PHYS_ADDR .globl __end_naca - .globl __start_stab + .globl __start_systemcfg __end_naca: -__start_stab: - - - . = 0x6000 - .globl __end_stab -__end_stab: +__start_systemcfg: + . = (SYSTEMCFG_PHYS_ADDR + PAGE_SIZE) + .globl __end_systemcfg +__end_systemcfg: #ifdef CONFIG_PPC_ISERIES /* @@ -408,7 +408,7 @@ .llong 1 /* # ESIDs to be mapped by hypervisor */ .llong 1 /* # memory ranges to be mapped by hypervisor */ - .llong 5 /* Page # of segment table within load area */ + .llong STAB0_PAGE /* Page # of segment table within load area */ .llong 0 /* Reserved */ .llong 0 /* Reserved */ .llong 0 /* Reserved */ @@ -529,6 +529,20 @@ MachineCheck_FWNMI: EXCEPTION_PROLOG_PSERIES(0x200, MachineCheck_common) + /* + * Space for the initial segment table + * For LPAR, the hypervisor must fill in at least one entry + * before we get control (with relocate on) + */ + . = STAB0_PHYS_ADDR + .globl __start_stab +__start_stab: + + . = (STAB0_PHYS_ADDR + PAGE_SIZE) + .globl __end_stab +__end_stab: + + /*** Common interrupt handlers ***/ STD_EXCEPTION_COMMON( 0x100, SystemReset, .SystemResetException ) @@ -782,11 +796,16 @@ FPUnavailable_common: EXCEPTION_PROLOG_COMMON bne .load_up_fpu /* if from user, just load it up */ - li r20,0 + addi r3,r1,STACK_FRAME_OVERHEAD +#ifdef DO_SOFT_DISABLE + ld r20,SOFTE(r1) +#else + rldicl r20,r23,49,63 /* copy EE bit from saved MSR */ +#endif li r6,0x800 - bl .save_remaining_regs /* if from kernel, take a trap */ - bl .KernelFP - b .ret_from_except + bl .save_remaining_regs + bl .KernelFPUnavailableException + BUG_OPCODE .globl SystemCall_common SystemCall_common: @@ -1032,7 +1051,7 @@ slbmfee r23,r22 rldicl r23,r23,37,63 cmpwi r23,0 - beq 3f /* Found an invalid entry */ + beq 4f /* Found an invalid entry */ addi r22,r22,1 cmpldi r22,64 @@ -1041,18 +1060,37 @@ /* No free entry - just take the next entry, round-robin */ /* XXX we should get the number of SLB entries from the naca */ SLB_NUM_ENTRIES = 64 - mfspr r21,SPRG3 +2: mfspr r21,SPRG3 ld r22,PACASTABRR(r21) addi r23,r22,1 cmpdi r23,SLB_NUM_ENTRIES - blt 2f + blt 3f li r23,1 -2: std r23,PACASTABRR(r21) +3: std r23,PACASTABRR(r21) /* r20 = vsid, r22 = entry */ -3: + + /* + * Never cast out the segment for our kernel stack. Since we + * dont invalidate the ERAT we could have a valid translation + * for the kernel stack during the first part of exception exit + * which gets invalidated due to a tlbie from another cpu at a + * non recoverable point (after setting srr0/1) - Anton + */ + slbmfee r23,r22 + srdi r23,r23,28 + /* + * This is incorrect (r1 is not the kernel stack) if we entered + * from userspace but there is no critical window from userspace + * so this should be OK. Also if we cast out the userspace stack + * segment while in userspace we will fault it straight back in. + */ + srdi r21,r1,28 + cmpd r21,r23 + beq- 2b + /* Put together the vsid portion of the entry. */ - li r21,0 +4: li r21,0 rldimi r21,r20,12,0 ori r20,r21,1024 ori r20,r20,128 /* set class bit for kernel region */ @@ -1060,17 +1098,6 @@ ori r20,r20,256 /* map kernel region with large ptes */ #endif - /* - * XXX we should handle this in the exception exit path in 2.5, - * we need to make this path quick - Anton - */ - /* Invalidate the old entry */ - slbmfee r21,r22 - lis r23,-2049 - ori r23,r23,65535 - and r21,r21,r23 - slbie r21 - /* Put together the esid portion of the entry. */ mfspr r21,DAR /* Get the new esid */ rldicl r21,r21,36,28 /* Permits a full 36b of ESID */ @@ -1252,9 +1279,12 @@ addi r2,r2,0x4000 addi r2,r2,0x4000 + LOADADDR(r9,systemcfg) + SET_REG_TO_CONST(r4, SYSTEMCFG_VIRT_ADDR) + std r4,0(r9) /* set the systemcfg pointer */ + LOADADDR(r9,naca) - SET_REG_TO_CONST(r4, KERNELBASE) - addi r4,r4,0x4000 + SET_REG_TO_CONST(r4, NACA_VIRT_ADDR) std r4,0(r9) /* set the naca pointer */ /* Get the pointer to the segment table */ @@ -1285,13 +1315,18 @@ /* Relocate the TOC from a virt addr to a real addr */ sub r2,r2,r3 + /* setup the systemcfg pointer which is needed by prom_init */ + LOADADDR(r9,systemcfg) + sub r9,r9,r3 /* addr of the variable systemcfg */ + SET_REG_TO_CONST(r4, SYSTEMCFG_VIRT_ADDR) + sub r4,r4,r3 + std r4,0(r9) /* set the value of systemcfg */ + /* setup the naca pointer which is needed by prom_init */ LOADADDR(r9,naca) sub r9,r9,r3 /* addr of the variable naca */ - - SET_REG_TO_CONST(r4, KERNELBASE) + SET_REG_TO_CONST(r4, NACA_VIRT_ADDR) sub r4,r4,r3 - addi r4,r4,0x4000 std r4,0(r9) /* set the value of naca */ /* DRENG / PPPBBB Fix the following comment!!! -Peter */ @@ -1410,11 +1445,13 @@ copy_to_here: /* + * load_up_fpu(unused, unused, tsk) * Disable FP for the task which had the FPU previously, * and save its floating-point registers in its thread_struct. * Enables the FPU for use in the kernel on return. * On SMP we know the fpu is free, since we give it up every - * switch. -- Cort + * switch (ie, no lazy save of the FP registers). + * On entry: r13 == 'current' && last_task_used_math != 'current' */ _STATIC(load_up_fpu) mfmsr r5 /* grab the current MSR */ @@ -1432,27 +1469,30 @@ ld r4,last_task_used_math@l(r3) cmpi 0,r4,0 beq 1f - addi r4,r4,THREAD /* want THREAD of last_task_used_math */ + /* Save FP state to last_task_used_math's THREAD struct */ + addi r4,r4,THREAD SAVE_32FPRS(0, r4) mffs fr0 stfd fr0,THREAD_FPSCR(r4) + /* Disable FP for last_task_used_math */ ld r5,PT_REGS(r4) ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) li r20,MSR_FP|MSR_FE0|MSR_FE1 - andc r4,r4,r20 /* disable FP for previous task */ + andc r4,r4,r20 std r4,_MSR-STACK_FRAME_OVERHEAD(r5) 1: #endif /* CONFIG_SMP */ /* enable use of FP after return */ ld r4,PACACURRENT(r13) addi r5,r4,THREAD /* Get THREAD */ - lwz r4,THREAD_FPEXC_MODE(r5) + ld r4,THREAD_FPEXC_MODE(r5) ori r23,r23,MSR_FP or r23,r23,r4 lfd fr0,THREAD_FPSCR(r5) mtfsf 0xff,fr0 REST_32FPRS(0, r5) #ifndef CONFIG_SMP + /* Update last_task_used_math to 'current' */ subi r4,r5,THREAD /* Back to 'current' */ std r4,last_task_used_math@l(r3) #endif /* CONFIG_SMP */ @@ -1460,19 +1500,16 @@ b fast_exception_return /* - * FP unavailable trap from kernel - print a message, but let - * the task use FP in the kernel until it returns to user mode. + * disable_kernel_fp() + * Disable the FPU. */ -_GLOBAL(KernelFP) - ld r3,_MSR(r1) - ori r3,r3,MSR_FP - std r3,_MSR(r1) /* enable use of FP after return */ - LOADADDR(r3,86f) - ld r4,PACACURRENT(r13) /* current */ - ld r5,_NIP(r1) - b .ret_from_except -86: .string "floating point used in kernel (task=%p, pc=%x)\n" - .align 4 +_GLOBAL(disable_kernel_fp) + mfmsr r3 + rldicl r0,r3,(63-MSR_FP_LG),1 + rldicl r3,r0,(MSR_FP_LG+1),0 + mtmsrd r3 /* disable use of fpu now */ + isync + blr /* * giveup_fpu(tsk) @@ -1562,8 +1599,8 @@ sc /* HvCall_setASR */ #else /* set the ASR */ - addi r3,0,0x4000 /* r3 = ptr to naca */ - lhz r3,PLATFORM(r3) /* r3 = platform flags */ + li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */ + lwz r3,PLATFORM(r3) /* r3 = platform flags */ cmpldi r3,PLATFORM_PSERIES_LPAR bne 98f mfspr r3,PVR @@ -1642,10 +1679,20 @@ bl .reloc_offset mr r26,r3 + mfmsr r6 + ori r6,r6,MSR_RI + mtmsrd r6 /* RI on */ + + /* setup the systemcfg pointer which is needed by *tab_initialize */ + LOADADDR(r6,systemcfg) + sub r6,r6,r26 /* addr of the variable systemcfg */ + li r27,SYSTEMCFG_PHYS_ADDR + std r27,0(r6) /* set the value of systemcfg */ + /* setup the naca pointer which is needed by *tab_initialize */ LOADADDR(r6,naca) sub r6,r6,r26 /* addr of the variable naca */ - li r27,0x4000 + li r27,NACA_PHYS_ADDR std r27,0(r6) /* set the value of naca */ #ifdef CONFIG_HMT @@ -1709,15 +1756,12 @@ sub r13,r13,r26 /* convert to physical addr */ mtspr SPRG3,r13 /* PPPBBB: Temp... -Peter */ - li r3,0x5000 - std r3,PACASTABREAL(r13) - LOADADDR(r24, __start_stab) - std r24,PACASTABVIRT(r13) + ld r3,PACASTABREAL(r13) ori r4,r3,1 /* turn on valid bit */ /* set the ASR */ - addi r3,0,0x4000 /* r3 = ptr to naca */ - lhz r3,PLATFORM(r3) /* r3 = platform flags */ + li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */ + lwz r3,PLATFORM(r3) /* r3 = platform flags */ cmpldi r3,PLATFORM_PSERIES_LPAR bne 98f mfspr r3,PVR @@ -1741,8 +1785,8 @@ bl .stab_initialize bl .htab_initialize - addi r3,0,0x4000 /* r3 = ptr to naca */ - lhz r3,PLATFORM(r3) /* r3 = platform flags */ + li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */ + lwz r3,PLATFORM(r3) /* r3 = platform flags */ cmpldi r3,PLATFORM_PSERIES bne 98f LOADADDR(r6,_SDR1) /* Only if NOT LPAR */ @@ -1791,11 +1835,14 @@ addi r2,r2,0x4000 addi r2,r2,0x4000 - /* setup the naca pointer */ - LOADADDR(r9,naca) + /* setup the systemcfg pointer */ + LOADADDR(r9,systemcfg) + SET_REG_TO_CONST(r8, SYSTEMCFG_VIRT_ADDR) + std r8,0(r9) - SET_REG_TO_CONST(r8, KERNELBASE) - addi r8,r8,0x4000 + /* setup the naca pointer */ + LOADADDR(r9,naca) + SET_REG_TO_CONST(r8, NACA_VIRT_ADDR) std r8,0(r9) /* set the value of the naca ptr */ LOADADDR(r26, boot_cpuid) @@ -1946,7 +1993,7 @@ hardware_int_paca0: .space 8*4096 -/* 1 page segment table per cpu (max 48) */ +/* 1 page segment table per cpu (max 48, cpu0 allocated at STAB0_PHYS_ADDR) */ .globl stab_array stab_array: .space 4096 * 48 diff -Nru a/arch/ppc64/kernel/htab.c b/arch/ppc64/kernel/htab.c --- a/arch/ppc64/kernel/htab.c Thu May 8 00:24:29 2003 +++ b/arch/ppc64/kernel/htab.c Thu May 8 00:24:29 2003 @@ -101,7 +101,7 @@ hpteg = ((hash & htab_data.htab_hash_mask)*HPTES_PER_GROUP); - if (naca->platform == PLATFORM_PSERIES_LPAR) + if (systemcfg->platform == PLATFORM_PSERIES_LPAR) ret = pSeries_lpar_hpte_insert(hpteg, va, (unsigned long)__v2a(addr) >> PAGE_SHIFT, 0, mode, 1, large); @@ -140,7 +140,7 @@ htab_data.htab_num_ptegs = pteg_count; htab_data.htab_hash_mask = pteg_count - 1; - if (naca->platform == PLATFORM_PSERIES) { + if (systemcfg->platform == PLATFORM_PSERIES) { /* Find storage for the HPT. Must be contiguous in * the absolute address space. */ @@ -165,15 +165,15 @@ mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX; /* XXX we currently map kernel text rw, should fix this */ - if (cpu_has_largepage() && naca->physicalMemorySize > 256*MB) { + if (cpu_has_largepage() && systemcfg->physicalMemorySize > 256*MB) { create_pte_mapping((unsigned long)KERNELBASE, KERNELBASE + 256*MB, mode_rw, 0); create_pte_mapping((unsigned long)KERNELBASE + 256*MB, - KERNELBASE + (naca->physicalMemorySize), + KERNELBASE + (systemcfg->physicalMemorySize), mode_rw, 1); } else { create_pte_mapping((unsigned long)KERNELBASE, - KERNELBASE+(naca->physicalMemorySize), + KERNELBASE+(systemcfg->physicalMemorySize), mode_rw, 0); } } diff -Nru a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c --- a/arch/ppc64/kernel/iSeries_setup.c Thu May 8 00:24:29 2003 +++ b/arch/ppc64/kernel/iSeries_setup.c Thu May 8 00:24:29 2003 @@ -561,13 +561,13 @@ * which should be equal to * nextPhysChunk */ - naca->physicalMemorySize = chunk_to_addr(nextPhysChunk); + systemcfg->physicalMemorySize = chunk_to_addr(nextPhysChunk); /* Bolt kernel mappings for all of memory */ - iSeries_bolt_kernel( 0, naca->physicalMemorySize ); + iSeries_bolt_kernel( 0, systemcfg->physicalMemorySize ); lmb_init(); - lmb_add( 0, naca->physicalMemorySize ); + lmb_add( 0, systemcfg->physicalMemorySize ); lmb_analyze(); /* ?? */ lmb_reserve( 0, __pa(klimit)); @@ -584,29 +584,28 @@ static void __init setup_iSeries_cache_sizes(void) { - unsigned i,n; - unsigned procIx = get_paca()->xLpPaca.xDynHvPhysicalProcIndex; + unsigned int i, n; + unsigned int procIx = get_paca()->xLpPaca.xDynHvPhysicalProcIndex; + + systemcfg->iCacheL1Size = xIoHriProcessorVpd[procIx].xInstCacheSize * 1024; + systemcfg->iCacheL1LineSize = xIoHriProcessorVpd[procIx].xInstCacheOperandSize; + systemcfg->dCacheL1Size = xIoHriProcessorVpd[procIx].xDataL1CacheSizeKB * 1024; + systemcfg->dCacheL1LineSize = xIoHriProcessorVpd[procIx].xDataCacheOperandSize; + naca->iCacheL1LinesPerPage = PAGE_SIZE / systemcfg->iCacheL1LineSize; + naca->dCacheL1LinesPerPage = PAGE_SIZE / systemcfg->dCacheL1LineSize; - naca->iCacheL1LineSize = xIoHriProcessorVpd[procIx].xInstCacheOperandSize; - naca->dCacheL1LineSize = xIoHriProcessorVpd[procIx].xDataCacheOperandSize; - naca->iCacheL1LinesPerPage = PAGE_SIZE / naca->iCacheL1LineSize; - naca->dCacheL1LinesPerPage = PAGE_SIZE / naca->dCacheL1LineSize; - i = naca->iCacheL1LineSize; + i = systemcfg->iCacheL1LineSize; n = 0; while ((i=(i/2))) ++n; naca->iCacheL1LogLineSize = n; - i = naca->dCacheL1LineSize; + + i = systemcfg->dCacheL1LineSize; n = 0; while ((i=(i/2))) ++n; naca->dCacheL1LogLineSize = n; - printk( "D-cache line size = %d (log = %d)\n", - (unsigned)naca->dCacheL1LineSize, - (unsigned)naca->dCacheL1LogLineSize ); - printk( "I-cache line size = %d (log = %d)\n", - (unsigned)naca->iCacheL1LineSize, - (unsigned)naca->iCacheL1LogLineSize ); - + printk( "D-cache line size = %d\n", (unsigned int)systemcfg->dCacheL1LineSize); + printk( "I-cache line size = %d\n", (unsigned int)systemcfg->iCacheL1LineSize); } /* @@ -648,6 +647,11 @@ void * eventStack; unsigned procIx = get_paca()->xLpPaca.xDynHvPhysicalProcIndex; + /* Add an eye catcher and the systemcfg layout version number */ + strcpy(systemcfg->eye_catcher, "SYSTEMCFG:PPC64"); + systemcfg->version.major = SYSTEMCFG_MAJOR; + systemcfg->version.minor = SYSTEMCFG_MINOR; + /* Setup the Lp Event Queue */ /* Allocate a page for the Event Stack @@ -696,8 +700,8 @@ printk("Time base frequency = %lu.%02lu\n", tbFreqMhz, tbFreqMhzHundreths ); - printk("Processor version = %x\n", - xIoHriProcessorVpd[procIx].xPVR ); + systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR; + printk("Processor version = %x\n", systemcfg->processor); } @@ -726,9 +730,9 @@ seq_printf(m,"time base\t: %lu.%02luMHz\n", tbFreqMhz, tbFreqMhzHundreths ); seq_printf(m,"i-cache\t\t: %d\n", - naca->iCacheL1LineSize); + systemcfg->iCacheL1LineSize); seq_printf(m,"d-cache\t\t: %d\n", - naca->dCacheL1LineSize); + systemcfg->dCacheL1LineSize); } diff -Nru a/arch/ppc64/kernel/ioctl32.c b/arch/ppc64/kernel/ioctl32.c --- a/arch/ppc64/kernel/ioctl32.c Thu May 8 00:24:30 2003 +++ b/arch/ppc64/kernel/ioctl32.c Thu May 8 00:24:30 2003 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -577,6 +579,17 @@ len += sizeof(struct ethtool_regs); break; } + case ETHTOOL_GEEPROM: + case ETHTOOL_SEEPROM: { + struct ethtool_eeprom *promaddr = (struct ethtool_eeprom *)A(data); + /* darned variable size arguments */ + if (get_user(len, (u32 *)&promaddr->len)) { + err = -EFAULT; + goto out; + } + len += sizeof(struct ethtool_eeprom); + break; + } case ETHTOOL_GSET: case ETHTOOL_SSET: len = sizeof(struct ethtool_cmd); break; default: @@ -659,6 +672,47 @@ return err; } +static inline void *alloc_user_space(long len) +{ + struct pt_regs *regs = current->thread.regs; + unsigned long usp = regs->gpr[1]; + + /* + * We cant access below the stack pointer in the 32bit ABI and + * can access 288 bytes in the 64bit ABI + */ + if (!(test_thread_flag(TIF_32BIT))) + usp -= 288; + + return (void *) (usp - len); +} + +int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct ifreq *u_ifreq64; + struct ifreq32 *u_ifreq32 = (struct ifreq32 *) arg; + char tmp_buf[IFNAMSIZ]; + void __user *data64; + u32 data32; + + if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]), + IFNAMSIZ)) + return -EFAULT; + if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data)) + return -EFAULT; + data64 = A(data32); + + u_ifreq64 = alloc_user_space(sizeof(*u_ifreq64)); + + /* Don't check these user accesses, just let that get trapped + * in the ioctl handler instead. + */ + copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], IFNAMSIZ); + __put_user(data64, &u_ifreq64->ifr_ifru.ifru_data); + + return sys_ioctl(fd, cmd, (unsigned long) u_ifreq64); +} + static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg) { struct ifreq ifr; @@ -3643,670 +3697,32 @@ #define BNEPGETCONNLIST _IOR('B', 210, int) #define BNEPGETCONNINFO _IOR('B', 211, int) -struct ioctl_trans { - unsigned long cmd; - unsigned long handler; - unsigned long next; -}; - -#define COMPATIBLE_IOCTL(cmd) { cmd, (unsigned long)sys_ioctl, 0 }, +#define HANDLE_IOCTL(cmd,handler) { cmd, (ioctl_trans_handler_t)handler, 0 }, +#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd,sys_ioctl) -#define HANDLE_IOCTL(cmd,handler) { cmd, (unsigned long)handler, 0 }, +#define IOCTL_TABLE_START \ + struct ioctl_trans ioctl_start[] = { +#define IOCTL_TABLE_END \ + }; struct ioctl_trans ioctl_end[0]; #define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int) #define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t) -static struct ioctl_trans ioctl_translations[] = { - /* List here explicitly which ioctl's need translation, - * all others default to calling sys_ioctl(). - */ -/* Big T */ -COMPATIBLE_IOCTL(TCGETA) -COMPATIBLE_IOCTL(TCSETA) -COMPATIBLE_IOCTL(TCSETAW) -COMPATIBLE_IOCTL(TCSETAF) -COMPATIBLE_IOCTL(TCSBRK) +IOCTL_TABLE_START +#include COMPATIBLE_IOCTL(TCSBRKP) -COMPATIBLE_IOCTL(TCXONC) -COMPATIBLE_IOCTL(TCFLSH) -COMPATIBLE_IOCTL(TCGETS) -COMPATIBLE_IOCTL(TCSETS) -COMPATIBLE_IOCTL(TCSETSW) -COMPATIBLE_IOCTL(TCSETSF) -COMPATIBLE_IOCTL(TIOCLINUX) COMPATIBLE_IOCTL(TIOCSTART) COMPATIBLE_IOCTL(TIOCSTOP) -/* Little t */ -COMPATIBLE_IOCTL(TIOCGETD) -COMPATIBLE_IOCTL(TIOCSETD) -COMPATIBLE_IOCTL(TIOCEXCL) -COMPATIBLE_IOCTL(TIOCNXCL) -COMPATIBLE_IOCTL(TIOCCONS) -COMPATIBLE_IOCTL(TIOCGSOFTCAR) -COMPATIBLE_IOCTL(TIOCSSOFTCAR) -COMPATIBLE_IOCTL(TIOCSWINSZ) -COMPATIBLE_IOCTL(TIOCGWINSZ) -COMPATIBLE_IOCTL(TIOCMGET) -COMPATIBLE_IOCTL(TIOCMBIC) -COMPATIBLE_IOCTL(TIOCMBIS) -COMPATIBLE_IOCTL(TIOCMSET) -COMPATIBLE_IOCTL(TIOCPKT) -COMPATIBLE_IOCTL(TIOCNOTTY) -COMPATIBLE_IOCTL(TIOCSTI) -COMPATIBLE_IOCTL(TIOCOUTQ) -COMPATIBLE_IOCTL(TIOCSPGRP) -COMPATIBLE_IOCTL(TIOCGPGRP) -COMPATIBLE_IOCTL(TIOCSCTTY) -COMPATIBLE_IOCTL(TIOCGPTN) -COMPATIBLE_IOCTL(TIOCSPTLCK) COMPATIBLE_IOCTL(TIOCGSERIAL) COMPATIBLE_IOCTL(TIOCSSERIAL) -COMPATIBLE_IOCTL(TIOCSERGETLSR) COMPATIBLE_IOCTL(TIOCSLTC) -/* Big F */ -COMPATIBLE_IOCTL(FBIOGET_VSCREENINFO) -COMPATIBLE_IOCTL(FBIOPUT_VSCREENINFO) -COMPATIBLE_IOCTL(FBIOPAN_DISPLAY) -COMPATIBLE_IOCTL(FBIOGET_CON2FBMAP) -COMPATIBLE_IOCTL(FBIOPUT_CON2FBMAP) #if 0 COMPATIBLE_IOCTL(FBIOBLANK) #endif -/* Little f */ -COMPATIBLE_IOCTL(FIOCLEX) -COMPATIBLE_IOCTL(FIONCLEX) -COMPATIBLE_IOCTL(FIOASYNC) -COMPATIBLE_IOCTL(FIONBIO) -COMPATIBLE_IOCTL(FIONREAD) /* This is also TIOCINQ */ -/* 0x00 */ -COMPATIBLE_IOCTL(FIBMAP) -COMPATIBLE_IOCTL(FIGETBSZ) -/* 0x03 -- HD/IDE ioctl's used by hdparm and friends. - * Some need translations, these do not. - */ -COMPATIBLE_IOCTL(HDIO_GET_IDENTITY) -COMPATIBLE_IOCTL(HDIO_SET_DMA) -COMPATIBLE_IOCTL(HDIO_SET_UNMASKINTR) -COMPATIBLE_IOCTL(HDIO_SET_NOWERR) -COMPATIBLE_IOCTL(HDIO_SET_32BIT) -COMPATIBLE_IOCTL(HDIO_SET_MULTCOUNT) -COMPATIBLE_IOCTL(HDIO_DRIVE_CMD) -COMPATIBLE_IOCTL(HDIO_SET_PIO_MODE) -COMPATIBLE_IOCTL(HDIO_SET_NICE) -/* 0x02 -- Floppy ioctls */ -COMPATIBLE_IOCTL(FDMSGON) -COMPATIBLE_IOCTL(FDMSGOFF) -COMPATIBLE_IOCTL(FDSETEMSGTRESH) -COMPATIBLE_IOCTL(FDFLUSH) -COMPATIBLE_IOCTL(FDWERRORCLR) -COMPATIBLE_IOCTL(FDSETMAXERRS) -COMPATIBLE_IOCTL(FDGETMAXERRS) -COMPATIBLE_IOCTL(FDGETDRVTYP) -COMPATIBLE_IOCTL(FDEJECT) -COMPATIBLE_IOCTL(FDCLRPRM) -COMPATIBLE_IOCTL(FDFMTBEG) -COMPATIBLE_IOCTL(FDFMTEND) -COMPATIBLE_IOCTL(FDRESET) -COMPATIBLE_IOCTL(FDTWADDLE) -COMPATIBLE_IOCTL(FDFMTTRK) -COMPATIBLE_IOCTL(FDRAWCMD) -/* 0x12 */ -COMPATIBLE_IOCTL(BLKROSET) -COMPATIBLE_IOCTL(BLKROGET) -COMPATIBLE_IOCTL(BLKRRPART) -COMPATIBLE_IOCTL(BLKFLSBUF) -COMPATIBLE_IOCTL(BLKSECTSET) -COMPATIBLE_IOCTL(BLKSSZGET) -COMPATIBLE_IOCTL(BLKRASET) -COMPATIBLE_IOCTL(BLKFRASET) -/* RAID */ -COMPATIBLE_IOCTL(RAID_VERSION) -COMPATIBLE_IOCTL(GET_ARRAY_INFO) -COMPATIBLE_IOCTL(GET_DISK_INFO) -COMPATIBLE_IOCTL(PRINT_RAID_DEBUG) -COMPATIBLE_IOCTL(CLEAR_ARRAY) -COMPATIBLE_IOCTL(ADD_NEW_DISK) -COMPATIBLE_IOCTL(HOT_REMOVE_DISK) -COMPATIBLE_IOCTL(SET_ARRAY_INFO) -COMPATIBLE_IOCTL(SET_DISK_INFO) -COMPATIBLE_IOCTL(WRITE_RAID_INFO) -COMPATIBLE_IOCTL(UNPROTECT_ARRAY) -COMPATIBLE_IOCTL(PROTECT_ARRAY) -COMPATIBLE_IOCTL(HOT_ADD_DISK) -COMPATIBLE_IOCTL(SET_DISK_FAULTY) -COMPATIBLE_IOCTL(RUN_ARRAY) -COMPATIBLE_IOCTL(START_ARRAY) -COMPATIBLE_IOCTL(STOP_ARRAY) -COMPATIBLE_IOCTL(STOP_ARRAY_RO) -COMPATIBLE_IOCTL(RESTART_ARRAY_RW) -/* Big K */ -COMPATIBLE_IOCTL(PIO_FONT) -COMPATIBLE_IOCTL(GIO_FONT) -COMPATIBLE_IOCTL(KDSIGACCEPT) -COMPATIBLE_IOCTL(KDGETKEYCODE) -COMPATIBLE_IOCTL(KDSETKEYCODE) -COMPATIBLE_IOCTL(KIOCSOUND) -COMPATIBLE_IOCTL(KDMKTONE) -COMPATIBLE_IOCTL(KDGKBTYPE) -COMPATIBLE_IOCTL(KDSETMODE) -COMPATIBLE_IOCTL(KDGETMODE) -COMPATIBLE_IOCTL(KDSKBMODE) -COMPATIBLE_IOCTL(KDGKBMODE) -COMPATIBLE_IOCTL(KDSKBMETA) -COMPATIBLE_IOCTL(KDGKBMETA) -COMPATIBLE_IOCTL(KDGKBENT) -COMPATIBLE_IOCTL(KDSKBENT) -COMPATIBLE_IOCTL(KDGKBSENT) -COMPATIBLE_IOCTL(KDSKBSENT) -COMPATIBLE_IOCTL(KDGKBDIACR) -COMPATIBLE_IOCTL(KDKBDREP) -COMPATIBLE_IOCTL(KDSKBDIACR) -COMPATIBLE_IOCTL(KDGKBLED) -COMPATIBLE_IOCTL(KDSKBLED) -COMPATIBLE_IOCTL(KDGETLED) -COMPATIBLE_IOCTL(KDSETLED) -COMPATIBLE_IOCTL(GIO_SCRNMAP) -COMPATIBLE_IOCTL(PIO_SCRNMAP) -COMPATIBLE_IOCTL(GIO_UNISCRNMAP) -COMPATIBLE_IOCTL(PIO_UNISCRNMAP) -COMPATIBLE_IOCTL(PIO_FONTRESET) -COMPATIBLE_IOCTL(PIO_UNIMAPCLR) -/* Big S */ -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN) -COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST) -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI) -COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK) -COMPATIBLE_IOCTL(SCSI_IOCTL_DOORUNLOCK) -COMPATIBLE_IOCTL(SCSI_IOCTL_TEST_UNIT_READY) -COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_ENABLE) -COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_DISABLE) -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER) -COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND) -/* Big T */ -COMPATIBLE_IOCTL(TUNSETNOCSUM) -COMPATIBLE_IOCTL(TUNSETDEBUG) -COMPATIBLE_IOCTL(TUNSETIFF) -COMPATIBLE_IOCTL(TUNSETPERSIST) -COMPATIBLE_IOCTL(TUNSETOWNER) -/* Big V */ -COMPATIBLE_IOCTL(VT_SETMODE) -COMPATIBLE_IOCTL(VT_GETMODE) -COMPATIBLE_IOCTL(VT_GETSTATE) -COMPATIBLE_IOCTL(VT_OPENQRY) -COMPATIBLE_IOCTL(VT_ACTIVATE) -COMPATIBLE_IOCTL(VT_WAITACTIVE) -COMPATIBLE_IOCTL(VT_RELDISP) -COMPATIBLE_IOCTL(VT_DISALLOCATE) -COMPATIBLE_IOCTL(VT_RESIZE) -COMPATIBLE_IOCTL(VT_RESIZEX) -COMPATIBLE_IOCTL(VT_LOCKSWITCH) -COMPATIBLE_IOCTL(VT_UNLOCKSWITCH) -/* Little v, the video4linux ioctls */ -COMPATIBLE_IOCTL(VIDIOCGCAP) -COMPATIBLE_IOCTL(VIDIOCGCHAN) -COMPATIBLE_IOCTL(VIDIOCSCHAN) -COMPATIBLE_IOCTL(VIDIOCGPICT) -COMPATIBLE_IOCTL(VIDIOCSPICT) -COMPATIBLE_IOCTL(VIDIOCCAPTURE) -COMPATIBLE_IOCTL(VIDIOCKEY) -COMPATIBLE_IOCTL(VIDIOCGAUDIO) -COMPATIBLE_IOCTL(VIDIOCSAUDIO) -COMPATIBLE_IOCTL(VIDIOCSYNC) -COMPATIBLE_IOCTL(VIDIOCMCAPTURE) -COMPATIBLE_IOCTL(VIDIOCGMBUF) -COMPATIBLE_IOCTL(VIDIOCGUNIT) -COMPATIBLE_IOCTL(VIDIOCGCAPTURE) -COMPATIBLE_IOCTL(VIDIOCSCAPTURE) -/* BTTV specific... */ -COMPATIBLE_IOCTL(_IOW('v', BASE_VIDIOCPRIVATE+0, char [256])) -COMPATIBLE_IOCTL(_IOR('v', BASE_VIDIOCPRIVATE+1, char [256])) -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int)) -COMPATIBLE_IOCTL(_IOW('v' , BASE_VIDIOCPRIVATE+3, char [16])) /* struct bttv_pll_info */ -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+4, int)) -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+5, int)) -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+6, int)) -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+7, int)) /* Little p (/dev/rtc, /dev/envctrl, etc.) */ COMPATIBLE_IOCTL(_IOR('p', 20, int[7])) /* RTCGET */ COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */ -COMPATIBLE_IOCTL(RTC_AIE_ON) -COMPATIBLE_IOCTL(RTC_AIE_OFF) -COMPATIBLE_IOCTL(RTC_UIE_ON) -COMPATIBLE_IOCTL(RTC_UIE_OFF) -COMPATIBLE_IOCTL(RTC_PIE_ON) -COMPATIBLE_IOCTL(RTC_PIE_OFF) -COMPATIBLE_IOCTL(RTC_WIE_ON) -COMPATIBLE_IOCTL(RTC_WIE_OFF) -COMPATIBLE_IOCTL(RTC_ALM_SET) -COMPATIBLE_IOCTL(RTC_ALM_READ) -COMPATIBLE_IOCTL(RTC_RD_TIME) -COMPATIBLE_IOCTL(RTC_SET_TIME) -COMPATIBLE_IOCTL(RTC_WKALM_SET) -COMPATIBLE_IOCTL(RTC_WKALM_RD) -/* Little m */ -COMPATIBLE_IOCTL(MTIOCTOP) -/* Socket level stuff */ -COMPATIBLE_IOCTL(FIOSETOWN) -COMPATIBLE_IOCTL(SIOCSPGRP) -COMPATIBLE_IOCTL(FIOGETOWN) -COMPATIBLE_IOCTL(SIOCGPGRP) -COMPATIBLE_IOCTL(SIOCATMARK) -COMPATIBLE_IOCTL(SIOCSIFLINK) -COMPATIBLE_IOCTL(SIOCSIFENCAP) -COMPATIBLE_IOCTL(SIOCGIFENCAP) -COMPATIBLE_IOCTL(SIOCSIFBR) -COMPATIBLE_IOCTL(SIOCGIFBR) -COMPATIBLE_IOCTL(SIOCSARP) -COMPATIBLE_IOCTL(SIOCGARP) -COMPATIBLE_IOCTL(SIOCDARP) -COMPATIBLE_IOCTL(SIOCSRARP) -COMPATIBLE_IOCTL(SIOCGRARP) -COMPATIBLE_IOCTL(SIOCDRARP) -COMPATIBLE_IOCTL(SIOCADDDLCI) -COMPATIBLE_IOCTL(SIOCDELDLCI) -COMPATIBLE_IOCTL(SIOCGMIIPHY) -COMPATIBLE_IOCTL(SIOCGMIIREG) -COMPATIBLE_IOCTL(SIOCSMIIREG) -COMPATIBLE_IOCTL(SIOCGIFVLAN) -COMPATIBLE_IOCTL(SIOCSIFVLAN) -/* SG stuff */ -COMPATIBLE_IOCTL(SG_SET_TIMEOUT) -COMPATIBLE_IOCTL(SG_GET_TIMEOUT) -COMPATIBLE_IOCTL(SG_EMULATED_HOST) -COMPATIBLE_IOCTL(SG_SET_TRANSFORM) -COMPATIBLE_IOCTL(SG_GET_TRANSFORM) -COMPATIBLE_IOCTL(SG_SET_RESERVED_SIZE) -COMPATIBLE_IOCTL(SG_GET_RESERVED_SIZE) -COMPATIBLE_IOCTL(SG_GET_SCSI_ID) -COMPATIBLE_IOCTL(SG_SET_FORCE_LOW_DMA) -COMPATIBLE_IOCTL(SG_GET_LOW_DMA) -COMPATIBLE_IOCTL(SG_SET_FORCE_PACK_ID) -COMPATIBLE_IOCTL(SG_GET_PACK_ID) -COMPATIBLE_IOCTL(SG_GET_NUM_WAITING) -COMPATIBLE_IOCTL(SG_SET_DEBUG) -COMPATIBLE_IOCTL(SG_GET_SG_TABLESIZE) -COMPATIBLE_IOCTL(SG_GET_COMMAND_Q) -COMPATIBLE_IOCTL(SG_SET_COMMAND_Q) -COMPATIBLE_IOCTL(SG_GET_VERSION_NUM) -COMPATIBLE_IOCTL(SG_NEXT_CMD_LEN) -COMPATIBLE_IOCTL(SG_SCSI_RESET) -COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE) -COMPATIBLE_IOCTL(SG_SET_KEEP_ORPHAN) -COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN) -/* PPP stuff */ -COMPATIBLE_IOCTL(PPPIOCGFLAGS) -COMPATIBLE_IOCTL(PPPIOCSFLAGS) -COMPATIBLE_IOCTL(PPPIOCGASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCSASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCGUNIT) -COMPATIBLE_IOCTL(PPPIOCGRASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCSRASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCGMRU) -COMPATIBLE_IOCTL(PPPIOCSMRU) -COMPATIBLE_IOCTL(PPPIOCSMAXCID) -COMPATIBLE_IOCTL(PPPIOCGXASYNCMAP) -COMPATIBLE_IOCTL(LPGETSTATUS) -COMPATIBLE_IOCTL(PPPIOCSXASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCXFERUNIT) -COMPATIBLE_IOCTL(PPPIOCGNPMODE) -COMPATIBLE_IOCTL(PPPIOCSNPMODE) -COMPATIBLE_IOCTL(PPPIOCGDEBUG) -COMPATIBLE_IOCTL(PPPIOCSDEBUG) -COMPATIBLE_IOCTL(PPPIOCNEWUNIT) -COMPATIBLE_IOCTL(PPPIOCATTACH) -COMPATIBLE_IOCTL(PPPIOCDETACH) -COMPATIBLE_IOCTL(PPPIOCSMRRU) -COMPATIBLE_IOCTL(PPPIOCCONNECT) -COMPATIBLE_IOCTL(PPPIOCDISCONN) -COMPATIBLE_IOCTL(PPPIOCATTCHAN) -COMPATIBLE_IOCTL(PPPIOCGCHAN) -/* PPPOX */ -COMPATIBLE_IOCTL(PPPOEIOCSFWD) -COMPATIBLE_IOCTL(PPPOEIOCDFWD) -/* CDROM stuff */ -COMPATIBLE_IOCTL(CDROMPAUSE) -COMPATIBLE_IOCTL(CDROMRESUME) -COMPATIBLE_IOCTL(CDROMPLAYMSF) -COMPATIBLE_IOCTL(CDROMPLAYTRKIND) -COMPATIBLE_IOCTL(CDROMREADTOCHDR) -COMPATIBLE_IOCTL(CDROMREADTOCENTRY) -COMPATIBLE_IOCTL(CDROMSTOP) -COMPATIBLE_IOCTL(CDROMSTART) -COMPATIBLE_IOCTL(CDROMEJECT) -COMPATIBLE_IOCTL(CDROMVOLCTRL) -COMPATIBLE_IOCTL(CDROMSUBCHNL) -COMPATIBLE_IOCTL(CDROMEJECT_SW) -COMPATIBLE_IOCTL(CDROMMULTISESSION) -COMPATIBLE_IOCTL(CDROM_GET_MCN) -COMPATIBLE_IOCTL(CDROMRESET) -COMPATIBLE_IOCTL(CDROMVOLREAD) -COMPATIBLE_IOCTL(CDROMSEEK) -COMPATIBLE_IOCTL(CDROMPLAYBLK) -COMPATIBLE_IOCTL(CDROMCLOSETRAY) -COMPATIBLE_IOCTL(CDROM_SET_OPTIONS) -COMPATIBLE_IOCTL(CDROM_CLEAR_OPTIONS) -COMPATIBLE_IOCTL(CDROM_SELECT_SPEED) -COMPATIBLE_IOCTL(CDROM_SELECT_DISC) -COMPATIBLE_IOCTL(CDROM_MEDIA_CHANGED) -COMPATIBLE_IOCTL(CDROM_DRIVE_STATUS) -COMPATIBLE_IOCTL(CDROM_DISC_STATUS) -COMPATIBLE_IOCTL(CDROM_CHANGER_NSLOTS) -COMPATIBLE_IOCTL(CDROM_LOCKDOOR) -COMPATIBLE_IOCTL(CDROM_DEBUG) -COMPATIBLE_IOCTL(CDROM_GET_CAPABILITY) -/* DVD ioctls */ -COMPATIBLE_IOCTL(DVD_READ_STRUCT) -COMPATIBLE_IOCTL(DVD_WRITE_STRUCT) -COMPATIBLE_IOCTL(DVD_AUTH) -/* Big L */ -COMPATIBLE_IOCTL(LOOP_SET_FD) -COMPATIBLE_IOCTL(LOOP_CLR_FD) -/* Big Q for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_SEQ_RESET) -COMPATIBLE_IOCTL(SNDCTL_SEQ_SYNC) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_INFO) -COMPATIBLE_IOCTL(SNDCTL_SEQ_CTRLRATE) -COMPATIBLE_IOCTL(SNDCTL_SEQ_GETOUTCOUNT) -COMPATIBLE_IOCTL(SNDCTL_SEQ_GETINCOUNT) -COMPATIBLE_IOCTL(SNDCTL_SEQ_PERCMODE) -COMPATIBLE_IOCTL(SNDCTL_FM_LOAD_INSTR) -COMPATIBLE_IOCTL(SNDCTL_SEQ_TESTMIDI) -COMPATIBLE_IOCTL(SNDCTL_SEQ_RESETSAMPLES) -COMPATIBLE_IOCTL(SNDCTL_SEQ_NRSYNTHS) -COMPATIBLE_IOCTL(SNDCTL_SEQ_NRMIDIS) -COMPATIBLE_IOCTL(SNDCTL_MIDI_INFO) -COMPATIBLE_IOCTL(SNDCTL_SEQ_THRESHOLD) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_MEMAVL) -COMPATIBLE_IOCTL(SNDCTL_FM_4OP_ENABLE) -COMPATIBLE_IOCTL(SNDCTL_SEQ_PANIC) -COMPATIBLE_IOCTL(SNDCTL_SEQ_OUTOFBAND) -COMPATIBLE_IOCTL(SNDCTL_SEQ_GETTIME) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_ID) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_CONTROL) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_REMOVESAMPLE) -/* Big T for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_TMR_TIMEBASE) -COMPATIBLE_IOCTL(SNDCTL_TMR_START) -COMPATIBLE_IOCTL(SNDCTL_TMR_STOP) -COMPATIBLE_IOCTL(SNDCTL_TMR_CONTINUE) -COMPATIBLE_IOCTL(SNDCTL_TMR_TEMPO) -COMPATIBLE_IOCTL(SNDCTL_TMR_SOURCE) -COMPATIBLE_IOCTL(SNDCTL_TMR_METRONOME) -COMPATIBLE_IOCTL(SNDCTL_TMR_SELECT) -/* Little m for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_MIDI_PRETIME) -COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUMODE) -COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUCMD) -/* Big P for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_DSP_RESET) -COMPATIBLE_IOCTL(SNDCTL_DSP_SYNC) -COMPATIBLE_IOCTL(SNDCTL_DSP_SPEED) -COMPATIBLE_IOCTL(SNDCTL_DSP_STEREO) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETBLKSIZE) -COMPATIBLE_IOCTL(SNDCTL_DSP_CHANNELS) -COMPATIBLE_IOCTL(SOUND_PCM_WRITE_FILTER) -COMPATIBLE_IOCTL(SNDCTL_DSP_POST) -COMPATIBLE_IOCTL(SNDCTL_DSP_SUBDIVIDE) -COMPATIBLE_IOCTL(SNDCTL_DSP_SETFRAGMENT) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETFMTS) -COMPATIBLE_IOCTL(SNDCTL_DSP_SETFMT) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETOSPACE) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETISPACE) -COMPATIBLE_IOCTL(SNDCTL_DSP_NONBLOCK) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETCAPS) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETTRIGGER) -COMPATIBLE_IOCTL(SNDCTL_DSP_SETTRIGGER) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETIPTR) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETOPTR) -/* SNDCTL_DSP_MAPINBUF, XXX needs translation */ -/* SNDCTL_DSP_MAPOUTBUF, XXX needs translation */ -COMPATIBLE_IOCTL(SNDCTL_DSP_SETSYNCRO) -COMPATIBLE_IOCTL(SNDCTL_DSP_SETDUPLEX) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETODELAY) -COMPATIBLE_IOCTL(SNDCTL_DSP_PROFILE) -COMPATIBLE_IOCTL(SOUND_PCM_READ_RATE) -COMPATIBLE_IOCTL(SOUND_PCM_READ_CHANNELS) -COMPATIBLE_IOCTL(SOUND_PCM_READ_BITS) -COMPATIBLE_IOCTL(SOUND_PCM_READ_FILTER) -/* Big C for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_COPR_RESET) -COMPATIBLE_IOCTL(SNDCTL_COPR_LOAD) -COMPATIBLE_IOCTL(SNDCTL_COPR_RDATA) -COMPATIBLE_IOCTL(SNDCTL_COPR_RCODE) -COMPATIBLE_IOCTL(SNDCTL_COPR_WDATA) -COMPATIBLE_IOCTL(SNDCTL_COPR_WCODE) -COMPATIBLE_IOCTL(SNDCTL_COPR_RUN) -COMPATIBLE_IOCTL(SNDCTL_COPR_HALT) -COMPATIBLE_IOCTL(SNDCTL_COPR_SENDMSG) -COMPATIBLE_IOCTL(SNDCTL_COPR_RCVMSG) -/* Big M for sound/OSS */ -COMPATIBLE_IOCTL(SOUND_MIXER_READ_VOLUME) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_BASS) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_TREBLE) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_SYNTH) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_PCM) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_SPEAKER) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_MIC) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_CD) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_IMIX) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_ALTPCM) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECLEV) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_IGAIN) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_OGAIN) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE1) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE2) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE3) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL1)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL2)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL3)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEIN)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEOUT)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_VIDEO)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_RADIO)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_MONITOR)) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_MUTE) -/* SOUND_MIXER_READ_ENHANCE, same value as READ_MUTE */ -/* SOUND_MIXER_READ_LOUD, same value as READ_MUTE */ -COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECSRC) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_DEVMASK) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECMASK) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_STEREODEVS) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_CAPS) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_VOLUME) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_BASS) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_TREBLE) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_SYNTH) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_PCM) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_SPEAKER) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MIC) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_CD) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_IMIX) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_ALTPCM) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_RECLEV) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_IGAIN) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_OGAIN) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE1) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE2) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE3) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL1)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL2)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL3)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEIN)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEOUT)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_VIDEO)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_RADIO)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_MONITOR)) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MUTE) -/* SOUND_MIXER_WRITE_ENHANCE, same value as WRITE_MUTE */ -/* SOUND_MIXER_WRITE_LOUD, same value as WRITE_MUTE */ -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_RECSRC) -COMPATIBLE_IOCTL(SOUND_MIXER_INFO) -COMPATIBLE_IOCTL(SOUND_OLD_MIXER_INFO) -COMPATIBLE_IOCTL(SOUND_MIXER_ACCESS) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE1) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE2) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE3) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE4) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE5) -COMPATIBLE_IOCTL(SOUND_MIXER_GETLEVELS) -COMPATIBLE_IOCTL(SOUND_MIXER_SETLEVELS) -COMPATIBLE_IOCTL(OSS_GETVERSION) -/* AUTOFS */ -COMPATIBLE_IOCTL(AUTOFS_IOC_READY) -COMPATIBLE_IOCTL(AUTOFS_IOC_FAIL) -COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC) -COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER) -COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE) -/* DEVFS */ -COMPATIBLE_IOCTL(DEVFSDIOC_GET_PROTO_REV) -COMPATIBLE_IOCTL(DEVFSDIOC_SET_EVENT_MASK) -COMPATIBLE_IOCTL(DEVFSDIOC_RELEASE_EVENT_QUEUE) -COMPATIBLE_IOCTL(DEVFSDIOC_SET_DEBUG_MASK) -/* Raw devices */ -COMPATIBLE_IOCTL(RAW_SETBIND) -COMPATIBLE_IOCTL(RAW_GETBIND) -/* SMB ioctls which do not need any translations */ -COMPATIBLE_IOCTL(SMB_IOC_NEWCONN) -/* NCP ioctls which do not need any translations */ -COMPATIBLE_IOCTL(NCP_IOC_CONN_LOGGED_IN) -COMPATIBLE_IOCTL(NCP_IOC_SIGN_INIT) -COMPATIBLE_IOCTL(NCP_IOC_SIGN_WANTED) -COMPATIBLE_IOCTL(NCP_IOC_SET_SIGN_WANTED) -COMPATIBLE_IOCTL(NCP_IOC_LOCKUNLOCK) -COMPATIBLE_IOCTL(NCP_IOC_GETROOT) -COMPATIBLE_IOCTL(NCP_IOC_SETROOT) -COMPATIBLE_IOCTL(NCP_IOC_GETCHARSETS) -COMPATIBLE_IOCTL(NCP_IOC_SETCHARSETS) -COMPATIBLE_IOCTL(NCP_IOC_GETDENTRYTTL) -COMPATIBLE_IOCTL(NCP_IOC_SETDENTRYTTL) -/* Little a */ -COMPATIBLE_IOCTL(ATMSIGD_CTRL) -COMPATIBLE_IOCTL(ATMARPD_CTRL) -COMPATIBLE_IOCTL(ATMLEC_CTRL) -COMPATIBLE_IOCTL(ATMLEC_MCAST) -COMPATIBLE_IOCTL(ATMLEC_DATA) -COMPATIBLE_IOCTL(ATM_SETSC) -COMPATIBLE_IOCTL(SIOCSIFATMTCP) -COMPATIBLE_IOCTL(SIOCMKCLIP) -COMPATIBLE_IOCTL(ATMARP_MKIP) -COMPATIBLE_IOCTL(ATMARP_SETENTRY) -COMPATIBLE_IOCTL(ATMARP_ENCAP) -COMPATIBLE_IOCTL(ATMTCP_CREATE) -COMPATIBLE_IOCTL(ATMTCP_REMOVE) -COMPATIBLE_IOCTL(ATMMPC_CTRL) -COMPATIBLE_IOCTL(ATMMPC_DATA) -#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) -COMPATIBLE_IOCTL(DRM_IOCTL_GET_MAGIC) -COMPATIBLE_IOCTL(DRM_IOCTL_IRQ_BUSID) -COMPATIBLE_IOCTL(DRM_IOCTL_AUTH_MAGIC) -COMPATIBLE_IOCTL(DRM_IOCTL_BLOCK) -COMPATIBLE_IOCTL(DRM_IOCTL_UNBLOCK) -COMPATIBLE_IOCTL(DRM_IOCTL_CONTROL) -COMPATIBLE_IOCTL(DRM_IOCTL_ADD_BUFS) -COMPATIBLE_IOCTL(DRM_IOCTL_MARK_BUFS) -COMPATIBLE_IOCTL(DRM_IOCTL_ADD_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_RM_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_MOD_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_GET_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_SWITCH_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_NEW_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_ADD_DRAW) -COMPATIBLE_IOCTL(DRM_IOCTL_RM_DRAW) -COMPATIBLE_IOCTL(DRM_IOCTL_LOCK) -COMPATIBLE_IOCTL(DRM_IOCTL_UNLOCK) -COMPATIBLE_IOCTL(DRM_IOCTL_FINISH) -#endif /* DRM */ -/* Big W */ -/* WIOC_GETSUPPORT not yet implemented -E */ -COMPATIBLE_IOCTL(WDIOC_GETSTATUS) -COMPATIBLE_IOCTL(WDIOC_GETBOOTSTATUS) -COMPATIBLE_IOCTL(WDIOC_GETTEMP) -COMPATIBLE_IOCTL(WDIOC_SETOPTIONS) -COMPATIBLE_IOCTL(WDIOC_KEEPALIVE) -/* Big R */ -COMPATIBLE_IOCTL(RNDGETENTCNT) -COMPATIBLE_IOCTL(RNDADDTOENTCNT) -COMPATIBLE_IOCTL(RNDGETPOOL) -COMPATIBLE_IOCTL(RNDADDENTROPY) -COMPATIBLE_IOCTL(RNDZAPENTCNT) -COMPATIBLE_IOCTL(RNDCLEARPOOL) -/* Bluetooth ioctls */ -COMPATIBLE_IOCTL(HCIDEVUP) -COMPATIBLE_IOCTL(HCIDEVDOWN) -COMPATIBLE_IOCTL(HCIDEVRESET) -COMPATIBLE_IOCTL(HCIDEVRESTAT) -COMPATIBLE_IOCTL(HCIGETDEVLIST) -COMPATIBLE_IOCTL(HCIGETDEVINFO) -COMPATIBLE_IOCTL(HCIGETCONNLIST) -COMPATIBLE_IOCTL(HCIGETCONNINFO) -COMPATIBLE_IOCTL(HCISETRAW) -COMPATIBLE_IOCTL(HCISETSCAN) -COMPATIBLE_IOCTL(HCISETAUTH) -COMPATIBLE_IOCTL(HCISETENCRYPT) -COMPATIBLE_IOCTL(HCISETPTYPE) -COMPATIBLE_IOCTL(HCISETLINKPOL) -COMPATIBLE_IOCTL(HCISETLINKMODE) -COMPATIBLE_IOCTL(HCISETACLMTU) -COMPATIBLE_IOCTL(HCISETSCOMTU) -COMPATIBLE_IOCTL(HCIINQUIRY) -COMPATIBLE_IOCTL(HCIUARTSETPROTO) -COMPATIBLE_IOCTL(HCIUARTGETPROTO) -COMPATIBLE_IOCTL(RFCOMMCREATEDEV) -COMPATIBLE_IOCTL(RFCOMMRELEASEDEV) -COMPATIBLE_IOCTL(RFCOMMGETDEVLIST) -COMPATIBLE_IOCTL(RFCOMMGETDEVINFO) -COMPATIBLE_IOCTL(RFCOMMSTEALDLC) -COMPATIBLE_IOCTL(BNEPCONNADD) -COMPATIBLE_IOCTL(BNEPCONNDEL) -COMPATIBLE_IOCTL(BNEPGETCONNLIST) -COMPATIBLE_IOCTL(BNEPGETCONNINFO) -COMPATIBLE_IOCTL(PCIIOC_CONTROLLER) -COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO) -COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM) -COMPATIBLE_IOCTL(PCIIOC_WRITE_COMBINE) -/* USB */ -COMPATIBLE_IOCTL(USBDEVFS_RESETEP) -COMPATIBLE_IOCTL(USBDEVFS_SETINTERFACE) -COMPATIBLE_IOCTL(USBDEVFS_SETCONFIGURATION) -COMPATIBLE_IOCTL(USBDEVFS_GETDRIVER) -COMPATIBLE_IOCTL(USBDEVFS_DISCARDURB) -COMPATIBLE_IOCTL(USBDEVFS_CLAIMINTERFACE) -COMPATIBLE_IOCTL(USBDEVFS_RELEASEINTERFACE) -COMPATIBLE_IOCTL(USBDEVFS_CONNECTINFO) -COMPATIBLE_IOCTL(USBDEVFS_HUB_PORTINFO) -COMPATIBLE_IOCTL(USBDEVFS_RESET) -COMPATIBLE_IOCTL(USBDEVFS_CLEAR_HALT) -/* MTD */ -COMPATIBLE_IOCTL(MEMGETINFO) -COMPATIBLE_IOCTL(MEMERASE) -COMPATIBLE_IOCTL(MEMLOCK) -COMPATIBLE_IOCTL(MEMUNLOCK) -COMPATIBLE_IOCTL(MEMGETREGIONCOUNT) -COMPATIBLE_IOCTL(MEMGETREGIONINFO) -/* NBD */ -COMPATIBLE_IOCTL(NBD_SET_SOCK) -COMPATIBLE_IOCTL(NBD_SET_BLKSIZE) -COMPATIBLE_IOCTL(NBD_SET_SIZE) -COMPATIBLE_IOCTL(NBD_DO_IT) -COMPATIBLE_IOCTL(NBD_CLEAR_SOCK) -COMPATIBLE_IOCTL(NBD_CLEAR_QUE) -COMPATIBLE_IOCTL(NBD_PRINT_DEBUG) -COMPATIBLE_IOCTL(NBD_SET_SIZE_BLOCKS) -COMPATIBLE_IOCTL(NBD_DISCONNECT) -/* device-mapper */ -COMPATIBLE_IOCTL(DM_VERSION) -COMPATIBLE_IOCTL(DM_REMOVE_ALL) -COMPATIBLE_IOCTL(DM_DEV_CREATE) -COMPATIBLE_IOCTL(DM_DEV_REMOVE) -COMPATIBLE_IOCTL(DM_DEV_RELOAD) -COMPATIBLE_IOCTL(DM_DEV_SUSPEND) -COMPATIBLE_IOCTL(DM_DEV_RENAME) -COMPATIBLE_IOCTL(DM_DEV_DEPS) -COMPATIBLE_IOCTL(DM_DEV_STATUS) -COMPATIBLE_IOCTL(DM_TARGET_STATUS) -COMPATIBLE_IOCTL(DM_TARGET_WAIT) + /* And these ioctls need translation */ HANDLE_IOCTL(MEMREADOOB32, mtd_rw_oob) HANDLE_IOCTL(MEMWRITEOOB32, mtd_rw_oob) @@ -4473,4 +3889,4 @@ HANDLE_IOCTL(BLKBSZGET_32, do_blkbszget) HANDLE_IOCTL(BLKBSZSET_32, do_blkbszset) HANDLE_IOCTL(BLKGETSIZE64_32, do_blkgetsize64) -}; +IOCTL_TABLE_END diff -Nru a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c --- a/arch/ppc64/kernel/irq.c Thu May 8 00:24:28 2003 +++ b/arch/ppc64/kernel/irq.c Thu May 8 00:24:28 2003 @@ -212,7 +212,8 @@ return -ENOENT; } -int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), +int request_irq(unsigned int irq, + irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id) { struct irqaction *action; @@ -695,7 +696,7 @@ struct proc_dir_entry *entry; char name [MAX_NAMELEN]; - if (!root_irq_dir || (irq_desc[irq].handler == NULL)) + if (!root_irq_dir || (irq_desc[irq].handler == NULL) || irq_dir[irq]) return; memset(name, 0, MAX_NAMELEN); @@ -743,6 +744,7 @@ } } -void no_action(int irq, void *dev, struct pt_regs *regs) +irqreturn_t no_action(int irq, void *dev, struct pt_regs *regs) { + return IRQ_NONE; } diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S --- a/arch/ppc64/kernel/misc.S Thu May 8 00:24:30 2003 +++ b/arch/ppc64/kernel/misc.S Thu May 8 00:24:30 2003 @@ -170,12 +170,14 @@ */ LOADADDR(r10,naca) /* Get Naca address */ ld r10,0(r10) - lhz r7,DCACHEL1LINESIZE(r10) /* Get cache line size */ + LOADADDR(r11,systemcfg) /* Get systemcfg address */ + ld r11,0(r11) + lwz r7,DCACHEL1LINESIZE(r11)/* Get cache line size */ addi r5,r7,-1 andc r6,r3,r5 /* round low to line bdy */ subf r8,r6,r4 /* compute length */ add r8,r8,r5 /* ensure we get enough */ - lhz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of cache line size */ + lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of cache line size */ srw. r8,r8,r9 /* compute line count */ beqlr /* nothing to do? */ mtctr r8 @@ -186,12 +188,12 @@ /* Now invalidate the instruction cache */ - lhz r7,ICACHEL1LINESIZE(r10) /* Get Icache line size */ + lwz r7,ICACHEL1LINESIZE(r11) /* Get Icache line size */ addi r5,r7,-1 andc r6,r3,r5 /* round low to line bdy */ subf r8,r6,r4 /* compute length */ add r8,r8,r5 - lhz r9,ICACHEL1LOGLINESIZE(r10) /* Get log-2 of Icache line size */ + lwz r9,ICACHEL1LOGLINESIZE(r10) /* Get log-2 of Icache line size */ srw. r8,r8,r9 /* compute line count */ beqlr /* nothing to do? */ mtctr r8 @@ -217,12 +219,14 @@ */ LOADADDR(r10,naca) /* Get Naca address */ ld r10,0(r10) - lhz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */ + LOADADDR(r11,systemcfg) /* Get systemcfg address */ + ld r11,0(r11) + lwz r7,DCACHEL1LINESIZE(r11) /* Get dcache line size */ addi r5,r7,-1 andc r6,r3,r5 /* round low to line bdy */ subf r8,r6,r4 /* compute length */ add r8,r8,r5 /* ensure we get enough */ - lhz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */ + lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */ srw. r8,r8,r9 /* compute line count */ beqlr /* nothing to do? */ mtctr r8 @@ -249,9 +253,11 @@ /* Flush the dcache */ LOADADDR(r7,naca) ld r7,0(r7) + LOADADDR(r8,systemcfg) /* Get systemcfg address */ + ld r8,0(r8) clrrdi r3,r3,12 /* Page align */ - lhz r4,DCACHEL1LINESPERPAGE(r7) /* Get # dcache lines per page */ - lhz r5,DCACHEL1LINESIZE(r7) /* Get dcache line size */ + lwz r4,DCACHEL1LINESPERPAGE(r7) /* Get # dcache lines per page */ + lwz r5,DCACHEL1LINESIZE(r8) /* Get dcache line size */ mr r6,r3 mtctr r4 0: dcbst 0,r6 @@ -261,8 +267,8 @@ /* Now invalidate the icache */ - lhz r4,ICACHEL1LINESPERPAGE(r7) /* Get # icache lines per page */ - lhz r5,ICACHEL1LINESIZE(r7) /* Get icache line size */ + lwz r4,ICACHEL1LINESPERPAGE(r7) /* Get # icache lines per page */ + lwz r5,ICACHEL1LINESIZE(r8) /* Get icache line size */ mtctr r4 1: icbi 0,r3 add r3,r3,r5 @@ -574,7 +580,7 @@ .llong .sys32_ssetmask .llong .sys_setreuid /* 70 */ .llong .sys_setregid - .llong .sys_sigsuspend + .llong .sys32_sigsuspend .llong .compat_sys_sigpending .llong .sys32_sethostname .llong .compat_sys_setrlimit /* 75 */ @@ -737,7 +743,7 @@ .llong .sys_set_tid_address .llong .ppc32_fadvise64 .llong .sys_exit_group - .llong .ppc32_lookup_dcookie /* 245 */ + .llong .ppc32_lookup_dcookie /* 235 */ .llong .sys_epoll_create .llong .sys_epoll_ctl .llong .sys_epoll_wait @@ -812,13 +818,13 @@ .llong .sys_getppid .llong .sys_getpgrp /* 65 */ .llong .sys_setsid - .llong .sys_sigaction + .llong .sys_ni_syscall .llong .sys_sgetmask .llong .sys_ssetmask .llong .sys_setreuid /* 70 */ .llong .sys_setregid - .llong .sys_sigsuspend - .llong .sys_sigpending + .llong .sys_ni_syscall + .llong .sys_ni_syscall .llong .sys_sethostname .llong .sys_setrlimit /* 75 */ .llong .sys_ni_syscall /* old getrlimit syscall */ @@ -864,14 +870,14 @@ .llong .sys_sysinfo .llong .sys_ipc .llong .sys_fsync - .llong .ppc64_sigreturn + .llong .sys_ni_syscall .llong .sys_clone /* 120 */ .llong .sys_setdomainname .llong .ppc64_newuname .llong .sys_ni_syscall /* old modify_ldt syscall */ .llong .sys_adjtimex .llong .sys_mprotect /* 125 */ - .llong .sys_sigprocmask + .llong .sys_ni_syscall .llong .sys_ni_syscall /* old create_module syscall */ .llong .sys_init_module .llong .sys_delete_module diff -Nru a/arch/ppc64/kernel/module.c b/arch/ppc64/kernel/module.c --- a/arch/ppc64/kernel/module.c Thu May 8 00:24:30 2003 +++ b/arch/ppc64/kernel/module.c Thu May 8 00:24:30 2003 @@ -20,6 +20,8 @@ #include #include #include +#include +#include /* FIXME: We don't do .init separately. To do this, we'd need to have a separate r2 value in the init and core section, and stub between @@ -374,15 +376,11 @@ return 0; } -/* In arch/ppc64/mm/extable.c */ -extern void sort_ex_table(struct exception_table_entry *start, - struct exception_table_entry *finish); - int module_finalize(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - struct module *me) + const Elf_Shdr *sechdrs, struct module *me) { - sort_ex_table(me->extable.entry, - me->extable.entry + me->extable.num_entries); + sort_ex_table((struct exception_table_entry *)me->extable, + (struct exception_table_entry *)me->extable + + me->num_exentries); return 0; } diff -Nru a/arch/ppc64/kernel/open_pic.c b/arch/ppc64/kernel/open_pic.c --- a/arch/ppc64/kernel/open_pic.c Thu May 8 00:24:29 2003 +++ b/arch/ppc64/kernel/open_pic.c Thu May 8 00:24:29 2003 @@ -111,7 +111,6 @@ * data has probably been corrupted and we're going to panic or deadlock later * anyway --Troy */ -extern unsigned long* _get_SP(void); #define check_arg_irq(irq) \ if (irq < open_pic_irq_offset || irq >= (NumSources+open_pic_irq_offset)){ \ printk(KERN_ERR "open_pic.c:%d: illegal irq %d\n", __LINE__, irq); \ @@ -765,9 +764,11 @@ openpic_eoi(); } -static void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs) +static irqreturn_t openpic_ipi_action(int cpl, void *dev_id, + struct pt_regs *regs) { smp_message_recv(cpl-openpic_vec_ipi, regs); + return IRQ_HANDLED; } #endif /* CONFIG_SMP */ diff -Nru a/arch/ppc64/kernel/open_pic_defs.h b/arch/ppc64/kernel/open_pic_defs.h --- a/arch/ppc64/kernel/open_pic_defs.h Thu May 8 00:24:29 2003 +++ b/arch/ppc64/kernel/open_pic_defs.h Thu May 8 00:24:29 2003 @@ -298,7 +298,8 @@ #ifdef CONFIG_SMP /* Interprocessor Interrupts */ static void openpic_initipi(u_int ipi, u_int pri, u_int vector); -static void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs); +static irqreturn_t openpic_ipi_action(int cpl, void *dev_id, + struct pt_regs *regs); #endif /* Timer Interrupts */ diff -Nru a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c --- a/arch/ppc64/kernel/pSeries_lpar.c Thu May 8 00:24:30 2003 +++ b/arch/ppc64/kernel/pSeries_lpar.c Thu May 8 00:24:30 2003 @@ -110,29 +110,6 @@ lbuf[0], lbuf[1], &dummy, &dummy, &dummy); } -long plpar_eoi(unsigned long xirr) -{ - return plpar_hcall_norets(H_EOI, xirr); -} - -long plpar_cppr(unsigned long cppr) -{ - return plpar_hcall_norets(H_CPPR, cppr); -} - -long plpar_ipi(unsigned long servernum, - unsigned long mfrr) -{ - return plpar_hcall_norets(H_IPI, servernum, mfrr); -} - -long plpar_xirr(unsigned long *xirr_ret) -{ - unsigned long dummy; - return plpar_hcall(H_XIRR, 0, 0, 0, 0, - xirr_ret, &dummy, &dummy); -} - static void tce_build_pSeriesLP(struct TceTable *tbl, long tcenum, unsigned long uaddr, int direction ) { @@ -179,66 +156,6 @@ } } - -/* PowerPC Interrupts for lpar. */ -/* NOTE: this typedef is duplicated (for now) from xics.c! */ -typedef struct { - int (*xirr_info_get)(int cpu); - void (*xirr_info_set)(int cpu, int val); - void (*cppr_info)(int cpu, u8 val); - void (*qirr_info)(int cpu, u8 val); -} xics_ops; -static int pSeriesLP_xirr_info_get(int n_cpu) -{ - unsigned long lpar_rc; - unsigned long return_value; - - lpar_rc = plpar_xirr(&return_value); - if (lpar_rc != H_Success) { - panic(" bad return code xirr - rc = %lx \n", lpar_rc); - } - return ((int)(return_value)); -} - -static void pSeriesLP_xirr_info_set(int n_cpu, int value) -{ - unsigned long lpar_rc; - unsigned long val64 = value & 0xffffffff; - - lpar_rc = plpar_eoi(val64); - if (lpar_rc != H_Success) { - panic(" bad return code EOI - rc = %ld, value=%lx \n", lpar_rc, val64); - } -} - -static void pSeriesLP_cppr_info(int n_cpu, u8 value) -{ - unsigned long lpar_rc; - - lpar_rc = plpar_cppr(value); - if (lpar_rc != H_Success) { - panic(" bad return code cppr - rc = %lx \n", lpar_rc); - } -} - -static void pSeriesLP_qirr_info(int n_cpu , u8 value) -{ - unsigned long lpar_rc; - - lpar_rc = plpar_ipi(n_cpu, value); - if (lpar_rc != H_Success) { - panic(" bad return code qirr -ipi - rc = %lx \n", lpar_rc); - } -} - -xics_ops pSeriesLP_ops = { - pSeriesLP_xirr_info_get, - pSeriesLP_xirr_info_set, - pSeriesLP_cppr_info, - pSeriesLP_qirr_info -}; -/* end TAI-LPAR */ - int vtermno; /* virtual terminal# for udbg */ diff -Nru a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c --- a/arch/ppc64/kernel/pacaData.c Thu May 8 00:24:29 2003 +++ b/arch/ppc64/kernel/pacaData.c Thu May 8 00:24:29 2003 @@ -20,6 +20,7 @@ #include struct naca_struct *naca; +struct systemcfg *systemcfg; /* The Paca is an array with one entry per processor. Each contains an * ItLpPaca, which contains the information shared between the @@ -65,9 +66,9 @@ struct paca_struct paca[MAX_PACAS] __page_aligned = { #ifdef CONFIG_PPC_ISERIES - PACAINITDATA( 0, 1, &xItLpQueue, 0, 0xc000000000005000), + PACAINITDATA( 0, 1, &xItLpQueue, 0, STAB0_VIRT_ADDR), #else - PACAINITDATA( 0, 1, 0, 0x5000, 0xc000000000005000), + PACAINITDATA( 0, 1, 0, STAB0_PHYS_ADDR, STAB0_VIRT_ADDR), #endif PACAINITDATA( 1, 0, 0, 0, 0), PACAINITDATA( 2, 0, 0, 0, 0), diff -Nru a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c --- a/arch/ppc64/kernel/pci.c Thu May 8 00:24:30 2003 +++ b/arch/ppc64/kernel/pci.c Thu May 8 00:24:30 2003 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/ppc64/kernel/pci_dma.c b/arch/ppc64/kernel/pci_dma.c --- a/arch/ppc64/kernel/pci_dma.c Thu May 8 00:24:29 2003 +++ b/arch/ppc64/kernel/pci_dma.c Thu May 8 00:24:29 2003 @@ -134,7 +134,7 @@ dev = ppc64_isabridge_dev; if (!dev) return NULL; - if (naca->platform == PLATFORM_ISERIES_LPAR) { + if (systemcfg->platform == PLATFORM_ISERIES_LPAR) { return ISERIES_DEVNODE(dev)->DevTceTable; } else { return PCI_GET_DN(dev)->tce_table; @@ -723,8 +723,8 @@ */ busdn->bussubno = bus->number; create_pci_bus_tce_table((unsigned long)busdn); - } else - create_tce_tables_for_busesLP(&bus->children); + } + create_tce_tables_for_busesLP(&bus->children); } } @@ -732,7 +732,7 @@ struct pci_dev *dev; struct device_node *dn, *mydn; - if (naca->platform == PLATFORM_PSERIES_LPAR) { + if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { create_tce_tables_for_busesLP(&pci_root_buses); } else { @@ -773,7 +773,7 @@ /* - Tce Table Share between buses, */ /* - Tce Table per logical slot. */ /*****************************************************************/ - if(naca->platform == PLATFORM_ISERIES_LPAR) { + if(systemcfg->platform == PLATFORM_ISERIES_LPAR) { struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)token; getTceTableParmsiSeries(DevNode,newTceTable); @@ -797,7 +797,7 @@ dn = (struct device_node *)token; phb = dn->phb; - if (naca->platform == PLATFORM_PSERIES) + if (systemcfg->platform == PLATFORM_PSERIES) getTceTableParmsPSeries(phb, dn, newTceTable); else getTceTableParmsPSeriesLP(phb, dn, newTceTable); @@ -1135,7 +1135,8 @@ /* Client asked for way to much space. This is checked later anyway */ /* It is easier to debug here for the drivers than in the tce tables.*/ if(order >= NUM_TCE_LEVELS) { - printk("PCI_DMA: pci_unmap_single 0x%lx size to large: 0x%lx \n",dma_handle,size); + printk("PCI_DMA: pci_unmap_single 0x%lx size too" + " large: 0x%lx \n", (long)dma_handle, (long)size); return; } diff -Nru a/arch/ppc64/kernel/proc_ppc64.c b/arch/ppc64/kernel/proc_ppc64.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/proc_ppc64.c Thu May 8 00:24:30 2003 @@ -0,0 +1,177 @@ +/* + * arch/ppc64/kernel/proc_ppc64.c + * + * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This 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 + */ + + +/* + * Change Activity: + * 2001 : mikec : Created + * 2001/06/05 : engebret : Software event count support. + * 2003/02/13 : bergner : Move PMC code to pmc.c + * End Change Activity + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +struct proc_ppc64_t proc_ppc64; + +void proc_ppc64_create_paca(int num); + +static loff_t page_map_seek( struct file *file, loff_t off, int whence); +static ssize_t page_map_read( struct file *file, char *buf, size_t nbytes, loff_t *ppos); +static int page_map_mmap( struct file *file, struct vm_area_struct *vma ); + +static struct file_operations page_map_fops = { + llseek: page_map_seek, + read: page_map_read, + mmap: page_map_mmap +}; + + +static int __init proc_ppc64_init(void) +{ + + printk(KERN_INFO "proc_ppc64: Creating /proc/ppc64/\n"); + + proc_ppc64.root = proc_mkdir("ppc64", 0); + if (!proc_ppc64.root) + return 0; + + proc_ppc64.naca = create_proc_entry("naca", S_IRUSR, proc_ppc64.root); + if ( proc_ppc64.naca ) { + proc_ppc64.naca->nlink = 1; + proc_ppc64.naca->data = naca; + proc_ppc64.naca->size = 4096; + proc_ppc64.naca->proc_fops = &page_map_fops; + } + + proc_ppc64.systemcfg = create_proc_entry("systemcfg", S_IFREG|S_IRUGO, proc_ppc64.root); + if ( proc_ppc64.systemcfg ) { + proc_ppc64.systemcfg->nlink = 1; + proc_ppc64.systemcfg->data = systemcfg; + proc_ppc64.systemcfg->size = 4096; + proc_ppc64.systemcfg->proc_fops = &page_map_fops; + } + + /* /proc/ppc64/paca/XX -- raw paca contents. Only readable to root */ + proc_ppc64.paca = proc_mkdir("paca", proc_ppc64.root); + if (proc_ppc64.paca) { + unsigned long i; + + for (i = 0; i < NR_CPUS; i++) { + if (!cpu_online(i)) + continue; + proc_ppc64_create_paca(i); + } + } + + /* Placeholder for rtas interfaces. */ + proc_ppc64.rtas = proc_mkdir("rtas", proc_ppc64.root); + + return 0; +} + + +/* + * NOTE: since paca data is always in flux the values will never be a consistant set. + * In theory it could be made consistent if we made the corresponding cpu + * copy the page for us (via an IPI). Probably not worth it. + * + */ +void proc_ppc64_create_paca(int num) +{ + struct proc_dir_entry *ent; + struct paca_struct *lpaca = paca + num; + char buf[16]; + + sprintf(buf, "%02x", num); + ent = create_proc_entry(buf, S_IRUSR, proc_ppc64.paca); + if ( ent ) { + ent->nlink = 1; + ent->data = lpaca; + ent->size = 4096; + ent->proc_fops = &page_map_fops; + } +} + + +static loff_t page_map_seek( struct file *file, loff_t off, int whence) +{ + loff_t new; + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + + switch(whence) { + case 0: + new = off; + break; + case 1: + new = file->f_pos + off; + break; + case 2: + new = dp->size + off; + break; + default: + return -EINVAL; + } + if ( new < 0 || new > dp->size ) + return -EINVAL; + return (file->f_pos = new); +} + +static ssize_t page_map_read( struct file *file, char *buf, size_t nbytes, loff_t *ppos) +{ + unsigned pos = *ppos; + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + + if ( pos >= dp->size ) + return 0; + if ( nbytes >= dp->size ) + nbytes = dp->size; + if ( pos + nbytes > dp->size ) + nbytes = dp->size - pos; + + copy_to_user( buf, (char *)dp->data + pos, nbytes ); + *ppos = pos + nbytes; + return nbytes; +} + +static int page_map_mmap( struct file *file, struct vm_area_struct *vma ) +{ + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + + vma->vm_flags |= VM_SHM | VM_LOCKED; + + if ((vma->vm_end - vma->vm_start) > dp->size) + return -EINVAL; + + remap_page_range( vma, vma->vm_start, __pa(dp->data), dp->size, vma->vm_page_prot ); + return 0; +} + +fs_initcall(proc_ppc64_init); + diff -Nru a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c --- a/arch/ppc64/kernel/process.c Thu May 8 00:24:29 2003 +++ b/arch/ppc64/kernel/process.c Thu May 8 00:24:29 2003 @@ -533,8 +533,6 @@ } while (count++ < 32); } -extern unsigned long *_get_SP(void); - void dump_stack(void) { show_tsk_stack(current, (unsigned long)_get_SP()); diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c --- a/arch/ppc64/kernel/prom.c Thu May 8 00:24:29 2003 +++ b/arch/ppc64/kernel/prom.c Thu May 8 00:24:29 2003 @@ -118,7 +118,6 @@ #define FB_MAX 8 #endif -static int ppc64_is_smp; struct prom_t prom = { 0, /* entry */ @@ -301,7 +300,9 @@ unsigned long offset = reloc_offset(); struct prom_t *_prom = PTRRELOC(&prom); struct naca_struct *_naca = RELOC(naca); + struct systemcfg *_systemcfg = RELOC(systemcfg); + /* NOTE: _naca->debug_switch is already initialized. */ #ifdef DEBUG_PROM prom_print(RELOC("prom_initialize_naca: start...\n")); #endif @@ -320,25 +321,35 @@ * d-cache and i-cache sizes... -Peter */ if ( num_cpus == 1 ) { - u32 size; + u32 size, lsize; call_prom(RELOC("getprop"), 4, 1, node, - RELOC("d-cache-line-size"), + RELOC("d-cache-size"), &size, sizeof(size)); - _naca->dCacheL1LineSize = size; - _naca->dCacheL1LogLineSize = __ilog2(size); - _naca->dCacheL1LinesPerPage = PAGE_SIZE / size; + call_prom(RELOC("getprop"), 4, 1, node, + RELOC("d-cache-line-size"), + &lsize, sizeof(lsize)); + + _systemcfg->dCacheL1Size = size; + _systemcfg->dCacheL1LineSize = lsize; + _naca->dCacheL1LogLineSize = __ilog2(lsize); + _naca->dCacheL1LinesPerPage = PAGE_SIZE/lsize; call_prom(RELOC("getprop"), 4, 1, node, - RELOC("i-cache-line-size"), + RELOC("i-cache-size"), &size, sizeof(size)); - _naca->iCacheL1LineSize = size; - _naca->iCacheL1LogLineSize = __ilog2(size); - _naca->iCacheL1LinesPerPage = PAGE_SIZE / size; + call_prom(RELOC("getprop"), 4, 1, node, + RELOC("i-cache-line-size"), + &lsize, sizeof(lsize)); - if (_naca->platform == PLATFORM_PSERIES_LPAR) { + _systemcfg->iCacheL1Size = size; + _systemcfg->iCacheL1LineSize = lsize; + _naca->iCacheL1LogLineSize = __ilog2(lsize); + _naca->iCacheL1LinesPerPage = PAGE_SIZE/lsize; + + if (_systemcfg->platform == PLATFORM_PSERIES_LPAR) { u32 pft_size[2]; call_prom(RELOC("getprop"), 4, 1, node, RELOC("ibm,pft-size"), @@ -408,20 +419,17 @@ } /* We gotta have at least 1 cpu... */ - if (num_cpus < 1) + if ( (_systemcfg->processorCount = num_cpus) < 1 ) PROM_BUG(); - if (num_cpus > 1) - RELOC(ppc64_is_smp) = 1; - - _naca->physicalMemorySize = lmb_phys_mem_size(); + _systemcfg->physicalMemorySize = lmb_phys_mem_size(); - if (_naca->platform == PLATFORM_PSERIES) { + if (_systemcfg->platform == PLATFORM_PSERIES) { unsigned long rnd_mem_size, pteg_count; /* round mem_size up to next power of 2 */ - rnd_mem_size = 1UL << __ilog2(_naca->physicalMemorySize); - if (rnd_mem_size < _naca->physicalMemorySize) + rnd_mem_size = 1UL << __ilog2(_systemcfg->physicalMemorySize); + if (rnd_mem_size < _systemcfg->physicalMemorySize) rnd_mem_size <<= 1; /* # pages / 2 */ @@ -442,49 +450,43 @@ */ _naca->slb_size = 64; -#ifdef DEBUG_PROM - prom_print(RELOC("naca->physicalMemorySize = 0x")); - prom_print_hex(_naca->physicalMemorySize); - prom_print_nl(); - - prom_print(RELOC("naca->pftSize = 0x")); - prom_print_hex(_naca->pftSize); - prom_print_nl(); - - prom_print(RELOC("naca->dCacheL1LineSize = 0x")); - prom_print_hex(_naca->dCacheL1LineSize); - prom_print_nl(); + /* Add an eye catcher and the systemcfg layout version number */ + strcpy(_systemcfg->eye_catcher, RELOC("SYSTEMCFG:PPC64")); + _systemcfg->version.major = SYSTEMCFG_MAJOR; + _systemcfg->version.minor = SYSTEMCFG_MINOR; + _systemcfg->processor = _get_PVR(); - prom_print(RELOC("naca->dCacheL1LogLineSize = 0x")); - prom_print_hex(_naca->dCacheL1LogLineSize); +#ifdef DEBUG_PROM + prom_print(RELOC("systemcfg->processorCount = 0x")); + prom_print_hex(_systemcfg->processorCount); prom_print_nl(); - prom_print(RELOC("naca->dCacheL1LinesPerPage = 0x")); - prom_print_hex(_naca->dCacheL1LinesPerPage); + prom_print(RELOC("systemcfg->physicalMemorySize = 0x")); + prom_print_hex(_systemcfg->physicalMemorySize); prom_print_nl(); - prom_print(RELOC("naca->iCacheL1LineSize = 0x")); - prom_print_hex(_naca->iCacheL1LineSize); + prom_print(RELOC("naca->pftSize = 0x")); + prom_print_hex(_naca->pftSize); prom_print_nl(); - prom_print(RELOC("naca->iCacheL1LogLineSize = 0x")); - prom_print_hex(_naca->iCacheL1LogLineSize); + prom_print(RELOC("systemcfg->dCacheL1LineSize = 0x")); + prom_print_hex(_systemcfg->dCacheL1LineSize); prom_print_nl(); - prom_print(RELOC("naca->iCacheL1LinesPerPage = 0x")); - prom_print_hex(_naca->iCacheL1LinesPerPage); + prom_print(RELOC("systemcfg->iCacheL1LineSize = 0x")); + prom_print_hex(_systemcfg->iCacheL1LineSize); prom_print_nl(); - prom_print(RELOC("naca->serialPortAddr = 0x")); + prom_print(RELOC("naca->serialPortAddr = 0x")); prom_print_hex(_naca->serialPortAddr); prom_print_nl(); - prom_print(RELOC("naca->interrupt_controller = 0x")); + prom_print(RELOC("naca->interrupt_controller = 0x")); prom_print_hex(_naca->interrupt_controller); prom_print_nl(); - prom_print(RELOC("naca->platform = 0x")); - prom_print_hex(_naca->platform); + prom_print(RELOC("systemcfg->platform = 0x")); + prom_print_hex(_systemcfg->platform); prom_print_nl(); prom_print(RELOC("prom_initialize_naca: end...\n")); @@ -549,7 +551,7 @@ unsigned long offset = reloc_offset(); struct prom_t *_prom = PTRRELOC(&prom); struct rtas_t *_rtas = PTRRELOC(&rtas); - struct naca_struct *_naca = RELOC(naca); + struct systemcfg *_systemcfg = RELOC(systemcfg); ihandle prom_rtas; u32 getprop_rval; @@ -565,7 +567,7 @@ RELOC("ibm,hypertas-functions"), hypertas_funcs, sizeof(hypertas_funcs))) > 0) { - _naca->platform = PLATFORM_PSERIES_LPAR; + _systemcfg->platform = PLATFORM_PSERIES_LPAR; } call_prom(RELOC("getprop"), @@ -582,7 +584,7 @@ * of physical memory (or within the RMO region) because RTAS * runs in 32-bit mode and relocate off. */ - if ( _naca->platform == PLATFORM_PSERIES_LPAR ) { + if ( _systemcfg->platform == PLATFORM_PSERIES_LPAR ) { struct lmb *_lmb = PTRRELOC(&lmb); rtas_region = min(_lmb->rmo_size, RTAS_INSTANTIATE_MAX); } @@ -767,13 +769,21 @@ * By doing this, we avoid the pitfalls of trying to DMA to * MMIO space and the DMA alias hole. */ - minsize = 4UL << 20; + /* + * On POWER4, firmware sets the TCE region by assuming + * each TCE table is 8MB. Using this memory for anything + * else will impact performance, so we always allocate 8MB. + * Anton + * + * XXX FIXME use a cpu feature here + */ + minsize = 8UL << 20; /* Align to the greater of the align or size */ - align = (minalign < minsize) ? minsize : minalign; + align = max(minalign, minsize); /* Carve out storage for the TCE table. */ - base = lmb_alloc(8UL << 20, 8UL << 20); + base = lmb_alloc(minsize, align); if ( !base ) { prom_print(RELOC("ERROR, cannot find space for TCE table.\n")); @@ -875,7 +885,7 @@ prom_hold_cpus(unsigned long mem) { unsigned long i; - unsigned int reg; + unsigned int cpuid; phandle node; unsigned long offset = reloc_offset(); char type[64], *path; @@ -885,9 +895,13 @@ unsigned long *spinloop = __v2a(&__secondary_hold_spinloop); unsigned long *acknowledge = __v2a(&__secondary_hold_acknowledge); unsigned long secondary_hold = (unsigned long)__v2a(*PTRRELOC((unsigned long *)__secondary_hold)); + struct systemcfg *_systemcfg = RELOC(systemcfg); struct paca_struct *_xPaca = PTRRELOC(&paca[0]); struct prom_t *_prom = PTRRELOC(&prom); + /* Initially, we must have one active CPU. */ + _systemcfg->processorCount = 1; + #ifdef DEBUG_PROM prom_print(RELOC("prom_hold_cpus: start...\n")); prom_print(RELOC(" 1) spinloop = 0x")); @@ -933,12 +947,12 @@ if (strcmp(type, RELOC("okay")) != 0) continue; - reg = -1; + cpuid = -1; call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"), - ®, sizeof(reg)); + &cpuid, sizeof(cpuid)); /* Only need to start secondary procs, not ourself. */ - if ( reg == _prom->cpu ) + if ( cpuid == _prom->cpu ) continue; path = (char *) mem; @@ -950,7 +964,7 @@ #ifdef DEBUG_PROM prom_print_nl(); prom_print(RELOC("cpu hw idx = 0x")); - prom_print_hex(reg); + prom_print_hex(cpuid); prom_print_nl(); #endif prom_print(RELOC("starting cpu ")); @@ -978,9 +992,8 @@ prom_print(RELOC(" 3) secondary_hold = 0x")); prom_print_hex(secondary_hold); prom_print_nl(); - prom_print_nl(); #endif - call_prom(RELOC("start-cpu"), 3, 0, node, secondary_hold, reg); + call_prom(RELOC("start-cpu"), 3, 0, node, secondary_hold, cpuid); prom_print(RELOC("...")); for ( i = 0 ; (i < 100000000) && (*acknowledge == ((unsigned long)-1)); i++ ) ; @@ -992,10 +1005,11 @@ prom_print_nl(); } #endif - if (*acknowledge == reg) { + if (*acknowledge == cpuid) { prom_print(RELOC("ok\n")); /* Set the number of active processors. */ - _xPaca[reg].active = 1; + _systemcfg->processorCount++; + _xPaca[cpuid].active = 1; } else { prom_print(RELOC("failed: ")); prom_print_hex(*acknowledge); @@ -1024,8 +1038,8 @@ } } _xPaca[i+1].active = 1; - RELOC(hmt_thread_data)[i].threadid = i+1; } + _systemcfg->processorCount *= 2; } else { prom_print(RELOC("Processor is not HMT capable\n")); } @@ -1046,20 +1060,21 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp, unsigned long r6, unsigned long r7) { + int chrp = 0; unsigned long mem; - ihandle prom_root, prom_cpu; + ihandle prom_mmu, prom_op, prom_root, prom_cpu; phandle cpu_pkg; unsigned long offset = reloc_offset(); - long l; + long l, sz; char *p, *d; unsigned long phys; u32 getprop_rval; - struct naca_struct *_naca = RELOC(naca); + struct systemcfg *_systemcfg = RELOC(systemcfg); struct paca_struct *_xPaca = PTRRELOC(&paca[0]); struct prom_t *_prom = PTRRELOC(&prom); /* Default machine type. */ - _naca->platform = PLATFORM_PSERIES; + _systemcfg->platform = PLATFORM_PSERIES; #if 0 /* Reset klimit to take into account the embedded system map */ @@ -1149,6 +1164,8 @@ mem = prom_bi_rec_reserve(mem); + mem = check_display(mem); + prom_instantiate_rtas(); /* Initialize some system info into the Naca early... */ @@ -1158,11 +1175,9 @@ * following, regardless of whether we have an SMP * kernel or not. */ - if (RELOC(ppc64_is_smp)) + if (_systemcfg->processorCount > 1) prom_hold_cpus(mem); - mem = check_display(mem); - #ifdef DEBUG_PROM prom_print(RELOC("copying OF device tree...\n")); #endif @@ -1172,7 +1187,7 @@ lmb_reserve(0, __pa(RELOC(klimit))); - if (_naca->platform == PLATFORM_PSERIES) + if (_systemcfg->platform == PLATFORM_PSERIES) prom_initialize_tce_table(); prom_print(RELOC("Calling quiesce ...\n")); diff -Nru a/arch/ppc64/kernel/ras.c b/arch/ppc64/kernel/ras.c --- a/arch/ppc64/kernel/ras.c Thu May 8 00:24:28 2003 +++ b/arch/ppc64/kernel/ras.c Thu May 8 00:24:28 2003 @@ -54,8 +54,10 @@ #include #include -static void ras_epow_interrupt(int irq, void *dev_id, struct pt_regs * regs); -static void ras_error_interrupt(int irq, void *dev_id, struct pt_regs * regs); +static irqreturn_t ras_epow_interrupt(int irq, void *dev_id, + struct pt_regs * regs); +static irqreturn_t ras_error_interrupt(int irq, void *dev_id, + struct pt_regs * regs); void init_ras_IRQ(void); /* #define DEBUG */ @@ -73,7 +75,7 @@ &len))) { for(i=0; i<(len / sizeof(*ireg)); i++) { request_irq(virt_irq_create_mapping(*(ireg)) + NUM_8259_INTERRUPTS, - &ras_error_interrupt, 0, + ras_error_interrupt, 0, "RAS_ERROR", NULL); ireg++; } @@ -84,7 +86,7 @@ &len))) { for(i=0; i<(len / sizeof(*ireg)); i++) { request_irq(virt_irq_create_mapping(*(ireg)) + NUM_8259_INTERRUPTS, - &ras_epow_interrupt, 0, + ras_epow_interrupt, 0, "RAS_EPOW", NULL); ireg++; } @@ -98,7 +100,7 @@ * to examine the type of power failure and take appropriate action where * the time horizon permits something useful to be done. */ -static void +static irqreturn_t ras_epow_interrupt(int irq, void *dev_id, struct pt_regs * regs) { struct rtas_error_log log_entry; @@ -114,7 +116,8 @@ udbg_printf("EPOW <0x%lx 0x%lx>\n", *((unsigned long *)&log_entry), status); printk(KERN_WARNING - "EPOW <0x%lx 0x%lx>\n",*((unsigned long *)&log_entry), status); + "EPOW <0x%lx 0x%lx>\n",*((unsigned long *)&log_entry), status); + return IRQ_HANDLED; } /* @@ -125,7 +128,7 @@ * For nonrecoverable errors, an error is logged and we stop all processing * as quickly as possible in order to prevent propagation of the failure. */ -static void +static irqreturn_t ras_error_interrupt(int irq, void *dev_id, struct pt_regs * regs) { struct rtas_error_log log_entry; @@ -158,7 +161,6 @@ printk(KERN_WARNING "Warning: Recoverable hardware error <0x%lx 0x%lx>\n", *((unsigned long *)&log_entry), status); - - return; } + return IRQ_HANDLED; } diff -Nru a/arch/ppc64/kernel/rtas-proc.c b/arch/ppc64/kernel/rtas-proc.c --- a/arch/ppc64/kernel/rtas-proc.c Thu May 8 00:24:28 2003 +++ b/arch/ppc64/kernel/rtas-proc.c Thu May 8 00:24:28 2003 @@ -201,7 +201,7 @@ struct proc_dir_entry *entry; rtas_node = find_devices("rtas"); - if ((rtas_node == NULL) || (naca->platform == PLATFORM_ISERIES_LPAR)) { + if ((rtas_node == NULL) || (systemcfg->platform == PLATFORM_ISERIES_LPAR)) { return; } @@ -506,21 +506,27 @@ int error, char * buf) { /* Defined return vales */ - const char * key_switch[] = { "Off\t", "Normal\t", "Secure\t", "Mainenance" }; + const char * key_switch[] = { "Off\t", "Normal\t", "Secure\t", + "Maintenance" }; const char * enclosure_switch[] = { "Closed", "Open" }; const char * lid_status[] = { " ", "Open", "Closed" }; - const char * power_source[] = { "AC\t", "Battery", "AC & Battery" }; + const char * power_source[] = { "AC\t", "Battery", + "AC & Battery" }; const char * battery_remaining[] = { "Very Low", "Low", "Mid", "High" }; const char * epow_sensor[] = { "EPOW Reset", "Cooling warning", "Power warning", "System shutdown", "System halt", "EPOW main enclosure", "EPOW power off" }; - const char * battery_cyclestate[] = { "None", "In progress", "Requested" }; - const char * battery_charging[] = { "Charging", "Discharching", "No current flow" }; - const char * ibm_drconnector[] = { "Empty", "Present" }; + const char * battery_cyclestate[] = { "None", "In progress", + "Requested" }; + const char * battery_charging[] = { "Charging", "Discharching", + "No current flow" }; + const char * ibm_drconnector[] = { "Empty", "Present", "Unusable", + "Exchange" }; const char * ibm_intqueue[] = { "Disabled", "Enabled" }; int have_strings = 0; + int num_states = 0; int temperature = 0; int unknown = 0; int n = 0; @@ -530,13 +536,20 @@ switch (s.token) { case KEY_SWITCH: n += sprintf(buf+n, "Key switch:\t"); - n += sprintf(buf+n, "%s\t", key_switch[state]); - have_strings = 1; + num_states = sizeof(key_switch) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", key_switch[state]); + have_strings = 1; + } break; case ENCLOSURE_SWITCH: n += sprintf(buf+n, "Enclosure switch:\t"); - n += sprintf(buf+n, "%s\t", enclosure_switch[state]); - have_strings = 1; + num_states = sizeof(enclosure_switch) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", + enclosure_switch[state]); + have_strings = 1; + } break; case THERMAL_SENSOR: n += sprintf(buf+n, "Temp. (°C/°F):\t"); @@ -544,39 +557,63 @@ break; case LID_STATUS: n += sprintf(buf+n, "Lid status:\t"); - n += sprintf(buf+n, "%s\t", lid_status[state]); - have_strings = 1; + num_states = sizeof(lid_status) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", lid_status[state]); + have_strings = 1; + } break; case POWER_SOURCE: n += sprintf(buf+n, "Power source:\t"); - n += sprintf(buf+n, "%s\t", power_source[state]); - have_strings = 1; + num_states = sizeof(power_source) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", + power_source[state]); + have_strings = 1; + } break; case BATTERY_VOLTAGE: n += sprintf(buf+n, "Battery voltage:\t"); break; case BATTERY_REMAINING: n += sprintf(buf+n, "Battery remaining:\t"); - n += sprintf(buf+n, "%s\t", battery_remaining[state]); - have_strings = 1; + num_states = sizeof(battery_remaining) / sizeof(char *); + if (state < num_states) + { + n += sprintf(buf+n, "%s\t", + battery_remaining[state]); + have_strings = 1; + } break; case BATTERY_PERCENTAGE: n += sprintf(buf+n, "Battery percentage:\t"); break; case EPOW_SENSOR: n += sprintf(buf+n, "EPOW Sensor:\t"); - n += sprintf(buf+n, "%s\t", epow_sensor[state]); - have_strings = 1; + num_states = sizeof(epow_sensor) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", epow_sensor[state]); + have_strings = 1; + } break; case BATTERY_CYCLESTATE: n += sprintf(buf+n, "Battery cyclestate:\t"); - n += sprintf(buf+n, "%s\t", battery_cyclestate[state]); - have_strings = 1; + num_states = sizeof(battery_cyclestate) / + sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", + battery_cyclestate[state]); + have_strings = 1; + } break; case BATTERY_CHARGING: n += sprintf(buf+n, "Battery Charging:\t"); - n += sprintf(buf+n, "%s\t", battery_charging[state]); - have_strings = 1; + num_states = sizeof(battery_charging) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", + battery_charging[state]); + have_strings = 1; + } break; case IBM_SURVEILLANCE: n += sprintf(buf+n, "Surveillance:\t"); @@ -589,16 +626,24 @@ break; case IBM_DRCONNECTOR: n += sprintf(buf+n, "DR connector:\t"); - n += sprintf(buf+n, "%s\t", ibm_drconnector[state]); - have_strings = 1; + num_states = sizeof(ibm_drconnector) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", + ibm_drconnector[state]); + have_strings = 1; + } break; case IBM_POWERSUPPLY: n += sprintf(buf+n, "Powersupply:\t"); break; case IBM_INTQUEUE: n += sprintf(buf+n, "Interrupt queue:\t"); - n += sprintf(buf+n, "%s\t", ibm_intqueue[state]); - have_strings = 1; + num_states = sizeof(ibm_intqueue) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", + ibm_intqueue[state]); + have_strings = 1; + } break; default: n += sprintf(buf+n, "Unkown sensor (type %d), ignoring it\n", diff -Nru a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c --- a/arch/ppc64/kernel/rtas.c Thu May 8 00:24:27 2003 +++ b/arch/ppc64/kernel/rtas.c Thu May 8 00:24:27 2003 @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -27,7 +28,6 @@ #include #include -struct proc_dir_entry *rtas_proc_dir; /* /proc/ppc64/rtas dir */ struct flash_block_list_header rtas_firmware_flash_list = {0, 0}; /* @@ -216,7 +216,11 @@ image_size += f->blocks[i].length; } next = f->next; - f->next = (struct flash_block_list *)virt_to_absolute((unsigned long)f->next); + /* Don't translate NULL pointer for last entry */ + if(f->next) + f->next = (struct flash_block_list *)virt_to_absolute((unsigned long)f->next); + else + f->next = 0LL; /* make num_blocks into the version/length field */ f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16); } @@ -283,7 +287,7 @@ rtas_power_off(); } -EXPORT_SYMBOL(rtas_proc_dir); +EXPORT_SYMBOL(proc_ppc64); EXPORT_SYMBOL(rtas_firmware_flash_list); EXPORT_SYMBOL(rtas_token); EXPORT_SYMBOL(rtas_call); diff -Nru a/arch/ppc64/kernel/rtas_flash.c b/arch/ppc64/kernel/rtas_flash.c --- a/arch/ppc64/kernel/rtas_flash.c Thu May 8 00:24:30 2003 +++ b/arch/ppc64/kernel/rtas_flash.c Thu May 8 00:24:30 2003 @@ -210,7 +210,7 @@ { struct proc_dir_entry *ent = NULL; - if (!rtas_proc_dir) { + if (!proc_ppc64.rtas) { printk(KERN_WARNING "rtas proc dir does not already exist"); return -ENOENT; } @@ -218,7 +218,7 @@ if (rtas_token("ibm,update-flash-64-and-reboot") != RTAS_UNKNOWN_SERVICE) flash_possible = 1; - if ((ent = create_proc_entry(FIRMWARE_FLASH_NAME, S_IRUSR | S_IWUSR, rtas_proc_dir)) != NULL) { + if ((ent = create_proc_entry(FIRMWARE_FLASH_NAME, S_IRUSR | S_IWUSR, proc_ppc64.rtas)) != NULL) { ent->nlink = 1; ent->proc_fops = &rtas_flash_operations; ent->owner = THIS_MODULE; @@ -228,9 +228,9 @@ void __exit rtas_flash_cleanup(void) { - if (!rtas_proc_dir) + if (!proc_ppc64.rtas) return; - remove_proc_entry(FIRMWARE_FLASH_NAME, rtas_proc_dir); + remove_proc_entry(FIRMWARE_FLASH_NAME, proc_ppc64.rtas); } module_init(rtas_flash_init); diff -Nru a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c --- a/arch/ppc64/kernel/setup.c Thu May 8 00:24:28 2003 +++ b/arch/ppc64/kernel/setup.c Thu May 8 00:24:28 2003 @@ -142,9 +142,6 @@ void setup_system(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { - /* This should be fixed properly in kernel/resource.c */ - iomem_resource.end = MEM_SPACE_LIMIT; - #ifdef CONFIG_XMON_DEFAULT debugger = xmon; debugger_bpt = xmon_bpt; @@ -156,10 +153,10 @@ #ifdef CONFIG_PPC_ISERIES /* pSeries systems are identified in prom.c via OF. */ if ( itLpNaca.xLparInstalled == 1 ) - naca->platform = PLATFORM_ISERIES_LPAR; + systemcfg->platform = PLATFORM_ISERIES_LPAR; #endif - switch (naca->platform) { + switch (systemcfg->platform) { #ifdef CONFIG_PPC_ISERIES case PLATFORM_ISERIES_LPAR: iSeries_init_early(); @@ -185,7 +182,7 @@ #endif } - if (naca->platform & PLATFORM_PSERIES) { + if (systemcfg->platform & PLATFORM_PSERIES) { early_console_initialized = 1; register_console(&udbg_console); } @@ -193,32 +190,27 @@ printk("Starting Linux PPC64 %s\n", UTS_RELEASE); printk("-----------------------------------------------------\n"); - printk("naca = 0x%p\n", naca); -#if 0 - printk("naca->processorCount = 0x%x\n", naca->processorCount); -#endif - printk("naca->physicalMemorySize = 0x%lx\n", naca->physicalMemorySize); - printk("naca->dCacheL1LineSize = 0x%x\n", naca->dCacheL1LineSize); - printk("naca->dCacheL1LogLineSize = 0x%x\n", naca->dCacheL1LogLineSize); - printk("naca->dCacheL1LinesPerPage = 0x%x\n", naca->dCacheL1LinesPerPage); - printk("naca->iCacheL1LineSize = 0x%x\n", naca->iCacheL1LineSize); - printk("naca->iCacheL1LogLineSize = 0x%x\n", naca->iCacheL1LogLineSize); - printk("naca->iCacheL1LinesPerPage = 0x%x\n", naca->iCacheL1LinesPerPage); - printk("naca->pftSize = 0x%lx\n", naca->pftSize); - printk("naca->debug_switch = 0x%lx\n", naca->debug_switch); - printk("naca->interrupt_controller = 0x%d\n", naca->interrupt_controller); - printk("htab_data.htab = 0x%p\n", htab_data.htab); - printk("htab_data.num_ptegs = 0x%lx\n", htab_data.htab_num_ptegs); + printk("naca = 0x%p\n", naca); + printk("naca->pftSize = 0x%lx\n", naca->pftSize); + printk("naca->debug_switch = 0x%lx\n", naca->debug_switch); + printk("naca->interrupt_controller = 0x%d\n", naca->interrupt_controller); + printk("systemcf = 0x%p\n", systemcfg); + printk("systemcfg->processorCount = 0x%x\n", systemcfg->processorCount); + printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize); + printk("systemcfg->dCacheL1LineSize = 0x%x\n", systemcfg->dCacheL1LineSize); + printk("systemcfg->iCacheL1LineSize = 0x%x\n", systemcfg->iCacheL1LineSize); + printk("htab_data.htab = 0x%p\n", htab_data.htab); + printk("htab_data.num_ptegs = 0x%lx\n", htab_data.htab_num_ptegs); printk("-----------------------------------------------------\n"); - if (naca->platform & PLATFORM_PSERIES) { + if (systemcfg->platform & PLATFORM_PSERIES) { finish_device_tree(); chrp_init(r3, r4, r5, r6, r7); } mm_init_ppc64(); - switch (naca->platform) { + switch (systemcfg->platform) { #ifdef CONFIG_PPC_ISERIES case PLATFORM_ISERIES_LPAR: iSeries_init(); @@ -312,7 +304,7 @@ * Assume here that all clock rates are the same in a * smp system. -- Cort */ - if (naca->platform != PLATFORM_ISERIES_LPAR) { + if (systemcfg->platform != PLATFORM_ISERIES_LPAR) { struct device_node *cpu_node; int *fp; @@ -516,8 +508,8 @@ * Systems with OF can look in the properties on the cpu node(s) * for a possibly more accurate value. */ - dcache_bsize = naca->dCacheL1LineSize; - icache_bsize = naca->iCacheL1LineSize; + dcache_bsize = systemcfg->dCacheL1LineSize; + icache_bsize = systemcfg->iCacheL1LineSize; /* reboot on panic */ panic_timeout = 180; diff -Nru a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c --- a/arch/ppc64/kernel/signal.c Thu May 8 00:24:27 2003 +++ b/arch/ppc64/kernel/signal.c Thu May 8 00:24:27 2003 @@ -43,57 +43,29 @@ #endif #define GP_REGS_SIZE MIN(sizeof(elf_gregset_t), sizeof(struct pt_regs)) +#define FP_REGS_SIZE sizeof(elf_fpregset_t) -/* - * These are the flags in the MSR that the user is allowed to change - * by modifying the saved value of the MSR on the stack. SE and BE - * should not be in this list since gdb may want to change these. I.e, - * you should be able to step out of a signal handler to see what - * instruction executes next after the signal handler completes. - * Alternately, if you stepped into a signal handler, you should be - * able to continue 'til the next breakpoint from within the signal - * handler, even if the handler returns. - */ -#if 0 -#define MSR_USERCHANGE (MSR_FE0 | MSR_FE1) -#else -/* - * glibc tries to set FE0/FE1 via a signal handler. Since it only ever - * sets both bits and this is the default setting we now disable this - * behaviour. This is done to insure the new prctl which alters FE0/FE1 does - * not get overriden by glibc. Setting and clearing FE0/FE1 via signal - * handler has always been bogus since load_up_fpu used to set FE0/FE1 - * unconditionally. - */ -#define MSR_USERCHANGE 0 -#endif +#define TRAMP_TRACEBACK 3 +#define TRAMP_SIZE 6 /* - * When we have signals to deliver, we set up on the - * user stack, going down from the original stack pointer: - * a sigregs struct - * one or more sigcontext structs with - * a gap of __SIGNAL_FRAMESIZE bytes - * - * Each of these things must be a multiple of 16 bytes in size. - * + * When we have signals to deliver, we set up on the user stack, + * going down from the original stack pointer: + * 1) a rt_sigframe struct which contains the ucontext + * 2) a gap of __SIGNAL_FRAMESIZE bytes which acts as a dummy caller + * frame for the signal handler. */ -struct sigregs { - elf_gregset_t gp_regs; - double fp_regs[ELF_NFPREG]; - unsigned int tramp[2]; - /* 64 bit API allows for 288 bytes below sp before - decrementing it. */ - int abigap[72]; -}; -struct rt_sigframe -{ - unsigned long _unused[2]; +struct rt_sigframe { + /* sys_rt_sigreturn requires the ucontext be the first field */ + struct ucontext uc; + unsigned long _unused[2]; + unsigned int tramp[TRAMP_SIZE]; struct siginfo *pinfo; void *puc; struct siginfo info; - struct ucontext uc; + /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */ + char abigap[288]; }; @@ -102,37 +74,6 @@ /* * Atomically swap in the new signal mask, and wait for a signal. */ -long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7, - struct pt_regs *regs) -{ - sigset_t saveset; - - mask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs->result = -EINTR; - regs->gpr[3] = EINTR; - regs->ccr |= 0x10000000; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(&saveset, regs)) - /* - * If a signal handler needs to be called, - * do_signal() has set R3 to the signal number (the - * first argument of the signal handler), so don't - * overwrite that with EINTR ! - * In the other cases, do_signal() doesn't touch - * R3, so it's still set to -EINTR (see above). - */ - return regs->gpr[3]; - } -} - long sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, int p3, int p4, int p6, int p7, struct pt_regs *regs) { @@ -170,339 +111,232 @@ return do_sigaltstack(uss, uoss, regs->gpr[1]); } -long sys_sigaction(int sig, const struct old_sigaction *act, - struct old_sigaction *oact) + +/* + * Set up the sigcontext for the signal frame. + */ + +static int +setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, + int signr, sigset_t *set, unsigned long handler) { - struct k_sigaction new_ka, old_ka; - int ret; + int err = 0; - if (act) { - old_sigset_t mask; + if (regs->msr & MSR_FP) + giveup_fpu(current); - if (verify_area(VERIFY_READ, act, sizeof(*act)) || - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) - return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); - siginitset(&new_ka.sa.sa_mask, mask); - } + current->thread.saved_msr = regs->msr & ~(MSR_FP | MSR_FE0 | MSR_FE1); + regs->msr = current->thread.saved_msr | current->thread.fpexc_mode; + current->thread.saved_softe = regs->softe; + + err |= __put_user(&sc->gp_regs, &sc->regs); + err |= __copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE); + err |= __copy_to_user(&sc->fp_regs, ¤t->thread.fpr, FP_REGS_SIZE); + err |= __put_user(signr, &sc->signal); + err |= __put_user(handler, &sc->handler); + if (set != NULL) + err |= __put_user(set->sig[0], &sc->oldmask); - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - if (!ret && oact) { - if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) - return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); - } + regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1); + current->thread.fpscr = 0; - return ret; + return err; } /* - * When we have rt signals to deliver, we set up on the - * user stack, going down from the original stack pointer: - * a sigregs struct - * one rt_sigframe struct (siginfo + ucontext) - * a gap of __SIGNAL_FRAMESIZE bytes - * - * Each of these things must be a multiple of 16 bytes in size. - * + * Restore the sigcontext from the signal frame. */ -int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, unsigned long r8, - struct pt_regs *regs) +static int +restore_sigcontext(struct pt_regs *regs, sigset_t *set, struct sigcontext *sc) { - struct rt_sigframe *rt_sf; - struct sigcontext sigctx; - struct sigregs *sr; - elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */ - sigset_t set; - stack_t st; + unsigned int err = 0; - rt_sf = (struct rt_sigframe *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); - if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx)) - || copy_from_user(&set, &rt_sf->uc.uc_sigmask, sizeof(set)) - || copy_from_user(&st, &rt_sf->uc.uc_stack, sizeof(st))) - goto badframe; - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); if (regs->msr & MSR_FP) giveup_fpu(current); - /* restore registers - - * sigctx is initialized to point to the - * preamble frame (where registers are stored) - * see handle_signal() - */ - sr = (struct sigregs *)sigctx.regs; - if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs))) - goto badframe; - saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) - | (saved_regs[PT_MSR] & MSR_USERCHANGE); - saved_regs[PT_SOFTE] = regs->softe; - memcpy(regs, saved_regs, GP_REGS_SIZE); - if (copy_from_user(current->thread.fpr, &sr->fp_regs, - sizeof(sr->fp_regs))) - goto badframe; - /* This function sets back the stack flags into - the current task structure. */ - sys_sigaltstack(&st, NULL, 0, 0, 0, 0, regs); + err |= __copy_from_user(regs, &sc->gp_regs, GP_REGS_SIZE); + err |= __copy_from_user(¤t->thread.fpr, &sc->fp_regs, FP_REGS_SIZE); + current->thread.fpexc_mode = regs->msr & (MSR_FE0 | MSR_FE1); + if (set != NULL) + err |= __get_user(set->sig[0], &sc->oldmask); + + /* Don't allow the signal handler to change these modulo FE{0,1} */ + regs->msr = current->thread.saved_msr & ~(MSR_FP | MSR_FE0 | MSR_FE1); + regs->softe = current->thread.saved_softe; - return regs->result; - -badframe: - do_exit(SIGSEGV); + return err; } -static void setup_rt_frame(struct pt_regs *regs, struct sigregs *frame, - signed long newsp) +/* + * Allocate space for the signal frame + */ +static inline void * +get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) { - struct rt_sigframe *rt_sf = (struct rt_sigframe *)newsp; - /* Handler is *really* a pointer to the function descriptor for - * the signal routine. The first entry in the function - * descriptor is the entry address of signal and the second - * entry is the TOC value we need to use. - */ - struct funct_descr_entry { - unsigned long entry; - unsigned long toc; - }; - - struct funct_descr_entry * funct_desc_ptr; - unsigned long temp_ptr; + unsigned long newsp; - /* Set up preamble frame */ - if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) - goto badframe; - if (regs->msr & MSR_FP) - giveup_fpu(current); - if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE) - || __copy_to_user(&frame->fp_regs, current->thread.fpr, - ELF_NFPREG * sizeof(double)) - /* li r0, __NR_rt_sigreturn */ - || __put_user(0x38000000UL + __NR_rt_sigreturn, &frame->tramp[0]) - /* sc */ - || __put_user(0x44000002UL, &frame->tramp[1])) - goto badframe; - flush_icache_range((unsigned long)&frame->tramp[0], - (unsigned long)&frame->tramp[2]); - current->thread.fpscr = 0; /* turn off all fp exceptions */ - - /* Retrieve rt_sigframe from stack and - set up registers for signal handler - */ - newsp -= __SIGNAL_FRAMESIZE; + /* Default to using normal stack */ + newsp = regs->gpr[1]; - if (get_user(temp_ptr, &rt_sf->uc.uc_mcontext.handler)) { - goto badframe; + if (ka->sa.sa_flags & SA_ONSTACK) { + if (! on_sig_stack(regs->gpr[1])) + newsp = (current->sas_ss_sp + current->sas_ss_size); } - funct_desc_ptr = (struct funct_descr_entry *)temp_ptr; - - if (put_user(regs->gpr[1], (unsigned long *)newsp) - || get_user(regs->nip, &funct_desc_ptr->entry) - || get_user(regs->gpr[2], &funct_desc_ptr->toc) - || get_user(regs->gpr[3], &rt_sf->uc.uc_mcontext.signal) - || get_user(regs->gpr[4], (unsigned long *)&rt_sf->pinfo) - || get_user(regs->gpr[5], (unsigned long *)&rt_sf->puc)) - goto badframe; + return (void *)((newsp - frame_size) & -8ul); +} - regs->gpr[1] = newsp; - regs->gpr[6] = (unsigned long)rt_sf; - regs->link = (unsigned long)frame->tramp; +static int +setup_trampoline(unsigned int syscall, unsigned int *tramp) +{ + int i, err = 0; - return; + /* addi r1, r1, __SIGNAL_FRAMESIZE # Pop the dummy stackframe */ + err |= __put_user(0x38210000UL | (__SIGNAL_FRAMESIZE & 0xffff), &tramp[0]); + /* li r0, __NR_[rt_]sigreturn| */ + err |= __put_user(0x38000000UL | (syscall & 0xffff), &tramp[1]); + /* sc */ + err |= __put_user(0x44000002UL, &tramp[2]); + + /* Minimal traceback info */ + for (i=TRAMP_TRACEBACK; i < TRAMP_SIZE ;i++) + err |= __put_user(0, &tramp[i]); + + if (!err) + flush_icache_range((unsigned long) &tramp[0], + (unsigned long) &tramp[TRAMP_SIZE]); -badframe: -#if DEBUG_SIG - printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", - regs, frame, newsp); -#endif - do_exit(SIGSEGV); + return err; } /* * Do a signal return; undo the signal stack. */ -long sys_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, unsigned long r8, - struct pt_regs *regs) -{ - struct sigcontext *sc, sigctx; - struct sigregs *sr; - elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */ + +int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, unsigned long r8, + struct pt_regs *regs) +{ + struct ucontext *uc = (struct ucontext *)regs->gpr[1]; sigset_t set; + stack_t st; - sc = (struct sigcontext *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); - if (copy_from_user(&sigctx, sc, sizeof(sigctx))) + if (verify_area(VERIFY_READ, uc, sizeof(*uc))) goto badframe; - set.sig[0] = sigctx.oldmask; -#if _NSIG_WORDS > 1 - set.sig[1] = sigctx._unused[3]; -#endif + if (__copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) + goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (regs->msr & MSR_FP) - giveup_fpu(current); - /* restore registers */ - sr = (struct sigregs *)sigctx.regs; - if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs))) + if (restore_sigcontext(regs, NULL, &uc->uc_mcontext)) goto badframe; - saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) - | (saved_regs[PT_MSR] & MSR_USERCHANGE); - saved_regs[PT_SOFTE] = regs->softe; - memcpy(regs, saved_regs, GP_REGS_SIZE); - if (copy_from_user(current->thread.fpr, &sr->fp_regs, - sizeof(sr->fp_regs))) + if (__copy_from_user(&st, &uc->uc_stack, sizeof(st))) goto badframe; + /* This function sets back the stack flags into + the current task structure. */ + sys_sigaltstack(&st, NULL, 0, 0, 0, 0, regs); return regs->result; badframe: +#if DEBUG_SIG + printk("badframe in sys_rt_sigreturn, regs=%p uc=%p &uc->uc_mcontext=%p\n", + regs, uc, &uc->uc_mcontext); +#endif do_exit(SIGSEGV); -} +} -/* - * Set up a signal frame. - */ -static void setup_frame(struct pt_regs *regs, struct sigregs *frame, - unsigned long newsp) +static void +setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs) { - /* Handler is *really* a pointer to the function descriptor for * the signal routine. The first entry in the function * descriptor is the entry address of signal and the second * entry is the TOC value we need to use. */ - struct funct_descr_entry { - unsigned long entry; - unsigned long toc; - }; - - struct funct_descr_entry * funct_desc_ptr; - unsigned long temp_ptr; + func_descr_t *funct_desc_ptr; + struct rt_sigframe *frame; + unsigned long newsp = 0; + int err = 0; - struct sigcontext *sc = (struct sigcontext *)newsp; - - if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) - goto badframe; - if (regs->msr & MSR_FP) - giveup_fpu(current); - if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE) - || __copy_to_user(&frame->fp_regs, current->thread.fpr, - ELF_NFPREG * sizeof(double)) - /* li r0, __NR_sigreturn */ - || __put_user(0x38000000UL + __NR_sigreturn, &frame->tramp[0]) - /* sc */ - || __put_user(0x44000002UL, &frame->tramp[1])) - goto badframe; - flush_icache_range((unsigned long)&frame->tramp[0], - (unsigned long)&frame->tramp[2]); - current->thread.fpscr = 0; /* turn off all fp exceptions */ + frame = get_sigframe(ka, regs, sizeof(*frame)); - newsp -= __SIGNAL_FRAMESIZE; - if (get_user(temp_ptr, &sc->handler)) + if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) goto badframe; - - funct_desc_ptr = (struct funct_descr_entry *)temp_ptr; - if (put_user(regs->gpr[1], (unsigned long *)newsp) - || get_user(regs->nip, &funct_desc_ptr ->entry) - || get_user(regs->gpr[2],&funct_desc_ptr->toc) - || get_user(regs->gpr[3], &sc->signal)) - goto badframe; + err |= __put_user(&frame->info, &frame->pinfo); + err |= __put_user(&frame->uc, &frame->puc); + err |= copy_siginfo_to_user(&frame->info, info); + if (err) + goto badframe; + + /* Create the ucontext. */ + err |= __put_user(0, &frame->uc.uc_flags); + err |= __put_user(0, &frame->uc.uc_link); + err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(regs->gpr[1]), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr, NULL, + (unsigned long)ka->sa.sa_handler); + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + if (err) + goto badframe; + + /* Set up to return from userspace. */ + err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); + if (err) + goto badframe; + + funct_desc_ptr = (func_descr_t *) ka->sa.sa_handler; + + /* Allocate a dummy caller frame for the signal handler. */ + newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE; + err |= put_user(0, (unsigned long *)newsp); + + /* Set up "regs" so we "return" to the signal handler. */ + err |= get_user(regs->nip, &funct_desc_ptr->entry); + regs->link = (unsigned long) &frame->tramp[0]; regs->gpr[1] = newsp; - regs->gpr[4] = (unsigned long)sc; - regs->link = (unsigned long)frame->tramp; + err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); + regs->gpr[3] = signr; + if (ka->sa.sa_flags & SA_SIGINFO) { + err |= get_user(regs->gpr[4], (unsigned long *)&frame->pinfo); + err |= get_user(regs->gpr[5], (unsigned long *)&frame->puc); + regs->gpr[6] = (unsigned long) frame; + } else { + regs->gpr[4] = (unsigned long)&frame->uc.uc_mcontext; + } + if (err) + goto badframe; return; badframe: #if DEBUG_SIG - printk("badframe in setup_frame, regs=%p frame=%p newsp=%lx\n", + printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif do_exit(SIGSEGV); } + /* * OK, we're invoking a handler */ -static void handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs, unsigned long *newspp, unsigned long frame) +static void +handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { - struct sigcontext *sc; - struct rt_sigframe *rt_sf; - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - - if (regs->trap == 0x0C00 /* System Call! */ - && ((int)regs->result == -ERESTARTNOHAND || - (int)regs->result == -ERESTART_RESTARTBLOCK || - ((int)regs->result == -ERESTARTSYS && - !(ka->sa.sa_flags & SA_RESTART)))) { - if ((int)regs->result == -ERESTART_RESTARTBLOCK) - current_thread_info()->restart_block.fn - = do_no_restart_syscall; - regs->result = -EINTR; - } - /* Set up Signal Frame */ - if (ka->sa.sa_flags & SA_SIGINFO) { - /* Put a Real Time Context onto stack */ - *newspp -= sizeof(*rt_sf); - rt_sf = (struct rt_sigframe *)*newspp; - if (verify_area(VERIFY_WRITE, rt_sf, sizeof(*rt_sf))) - goto badframe; - - if (__put_user((unsigned long)ka->sa.sa_handler, - &rt_sf->uc.uc_mcontext.handler) - || __put_user(&rt_sf->info, &rt_sf->pinfo) - || __put_user(&rt_sf->uc, &rt_sf->puc) - /* Put the siginfo */ - || copy_siginfo_to_user(&rt_sf->info, info) - /* Create the ucontext */ - || __put_user(0, &rt_sf->uc.uc_flags) - || __put_user(0, &rt_sf->uc.uc_link) - || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp) - || __put_user(sas_ss_flags(regs->gpr[1]), - &rt_sf->uc.uc_stack.ss_flags) - || __put_user(current->sas_ss_size, - &rt_sf->uc.uc_stack.ss_size) - || __copy_to_user(&rt_sf->uc.uc_sigmask, - oldset, sizeof(*oldset)) - /* mcontext.regs points to preamble register frame */ - || __put_user((struct pt_regs *)frame, &rt_sf->uc.uc_mcontext.regs) - || __put_user(sig, &rt_sf->uc.uc_mcontext.signal)) - goto badframe; - } else { - /* Put a sigcontext on the stack */ - *newspp -= sizeof(*sc); - sc = (struct sigcontext *)*newspp; - if (verify_area(VERIFY_WRITE, sc, sizeof(*sc))) - goto badframe; - - if (__put_user((unsigned long)ka->sa.sa_handler, &sc->handler) - || __put_user(oldset->sig[0], &sc->oldmask) -#if _NSIG_WORDS > 1 - || __put_user(oldset->sig[1], &sc->_unused[3]) -#endif - || __put_user((struct pt_regs *)frame, &sc->regs) - || __put_user(sig, &sc->signal)) - goto badframe; - } + setup_rt_frame(sig, ka, info, oldset, regs); if (ka->sa.sa_flags & SA_ONESHOT) ka->sa.sa_handler = SIG_DFL; @@ -515,14 +349,40 @@ spin_unlock_irq(¤t->sighand->siglock); } return; +} -badframe: -#if DEBUG_SIG - printk("badframe in handle_signal, regs=%p frame=%lx newsp=%lx\n", - regs, frame, *newspp); - printk("sc=%p sig=%d ka=%p info=%p oldset=%p\n", sc, sig, ka, info, oldset); -#endif - do_exit(SIGSEGV); +static inline void +syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) +{ + switch ((int)regs->result) { + case -ERESTART_RESTARTBLOCK: + current_thread_info()->restart_block.fn = do_no_restart_syscall; + /* fallthrough */ + case -ERESTARTNOHAND: + /* ERESTARTNOHAND means that the syscall should only be + * restarted if there was no handler for the signal, and since + * we only get here if there is a handler, we dont restart. + */ + regs->result = -EINTR; + break; + case -ERESTARTSYS: + /* ERESTARTSYS means to restart the syscall if there is no + * handler or the handler was registered with SA_RESTART + */ + if (!(ka->sa.sa_flags & SA_RESTART)) { + regs->result = -EINTR; + break; + } + /* fallthrough */ + case -ERESTARTNOINTR: + /* ERESTARTNOINTR means that the syscall should be + * called again after the signal handler returns. + */ + regs->gpr[3] = regs->orig_gpr3; + regs->nip -= 4; + regs->result = 0; + break; + } } /* @@ -535,8 +395,6 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) { siginfo_t info; - struct k_sigaction *ka; - unsigned long frame, newsp; int signr; /* @@ -549,20 +407,15 @@ if (!oldset) oldset = ¤t->blocked; - newsp = frame = 0; - signr = get_signal_to_deliver(&info, regs, NULL); if (signr > 0) { - ka = ¤t->sighand->action[signr-1]; - if ((ka->sa.sa_flags & SA_ONSTACK) - && (!on_sig_stack(regs->gpr[1]))) - newsp = (current->sas_ss_sp + current->sas_ss_size); - else - newsp = regs->gpr[1]; - newsp = frame = newsp - sizeof(struct sigregs); + struct k_sigaction *ka = ¤t->sighand->action[signr-1]; /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, oldset, regs, &newsp, frame); + if (regs->trap == 0x0C00) + syscall_restart(regs, ka); + handle_signal(signr, ka, &info, oldset, regs); + return 1; } if (regs->trap == 0x0C00) { /* System Call! */ @@ -579,13 +432,8 @@ } } - if (newsp == frame) - return 0; /* no signals delivered */ - - /* Invoke correct stack setup routine */ - if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame(regs, (struct sigregs *)frame, newsp); - else - setup_frame(regs, (struct sigregs *)frame, newsp); - return 1; + return 0; } + + + diff -Nru a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c --- a/arch/ppc64/kernel/signal32.c Thu May 8 00:24:30 2003 +++ b/arch/ppc64/kernel/signal32.c Thu May 8 00:24:30 2003 @@ -114,6 +114,40 @@ * setup_frame32 */ +/* + * Atomically swap in the new signal mask, and wait for a signal. + */ +long sys32_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7, + struct pt_regs *regs) +{ + sigset_t saveset; + + mask &= _BLOCKABLE; + spin_lock_irq(¤t->sighand->siglock); + saveset = current->blocked; + siginitset(¤t->blocked, mask); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + regs->result = -EINTR; + regs->gpr[3] = EINTR; + regs->ccr |= 0x10000000; + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (do_signal32(&saveset, regs)) + /* + * If a signal handler needs to be called, + * do_signal32() has set R3 to the signal number (the + * first argument of the signal handler), so don't + * overwrite that with EINTR ! + * In the other cases, do_signal32() doesn't touch + * R3, so it's still set to -EINTR (see above). + */ + return regs->gpr[3]; + } +} + long sys32_sigaction(int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact) { @@ -792,13 +826,13 @@ while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(&saveset, regs)) + if (do_signal32(&saveset, regs)) /* * If a signal handler needs to be called, - * do_signal() has set R3 to the signal number (the + * do_signal32() has set R3 to the signal number (the * first argument of the signal handler), so don't * overwrite that with EINTR ! - * In the other cases, do_signal() doesn't touch + * In the other cases, do_signal32() doesn't touch * R3, so it's still set to -EINTR (see above). */ return regs->gpr[3]; diff -Nru a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c --- a/arch/ppc64/kernel/smp.c Thu May 8 00:24:29 2003 +++ b/arch/ppc64/kernel/smp.c Thu May 8 00:24:29 2003 @@ -46,8 +46,9 @@ #include #include "open_pic.h" #include +#include -int smp_threads_ready = 0; +int smp_threads_ready; unsigned long cache_decay_ticks; /* initialised so it doesn't end up in bss */ @@ -63,18 +64,6 @@ void smp_call_function_interrupt(void); void smp_message_pass(int target, int msg, unsigned long data, int wait); -void xics_setup_cpu(void); -void xics_cause_IPI(int cpu); - -/* - * XICS only has a single IPI, so encode the messages per CPU - */ -struct xics_ipi_struct { - volatile unsigned long value; -} ____cacheline_aligned; - -struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; - #define smp_message_pass(t,m,d,w) smp_ops->message_pass((t),(m),(d),(w)) static inline void set_tb(unsigned int upper, unsigned int lower) @@ -189,7 +178,7 @@ smp_ops->kick_cpu = smp_iSeries_kick_cpu; smp_ops->setup_cpu = smp_iSeries_setup_cpu; #warning fix for iseries - naca->processorCount = smp_iSeries_numProcs(); + systemcfg->processorCount = smp_iSeries_numProcs(); } #endif @@ -353,7 +342,7 @@ smp_ops->probe = smp_xics_probe; } - if (naca->platform == PLATFORM_PSERIES) { + if (systemcfg->platform == PLATFORM_PSERIES) { smp_ops->give_timebase = pSeries_give_timebase; smp_ops->take_timebase = pSeries_take_timebase; } diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c --- a/arch/ppc64/kernel/sys_ppc32.c Thu May 8 00:24:29 2003 +++ b/arch/ppc64/kernel/sys_ppc32.c Thu May 8 00:24:29 2003 @@ -1801,7 +1801,7 @@ err = do_sys32_shmctl(first, second, (void *)AA(ptr)); break; default: - err = -EINVAL; + err = -ENOSYS; break; } return err; diff -Nru a/arch/ppc64/kernel/syscalls.c b/arch/ppc64/kernel/syscalls.c --- a/arch/ppc64/kernel/syscalls.c Thu May 8 00:24:29 2003 +++ b/arch/ppc64/kernel/syscalls.c Thu May 8 00:24:29 2003 @@ -68,7 +68,7 @@ version = call >> 16; /* hack for backward compatibility */ call &= 0xffff; - ret = -EINVAL; + ret = -ENOSYS; switch (call) { case SEMOP: ret = sys_semop (first, (struct sembuf *)ptr, second); diff -Nru a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c --- a/arch/ppc64/kernel/traps.c Thu May 8 00:24:29 2003 +++ b/arch/ppc64/kernel/traps.c Thu May 8 00:24:29 2003 @@ -55,14 +55,12 @@ * Trap & Exception support */ -/* Should we panic on bad kernel exceptions or try to recover */ -#undef PANIC_ON_ERROR - static spinlock_t die_lock = SPIN_LOCK_UNLOCKED; void die(const char *str, struct pt_regs *regs, long err) { static int die_counter; + console_verbose(); spin_lock_irq(&die_lock); bust_spinlocks(1); @@ -71,11 +69,16 @@ bust_spinlocks(0); spin_unlock_irq(&die_lock); -#ifdef PANIC_ON_ERROR - panic(str); -#else + if (in_interrupt()) + panic("Fatal exception in interrupt"); + + if (panic_on_oops) { + printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n"); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(5 * HZ); + panic("Fatal exception"); + } do_exit(SIGSEGV); -#endif } static void @@ -139,15 +142,13 @@ #ifdef CONFIG_DEBUG_KERNEL if (debugger) debugger(regs); + else #endif + panic("System Reset"); -#ifdef PANIC_ON_ERROR - panic("System Reset"); -#else /* Must die if the interrupt is not recoverable */ if (!(regs->msr & MSR_RI)) panic("Unrecoverable System Reset"); -#endif /* What should we do here? We could issue a shutdown or hard reset. */ } @@ -343,6 +344,14 @@ info.si_addr = (void *)regs->nip; _exception(SIGILL, &info, regs); } +} + + void +KernelFPUnavailableException(struct pt_regs *regs) +{ + printk("Illegal floating point used in kernel (task=0x%016lx, pc=0x%016lx, trap=0x%08x)\n", + current, regs->nip, regs->trap); + panic("Unrecoverable FP Unavailable Exception in Kernel"); } void diff -Nru a/arch/ppc64/kernel/udbg.c b/arch/ppc64/kernel/udbg.c --- a/arch/ppc64/kernel/udbg.c Thu May 8 00:24:27 2003 +++ b/arch/ppc64/kernel/udbg.c Thu May 8 00:24:27 2003 @@ -176,7 +176,7 @@ void udbg_printSP(const char *s) { - if (naca->platform == PLATFORM_PSERIES) { + if (systemcfg->platform == PLATFORM_PSERIES) { unsigned long sp; asm("mr %0,1" : "=r" (sp) :); if (s) diff -Nru a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c --- a/arch/ppc64/kernel/xics.c Thu May 8 00:24:29 2003 +++ b/arch/ppc64/kernel/xics.c Thu May 8 00:24:29 2003 @@ -1,5 +1,5 @@ /* - * arch/ppc/kernel/xics.c + * arch/ppc64/kernel/xics.c * * Copyright 2000 IBM Corporation. * @@ -22,10 +22,11 @@ #include #include #include -#include "i8259.h" #include #include -#include +#include + +#include "i8259.h" void xics_enable_irq(u_int irq); void xics_disable_irq(u_int irq); @@ -61,33 +62,39 @@ /* Want a priority other than 0. Various HW issues require this. */ #define DEFAULT_PRIORITY 5 +/* + * Mark IPIs as higher priority so we can take them inside interrupts that + * arent marked SA_INTERRUPT + */ +#define IPI_PRIORITY 4 + struct xics_ipl { union { - u32 word; - u8 bytes[4]; + u32 word; + u8 bytes[4]; } xirr_poll; union { u32 word; - u8 bytes[4]; + u8 bytes[4]; } xirr; - u32 dummy; + u32 dummy; union { - u32 word; - u8 bytes[4]; + u32 word; + u8 bytes[4]; } qirr; }; -struct xics_info { - volatile struct xics_ipl * per_cpu[NR_CPUS]; -}; +static struct xics_ipl *xics_per_cpu[NR_CPUS]; -struct xics_info xics_info; +static int xics_irq_8259_cascade = 0; +static int xics_irq_8259_cascade_real = 0; +static unsigned int default_server = 0xFF; +static unsigned int default_distrib_server = 0; -unsigned long long intr_base = 0; -int xics_irq_8259_cascade = 0; -int xics_irq_8259_cascade_real = 0; -unsigned int default_server = 0xFF; -unsigned int default_distrib_server = 0; +/* + * XICS only has a single IPI, so encode the messages per CPU + */ +struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; /* RTAS service tokens */ int ibm_get_xive; @@ -95,11 +102,6 @@ int ibm_int_on; int ibm_int_off; -struct xics_interrupt_node { - unsigned long long addr; - unsigned long long size; -} inodes[NR_CPUS*2]; - typedef struct { int (*xirr_info_get)(int cpu); void (*xirr_info_set)(int cpu, int val); @@ -108,24 +110,26 @@ } xics_ops; +/* SMP */ + static int pSeries_xirr_info_get(int n_cpu) { - return (xics_info.per_cpu[n_cpu]->xirr.word); + return xics_per_cpu[n_cpu]->xirr.word; } static void pSeries_xirr_info_set(int n_cpu, int value) { - xics_info.per_cpu[n_cpu]->xirr.word = value; + xics_per_cpu[n_cpu]->xirr.word = value; } static void pSeries_cppr_info(int n_cpu, u8 value) { - xics_info.per_cpu[n_cpu]->xirr.bytes[0] = value; + xics_per_cpu[n_cpu]->xirr.bytes[0] = value; } -static void pSeries_qirr_info(int n_cpu , u8 value) +static void pSeries_qirr_info(int n_cpu, u8 value) { - xics_info.per_cpu[n_cpu]->qirr.bytes[0] = value; + xics_per_cpu[n_cpu]->qirr.bytes[0] = value; } static xics_ops pSeries_ops = { @@ -136,113 +140,174 @@ }; static xics_ops *ops = &pSeries_ops; -extern xics_ops pSeriesLP_ops; -void -xics_enable_irq( - u_int virq - ) +/* LPAR */ + +static inline long plpar_eoi(unsigned long xirr) { - u_int irq; - unsigned long status; - long call_status; + return plpar_hcall_norets(H_EOI, xirr); +} + +static inline long plpar_cppr(unsigned long cppr) +{ + return plpar_hcall_norets(H_CPPR, cppr); +} + +static inline long plpar_ipi(unsigned long servernum, unsigned long mfrr) +{ + return plpar_hcall_norets(H_IPI, servernum, mfrr); +} + +static inline long plpar_xirr(unsigned long *xirr_ret) +{ + unsigned long dummy; + return plpar_hcall(H_XIRR, 0, 0, 0, 0, xirr_ret, &dummy, &dummy); +} + +static int pSeriesLP_xirr_info_get(int n_cpu) +{ + unsigned long lpar_rc; + unsigned long return_value; + + lpar_rc = plpar_xirr(&return_value); + if (lpar_rc != H_Success) + panic(" bad return code xirr - rc = %lx \n", lpar_rc); + return (int)return_value; +} + +static void pSeriesLP_xirr_info_set(int n_cpu, int value) +{ + unsigned long lpar_rc; + unsigned long val64 = value & 0xffffffff; + + lpar_rc = plpar_eoi(val64); + if (lpar_rc != H_Success) + panic("bad return code EOI - rc = %ld, value=%lx\n", lpar_rc, + val64); +} + +static void pSeriesLP_cppr_info(int n_cpu, u8 value) +{ + unsigned long lpar_rc; + + lpar_rc = plpar_cppr(value); + if (lpar_rc != H_Success) + panic("bad return code cppr - rc = %lx\n", lpar_rc); +} + +static void pSeriesLP_qirr_info(int n_cpu , u8 value) +{ + unsigned long lpar_rc; + + lpar_rc = plpar_ipi(n_cpu, value); + if (lpar_rc != H_Success) + panic("bad return code qirr - rc = %lx\n", lpar_rc); +} + +xics_ops pSeriesLP_ops = { + pSeriesLP_xirr_info_get, + pSeriesLP_xirr_info_set, + pSeriesLP_cppr_info, + pSeriesLP_qirr_info +}; + +void xics_enable_irq(u_int virq) +{ + u_int irq; + long call_status; + unsigned int server; virq -= XICS_IRQ_OFFSET; irq = virt_irq_to_real(virq); if (irq == XICS_IPI) return; + #ifdef CONFIG_IRQ_ALL_CPUS - call_status = rtas_call(ibm_set_xive, 3, 1, (unsigned long*)&status, - irq, smp_threads_ready ? default_distrib_server : default_server, DEFAULT_PRIORITY); + if (smp_threads_ready) + server = default_distrib_server; + else + server = default_server; #else - call_status = rtas_call(ibm_set_xive, 3, 1, (unsigned long*)&status, - irq, default_server, DEFAULT_PRIORITY); + server = default_server; #endif - if( call_status != 0 ) { - printk("xics_enable_irq: irq=%x: rtas_call failed; retn=%lx, status=%lx\n", - irq, call_status, status); + + call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, + DEFAULT_PRIORITY); + if (call_status != 0) { + printk("xics_enable_irq: irq=%x: ibm_set_xive returned %lx\n", + irq, call_status); return; } + /* Now unmask the interrupt (often a no-op) */ - call_status = rtas_call(ibm_int_on, 1, 1, (unsigned long*)&status, - irq); - if( call_status != 0 ) { - printk("xics_disable_irq on: irq=%x: rtas_call failed, retn=%lx\n", + call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq); + if (call_status != 0) { + printk("xics_enable_irq: irq=%x: ibm_int_on returned %lx\n", irq, call_status); return; } } -void -xics_disable_irq( - u_int virq - ) -{ - u_int irq; - unsigned long status; - long call_status; +void xics_disable_irq(u_int virq) +{ + u_int irq; + long call_status; virq -= XICS_IRQ_OFFSET; irq = virt_irq_to_real(virq); - call_status = rtas_call(ibm_int_off, 1, 1, (unsigned long*)&status, - irq); - if( call_status != 0 ) { - printk("xics_disable_irq: irq=%x: rtas_call failed, retn=%lx\n", + if (irq == XICS_IPI) + return; + + call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq); + if (call_status != 0) { + printk("xics_disable_irq: irq=%x: ibm_int_off returned %lx\n", irq, call_status); return; } } -void -xics_end_irq( - u_int irq - ) +void xics_end_irq(u_int irq) { int cpu = smp_processor_id(); - ops->cppr_info(cpu, 0); /* actually the value overwritten by ack */ - iosync(); - ops->xirr_info_set(cpu, ((0xff<<24) | (virt_irq_to_real(irq-XICS_IRQ_OFFSET)))); iosync(); + ops->xirr_info_set(cpu, ((0xff<<24) | + (virt_irq_to_real(irq-XICS_IRQ_OFFSET)))); } -void -xics_mask_and_ack_irq(u_int irq) +void xics_mask_and_ack_irq(u_int irq) { int cpu = smp_processor_id(); - if( irq < XICS_IRQ_OFFSET ) { + if (irq < XICS_IRQ_OFFSET) { i8259_pic.ack(irq); iosync(); - ops->xirr_info_set(cpu, ((0xff<<24) | xics_irq_8259_cascade_real)); - iosync(); - } - else { - ops->cppr_info(cpu, 0xff); + ops->xirr_info_set(cpu, ((0xff<<24) | + xics_irq_8259_cascade_real)); iosync(); } } -int -xics_get_irq(struct pt_regs *regs) +int xics_get_irq(struct pt_regs *regs) { - u_int cpu = smp_processor_id(); - u_int vec; + u_int cpu = smp_processor_id(); + u_int vec; int irq; vec = ops->xirr_info_get(cpu); /* (vec >> 24) == old priority */ vec &= 0x00ffffff; + /* for sanity, this had better be < NR_IRQS - 16 */ - if( vec == xics_irq_8259_cascade_real ) { + if (vec == xics_irq_8259_cascade_real) { irq = i8259_irq(cpu); - if(irq == -1) { + if (irq == -1) { /* Spurious cascaded interrupt. Still must ack xics */ xics_end_irq(XICS_IRQ_OFFSET + xics_irq_8259_cascade); irq = -1; } - } else if( vec == XICS_IRQ_SPURIOUS ) { + } else if (vec == XICS_IRQ_SPURIOUS) { irq = -1; } else { irq = real_irq_to_virt(vec) + XICS_IRQ_OFFSET; @@ -250,45 +315,49 @@ return irq; } -struct xics_ipi_struct { - volatile unsigned long value; -} ____cacheline_aligned; +#ifdef CONFIG_SMP extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; -#ifdef CONFIG_SMP -void xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs) { int cpu = smp_processor_id(); + int handled = 0; ops->qirr_info(cpu, 0xff); while (xics_ipi_message[cpu].value) { - if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION, &xics_ipi_message[cpu].value)) { + handled = 1; + if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION, + &xics_ipi_message[cpu].value)) { mb(); smp_message_recv(PPC_MSG_CALL_FUNCTION, regs); } - if (test_and_clear_bit(PPC_MSG_RESCHEDULE, &xics_ipi_message[cpu].value)) { + if (test_and_clear_bit(PPC_MSG_RESCHEDULE, + &xics_ipi_message[cpu].value)) { mb(); smp_message_recv(PPC_MSG_RESCHEDULE, regs); } #if 0 - if (test_and_clear_bit(PPC_MSG_MIGRATE_TASK, &xics_ipi_message[cpu].value)) { + if (test_and_clear_bit(PPC_MSG_MIGRATE_TASK, + &xics_ipi_message[cpu].value)) { mb(); smp_message_recv(PPC_MSG_MIGRATE_TASK, regs); } #endif #ifdef CONFIG_XMON - if (test_and_clear_bit(PPC_MSG_XMON_BREAK, &xics_ipi_message[cpu].value)) { + if (test_and_clear_bit(PPC_MSG_XMON_BREAK, + &xics_ipi_message[cpu].value)) { mb(); smp_message_recv(PPC_MSG_XMON_BREAK, regs); } #endif } + return IRQ_RETVAL(handled); } void xics_cause_IPI(int cpu) { - ops->qirr_info(cpu,0) ; + ops->qirr_info(cpu, IPI_PRIORITY); } void xics_setup_cpu(void) @@ -298,15 +367,20 @@ ops->cppr_info(cpu, 0xff); iosync(); } + #endif /* CONFIG_SMP */ -void -xics_init_IRQ( void ) +void xics_init_IRQ(void) { int i; unsigned long intr_size = 0; struct device_node *np; uint *ireg, ilen, indx=0; + unsigned long intr_base = 0; + struct xics_interrupt_node { + unsigned long long addr; + unsigned long long size; + } inodes[NR_CPUS*2]; ppc64_boot_msg(0x20, "XICS Init"); @@ -386,23 +460,24 @@ xics_irq_8259_cascade = virt_irq_create_mapping(xics_irq_8259_cascade_real); } - if (naca->platform == PLATFORM_PSERIES) { + if (systemcfg->platform == PLATFORM_PSERIES) { #ifdef CONFIG_SMP for (i = 0; i < NR_CPUS; ++i) { if (!cpu_possible(i)) continue; - xics_info.per_cpu[i] = - __ioremap((ulong)inodes[i].addr, - (ulong)inodes[i].size, _PAGE_NO_CACHE); + xics_per_cpu[i] = __ioremap((ulong)inodes[i].addr, + (ulong)inodes[i].size, + _PAGE_NO_CACHE); } #else - xics_info.per_cpu[0] = __ioremap((ulong)intr_base, intr_size, _PAGE_NO_CACHE); + xics_per_cpu[0] = __ioremap((ulong)intr_base, intr_size, + _PAGE_NO_CACHE); #endif /* CONFIG_SMP */ #ifdef CONFIG_PPC_PSERIES /* actually iSeries does not use any of xics...but it has link dependencies * for now, except this new one... */ - } else if (naca->platform == PLATFORM_PSERIES_LPAR) { + } else if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { ops = &pSeriesLP_ops; #endif } @@ -417,8 +492,8 @@ ops->cppr_info(boot_cpuid, 0xff); iosync(); if (xics_irq_8259_cascade != -1) { - if (request_irq(xics_irq_8259_cascade + XICS_IRQ_OFFSET, no_action, - 0, "8259 cascade", 0)) + if (request_irq(xics_irq_8259_cascade + XICS_IRQ_OFFSET, + no_action, 0, "8259 cascade", 0)) printk(KERN_ERR "xics_init_IRQ: couldn't get 8259 cascade\n"); i8259_init(); } diff -Nru a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c --- a/arch/ppc64/mm/fault.c Thu May 8 00:24:29 2003 +++ b/arch/ppc64/mm/fault.c Thu May 8 00:24:29 2003 @@ -75,8 +75,8 @@ } #endif - /* On an SLB miss we can only check for a valid exception entry */ - if (regs->trap == 0x380) { + /* On a kernel SLB miss we can only check for a valid exception entry */ + if (!user_mode(regs) && (regs->trap == 0x380)) { bad_page_fault(regs, address, SIGSEGV); return; } diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c --- a/arch/ppc64/mm/init.c Thu May 8 00:24:29 2003 +++ b/arch/ppc64/mm/init.c Thu May 8 00:24:29 2003 @@ -69,8 +69,6 @@ int mem_init_done; unsigned long ioremap_bot = IMALLOC_BASE; -static int boot_mapsize; - extern pgd_t swapper_pg_dir[]; extern char __init_begin, __init_end; extern char _start[], _end[]; @@ -454,6 +452,7 @@ unsigned long i; unsigned long start, bootmap_pages; unsigned long total_pages = lmb_end_of_DRAM() >> PAGE_SHIFT; + int boot_mapsize; /* * Find an area to use for the bootmem bitmap. Calculate the size of @@ -532,7 +531,7 @@ int nid; for (nid = 0; nid < numnodes; nid++) { - if (numa_node_exists[nid]) { + if (node_data[nid].node_size != 0) { printk("freeing bootmem node %x\n", nid); totalram_pages += free_all_bootmem_node(NODE_DATA(nid)); diff -Nru a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c --- a/arch/ppc64/mm/numa.c Thu May 8 00:24:29 2003 +++ b/arch/ppc64/mm/numa.c Thu May 8 00:24:29 2003 @@ -24,11 +24,18 @@ int numa_cpu_lookup_table[NR_CPUS] = { [ 0 ... (NR_CPUS - 1)] = -1}; int numa_memory_lookup_table[MAX_MEMORY >> MEMORY_INCREMENT_SHIFT] = { [ 0 ... ((MAX_MEMORY >> MEMORY_INCREMENT_SHIFT) - 1)] = -1}; -int numa_node_exists[MAX_NUMNODES]; +unsigned long numa_cpumask_lookup_table[MAX_NUMNODES]; struct pglist_data node_data[MAX_NUMNODES]; bootmem_data_t plat_node_bdata[MAX_NUMNODES]; +static inline void map_cpu_to_node(int cpu, int node) +{ + dbg("cpu %d maps to domain %d\n", cpu, node); + numa_cpu_lookup_table[cpu] = node; + numa_cpumask_lookup_table[node] |= 1UL << cpu; +} + static int __init parse_numa_properties(void) { struct device_node *cpu; @@ -88,9 +95,7 @@ if (max_domain < numa_domain) max_domain = numa_domain; - numa_cpu_lookup_table[cpu_nr] = numa_domain; - - dbg("cpu %d maps to domain %d\n", cpu_nr, numa_domain); + map_cpu_to_node(cpu_nr, numa_domain); } for (memory = find_type_devices("memory"); memory; @@ -135,7 +140,7 @@ /* FIXME */ if (numa_domain == 0xffff) { - dbg("cpu has no numa doman\n"); + dbg("memory has no numa doman\n"); numa_domain = 0; } @@ -145,7 +150,8 @@ if (max_domain < numa_domain) max_domain = numa_domain; - numa_node_exists[numa_domain] = 1; + node_data[numa_domain].node_start_pfn = start / PAGE_SIZE; + node_data[numa_domain].node_size = size / PAGE_SIZE; for (i = start ; i < (start+size); i += MEMORY_INCREMENT) numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = @@ -176,27 +182,17 @@ BUG(); for (nid = 0; nid < numnodes; nid++) { - unsigned long start, end; unsigned long start_paddr, end_paddr; int i; unsigned long bootmem_paddr; unsigned long bootmap_pages; - if (!numa_node_exists[nid]) + if (node_data[nid].node_size == 0) continue; - /* Find start and end of this zone */ - start = 0; - while (numa_memory_lookup_table[start] != nid) - start++; - - end = (MAX_MEMORY >> MEMORY_INCREMENT_SHIFT) - 1; - while (numa_memory_lookup_table[end] != nid) - end--; - end++; - - start_paddr = start << MEMORY_INCREMENT_SHIFT; - end_paddr = end << MEMORY_INCREMENT_SHIFT; + start_paddr = node_data[nid].node_start_pfn * PAGE_SIZE; + end_paddr = start_paddr + + (node_data[nid].node_size * PAGE_SIZE); dbg("node %d\n", nid); dbg("start_paddr = %lx\n", start_paddr); @@ -278,7 +274,7 @@ unsigned long start_pfn; unsigned long end_pfn; - if (!numa_node_exists[nid]) + if (node_data[nid].node_size == 0) continue; start_pfn = plat_node_bdata[nid].node_boot_start >> PAGE_SHIFT; diff -Nru a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c --- a/arch/ppc64/xmon/xmon.c Thu May 8 00:24:30 2003 +++ b/arch/ppc64/xmon/xmon.c Thu May 8 00:24:30 2003 @@ -453,7 +453,7 @@ int i; struct bpt *bp; - if (naca->platform != PLATFORM_PSERIES) + if (systemcfg->platform != PLATFORM_PSERIES) return; bp = bpts; for (i = 0; i < NBPTS; ++i, ++bp) { @@ -469,12 +469,10 @@ } } - if (!__is_processor(PV_POWER4) && !__is_processor(PV_POWER4p)) { - if (dabr.enabled) - set_dabr(dabr.address); - if (iabr.enabled) - set_iabr(iabr.address); - } + if (cpu_has_dabr() && dabr.enabled) + set_dabr(dabr.address); + if (cpu_has_iabr() && iabr.enabled) + set_iabr(iabr.address); } static void @@ -484,12 +482,13 @@ struct bpt *bp; unsigned instr; - if (naca->platform != PLATFORM_PSERIES) + if (systemcfg->platform != PLATFORM_PSERIES) return; - if (!__is_processor(PV_POWER4) && !__is_processor(PV_POWER4p)) { + + if (cpu_has_dabr()) set_dabr(0); + if (cpu_has_iabr()) set_iabr(0); - } bp = bpts; for (i = 0; i < NBPTS; ++i, ++bp) { @@ -778,8 +777,8 @@ cmd = inchar(); switch (cmd) { case 'd': /* bd - hardware data breakpoint */ - if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) { - printf("Not implemented on POWER4\n"); + if (cpu_has_dabr()) { + printf("Not implemented on this cpu\n"); break; } mode = 7; @@ -798,7 +797,7 @@ dabr.address = (dabr.address & ~7) | mode; break; case 'i': /* bi - hardware instr breakpoint */ - if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) { + if (cpu_has_iabr()) { printf("Not implemented on POWER4\n"); break; } diff -Nru a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c --- a/arch/sparc64/kernel/power.c Thu May 8 00:24:30 2003 +++ b/arch/sparc64/kernel/power.c Thu May 8 00:24:30 2003 @@ -84,6 +84,16 @@ return 0; } +static int __init has_button_interrupt(struct linux_ebus_device *edev) +{ + if (edev->irqs[0] == PCI_IRQ_NONE) + return 0; + if (!prom_node_has_property(edev->prom_node, "button")) + return 0; + + return 1; +} + void __init power_init(void) { struct linux_ebus *ebus; @@ -106,7 +116,7 @@ power_reg = (unsigned long)ioremap(edev->resource[0].start, 0x4); printk("power: Control reg at %016lx ... ", power_reg); poweroff_method = machine_halt; /* able to use the standard halt */ - if (edev->irqs[0] != PCI_IRQ_NONE) { + if (has_button_interrupt(edev)) { if (kernel_thread(powerd, 0, CLONE_FS) < 0) { printk("Failed to start power daemon.\n"); return; diff -Nru a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c --- a/arch/sparc64/solaris/socksys.c Thu May 8 00:24:28 2003 +++ b/arch/sparc64/solaris/socksys.c Thu May 8 00:24:28 2003 @@ -191,10 +191,9 @@ printk ("Couldn't create socket\n"); return ret; } - devfs_register (NULL, "socksys", DEVFS_FL_DEFAULT, - 30, 0, - S_IFCHR | S_IRUSR | S_IWUSR, - &socksys_fops, NULL); + + devfs_mk_cdev(MKDEV(30, 0), S_IFCHR|S_IRUSR|S_IWUSR, "socksys"); + file = fcheck(ret); /* N.B. Is this valid? Suppose the f_ops are in a module ... */ socksys_file_ops = *file->f_op; diff -Nru a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c --- a/arch/um/drivers/mmapper_kern.c Thu May 8 00:24:27 2003 +++ b/arch/um/drivers/mmapper_kern.c Thu May 8 00:24:27 2003 @@ -124,9 +124,7 @@ p_buf = __pa(v_buf); - devfs_register (NULL, "mmapper", DEVFS_FL_DEFAULT, - 30, 0, S_IFCHR | S_IRUGO | S_IWUGO, - &mmapper_fops, NULL); + devfs_mk_cdev(MKDEV(30, 0), S_IFCHR|S_IRUGO|S_IWUGO, "mmapper"); devfs_mk_symlink("mmapper0", "mmapper"); return(0); } diff -Nru a/drivers/acpi/acpi_ksyms.c b/drivers/acpi/acpi_ksyms.c --- a/drivers/acpi/acpi_ksyms.c Thu May 8 00:24:28 2003 +++ b/drivers/acpi/acpi_ksyms.c Thu May 8 00:24:28 2003 @@ -80,6 +80,7 @@ EXPORT_SYMBOL(acpi_get_possible_resources); EXPORT_SYMBOL(acpi_walk_resources); EXPORT_SYMBOL(acpi_set_current_resources); +EXPORT_SYMBOL(acpi_resource_to_address64); EXPORT_SYMBOL(acpi_enable_event); EXPORT_SYMBOL(acpi_disable_event); EXPORT_SYMBOL(acpi_clear_event); diff -Nru a/drivers/atm/Kconfig b/drivers/atm/Kconfig --- a/drivers/atm/Kconfig Thu May 8 00:24:28 2003 +++ b/drivers/atm/Kconfig Thu May 8 00:24:28 2003 @@ -440,5 +440,19 @@ default m if ATM_FORE200E_MAYBE!=y default y if ATM_FORE200E_MAYBE=y +config ATM_HE + tristate "ForeRunner HE Series" + depends on PCI && ATM + help + This is a driver for the Marconi ForeRunner HE-series ATM adapter + cards. It simultaneously supports the 155 and 622 versions. + +config ATM_HE_USE_SUNI + bool "Use S/UNI PHY driver" + depends on ATM_HE + help + Support for the S/UNI-Ultra and S/UNI-622 found in the ForeRunner + HE cards. This driver provides carrier detection some statistics. + endmenu diff -Nru a/drivers/atm/Makefile b/drivers/atm/Makefile --- a/drivers/atm/Makefile Thu May 8 00:24:27 2003 +++ b/drivers/atm/Makefile Thu May 8 00:24:27 2003 @@ -49,6 +49,10 @@ CONFIG_ATM_FORE200E_SBA_FW := $(obj)/sba200e_ecd.bin2 endif endif +obj-$(CONFIG_ATM_HE) += he.o +ifeq ($(CONFIG_ATM_HE_USE_SUNI),y) + obj-$(CONFIG_ATM_HE) += suni.o +endif # FORE Systems 200E-series firmware magic $(obj)/fore200e_pca_fw.c: $(patsubst "%", %, $(CONFIG_ATM_FORE200E_PCA_FW)) \ diff -Nru a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c --- a/drivers/atm/ambassador.c Thu May 8 00:24:27 2003 +++ b/drivers/atm/ambassador.c Thu May 8 00:24:27 2003 @@ -290,12 +290,11 @@ /********** microcode **********/ #ifdef AMB_NEW_MICROCODE -#define UCODE(x) UCODE1(atmsar12.,x) +#define UCODE(x) UCODE2(atmsar12.x) #else -#define UCODE(x) UCODE1(atmsar11.,x) +#define UCODE(x) UCODE2(atmsar11.x) #endif #define UCODE2(x) #x -#define UCODE1(x,y) UCODE2(x ## y) static u32 __initdata ucode_start = #include UCODE(start) diff -Nru a/drivers/atm/he.c b/drivers/atm/he.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/atm/he.c Thu May 8 00:24:30 2003 @@ -0,0 +1,3419 @@ +/* $Id: he.c,v 1.18 2003/05/06 22:57:15 chas Exp $ */ + +/* + + he.c + + ForeRunnerHE ATM Adapter driver for ATM on Linux + Copyright (C) 1999-2001 Naval Research Laboratory + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/* + + he.c + + ForeRunnerHE ATM Adapter driver for ATM on Linux + Copyright (C) 1999-2001 Naval Research Laboratory + + Permission to use, copy, modify and distribute this software and its + documentation is hereby granted, provided that both the copyright + notice and this permission notice appear in all copies of the software, + derivative works or modified versions, and any portions thereof, and + that both notices appear in supporting documentation. + + NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND + DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER + RESULTING FROM THE USE OF THIS SOFTWARE. + + This driver was written using the "Programmer's Reference Manual for + ForeRunnerHE(tm)", MANU0361-01 - Rev. A, 08/21/98. + + AUTHORS: + chas williams + eric kinzie + + NOTES: + 4096 supported 'connections' + group 0 is used for all traffic + interrupt queue 0 is used for all interrupts + aal0 support for receive only + + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#ifndef ATM_OC12_PCR +#define ATM_OC12_PCR (622080000/1080*1040/8/53) +#endif + +#ifdef BUS_INT_WAR +void sn_add_polled_interrupt(int irq, int interval); +void sn_delete_polled_interrupt(int irq); +#endif + +#define USE_TASKLET +#define USE_HE_FIND_VCC +#undef USE_SCATTERGATHER +#undef USE_CHECKSUM_HW /* still confused about this */ +#define USE_RBPS +#undef USE_RBPS_POOL /* if memory is tight try this */ +#undef USE_RBPL_POOL /* if memory is tight try this */ +#define USE_TPD_POOL +/* #undef CONFIG_ATM_HE_USE_SUNI */ + +/* 2.2 kernel support */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43) +#define dev_kfree_skb_irq(skb) dev_kfree_skb(skb) +#define dev_kfree_skb_any(skb) dev_kfree_skb(skb) +#undef USE_TASKLET +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18) +#define set_current_state(x) current->state = (x); +#endif + +#include "he.h" + +#include "suni.h" + +#include + +#define hprintk(fmt,args...) printk(DEV_LABEL "%d: " fmt, he_dev->number, args) +#define hprintk1(fmt) printk(DEV_LABEL "%d: " fmt, he_dev->number) + +#undef DEBUG +#ifdef DEBUG +#define HPRINTK(fmt,args...) hprintk(fmt,args) +#define HPRINTK1(fmt) hprintk1(fmt) +#else +#define HPRINTK(fmt,args...) +#define HPRINTK1(fmt,args...) +#endif /* DEBUG */ + + +/* version definition */ + +static char *version = "$Id: he.c,v 1.18 2003/05/06 22:57:15 chas Exp $"; + +/* defines */ +#define ALIGN_ADDRESS(addr, alignment) \ + ((((unsigned long) (addr)) + (((unsigned long) (alignment)) - 1)) & ~(((unsigned long) (alignment)) - 1)) + +/* declarations */ + +static int he_open(struct atm_vcc *vcc, short vpi, int vci); +static void he_close(struct atm_vcc *vcc); +static int he_send(struct atm_vcc *vcc, struct sk_buff *skb); +static int he_sg_send(struct atm_vcc *vcc, unsigned long start, unsigned long size); +static int he_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,69) +static irqreturn_t he_irq_handler(int irq, void *dev_id, struct pt_regs *regs); +#else +static void he_irq_handler(int irq, void *dev_id, struct pt_regs *regs); +#endif +static void he_tasklet(unsigned long data); +static int he_proc_read(struct atm_dev *dev,loff_t *pos,char *page); +static int he_start(struct atm_dev *dev); +static void he_stop(struct he_dev *dev); +static void he_phy_put(struct atm_dev *, unsigned char, unsigned long); +static unsigned char he_phy_get(struct atm_dev *, unsigned long); + +static u8 read_prom_byte(struct he_dev *he_dev, int addr); + +/* globals */ + +struct he_dev *he_devs = NULL; +static short disable64 = -1; +static short nvpibits = -1; +static short nvcibits = -1; +static short rx_skb_reserve = 16; +static short irq_coalesce = 1; +static short sdh = 1; + +static struct atmdev_ops he_ops = +{ + open: he_open, + close: he_close, + ioctl: he_ioctl, + send: he_send, + sg_send: he_sg_send, + phy_put: he_phy_put, + phy_get: he_phy_get, + proc_read: he_proc_read, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,1) + owner: THIS_MODULE +#endif +}; + +/* see the comments in he.h about global_lock */ + +#define HE_SPIN_LOCK(dev, flags) spin_lock_irqsave(&(dev)->global_lock, flags) +#define HE_SPIN_UNLOCK(dev, flags) spin_unlock_irqrestore(&(dev)->global_lock, flags) + +#define he_writel(dev, val, reg) do { writel(val, (dev)->membase + (reg)); wmb(); } while(0) +#define he_readl(dev, reg) readl((dev)->membase + (reg)) + +/* section 2.12 connection memory access */ + +static __inline__ void +he_writel_internal(struct he_dev *he_dev, unsigned val, unsigned addr, + unsigned flags) +{ + he_writel(he_dev, val, CON_DAT); +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl(he_dev, CON_DAT); +#endif + he_writel(he_dev, flags | CON_CTL_WRITE | CON_CTL_ADDR(addr), CON_CTL); + while(he_readl(he_dev, CON_CTL) & CON_CTL_BUSY); +} + +#define he_writel_rcm(dev, val, reg) \ + he_writel_internal(dev, val, reg, CON_CTL_RCM) + +#define he_writel_tcm(dev, val, reg) \ + he_writel_internal(dev, val, reg, CON_CTL_TCM) + +#define he_writel_mbox(dev, val, reg) \ + he_writel_internal(dev, val, reg, CON_CTL_MBOX) + +static unsigned +he_readl_internal(struct he_dev *he_dev, unsigned addr, unsigned flags) +{ + he_writel(he_dev, flags | CON_CTL_READ | CON_CTL_ADDR(addr), CON_CTL); + while(he_readl(he_dev, CON_CTL) & CON_CTL_BUSY); + return he_readl(he_dev, CON_DAT); +} + +#define he_readl_rcm(dev, reg) \ + he_readl_internal(dev, reg, CON_CTL_RCM) + +#define he_readl_tcm(dev, reg) \ + he_readl_internal(dev, reg, CON_CTL_TCM) + +#define he_readl_mbox(dev, reg) \ + he_readl_internal(dev, reg, CON_CTL_MBOX) + + +/* figure 2.2 connection id */ + +#define he_mkcid(dev, vpi, vci) (((vpi<<(dev)->vcibits) | vci) & 0x1fff) + +/* 2.5.1 per connection transmit state registers */ + +#define he_writel_tsr0(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 0) +#define he_readl_tsr0(dev, cid) \ + he_readl_tcm(dev, CONFIG_TSRA | (cid<<3) | 0) + +#define he_writel_tsr1(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 1) + +#define he_writel_tsr2(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 2) + +#define he_writel_tsr3(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 3) + +#define he_writel_tsr4(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 4) + + /* from page 2-20 + * + * NOTE While the transmit connection is active, bits 23 through 0 + * of this register must not be written by the host. Byte + * enables should be used during normal operation when writing + * the most significant byte. + */ + +#define he_writel_tsr4_upper(dev, val, cid) \ + he_writel_internal(dev, val, CONFIG_TSRA | (cid<<3) | 4, \ + CON_CTL_TCM \ + | CON_BYTE_DISABLE_2 \ + | CON_BYTE_DISABLE_1 \ + | CON_BYTE_DISABLE_0) + +#define he_readl_tsr4(dev, cid) \ + he_readl_tcm(dev, CONFIG_TSRA | (cid<<3) | 4) + +#define he_writel_tsr5(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 5) + +#define he_writel_tsr6(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 6) + +#define he_writel_tsr7(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 7) + + +#define he_writel_tsr8(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<2) | 0) + +#define he_writel_tsr9(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<2) | 1) + +#define he_writel_tsr10(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<2) | 2) + +#define he_writel_tsr11(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<2) | 3) + + +#define he_writel_tsr12(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRC | (cid<<1) | 0) + +#define he_writel_tsr13(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRC | (cid<<1) | 1) + + +#define he_writel_tsr14(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRD | cid) + +#define he_writel_tsr14_upper(dev, val, cid) \ + he_writel_internal(dev, val, CONFIG_TSRD | cid, \ + CON_CTL_TCM \ + | CON_BYTE_DISABLE_2 \ + | CON_BYTE_DISABLE_1 \ + | CON_BYTE_DISABLE_0) + +/* 2.7.1 per connection receive state registers */ + +#define he_writel_rsr0(dev, val, cid) \ + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 0) +#define he_readl_rsr0(dev, cid) \ + he_readl_rcm(dev, 0x00000 | (cid<<3) | 0) + +#define he_writel_rsr1(dev, val, cid) \ + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 1) + +#define he_writel_rsr2(dev, val, cid) \ + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 2) + +#define he_writel_rsr3(dev, val, cid) \ + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 3) + +#define he_writel_rsr4(dev, val, cid) \ + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 4) + +#define he_writel_rsr5(dev, val, cid) \ + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 5) + +#define he_writel_rsr6(dev, val, cid) \ + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 6) + +#define he_writel_rsr7(dev, val, cid) \ + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 7) + +static __inline__ struct atm_vcc* +he_find_vcc(struct he_dev *he_dev, unsigned cid) +{ + struct atm_vcc *vcc; + short vpi; + int vci; + + vpi = cid >> he_dev->vcibits; + vci = cid & ((1<vcibits)-1); + + for (vcc = he_dev->atm_dev->vccs; vcc; vcc = vcc->next) + if (vcc->vci == vci && vcc->vpi == vpi + && vcc->qos.rxtp.traffic_class != ATM_NONE) return vcc; + + return NULL; +} + +static int __devinit +he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) +{ + struct atm_dev *atm_dev; + struct he_dev *he_dev; + + printk(KERN_INFO "he: %s\n", version); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,43) + if (pci_enable_device(pci_dev)) return -EIO; +#endif + if (pci_set_dma_mask(pci_dev, HE_DMA_MASK) != 0) + { + printk(KERN_WARNING "he: no suitable dma available\n"); + return -EIO; + } + + atm_dev = atm_dev_register(DEV_LABEL, &he_ops, -1, 0); + if (!atm_dev) return -ENODEV; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,3) + pci_set_drvdata(pci_dev, atm_dev); +#else + pci_dev->driver_data = atm_dev; +#endif + + he_dev = (struct he_dev *) kmalloc(sizeof(struct he_dev), + GFP_KERNEL); + if (!he_dev) return -ENOMEM; + memset(he_dev, 0, sizeof(struct he_dev)); + + he_dev->pci_dev = pci_dev; + he_dev->atm_dev = atm_dev; + he_dev->atm_dev->dev_data = he_dev; + HE_DEV(atm_dev) = he_dev; + he_dev->number = atm_dev->number; /* was devs */ + if (he_start(atm_dev)) { + atm_dev_deregister(atm_dev); + he_stop(he_dev); + kfree(he_dev); + return -ENODEV; + } + he_dev->next = NULL; + if (he_devs) he_dev->next = he_devs; + he_devs = he_dev; + + return 0; +} + +static void __devexit +he_remove_one (struct pci_dev *pci_dev) +{ + struct atm_dev *atm_dev; + struct he_dev *he_dev; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,3) + atm_dev = pci_get_drvdata(pci_dev); +#else + atm_dev = pci_dev->driver_data; +#endif + he_dev = HE_DEV(atm_dev); + + /* need to remove from he_devs */ + + he_stop(he_dev); + atm_dev_deregister(atm_dev); + kfree(he_dev); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,3) + pci_set_drvdata(pci_dev, NULL); +#else + pci_dev->driver_data = NULL; +#endif +} + + +static unsigned +rate_to_atmf(unsigned rate) /* cps to atm forum format */ +{ +#define NONZERO (1<<14) + + unsigned exp = 0; + + if (rate == 0) return(0); + + rate <<= 9; + while (rate > 0x3ff) + { + ++exp; + rate >>= 1; + } + + return (NONZERO | (exp << 9) | (rate & 0x1ff)); +} + +static void __init +he_init_rx_lbfp0(struct he_dev *he_dev) +{ + unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count; + unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf; + unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD; + unsigned row_offset = he_dev->r0_startrow * he_dev->bytes_per_row; + + lbufd_index = 0; + lbm_offset = he_readl(he_dev, RCMLBM_BA); + + he_writel(he_dev, lbufd_index, RLBF0_H); + + for (i = 0, lbuf_count = 0; i < he_dev->r0_numbuffs; ++i) + { + lbufd_index += 2; + lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32; + + he_writel_rcm(he_dev, lbuf_addr, lbm_offset); + he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1); + + if (++lbuf_count == lbufs_per_row) + { + lbuf_count = 0; + row_offset += he_dev->bytes_per_row; + } + lbm_offset += 4; + } + + he_writel(he_dev, lbufd_index - 2, RLBF0_T); + he_writel(he_dev, he_dev->r0_numbuffs, RLBF0_C); +} + +static void __init +he_init_rx_lbfp1(struct he_dev *he_dev) +{ + unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count; + unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf; + unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD; + unsigned row_offset = he_dev->r1_startrow * he_dev->bytes_per_row; + + lbufd_index = 1; + lbm_offset = he_readl(he_dev, RCMLBM_BA) + (2 * lbufd_index); + + he_writel(he_dev, lbufd_index, RLBF1_H); + + for (i = 0, lbuf_count = 0; i < he_dev->r1_numbuffs; ++i) + { + lbufd_index += 2; + lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32; + + he_writel_rcm(he_dev, lbuf_addr, lbm_offset); + he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1); + + if (++lbuf_count == lbufs_per_row) + { + lbuf_count = 0; + row_offset += he_dev->bytes_per_row; + } + lbm_offset += 4; + } + + he_writel(he_dev, lbufd_index - 2, RLBF1_T); + he_writel(he_dev, he_dev->r1_numbuffs, RLBF1_C); +} + +static void __init +he_init_tx_lbfp(struct he_dev *he_dev) +{ + unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count; + unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf; + unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD; + unsigned row_offset = he_dev->tx_startrow * he_dev->bytes_per_row; + + lbufd_index = he_dev->r0_numbuffs + he_dev->r1_numbuffs; + lbm_offset = he_readl(he_dev, RCMLBM_BA) + (2 * lbufd_index); + + he_writel(he_dev, lbufd_index, TLBF_H); + + for (i = 0, lbuf_count = 0; i < he_dev->tx_numbuffs; ++i) + { + lbufd_index += 1; + lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32; + + he_writel_rcm(he_dev, lbuf_addr, lbm_offset); + he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1); + + if (++lbuf_count == lbufs_per_row) + { + lbuf_count = 0; + row_offset += he_dev->bytes_per_row; + } + lbm_offset += 2; + } + + he_writel(he_dev, lbufd_index - 1, TLBF_T); +} + +static int __init +he_init_tpdrq(struct he_dev *he_dev) +{ + he_dev->tpdrq_base = pci_alloc_consistent(he_dev->pci_dev, + CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq), &he_dev->tpdrq_phys); + if (he_dev->tpdrq_base == NULL) + { + hprintk1("failed to alloc tpdrq\n"); + return -ENOMEM; + } + memset(he_dev->tpdrq_base, 0, + CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq)); + + he_dev->tpdrq_tail = he_dev->tpdrq_base; + he_dev->tpdrq_head = he_dev->tpdrq_base; + + he_writel(he_dev, he_dev->tpdrq_phys, TPDRQ_B_H); + he_writel(he_dev, 0, TPDRQ_T); + he_writel(he_dev, CONFIG_TPDRQ_SIZE - 1, TPDRQ_S); + + return 0; +} + +static void __init +he_init_cs_block(struct he_dev *he_dev) +{ + unsigned clock, rate, delta; + int reg; + + /* 5.1.7 cs block initialization */ + + for(reg = 0; reg < 0x20; ++reg) + he_writel_mbox(he_dev, 0x0, CS_STTIM0 + reg); + + /* rate grid timer reload values */ + + clock = he_is622(he_dev) ? 66667000 : 50000000; + rate = he_dev->atm_dev->link_rate; + delta = rate / 16 / 2; + + for(reg = 0; reg < 0x10; ++reg) + { + /* 2.4 internal transmit function + * + * we initialize the first row in the rate grid. + * values are period (in clock cycles) of timer + */ + unsigned period = clock / rate; + + he_writel_mbox(he_dev, period, CS_TGRLD0 + reg); + rate -= delta; + } + + if (he_is622(he_dev)) + { + /* table 5.2 (4 cells per lbuf) */ + he_writel_mbox(he_dev, 0x000800fa, CS_ERTHR0); + he_writel_mbox(he_dev, 0x000c33cb, CS_ERTHR1); + he_writel_mbox(he_dev, 0x0010101b, CS_ERTHR2); + he_writel_mbox(he_dev, 0x00181dac, CS_ERTHR3); + he_writel_mbox(he_dev, 0x00280600, CS_ERTHR4); + + /* table 5.3, 5.4, 5.5, 5.6, 5.7 */ + he_writel_mbox(he_dev, 0x023de8b3, CS_ERCTL0); + he_writel_mbox(he_dev, 0x1801, CS_ERCTL1); + he_writel_mbox(he_dev, 0x68b3, CS_ERCTL2); + he_writel_mbox(he_dev, 0x1280, CS_ERSTAT0); + he_writel_mbox(he_dev, 0x68b3, CS_ERSTAT1); + he_writel_mbox(he_dev, 0x14585, CS_RTFWR); + + he_writel_mbox(he_dev, 0x4680, CS_RTATR); + + /* table 5.8 */ + he_writel_mbox(he_dev, 0x00159ece, CS_TFBSET); + he_writel_mbox(he_dev, 0x68b3, CS_WCRMAX); + he_writel_mbox(he_dev, 0x5eb3, CS_WCRMIN); + he_writel_mbox(he_dev, 0xe8b3, CS_WCRINC); + he_writel_mbox(he_dev, 0xdeb3, CS_WCRDEC); + he_writel_mbox(he_dev, 0x68b3, CS_WCRCEIL); + + /* table 5.9 */ + he_writel_mbox(he_dev, 0x5, CS_OTPPER); + he_writel_mbox(he_dev, 0x14, CS_OTWPER); + } + else + { + /* table 5.1 (4 cells per lbuf) */ + he_writel_mbox(he_dev, 0x000400ea, CS_ERTHR0); + he_writel_mbox(he_dev, 0x00063388, CS_ERTHR1); + he_writel_mbox(he_dev, 0x00081018, CS_ERTHR2); + he_writel_mbox(he_dev, 0x000c1dac, CS_ERTHR3); + he_writel_mbox(he_dev, 0x0014051a, CS_ERTHR4); + + /* table 5.3, 5.4, 5.5, 5.6, 5.7 */ + he_writel_mbox(he_dev, 0x0235e4b1, CS_ERCTL0); + he_writel_mbox(he_dev, 0x4701, CS_ERCTL1); + he_writel_mbox(he_dev, 0x64b1, CS_ERCTL2); + he_writel_mbox(he_dev, 0x1280, CS_ERSTAT0); + he_writel_mbox(he_dev, 0x64b1, CS_ERSTAT1); + he_writel_mbox(he_dev, 0xf424, CS_RTFWR); + + he_writel_mbox(he_dev, 0x4680, CS_RTATR); + + /* table 5.8 */ + he_writel_mbox(he_dev, 0x000563b7, CS_TFBSET); + he_writel_mbox(he_dev, 0x64b1, CS_WCRMAX); + he_writel_mbox(he_dev, 0x5ab1, CS_WCRMIN); + he_writel_mbox(he_dev, 0xe4b1, CS_WCRINC); + he_writel_mbox(he_dev, 0xdab1, CS_WCRDEC); + he_writel_mbox(he_dev, 0x64b1, CS_WCRCEIL); + + /* table 5.9 */ + he_writel_mbox(he_dev, 0x6, CS_OTPPER); + he_writel_mbox(he_dev, 0x1e, CS_OTWPER); + + } + + he_writel_mbox(he_dev, 0x8, CS_OTTLIM); + + for(reg = 0; reg < 0x8; ++reg) + he_writel_mbox(he_dev, 0x0, CS_HGRRT0 + reg); + +} + +static void __init +he_init_cs_block_rcm(struct he_dev *he_dev) +{ + unsigned rategrid[16][16]; + unsigned rate, delta; + int i, j, reg; + + unsigned rate_atmf, exp, man; + unsigned long long rate_cps; + int mult, buf, buf_limit = 4; + + /* initialize rate grid group table */ + + for (reg = 0x0; reg < 0xff; ++reg) + he_writel_rcm(he_dev, 0x0, CONFIG_RCMABR + reg); + + /* initialize rate controller groups */ + + for (reg = 0x100; reg < 0x1ff; ++reg) + he_writel_rcm(he_dev, 0x0, CONFIG_RCMABR + reg); + + /* initialize tNrm lookup table */ + + /* the manual makes reference to a routine in a sample driver + for proper configuration; fortunately, we only need this + in order to support abr connection */ + + /* initialize rate to group table */ + + rate = he_dev->atm_dev->link_rate; + delta = rate / 32; + + /* + * 2.4 transmit internal functions + * + * we construct a copy of the rate grid used by the scheduler + * in order to construct the rate to group table below + */ + + for (j = 0; j < 16; j++) + { + rategrid[0][j] = rate; + rate -= delta; + } + + for (i = 1; i < 16; i++) + for (j = 0; j < 16; j++) + if (i > 14) + rategrid[i][j] = rategrid[i - 1][j] / 4; + else + rategrid[i][j] = rategrid[i - 1][j] / 2; + + /* + * 2.4 transmit internal function + * + * this table maps the upper 5 bits of exponent and mantissa + * of the atm forum representation of the rate into an index + * on rate grid + */ + + rate_atmf = 0; + while (rate_atmf < 0x400) + { + man = (rate_atmf & 0x1f) << 4; + exp = rate_atmf >> 5; + + /* + instead of '/ 512', use '>> 9' to prevent a call + to divdu3 on x86 platforms + */ + rate_cps = (unsigned long long) (1 << exp) * (man + 512) >> 9; + + if (rate_cps < 10) rate_cps = 10; + /* 2.2.1 minimum payload rate is 10 cps */ + + for (i = 255; i > 0; i--) + if (rategrid[i/16][i%16] >= rate_cps) break; + /* pick nearest rate instead? */ + + /* + * each table entry is 16 bits: (rate grid index (8 bits) + * and a buffer limit (8 bits) + * there are two table entries in each 32-bit register + */ + +#ifdef notdef + buf = rate_cps * he_dev->tx_numbuffs / + (he_dev->atm_dev->link_rate * 2); +#else + /* this is pretty, but avoids _divdu3 and is mostly correct */ + buf = 0; + mult = he_dev->atm_dev->link_rate / ATM_OC3_PCR; + if (rate_cps > (68 * mult)) buf = 1; + if (rate_cps > (136 * mult)) buf = 2; + if (rate_cps > (204 * mult)) buf = 3; + if (rate_cps > (272 * mult)) buf = 4; +#endif + if (buf > buf_limit) buf = buf_limit; + reg = (reg<<16) | ((i<<8) | buf); + +#define RTGTBL_OFFSET 0x400 + + if (rate_atmf & 0x1) + he_writel_rcm(he_dev, reg, + CONFIG_RCMABR + RTGTBL_OFFSET + (rate_atmf>>1)); + + ++rate_atmf; + } +} + +static int __init +he_init_group(struct he_dev *he_dev, int group) +{ + int i; + +#ifdef USE_RBPS + /* small buffer pool */ +#ifdef USE_RBPS_POOL +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44) + he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev, + CONFIG_RBPS_BUFSIZE, 8, 0, SLAB_KERNEL); +#else + he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev, + CONFIG_RBPS_BUFSIZE, 8, 0); +#endif + if (he_dev->rbps_pool == NULL) + { + hprintk1("unable to create rbps pages\n"); + return -ENOMEM; + } +#else /* !USE_RBPS_POOL */ + he_dev->rbps_pages = pci_alloc_consistent(he_dev->pci_dev, + CONFIG_RBPS_SIZE * CONFIG_RBPS_BUFSIZE, &he_dev->rbps_pages_phys); + if (he_dev->rbps_pages == NULL) { + hprintk1("unable to create rbps page pool\n"); + return -ENOMEM; + } +#endif /* USE_RBPS_POOL */ + + he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev, + CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys); + if (he_dev->rbps_base == NULL) + { + hprintk1("failed to alloc rbps\n"); + return -ENOMEM; + } + memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp)); + he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL); + + for (i = 0; i < CONFIG_RBPS_SIZE; ++i) + { + dma_addr_t dma_handle; + void *cpuaddr; + +#ifdef USE_RBPS_POOL + cpuaddr = pci_pool_alloc(he_dev->rbps_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle); + if (cpuaddr == NULL) + return -ENOMEM; +#else + cpuaddr = he_dev->rbps_pages + (i * CONFIG_RBPS_BUFSIZE); + dma_handle = he_dev->rbps_pages_phys + (i * CONFIG_RBPS_BUFSIZE); +#endif + + he_dev->rbps_virt[i].virt = cpuaddr; + he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF); + he_dev->rbps_base[i].phys = dma_handle; + + } + he_dev->rbps_tail = &he_dev->rbps_base[CONFIG_RBPS_SIZE-1]; + + he_writel(he_dev, he_dev->rbps_phys, G0_RBPS_S + (group * 32)); + he_writel(he_dev, RBPS_MASK(he_dev->rbps_tail), + G0_RBPS_T + (group * 32)); + he_writel(he_dev, CONFIG_RBPS_BUFSIZE/4, + G0_RBPS_BS + (group * 32)); + he_writel(he_dev, + RBP_THRESH(CONFIG_RBPS_THRESH) | + RBP_QSIZE(CONFIG_RBPS_SIZE-1) | + RBP_INT_ENB, + G0_RBPS_QI + (group * 32)); +#else /* !USE_RBPS */ + he_writel(he_dev, 0x0, G0_RBPS_S + (group * 32)); + he_writel(he_dev, 0x0, G0_RBPS_T + (group * 32)); + he_writel(he_dev, 0x0, G0_RBPS_QI + (group * 32)); + he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0), + G0_RBPS_BS + (group * 32)); +#endif /* USE_RBPS */ + + /* large buffer pool */ +#ifdef USE_RBPL_POOL +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44) + he_dev->rbpl_pool = pci_pool_create("rbpl", he_dev->pci_dev, + CONFIG_RBPL_BUFSIZE, 8, 0, SLAB_KERNEL); +#else + he_dev->rbpl_pool = pci_pool_create("rbpl", he_dev->pci_dev, + CONFIG_RBPL_BUFSIZE, 8, 0); +#endif + if (he_dev->rbpl_pool == NULL) + { + hprintk1("unable to create rbpl pool\n"); + return -ENOMEM; + } +#else /* !USE_RBPL_POOL */ + he_dev->rbpl_pages = (void *) pci_alloc_consistent(he_dev->pci_dev, + CONFIG_RBPL_SIZE * CONFIG_RBPL_BUFSIZE, &he_dev->rbpl_pages_phys); + if (he_dev->rbpl_pages == NULL) + { + hprintk1("unable to create rbpl pages\n"); + return -ENOMEM; + } +#endif /* USE_RBPL_POOL */ + + he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev, + CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys); + if (he_dev->rbpl_base == NULL) + { + hprintk1("failed to alloc rbpl\n"); + return -ENOMEM; + } + memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp)); + he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL); + + for (i = 0; i < CONFIG_RBPL_SIZE; ++i) + { + dma_addr_t dma_handle; + void *cpuaddr; + +#ifdef USE_RBPL_POOL + cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle); + if (cpuaddr == NULL) + return -ENOMEM; +#else + cpuaddr = he_dev->rbpl_pages + (i * CONFIG_RBPL_BUFSIZE); + dma_handle = he_dev->rbpl_pages_phys + (i * CONFIG_RBPL_BUFSIZE); +#endif + + he_dev->rbpl_virt[i].virt = cpuaddr; + he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF); + he_dev->rbpl_base[i].phys = dma_handle; + + } + he_dev->rbpl_tail = &he_dev->rbpl_base[CONFIG_RBPL_SIZE-1]; + + he_writel(he_dev, he_dev->rbpl_phys, G0_RBPL_S + (group * 32)); + he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail), + G0_RBPL_T + (group * 32)); + he_writel(he_dev, CONFIG_RBPL_BUFSIZE/4, + G0_RBPL_BS + (group * 32)); + he_writel(he_dev, + RBP_THRESH(CONFIG_RBPL_THRESH) | + RBP_QSIZE(CONFIG_RBPL_SIZE-1) | + RBP_INT_ENB, + G0_RBPL_QI + (group * 32)); + + /* rx buffer ready queue */ + + he_dev->rbrq_base = pci_alloc_consistent(he_dev->pci_dev, + CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys); + if (he_dev->rbrq_base == NULL) + { + hprintk1("failed to allocate rbrq\n"); + return -ENOMEM; + } + memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq)); + + he_dev->rbrq_head = he_dev->rbrq_base; + he_writel(he_dev, he_dev->rbrq_phys, G0_RBRQ_ST + (group * 16)); + he_writel(he_dev, 0, G0_RBRQ_H + (group * 16)); + he_writel(he_dev, + RBRQ_THRESH(CONFIG_RBRQ_THRESH) | RBRQ_SIZE(CONFIG_RBRQ_SIZE-1), + G0_RBRQ_Q + (group * 16)); + if (irq_coalesce) + { + hprintk1("coalescing interrupts\n"); + he_writel(he_dev, RBRQ_TIME(768) | RBRQ_COUNT(7), + G0_RBRQ_I + (group * 16)); + } + else + he_writel(he_dev, RBRQ_TIME(0) | RBRQ_COUNT(1), + G0_RBRQ_I + (group * 16)); + + /* tx buffer ready queue */ + + he_dev->tbrq_base = pci_alloc_consistent(he_dev->pci_dev, + CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys); + if (he_dev->tbrq_base == NULL) + { + hprintk1("failed to allocate tbrq\n"); + return -ENOMEM; + } + memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq)); + + he_dev->tbrq_head = he_dev->tbrq_base; + + he_writel(he_dev, he_dev->tbrq_phys, G0_TBRQ_B_T + (group * 16)); + he_writel(he_dev, 0, G0_TBRQ_H + (group * 16)); + he_writel(he_dev, CONFIG_TBRQ_SIZE - 1, G0_TBRQ_S + (group * 16)); + he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16)); + + return 0; +} + +static int __init +he_init_irq(struct he_dev *he_dev) +{ + int i; + + /* 2.9.3.5 tail offset for each interrupt queue is located after the + end of the interrupt queue */ + + he_dev->irq_base = pci_alloc_consistent(he_dev->pci_dev, + (CONFIG_IRQ_SIZE+1) * sizeof(struct he_irq), &he_dev->irq_phys); + if (he_dev->irq_base == NULL) + { + hprintk1("failed to allocate irq\n"); + return -ENOMEM; + } + he_dev->irq_tailoffset = (unsigned *) + &he_dev->irq_base[CONFIG_IRQ_SIZE]; + *he_dev->irq_tailoffset = 0; + he_dev->irq_head = he_dev->irq_base; + he_dev->irq_tail = he_dev->irq_base; + + for(i=0; i < CONFIG_IRQ_SIZE; ++i) + he_dev->irq_base[i].isw = ITYPE_INVALID; + + he_writel(he_dev, he_dev->irq_phys, IRQ0_BASE); + he_writel(he_dev, + IRQ_SIZE(CONFIG_IRQ_SIZE) | IRQ_THRESH(CONFIG_IRQ_THRESH), + IRQ0_HEAD); + he_writel(he_dev, IRQ_INT_A | IRQ_TYPE_LINE, IRQ0_CNTL); + he_writel(he_dev, 0x0, IRQ0_DATA); + + he_writel(he_dev, 0x0, IRQ1_BASE); + he_writel(he_dev, 0x0, IRQ1_HEAD); + he_writel(he_dev, 0x0, IRQ1_CNTL); + he_writel(he_dev, 0x0, IRQ1_DATA); + + he_writel(he_dev, 0x0, IRQ2_BASE); + he_writel(he_dev, 0x0, IRQ2_HEAD); + he_writel(he_dev, 0x0, IRQ2_CNTL); + he_writel(he_dev, 0x0, IRQ2_DATA); + + he_writel(he_dev, 0x0, IRQ3_BASE); + he_writel(he_dev, 0x0, IRQ3_HEAD); + he_writel(he_dev, 0x0, IRQ3_CNTL); + he_writel(he_dev, 0x0, IRQ3_DATA); + + /* 2.9.3.2 interrupt queue mapping registers */ + + he_writel(he_dev, 0x0, GRP_10_MAP); + he_writel(he_dev, 0x0, GRP_32_MAP); + he_writel(he_dev, 0x0, GRP_54_MAP); + he_writel(he_dev, 0x0, GRP_76_MAP); + + if (request_irq(he_dev->pci_dev->irq, he_irq_handler, SA_INTERRUPT|SA_SHIRQ, DEV_LABEL, he_dev)) + { + hprintk("irq %d already in use\n", he_dev->pci_dev->irq); + return -EINVAL; + } + + he_dev->irq = he_dev->pci_dev->irq; + +#ifdef BUS_INT_WAR + HPRINTK("sn_add_polled_interrupt(irq %d, 1)\n", he_dev->irq); + sn_add_polled_interrupt(he_dev->irq, 1); +#endif + + return 0; +} + +static int __init +he_start(struct atm_dev *dev) +{ + struct he_dev *he_dev; + struct pci_dev *pci_dev; + + u16 command; + u32 gen_cntl_0, host_cntl, lb_swap; + u8 cache_size, timer; + + unsigned err; + unsigned int status, reg; + int i, group; + + he_dev = HE_DEV(dev); + pci_dev = he_dev->pci_dev; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,3) + he_dev->membase = pci_dev->resource[0].start; +#else + he_dev->membase = pci_dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK; +#endif + HPRINTK("membase = 0x%lx irq = %d.\n", he_dev->membase, pci_dev->irq); + + /* + * pci bus controller initialization + */ + + /* 4.3 pci bus controller-specific initialization */ + if (pci_read_config_dword(pci_dev, GEN_CNTL_0, &gen_cntl_0) != 0) + { + hprintk1("can't read GEN_CNTL_0\n"); + return -EINVAL; + } + gen_cntl_0 |= (MRL_ENB | MRM_ENB | IGNORE_TIMEOUT); + if (pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0) != 0) + { + hprintk1("can't write GEN_CNTL_0.\n"); + return -EINVAL; + } + + if (pci_read_config_word(pci_dev, PCI_COMMAND, &command) != 0) + { + hprintk1("can't read PCI_COMMAND.\n"); + return -EINVAL; + } + + command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE); + if (pci_write_config_word(pci_dev, PCI_COMMAND, command) != 0) + { + hprintk1("can't enable memory.\n"); + return -EINVAL; + } + + if (pci_read_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, &cache_size)) + { + hprintk1("can't read cache line size?\n"); + return -EINVAL; + } + + if (cache_size < 16) + { + cache_size = 16; + if (pci_write_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, cache_size)) + hprintk("can't set cache line size to %d\n", cache_size); + } + + if (pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &timer)) + { + hprintk1("can't read latency timer?\n"); + return -EINVAL; + } + + /* from table 3.9 + * + * LAT_TIMER = 1 + AVG_LAT + BURST_SIZE/BUS_SIZE + * + * AVG_LAT: The average first data read/write latency [maximum 16 clock cycles] + * BURST_SIZE: 1536 bytes (read) for 622, 768 bytes (read) for 155 [192 clock cycles] + * + */ +#define LAT_TIMER 209 + if (timer < LAT_TIMER) + { + HPRINTK("latency timer was %d, setting to %d\n", timer, LAT_TIMER); + timer = LAT_TIMER; + if (pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, timer)) + hprintk("can't set latency timer to %d\n", timer); + } + + if (!(he_dev->membase = (unsigned long) ioremap(he_dev->membase, HE_REGMAP_SIZE))) { + hprintk1("can't set up page mapping\n"); + return -EINVAL; + } + + /* 4.4 card reset */ + he_writel(he_dev, 0x0, RESET_CNTL); + he_writel(he_dev, 0xff, RESET_CNTL); + + udelay(16*1000); /* 16 ms */ + status = he_readl(he_dev, RESET_CNTL); + if ((status & BOARD_RST_STATUS) == 0) + { + hprintk1("reset failed\n"); + return -EINVAL; + } + + /* 4.5 set bus width */ + host_cntl = he_readl(he_dev, HOST_CNTL); + if (host_cntl & PCI_BUS_SIZE64) + gen_cntl_0 |= ENBL_64; + else + gen_cntl_0 &= ~ENBL_64; + + if (disable64 == 1) + { + hprintk1("disabling 64-bit pci bus transfers\n"); + gen_cntl_0 &= ~ENBL_64; + } + + if (gen_cntl_0 & ENBL_64) hprintk1("64-bit transfers enabled\n"); + + pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0); + + /* 4.7 read prom contents */ + for(i=0; iprod_id[i] = read_prom_byte(he_dev, PROD_ID + i); + + he_dev->media = read_prom_byte(he_dev, MEDIA); + + for(i=0; i<6; ++i) + dev->esi[i] = read_prom_byte(he_dev, MAC_ADDR + i); + + hprintk("%s%s, %x:%x:%x:%x:%x:%x\n", + he_dev->prod_id, + he_dev->media & 0x40 ? "SM" : "MM", + dev->esi[0], + dev->esi[1], + dev->esi[2], + dev->esi[3], + dev->esi[4], + dev->esi[5]); + he_dev->atm_dev->link_rate = he_is622(he_dev) ? + ATM_OC12_PCR : ATM_OC3_PCR; + + /* 4.6 set host endianess */ + lb_swap = he_readl(he_dev, LB_SWAP); + if (he_is622(he_dev)) + lb_swap &= ~XFER_SIZE; /* 4 cells */ + else + lb_swap |= XFER_SIZE; /* 8 cells */ +#ifdef __BIG_ENDIAN + lb_swap |= DESC_WR_SWAP | INTR_SWAP | BIG_ENDIAN_HOST; +#else + lb_swap &= ~(DESC_WR_SWAP | INTR_SWAP | BIG_ENDIAN_HOST | + DATA_WR_SWAP | DATA_RD_SWAP | DESC_RD_SWAP); +#endif /* __BIG_ENDIAN */ + he_writel(he_dev, lb_swap, LB_SWAP); + + /* 4.8 sdram controller initialization */ + he_writel(he_dev, he_is622(he_dev) ? LB_64_ENB : 0x0, SDRAM_CTL); + + /* 4.9 initialize rnum value */ + lb_swap |= SWAP_RNUM_MAX(0xf); + he_writel(he_dev, lb_swap, LB_SWAP); + + /* 4.10 initialize the interrupt queues */ + if ((err = he_init_irq(he_dev)) != 0) return err; + +#ifdef USE_TASKLET + tasklet_init(&he_dev->tasklet, he_tasklet, (unsigned long) he_dev); +#endif + spin_lock_init(&he_dev->global_lock); + + /* 4.11 enable pci bus controller state machines */ + host_cntl |= (OUTFF_ENB | CMDFF_ENB | + QUICK_RD_RETRY | QUICK_WR_RETRY | PERR_INT_ENB); + he_writel(he_dev, host_cntl, HOST_CNTL); + + gen_cntl_0 |= INT_PROC_ENBL|INIT_ENB; + pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0); + + /* + * atm network controller initialization + */ + + /* 5.1.1 generic configuration state */ + + /* + * local (cell) buffer memory map + * + * HE155 HE622 + * + * 0 ____________1023 bytes 0 _______________________2047 bytes + * | | | | | + * | utility | | rx0 | | + * 5|____________| 255|___________________| u | + * 6| | 256| | t | + * | | | | i | + * | rx0 | row | tx | l | + * | | | | i | + * | | 767|___________________| t | + * 517|____________| 768| | y | + * row 518| | | rx1 | | + * | | 1023|___________________|___| + * | | + * | tx | + * | | + * | | + * 1535|____________| + * 1536| | + * | rx1 | + * 2047|____________| + * + */ + + /* total 4096 connections */ + he_dev->vcibits = CONFIG_DEFAULT_VCIBITS; + he_dev->vpibits = CONFIG_DEFAULT_VPIBITS; + + if (nvpibits != -1 && nvcibits != -1 && nvpibits+nvcibits != HE_MAXCIDBITS) + { + hprintk("nvpibits + nvcibits != %d\n", HE_MAXCIDBITS); + return -ENODEV; + } + + if (nvpibits != -1) + { + he_dev->vpibits = nvpibits; + he_dev->vcibits = HE_MAXCIDBITS - nvpibits; + } + + if (nvcibits != -1) + { + he_dev->vcibits = nvcibits; + he_dev->vpibits = HE_MAXCIDBITS - nvcibits; + } + + + if (he_is622(he_dev)) + { + he_dev->cells_per_row = 40; + he_dev->bytes_per_row = 2048; + he_dev->r0_numrows = 256; + he_dev->tx_numrows = 512; + he_dev->r1_numrows = 256; + he_dev->r0_startrow = 0; + he_dev->tx_startrow = 256; + he_dev->r1_startrow = 768; + } + else + { + he_dev->cells_per_row = 20; + he_dev->bytes_per_row = 1024; + he_dev->r0_numrows = 512; + he_dev->tx_numrows = 1018; + he_dev->r1_numrows = 512; + he_dev->r0_startrow = 6; + he_dev->tx_startrow = 518; + he_dev->r1_startrow = 1536; + } + + he_dev->cells_per_lbuf = 4; + he_dev->buffer_limit = 4; + he_dev->r0_numbuffs = he_dev->r0_numrows * + he_dev->cells_per_row / he_dev->cells_per_lbuf; + if (he_dev->r0_numbuffs > 2560) he_dev->r0_numbuffs = 2560; + + he_dev->r1_numbuffs = he_dev->r1_numrows * + he_dev->cells_per_row / he_dev->cells_per_lbuf; + if (he_dev->r1_numbuffs > 2560) he_dev->r1_numbuffs = 2560; + + he_dev->tx_numbuffs = he_dev->tx_numrows * + he_dev->cells_per_row / he_dev->cells_per_lbuf; + if (he_dev->tx_numbuffs > 5120) he_dev->tx_numbuffs = 5120; + + /* 5.1.2 configure hardware dependent registers */ + + he_writel(he_dev, + SLICE_X(0x2) | ARB_RNUM_MAX(0xf) | TH_PRTY(0x3) | + RH_PRTY(0x3) | TL_PRTY(0x2) | RL_PRTY(0x1) | + (he_is622(he_dev) ? BUS_MULTI(0x28) : BUS_MULTI(0x46)) | + (he_is622(he_dev) ? NET_PREF(0x50) : NET_PREF(0x8c)), + LBARB); + + he_writel(he_dev, BANK_ON | + (he_is622(he_dev) ? (REF_RATE(0x384) | WIDE_DATA) : REF_RATE(0x150)), + SDRAMCON); + + he_writel(he_dev, + (he_is622(he_dev) ? RM_BANK_WAIT(1) : RM_BANK_WAIT(0)) | + RM_RW_WAIT(1), RCMCONFIG); + he_writel(he_dev, + (he_is622(he_dev) ? TM_BANK_WAIT(2) : TM_BANK_WAIT(1)) | + TM_RW_WAIT(1), TCMCONFIG); + + he_writel(he_dev, he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD, LB_CONFIG); + + he_writel(he_dev, + (he_is622(he_dev) ? UT_RD_DELAY(8) : UT_RD_DELAY(0)) | + (he_is622(he_dev) ? RC_UT_MODE(0) : RC_UT_MODE(1)) | + RX_VALVP(he_dev->vpibits) | + RX_VALVC(he_dev->vcibits), RC_CONFIG); + + he_writel(he_dev, DRF_THRESH(0x20) | + (he_is622(he_dev) ? TX_UT_MODE(0) : TX_UT_MODE(1)) | + TX_VCI_MASK(he_dev->vcibits) | + LBFREE_CNT(he_dev->tx_numbuffs), TX_CONFIG); + + he_writel(he_dev, 0x0, TXAAL5_PROTO); + + he_writel(he_dev, PHY_INT_ENB | + (he_is622(he_dev) ? PTMR_PRE(67-1) : PTMR_PRE(50-1)), + RH_CONFIG); + + /* 5.1.3 initialize connection memory */ + + for(i=0; i < TCM_MEM_SIZE; ++i) + he_writel_tcm(he_dev, 0, i); + + for(i=0; i < RCM_MEM_SIZE; ++i) + he_writel_rcm(he_dev, 0, i); + + /* + * transmit connection memory map + * + * tx memory + * 0x0 ___________________ + * | | + * | | + * | TSRa | + * | | + * | | + * 0x8000|___________________| + * | | + * | TSRb | + * 0xc000|___________________| + * | | + * | TSRc | + * 0xe000|___________________| + * | TSRd | + * 0xf000|___________________| + * | tmABR | + * 0x10000|___________________| + * | | + * | tmTPD | + * |___________________| + * | | + * .... + * 0x1ffff|___________________| + * + * + */ + + he_writel(he_dev, CONFIG_TSRB, TSRB_BA); + he_writel(he_dev, CONFIG_TSRC, TSRC_BA); + he_writel(he_dev, CONFIG_TSRD, TSRD_BA); + he_writel(he_dev, CONFIG_TMABR, TMABR_BA); + he_writel(he_dev, CONFIG_TPDBA, TPD_BA); + + + /* + * receive connection memory map + * + * 0x0 ___________________ + * | | + * | | + * | RSRa | + * | | + * | | + * 0x8000|___________________| + * | | + * | rx0/1 | + * | LBM | link lists of local + * | tx | buffer memory + * | | + * 0xd000|___________________| + * | | + * | rmABR | + * 0xe000|___________________| + * | | + * | RSRb | + * |___________________| + * | | + * .... + * 0xffff|___________________| + */ + + he_writel(he_dev, 0x08000, RCMLBM_BA); + he_writel(he_dev, 0x0e000, RCMRSRB_BA); + he_writel(he_dev, 0x0d800, RCMABR_BA); + + /* 5.1.4 initialize local buffer free pools linked lists */ + + he_init_rx_lbfp0(he_dev); + he_init_rx_lbfp1(he_dev); + + he_writel(he_dev, 0x0, RLBC_H); + he_writel(he_dev, 0x0, RLBC_T); + he_writel(he_dev, 0x0, RLBC_H2); + + he_writel(he_dev, 512, RXTHRSH); /* 10% of r0+r1 buffers */ + he_writel(he_dev, 256, LITHRSH); /* 5% of r0+r1 buffers */ + + he_init_tx_lbfp(he_dev); + + he_writel(he_dev, he_is622(he_dev) ? 0x104780 : 0x800, UBUFF_BA); + + /* 5.1.5 initialize intermediate receive queues */ + + if (he_is622(he_dev)) + { + he_writel(he_dev, 0x000f, G0_INMQ_S); + he_writel(he_dev, 0x200f, G0_INMQ_L); + + he_writel(he_dev, 0x001f, G1_INMQ_S); + he_writel(he_dev, 0x201f, G1_INMQ_L); + + he_writel(he_dev, 0x002f, G2_INMQ_S); + he_writel(he_dev, 0x202f, G2_INMQ_L); + + he_writel(he_dev, 0x003f, G3_INMQ_S); + he_writel(he_dev, 0x203f, G3_INMQ_L); + + he_writel(he_dev, 0x004f, G4_INMQ_S); + he_writel(he_dev, 0x204f, G4_INMQ_L); + + he_writel(he_dev, 0x005f, G5_INMQ_S); + he_writel(he_dev, 0x205f, G5_INMQ_L); + + he_writel(he_dev, 0x006f, G6_INMQ_S); + he_writel(he_dev, 0x206f, G6_INMQ_L); + + he_writel(he_dev, 0x007f, G7_INMQ_S); + he_writel(he_dev, 0x207f, G7_INMQ_L); + } + else + { + he_writel(he_dev, 0x0000, G0_INMQ_S); + he_writel(he_dev, 0x0008, G0_INMQ_L); + + he_writel(he_dev, 0x0001, G1_INMQ_S); + he_writel(he_dev, 0x0009, G1_INMQ_L); + + he_writel(he_dev, 0x0002, G2_INMQ_S); + he_writel(he_dev, 0x000a, G2_INMQ_L); + + he_writel(he_dev, 0x0003, G3_INMQ_S); + he_writel(he_dev, 0x000b, G3_INMQ_L); + + he_writel(he_dev, 0x0004, G4_INMQ_S); + he_writel(he_dev, 0x000c, G4_INMQ_L); + + he_writel(he_dev, 0x0005, G5_INMQ_S); + he_writel(he_dev, 0x000d, G5_INMQ_L); + + he_writel(he_dev, 0x0006, G6_INMQ_S); + he_writel(he_dev, 0x000e, G6_INMQ_L); + + he_writel(he_dev, 0x0007, G7_INMQ_S); + he_writel(he_dev, 0x000f, G7_INMQ_L); + } + + /* 5.1.6 application tunable parameters */ + + he_writel(he_dev, 0x0, MCC); + he_writel(he_dev, 0x0, OEC); + he_writel(he_dev, 0x0, DCC); + he_writel(he_dev, 0x0, CEC); + + /* 5.1.7 cs block initialization */ + + he_init_cs_block(he_dev); + + /* 5.1.8 cs block connection memory initialization */ + + he_init_cs_block_rcm(he_dev); + + /* 5.1.10 initialize host structures */ + + he_init_tpdrq(he_dev); + +#ifdef USE_TPD_POOL +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44) + he_dev->tpd_pool = pci_pool_create("tpd", he_dev->pci_dev, + sizeof(struct he_tpd), TPD_ALIGNMENT, 0, SLAB_KERNEL); +#else + he_dev->tpd_pool = pci_pool_create("tpd", he_dev->pci_dev, + sizeof(struct he_tpd), TPD_ALIGNMENT, 0); +#endif + if (he_dev->tpd_pool == NULL) + { + hprintk1("unable to create tpd pci_pool\n"); + return -ENOMEM; + } + + INIT_LIST_HEAD(&he_dev->outstanding_tpds); +#else + he_dev->tpd_base = (void *) pci_alloc_consistent(he_dev->pci_dev, + CONFIG_NUMTPDS * sizeof(struct he_tpd), &he_dev->tpd_base_phys); + if (!he_dev->tpd_base) + return -ENOMEM; + + for(i = 0; i < CONFIG_NUMTPDS; ++i) + { + he_dev->tpd_base[i].status = (i << TPD_ADDR_SHIFT); + he_dev->tpd_base[i].inuse = 0; + } + + he_dev->tpd_head = he_dev->tpd_base; + he_dev->tpd_end = &he_dev->tpd_base[CONFIG_NUMTPDS-1]; +#endif + + if (he_init_group(he_dev, 0) != 0) + return -ENOMEM; + + for (group = 1; group < HE_NUM_GROUPS; ++group) + { + he_writel(he_dev, 0x0, G0_RBPS_S + (group * 32)); + he_writel(he_dev, 0x0, G0_RBPS_T + (group * 32)); + he_writel(he_dev, 0x0, G0_RBPS_QI + (group * 32)); + he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0), + G0_RBPS_BS + (group * 32)); + + he_writel(he_dev, 0x0, G0_RBPL_S + (group * 32)); + he_writel(he_dev, 0x0, G0_RBPL_T + (group * 32)); + he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0), + G0_RBPL_QI + (group * 32)); + he_writel(he_dev, 0x0, G0_RBPL_BS + (group * 32)); + + he_writel(he_dev, 0x0, G0_RBRQ_ST + (group * 16)); + he_writel(he_dev, 0x0, G0_RBRQ_H + (group * 16)); + he_writel(he_dev, RBRQ_THRESH(0x1) | RBRQ_SIZE(0x0), + G0_RBRQ_Q + (group * 16)); + he_writel(he_dev, 0x0, G0_RBRQ_I + (group * 16)); + + he_writel(he_dev, 0x0, G0_TBRQ_B_T + (group * 16)); + he_writel(he_dev, 0x0, G0_TBRQ_H + (group * 16)); + he_writel(he_dev, TBRQ_THRESH(0x1), + G0_TBRQ_THRESH + (group * 16)); + he_writel(he_dev, 0x0, G0_TBRQ_S + (group * 16)); + } + + /* host status page */ + + he_dev->hsp = pci_alloc_consistent(he_dev->pci_dev, + sizeof(struct he_hsp), &he_dev->hsp_phys); + if (he_dev->hsp == NULL) + { + hprintk1("failed to allocate host status page\n"); + return -ENOMEM; + } + memset(he_dev->hsp, 0, sizeof(struct he_hsp)); + he_writel(he_dev, he_dev->hsp_phys, HSP_BA); + + /* initialize framer */ + +#ifdef CONFIG_ATM_HE_USE_SUNI + suni_init(he_dev->atm_dev); + if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->start) + he_dev->atm_dev->phy->start(he_dev->atm_dev); +#endif /* CONFIG_ATM_HE_USE_SUNI */ + + if (sdh) + { + /* this really should be in suni.c but for now... */ + + int val; + + val = he_phy_get(he_dev->atm_dev, SUNI_TPOP_APM); + val = (val & ~SUNI_TPOP_APM_S) | ( 0x2 << SUNI_TPOP_APM_S_SHIFT); + he_phy_put(he_dev->atm_dev, val, SUNI_TPOP_APM); + } + + /* 5.1.12 enable transmit and receive */ + + reg = he_readl_mbox(he_dev, CS_ERCTL0); + reg |= TX_ENABLE|ER_ENABLE; + he_writel_mbox(he_dev, reg, CS_ERCTL0); + + reg = he_readl(he_dev, RC_CONFIG); + reg |= RX_ENABLE; + he_writel(he_dev, reg, RC_CONFIG); + +#ifndef USE_HE_FIND_VCC + he_dev->he_vcc_table = kmalloc(sizeof(struct he_vcc_table) * + (1 << (he_dev->vcibits + he_dev->vpibits)), GFP_KERNEL); + if (he_dev->he_vcc_table == NULL) + { + hprintk1("failed to alloc he_vcc_table\n"); + return -ENOMEM; + } + memset(he_dev->he_vcc_table, 0, sizeof(struct he_vcc_table) * + (1 << (he_dev->vcibits + he_dev->vpibits))); +#endif + + for (i = 0; i < HE_NUM_CS_STPER; ++i) + { + he_dev->cs_stper[i].inuse = 0; + he_dev->cs_stper[i].pcr = -1; + } + he_dev->total_bw = 0; + + + /* atm linux initialization */ + + he_dev->atm_dev->ci_range.vpi_bits = he_dev->vpibits; + he_dev->atm_dev->ci_range.vci_bits = he_dev->vcibits; + + he_dev->irq_peak = 0; + he_dev->rbrq_peak = 0; + he_dev->rbpl_peak = 0; + he_dev->tbrq_peak = 0; + + HPRINTK("hell bent for leather!\n"); + + return 0; +} + +static void +he_stop(struct he_dev *he_dev) +{ + u16 command; + u32 gen_cntl_0, reg; + struct pci_dev *pci_dev; + + pci_dev = he_dev->pci_dev; + + /* disable interrupts */ + + if (he_dev->membase) + { + pci_read_config_dword(pci_dev, GEN_CNTL_0, &gen_cntl_0); + gen_cntl_0 &= ~(INT_PROC_ENBL | INIT_ENB); + pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0); + +#ifdef USE_TASKLET + tasklet_disable(&he_dev->tasklet); +#endif + + /* disable recv and transmit */ + + reg = he_readl_mbox(he_dev, CS_ERCTL0); + reg &= ~(TX_ENABLE|ER_ENABLE); + he_writel_mbox(he_dev, reg, CS_ERCTL0); + + reg = he_readl(he_dev, RC_CONFIG); + reg &= ~(RX_ENABLE); + he_writel(he_dev, reg, RC_CONFIG); + } + +#ifdef CONFIG_ATM_HE_USE_SUNI + if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->stop) + he_dev->atm_dev->phy->stop(he_dev->atm_dev); +#endif /* CONFIG_ATM_HE_USE_SUNI */ + + if (he_dev->irq) + { +#ifdef BUS_INT_WAR + sn_delete_polled_interrupt(he_dev->irq); +#endif + free_irq(he_dev->irq, he_dev); + } + + if (he_dev->irq_base) + pci_free_consistent(he_dev->pci_dev, (CONFIG_IRQ_SIZE+1) + * sizeof(struct he_irq), he_dev->irq_base, he_dev->irq_phys); + + if (he_dev->hsp) + pci_free_consistent(he_dev->pci_dev, sizeof(struct he_hsp), + he_dev->hsp, he_dev->hsp_phys); + + if (he_dev->rbpl_base) + { +#ifdef USE_RBPL_POOL + for (i=0; irbpl_virt[i].virt; + dma_addr_t dma_handle = he_dev->rbpl_base[i].phys; + + pci_pool_free(he_dev->rbpl_pool, cpuaddr, dma_handle); + } +#else + pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE + * CONFIG_RBPL_BUFSIZE, he_dev->rbpl_pages, he_dev->rbpl_pages_phys); +#endif + pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE + * sizeof(struct he_rbp), he_dev->rbpl_base, he_dev->rbpl_phys); + } + +#ifdef USE_RBPL_POOL + if (he_dev->rbpl_pool) + pci_pool_destroy(he_dev->rbpl_pool); +#endif + +#ifdef USE_RBPS + if (he_dev->rbps_base) + { +#ifdef USE_RBPS_POOL + for (i=0; irbps_virt[i].virt; + dma_addr_t dma_handle = he_dev->rbps_base[i].phys; + + pci_pool_free(he_dev->rbps_pool, cpuaddr, dma_handle); + } +#else + pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE + * CONFIG_RBPS_BUFSIZE, he_dev->rbps_pages, he_dev->rbps_pages_phys); +#endif + pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE + * sizeof(struct he_rbp), he_dev->rbps_base, he_dev->rbps_phys); + } + +#ifdef USE_RBPS_POOL + if (he_dev->rbps_pool) + pci_pool_destroy(he_dev->rbps_pool); +#endif + +#endif /* USE_RBPS */ + + if (he_dev->rbrq_base) + pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), + he_dev->rbrq_base, he_dev->rbrq_phys); + + if (he_dev->tbrq_base) + pci_free_consistent(he_dev->pci_dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), + he_dev->tbrq_base, he_dev->tbrq_phys); + + if (he_dev->tpdrq_base) + pci_free_consistent(he_dev->pci_dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), + he_dev->tpdrq_base, he_dev->tpdrq_phys); + +#ifdef USE_TPD_POOL + if (he_dev->tpd_pool) + pci_pool_destroy(he_dev->tpd_pool); +#else + if (he_dev->tpd_base) + pci_free_consistent(he_dev->pci_dev, CONFIG_NUMTPDS * sizeof(struct he_tpd), + he_dev->tpd_base, he_dev->tpd_base_phys); +#endif + +#ifndef USE_HE_FIND_VCC + if (he_dev->he_vcc_table) + kfree(he_dev->he_vcc_table); +#endif + + if (he_dev->pci_dev) + { + pci_read_config_word(he_dev->pci_dev, PCI_COMMAND, &command); + command &= ~(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + pci_write_config_word(he_dev->pci_dev, PCI_COMMAND, command); + } + + if (he_dev->membase) iounmap((void *) he_dev->membase); +} + +static struct he_tpd * +__alloc_tpd(struct he_dev *he_dev) +{ +#ifdef USE_TPD_POOL + struct he_tpd *tpd; + dma_addr_t dma_handle; + + tpd = pci_pool_alloc(he_dev->tpd_pool, SLAB_ATOMIC|SLAB_DMA, &dma_handle); + if (tpd == NULL) + return NULL; + + tpd->status = TPD_ADDR(dma_handle); + tpd->reserved = 0; + tpd->iovec[0].addr = 0; tpd->iovec[0].len = 0; + tpd->iovec[1].addr = 0; tpd->iovec[1].len = 0; + tpd->iovec[2].addr = 0; tpd->iovec[2].len = 0; + + return tpd; +#else + int i; + + for(i = 0; i < CONFIG_NUMTPDS; ++i) + { + ++he_dev->tpd_head; + if (he_dev->tpd_head > he_dev->tpd_end) { + he_dev->tpd_head = he_dev->tpd_base; + } + + if (!he_dev->tpd_head->inuse) { + he_dev->tpd_head->inuse = 1; + he_dev->tpd_head->status &= TPD_MASK; + he_dev->tpd_head->iovec[0].addr = 0; he_dev->tpd_head->iovec[0].len = 0; + he_dev->tpd_head->iovec[1].addr = 0; he_dev->tpd_head->iovec[1].len = 0; + he_dev->tpd_head->iovec[2].addr = 0; he_dev->tpd_head->iovec[2].len = 0; + return he_dev->tpd_head; + } + } + hprintk("out of tpds -- increase CONFIG_NUMTPDS (%d)\n", CONFIG_NUMTPDS); + return NULL; +#endif +} + +#define AAL5_LEN(buf,len) \ + ((((unsigned char *)(buf))[(len)-6]<<8) | \ + (((unsigned char *)(buf))[(len)-5])) + +/* 2.10.1.2 receive + * + * aal5 packets can optionally return the tcp checksum in the lower + * 16 bits of the crc (RSR0_TCP_CKSUM) + */ + +#define TCP_CKSUM(buf,len) \ + ((((unsigned char *)(buf))[(len)-2]<<8) | \ + (((unsigned char *)(buf))[(len-1)])) + +static int +he_service_rbrq(struct he_dev *he_dev, int group) +{ + struct he_rbrq *rbrq_tail = (struct he_rbrq *) + ((unsigned long)he_dev->rbrq_base | + he_dev->hsp->group[group].rbrq_tail); + struct he_rbp *rbp = NULL; + unsigned cid, lastcid = -1; + unsigned buf_len = 0; + struct sk_buff *skb; + struct atm_vcc *vcc = NULL; + struct he_vcc *he_vcc; + struct iovec *iov; + int pdus_assembled = 0; + int updated = 0; + + while (he_dev->rbrq_head != rbrq_tail) + { + ++updated; + + HPRINTK("%p rbrq%d 0x%x len=%d cid=0x%x %s%s%s%s%s%s\n", + he_dev->rbrq_head, group, + RBRQ_ADDR(he_dev->rbrq_head), + RBRQ_BUFLEN(he_dev->rbrq_head), + RBRQ_CID(he_dev->rbrq_head), + RBRQ_CRC_ERR(he_dev->rbrq_head) ? " CRC_ERR" : "", + RBRQ_LEN_ERR(he_dev->rbrq_head) ? " LEN_ERR" : "", + RBRQ_END_PDU(he_dev->rbrq_head) ? " END_PDU" : "", + RBRQ_AAL5_PROT(he_dev->rbrq_head) ? " AAL5_PROT" : "", + RBRQ_CON_CLOSED(he_dev->rbrq_head) ? " CON_CLOSED" : "", + RBRQ_HBUF_ERR(he_dev->rbrq_head) ? " HBUF_ERR" : ""); + +#ifdef USE_RBPS + if (RBRQ_ADDR(he_dev->rbrq_head) & RBP_SMALLBUF) + rbp = &he_dev->rbps_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))]; + else +#endif + rbp = &he_dev->rbpl_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))]; + + buf_len = RBRQ_BUFLEN(he_dev->rbrq_head) * 4; + cid = RBRQ_CID(he_dev->rbrq_head); + +#ifdef USE_HE_FIND_VCC + if (cid != lastcid) + vcc = he_find_vcc(he_dev, cid); + lastcid = cid; +#else + vcc = HE_LOOKUP_VCC(he_dev, cid); +#endif + if (vcc == NULL) + { + hprintk("vcc == NULL (cid 0x%x)\n", cid); + if (!RBRQ_HBUF_ERR(he_dev->rbrq_head)) + rbp->status &= ~RBP_LOANED; + + goto next_rbrq_entry; + } + + he_vcc = HE_VCC(vcc); + if (he_vcc == NULL) + { + hprintk("he_vcc == NULL (cid 0x%x)\n", cid); + if (!RBRQ_HBUF_ERR(he_dev->rbrq_head)) + rbp->status &= ~RBP_LOANED; + goto next_rbrq_entry; + } + + if (RBRQ_HBUF_ERR(he_dev->rbrq_head)) + { + hprintk("HBUF_ERR! (cid 0x%x)\n", cid); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99) + ++vcc->stats->rx_drop; +#else + atomic_inc(&vcc->stats->rx_drop); +#endif + goto return_host_buffers; + } + + he_vcc->iov_tail->iov_base = (void *) RBRQ_ADDR(he_dev->rbrq_head); + he_vcc->iov_tail->iov_len = buf_len; + he_vcc->pdu_len += buf_len; + ++he_vcc->iov_tail; + + if (RBRQ_CON_CLOSED(he_dev->rbrq_head)) + { + lastcid = -1; + HPRINTK("wake_up rx_waitq (cid 0x%x)\n", cid); + wake_up(&he_vcc->rx_waitq); + goto return_host_buffers; + } + +#ifdef notdef + if (he_vcc->iov_tail - he_vcc->iov_head > 32) + { + hprintk("iovec full! cid 0x%x\n", cid); + goto return_host_buffers; + } +#endif + if (!RBRQ_END_PDU(he_dev->rbrq_head)) goto next_rbrq_entry; + + if (RBRQ_LEN_ERR(he_dev->rbrq_head) + || RBRQ_CRC_ERR(he_dev->rbrq_head)) + { + HPRINTK("%s%s (%d.%d)\n", + RBRQ_CRC_ERR(he_dev->rbrq_head) + ? "CRC_ERR " : "", + RBRQ_LEN_ERR(he_dev->rbrq_head) + ? "LEN_ERR" : "", + vcc->vpi, vcc->vci); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99) + ++vcc->stats->rx_err; +#else + atomic_inc(&vcc->stats->rx_err); +#endif + goto return_host_buffers; + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,15) + skb = atm_alloc_charge(vcc, he_vcc->pdu_len + rx_skb_reserve, + GFP_ATOMIC); +#else + if (!atm_charge(vcc, atm_pdu2truesize(he_vcc->pdu_len + rx_skb_reserve))) + skb = NULL; + else + { + skb = alloc_skb(he_vcc->pdu_len + rx_skb_reserve, GFP_ATOMIC); + if (!skb) atm_return(vcc, + atm_pdu2truesize(he_vcc->pdu_len + rx_skb_reserve)); + } +#endif + if (!skb) + { + HPRINTK("charge failed (%d.%d)\n", vcc->vpi, vcc->vci); + goto return_host_buffers; + } + + if (rx_skb_reserve > 0) skb_reserve(skb, rx_skb_reserve); + + do_gettimeofday(&skb->stamp); + + for(iov = he_vcc->iov_head; + iov < he_vcc->iov_tail; ++iov) + { +#ifdef USE_RBPS + if ((u32)iov->iov_base & RBP_SMALLBUF) + memcpy(skb_put(skb, iov->iov_len), + he_dev->rbps_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len); + else +#endif + memcpy(skb_put(skb, iov->iov_len), + he_dev->rbpl_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len); + } + + switch(vcc->qos.aal) + { + case ATM_AAL0: + /* 2.10.1.5 raw cell receive */ + skb->len = ATM_AAL0_SDU; + skb->tail = skb->data + skb->len; + break; + case ATM_AAL5: + /* 2.10.1.2 aal5 receive */ + + skb->len = AAL5_LEN(skb->data, he_vcc->pdu_len); + skb->tail = skb->data + skb->len; +#ifdef USE_CHECKSUM_HW + if (vcc->vpi == 0 && vcc->vci >= ATM_NOT_RSV_VCI) + { + skb->ip_summed = CHECKSUM_HW; + skb->csum = TCP_CKSUM(skb->data, + he_vcc->pdu_len); + } +#endif + break; + } + +#ifdef should_never_happen + if (skb->len > vcc->qos.rxtp.max_sdu) + hprintk("pdu_len (%d) > vcc->qos.rxtp.max_sdu (%d)! cid 0x%x\n", skb->len, vcc->qos.rxtp.max_sdu, cid); +#endif + +#ifdef notdef + ATM_SKB(skb)->vcc = vcc; +#endif + vcc->push(vcc, skb); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99) + ++vcc->stats->rx; +#else + atomic_inc(&vcc->stats->rx); +#endif + +return_host_buffers: + ++pdus_assembled; + + for(iov = he_vcc->iov_head; + iov < he_vcc->iov_tail; ++iov) + { +#ifdef USE_RBPS + if ((u32)iov->iov_base & RBP_SMALLBUF) + rbp = &he_dev->rbps_base[RBP_INDEX(iov->iov_base)]; + else +#endif + rbp = &he_dev->rbpl_base[RBP_INDEX(iov->iov_base)]; + + rbp->status &= ~RBP_LOANED; + } + + he_vcc->iov_tail = he_vcc->iov_head; + he_vcc->pdu_len = 0; + +next_rbrq_entry: + he_dev->rbrq_head = (struct he_rbrq *) + ((unsigned long) he_dev->rbrq_base | + RBRQ_MASK(++he_dev->rbrq_head)); + + } + + if (updated) + { + if (updated > he_dev->rbrq_peak) he_dev->rbrq_peak = updated; + + he_writel(he_dev, RBRQ_MASK(he_dev->rbrq_head), + G0_RBRQ_H + (group * 16)); +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl(he_dev, G0_RBRQ_H + (group * 16)); +#endif + } + + return pdus_assembled; +} + +static void +he_service_tbrq(struct he_dev *he_dev, int group) +{ + struct he_tbrq *tbrq_tail = (struct he_tbrq *) + ((unsigned long)he_dev->tbrq_base | + he_dev->hsp->group[group].tbrq_tail); + struct he_tpd *tpd; + int slot, updated = 0; +#ifdef USE_TPD_POOL + struct list_head *p; +#endif + + /* 2.1.6 transmit buffer return queue */ + + while (he_dev->tbrq_head != tbrq_tail) + { + ++updated; + + HPRINTK("tbrq%d 0x%x%s%s\n", + group, + TBRQ_TPD(he_dev->tbrq_head), + TBRQ_EOS(he_dev->tbrq_head) ? " EOS" : "", + TBRQ_MULTIPLE(he_dev->tbrq_head) ? " MULTIPLE" : ""); +#ifdef USE_TPD_POOL + tpd = NULL; + p = &he_dev->outstanding_tpds; + while ((p = p->next) != &he_dev->outstanding_tpds) + { + struct he_tpd *__tpd = list_entry(p, struct he_tpd, entry); + if (TPD_ADDR(__tpd->status) == TBRQ_TPD(he_dev->tbrq_head)) + { + tpd = __tpd; + list_del(&__tpd->entry); + break; + } + } + + if (tpd == NULL) + { + hprintk("unable to locate tpd for dma buffer %x\n", + TBRQ_TPD(he_dev->tbrq_head)); + goto next_tbrq_entry; + } +#else + tpd = &he_dev->tpd_base[ TPD_INDEX(TBRQ_TPD(he_dev->tbrq_head)) ]; +#endif + + if (TBRQ_EOS(he_dev->tbrq_head)) + { + HPRINTK("wake_up(tx_waitq) cid 0x%x\n", + he_mkcid(he_dev, tpd->vcc->vpi, tpd->vcc->vci)); + if (tpd->vcc) + wake_up(&HE_VCC(tpd->vcc)->tx_waitq); + + goto next_tbrq_entry; + } + + for(slot = 0; slot < TPD_MAXIOV; ++slot) + { + if (tpd->iovec[slot].addr) + pci_unmap_single(he_dev->pci_dev, + tpd->iovec[slot].addr, + tpd->iovec[slot].len & TPD_LEN_MASK, + PCI_DMA_TODEVICE); + if (tpd->iovec[slot].len & TPD_LST) break; + + } + + if (tpd->skb) /* && !TBRQ_MULTIPLE(he_dev->tbrq_head) */ + { + if (tpd->vcc && tpd->vcc->pop) + tpd->vcc->pop(tpd->vcc, tpd->skb); + else + dev_kfree_skb_any(tpd->skb); + } + +next_tbrq_entry: +#ifdef USE_TPD_POOL + if (tpd) pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status)); +#else + tpd->inuse = 0; +#endif + he_dev->tbrq_head = (struct he_tbrq *) + ((unsigned long) he_dev->tbrq_base | + TBRQ_MASK(++he_dev->tbrq_head)); + } + + if (updated) + { + if (updated > he_dev->tbrq_peak) he_dev->tbrq_peak = updated; + + he_writel(he_dev, TBRQ_MASK(he_dev->tbrq_head), + G0_TBRQ_H + (group * 16)); +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl(he_dev, G0_TBRQ_H + (group * 16)); +#endif + } +} + + +static void +he_service_rbpl(struct he_dev *he_dev, int group) +{ + struct he_rbp *newtail; + struct he_rbp *rbpl_head; + int moved = 0; + + rbpl_head = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base | + RBPL_MASK(he_readl(he_dev, G0_RBPL_S))); + + for(;;) + { + newtail = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base | + RBPL_MASK(he_dev->rbpl_tail+1)); + + /* table 3.42 -- rbpl_tail should never be set to rbpl_head */ + if ((newtail == rbpl_head) || (newtail->status & RBP_LOANED)) + break; + + newtail->status |= RBP_LOANED; + he_dev->rbpl_tail = newtail; + ++moved; + + } + + if (moved) { + he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail), G0_RBPL_T); +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl(he_dev, G0_RBPL_T); +#endif + } +} + +#ifdef USE_RBPS +static void +he_service_rbps(struct he_dev *he_dev, int group) +{ + struct he_rbp *newtail; + struct he_rbp *rbps_head; + int moved = 0; + + rbps_head = (struct he_rbp *) ((unsigned long)he_dev->rbps_base | + RBPS_MASK(he_readl(he_dev, G0_RBPS_S))); + + for(;;) + { + newtail = (struct he_rbp *) ((unsigned long)he_dev->rbps_base | + RBPS_MASK(he_dev->rbps_tail+1)); + + /* table 3.42 -- rbps_tail should never be set to rbps_head */ + if ((newtail == rbps_head) || (newtail->status & RBP_LOANED)) + break; + + newtail->status |= RBP_LOANED; + he_dev->rbps_tail = newtail; + ++moved; + + } + + if (moved) { + he_writel(he_dev, RBPS_MASK(he_dev->rbps_tail), G0_RBPS_T); +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl(he_dev, G0_RBPS_T); +#endif + } +} +#endif /* USE_RBPS */ + +static void +he_tasklet(unsigned long data) +{ + unsigned long flags; + struct he_dev *he_dev = (struct he_dev *) data; + int group, type; + int updated = 0; + + HPRINTK("tasklet (0x%lx)\n", data); +#ifdef USE_TASKLET + HE_SPIN_LOCK(he_dev, flags); +#endif + + while(he_dev->irq_head != he_dev->irq_tail) + { + ++updated; + + type = ITYPE_TYPE(he_dev->irq_head->isw); + group = ITYPE_GROUP(he_dev->irq_head->isw); + + switch (type) + { + case ITYPE_RBRQ_THRESH: + hprintk("rbrq%d threshold\n", group); + case ITYPE_RBRQ_TIMER: + if (he_service_rbrq(he_dev, group)) + { + he_service_rbpl(he_dev, group); +#ifdef USE_RBPS + he_service_rbps(he_dev, group); +#endif /* USE_RBPS */ + } + break; + case ITYPE_TBRQ_THRESH: + hprintk("tbrq%d threshold\n", group); + case ITYPE_TPD_COMPLETE: + he_service_tbrq(he_dev, group); + break; + case ITYPE_RBPL_THRESH: + he_service_rbpl(he_dev, group); + break; + case ITYPE_RBPS_THRESH: +#ifdef USE_RBPS + he_service_rbps(he_dev, group); +#endif /* USE_RBPS */ + break; + case ITYPE_PHY: +#ifdef CONFIG_ATM_HE_USE_SUNI + HE_SPIN_UNLOCK(he_dev, flags); + if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->interrupt) + he_dev->atm_dev->phy->interrupt(he_dev->atm_dev); + HE_SPIN_LOCK(he_dev, flags); +#endif + HPRINTK1("phy interrupt\n"); + break; + case ITYPE_OTHER: + switch (type|group) + { + case ITYPE_PARITY: + hprintk1("parity error\n"); + break; + case ITYPE_ABORT: + hprintk("abort 0x%x\n", he_readl(he_dev, ABORT_ADDR)); + break; + } + break; + default: + if (he_dev->irq_head->isw == ITYPE_INVALID) + { + /* see 8.1.1 -- check all queues */ + + HPRINTK("isw not updated 0x%x\n", + he_dev->irq_head->isw); + + he_service_rbrq(he_dev, 0); + he_service_rbpl(he_dev, 0); +#ifdef USE_RBPS + he_service_rbps(he_dev, 0); +#endif /* USE_RBPS */ + he_service_tbrq(he_dev, 0); + } + else + hprintk("bad isw = 0x%x?\n", + he_dev->irq_head->isw); + } + + he_dev->irq_head->isw = ITYPE_INVALID; + + he_dev->irq_head = (struct he_irq *) NEXT_ENTRY(he_dev->irq_base, he_dev->irq_head, IRQ_MASK); + } + + if (updated) + { + if (updated > he_dev->irq_peak) he_dev->irq_peak = updated; + + he_writel(he_dev, + IRQ_SIZE(CONFIG_IRQ_SIZE) | + IRQ_THRESH(CONFIG_IRQ_THRESH) | + IRQ_TAIL(he_dev->irq_tail), IRQ0_HEAD); + (void) he_readl(he_dev, INT_FIFO); /* 8.1.2 controller errata */ + } +#ifdef USE_TASKLET + HE_SPIN_UNLOCK(he_dev, flags); +#endif +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,69) +static irqreturn_t +#else +static void +#endif +he_irq_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long flags; + struct he_dev *he_dev = (struct he_dev * )dev_id; + int handled = 0; + + if (he_dev == NULL) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,69) + return IRQ_NONE; +#else + return; +#endif + + HE_SPIN_LOCK(he_dev, flags); + + he_dev->irq_tail = (struct he_irq *) (((unsigned long)he_dev->irq_base) | + (*he_dev->irq_tailoffset << 2)); + + if (he_dev->irq_tail == he_dev->irq_head) + { + HPRINTK1("tailoffset not updated?\n"); + he_dev->irq_tail = (struct he_irq *) ((unsigned long)he_dev->irq_base | + ((he_readl(he_dev, IRQ0_BASE) & IRQ_MASK) << 2)); + (void) he_readl(he_dev, INT_FIFO); /* 8.1.2 controller errata */ + } + +#ifdef DEBUG + if (he_dev->irq_head == he_dev->irq_tail /* && !IRQ_PENDING */) + hprintk1("spurious (or shared) interrupt?\n"); +#endif + + if (he_dev->irq_head != he_dev->irq_tail) + { + handled = 1; +#ifdef USE_TASKLET + tasklet_schedule(&he_dev->tasklet); +#else + he_tasklet((unsigned long) he_dev); +#endif + he_writel(he_dev, INT_CLEAR_A, INT_FIFO); + /* clear interrupt */ +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl(he_dev, INT_FIFO); +#endif + } + HE_SPIN_UNLOCK(he_dev, flags); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,69) + return IRQ_RETVAL(handled); +#else + return; +#endif + +} + +static __inline__ void +__enqueue_tpd(struct he_dev *he_dev, struct he_tpd *tpd, unsigned cid) +{ + struct he_tpdrq *new_tail; + + HPRINTK("tpdrq %p cid 0x%x -> tpdrq_tail %p\n", + tpd, cid, he_dev->tpdrq_tail); + + /* new_tail = he_dev->tpdrq_tail; */ + new_tail = (struct he_tpdrq *) ((unsigned long) he_dev->tpdrq_base | + TPDRQ_MASK(he_dev->tpdrq_tail+1)); + + /* + * check to see if we are about to set the tail == head + * if true, update the head pointer from the adapter + * to see if this is really the case (reading the queue + * head for every enqueue would be unnecessarily slow) + */ + + if (new_tail == he_dev->tpdrq_head) + { + he_dev->tpdrq_head = (struct he_tpdrq *) + (((unsigned long)he_dev->tpdrq_base) | + TPDRQ_MASK(he_readl(he_dev, TPDRQ_B_H))); + + if (new_tail == he_dev->tpdrq_head) + { + hprintk("tpdrq full (cid 0x%x)\n", cid); + /* + * FIXME + * push tpd onto a transmit backlog queue + * after service_tbrq, service the backlog + * for now, we just drop the pdu + */ + if (tpd->skb) + { + if (tpd->vcc->pop) + tpd->vcc->pop(tpd->vcc, tpd->skb); + else + dev_kfree_skb_any(tpd->skb); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99) + ++tpd->vcc->stats->tx_err; +#else + atomic_inc(&tpd->vcc->stats->tx_err); +#endif + } +#ifdef USE_TPD_POOL + pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status)); +#else + tpd->inuse = 0; +#endif + return; + } + } + + /* 2.1.5 transmit packet descriptor ready queue */ +#ifdef USE_TPD_POOL + list_add_tail(&tpd->entry, &he_dev->outstanding_tpds); + he_dev->tpdrq_tail->tpd = TPD_ADDR(tpd->status); +#else + he_dev->tpdrq_tail->tpd = he_dev->tpd_base_phys + + (TPD_INDEX(tpd->status) * sizeof(struct he_tpd)); +#endif + he_dev->tpdrq_tail->cid = cid; + wmb(); + + he_dev->tpdrq_tail = new_tail; + + he_writel(he_dev, TPDRQ_MASK(he_dev->tpdrq_tail), TPDRQ_T); +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl(he_dev, TPDRQ_T); +#endif +} + +static int +he_open(struct atm_vcc *vcc, short vpi, int vci) +{ + unsigned long flags; + struct he_dev *he_dev = HE_DEV(vcc->dev); + struct he_vcc *he_vcc; + int err = 0; + unsigned cid, rsr0, rsr1, rsr4, tsr0, tsr0_aal, tsr4, period, reg, clock; + + + if ((err = atm_find_ci(vcc, &vpi, &vci))) + { + HPRINTK("atm_find_ci err = %d\n", err); + return err; + } + if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC) return 0; + vcc->vpi = vpi; + vcc->vci = vci; + + HPRINTK("open vcc %p %d.%d\n", vcc, vpi, vci); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1) + vcc->flags |= ATM_VF_ADDR; +#else + set_bit(ATM_VF_ADDR, &vcc->flags); +#endif + + cid = he_mkcid(he_dev, vpi, vci); + + he_vcc = (struct he_vcc *) kmalloc(sizeof(struct he_vcc), GFP_ATOMIC); + if (he_vcc == NULL) + { + hprintk1("unable to allocate he_vcc during open\n"); + return -ENOMEM; + } + + he_vcc->iov_tail = he_vcc->iov_head; + he_vcc->pdu_len = 0; + he_vcc->rc_index = -1; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1) + init_waitqueue(&he_vcc->rx_waitq); + init_waitqueue(&he_vcc->tx_waitq); +#else + init_waitqueue_head(&he_vcc->rx_waitq); + init_waitqueue_head(&he_vcc->tx_waitq); +#endif + + HE_VCC(vcc) = he_vcc; + + if (vcc->qos.txtp.traffic_class != ATM_NONE) + { + int pcr_goal; + + pcr_goal = atm_pcr_goal(&vcc->qos.txtp); + if (pcr_goal == 0) + pcr_goal = he_dev->atm_dev->link_rate; + if (pcr_goal < 0) /* means round down, technically */ + pcr_goal = -pcr_goal; + + HPRINTK("open tx cid 0x%x pcr_goal %d\n", cid, pcr_goal); + + switch (vcc->qos.aal) + { + case ATM_AAL5: + tsr0_aal = TSR0_AAL5; + tsr4 = TSR4_AAL5; + break; + case ATM_AAL0: + tsr0_aal = TSR0_AAL0_SDU; + tsr4 = TSR4_AAL0_SDU; + break; + default: + err = -EINVAL; + goto open_failed; + } + + HE_SPIN_LOCK(he_dev, flags); + tsr0 = he_readl_tsr0(he_dev, cid); + HE_SPIN_UNLOCK(he_dev, flags); + + if (TSR0_CONN_STATE(tsr0) != 0) + { + hprintk("cid 0x%x not idle (tsr0 = 0x%x)\n", cid, tsr0); + err = -EBUSY; + goto open_failed; + } + + switch(vcc->qos.txtp.traffic_class) + { + case ATM_UBR: + /* 2.3.3.1 open connection ubr */ + + tsr0 = TSR0_UBR | TSR0_GROUP(0) | tsr0_aal | + TSR0_USE_WMIN | TSR0_UPDATE_GER; + break; + + case ATM_CBR: + /* 2.3.3.2 open connection cbr */ + + /* 8.2.3 cbr scheduler wrap problem -- limit to 90% total link rate */ + if ((he_dev->total_bw + pcr_goal) + > (he_dev->atm_dev->link_rate * 9 / 10)) + { + err = -EBUSY; + goto open_failed; + } + + HE_SPIN_LOCK(he_dev, flags); /* also protects he_dev->cs_stper[] */ + + /* find an unused cs_stper register */ + for(reg = 0; reg < HE_NUM_CS_STPER; ++reg) + if (he_dev->cs_stper[reg].inuse == 0 || + he_dev->cs_stper[reg].pcr == pcr_goal) + break; + + if (reg == HE_NUM_CS_STPER) + { + err = -EBUSY; + HE_SPIN_UNLOCK(he_dev, flags); + goto open_failed; + } + + he_dev->total_bw += pcr_goal; + + he_vcc->rc_index = reg; + ++he_dev->cs_stper[reg].inuse; + he_dev->cs_stper[reg].pcr = pcr_goal; + + clock = he_is622(he_dev) ? 66667000 : 50000000; + period = clock / pcr_goal; + + HPRINTK("rc_index = %d period = %d\n", + reg, period); + + he_writel_mbox(he_dev, rate_to_atmf(period/2), + CS_STPER0 + reg); + HE_SPIN_UNLOCK(he_dev, flags); + + tsr0 = TSR0_CBR | TSR0_GROUP(0) | tsr0_aal | + TSR0_RC_INDEX(reg); + + break; + default: + err = -EINVAL; + goto open_failed; + } + + HE_SPIN_LOCK(he_dev, flags); + + he_writel_tsr0(he_dev, tsr0, cid); + he_writel_tsr4(he_dev, tsr4 | 1, cid); + he_writel_tsr1(he_dev, TSR1_MCR(rate_to_atmf(0)) | + TSR1_PCR(rate_to_atmf(pcr_goal)), cid); + he_writel_tsr2(he_dev, TSR2_ACR(rate_to_atmf(pcr_goal)), cid); + he_writel_tsr9(he_dev, TSR9_OPEN_CONN, cid); + + he_writel_tsr3(he_dev, 0x0, cid); + he_writel_tsr5(he_dev, 0x0, cid); + he_writel_tsr6(he_dev, 0x0, cid); + he_writel_tsr7(he_dev, 0x0, cid); + he_writel_tsr8(he_dev, 0x0, cid); + he_writel_tsr10(he_dev, 0x0, cid); + he_writel_tsr11(he_dev, 0x0, cid); + he_writel_tsr12(he_dev, 0x0, cid); + he_writel_tsr13(he_dev, 0x0, cid); + he_writel_tsr14(he_dev, 0x0, cid); +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl_tsr0(he_dev, cid); +#endif + HE_SPIN_UNLOCK(he_dev, flags); + } + + if (vcc->qos.rxtp.traffic_class != ATM_NONE) + { + unsigned aal; + + HPRINTK("open rx cid 0x%x (rx_waitq %p)\n", cid, + &HE_VCC(vcc)->rx_waitq); + + switch (vcc->qos.aal) + { + case ATM_AAL5: + aal = RSR0_AAL5; + break; + case ATM_AAL0: + aal = RSR0_RAWCELL; + break; + default: + err = -EINVAL; + goto open_failed; + } + + HE_SPIN_LOCK(he_dev, flags); + + rsr0 = he_readl_rsr0(he_dev, cid); + if (rsr0 & RSR0_OPEN_CONN) + { + HE_SPIN_UNLOCK(he_dev, flags); + + hprintk("cid 0x%x not idle (rsr0 = 0x%x)\n", cid, rsr0); + err = -EBUSY; + goto open_failed; + } + +#ifdef USE_RBPS + rsr1 = RSR1_GROUP(0); + rsr4 = RSR4_GROUP(0); +#else /* !USE_RBPS */ + rsr1 = RSR1_GROUP(0)|RSR1_RBPL_ONLY; + rsr4 = RSR4_GROUP(0)|RSR4_RBPL_ONLY; +#endif /* USE_RBPS */ + rsr0 = vcc->qos.rxtp.traffic_class == ATM_UBR ? + (RSR0_EPD_ENABLE|RSR0_PPD_ENABLE) : 0; + +#ifdef USE_CHECKSUM_HW + if (vpi == 0 && vci >= ATM_NOT_RSV_VCI) rsr0 |= RSR0_TCP_CKSUM; +#endif + + he_writel_rsr4(he_dev, rsr4, cid); + he_writel_rsr1(he_dev, rsr1, cid); + /* 5.1.11 last parameter initialized should be + the open/closed indication in rsr0 */ + he_writel_rsr0(he_dev, + rsr0 | RSR0_START_PDU | RSR0_OPEN_CONN | aal, cid); +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl_rsr0(he_dev, cid); +#endif + + HE_SPIN_UNLOCK(he_dev, flags); + +#ifndef USE_HE_FIND_VCC + HE_LOOKUP_VCC(he_dev, cid) = vcc; +#endif + } + +open_failed: + + if (err) + { + if (he_vcc) kfree(he_vcc); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1) + vcc->flags &= ~ATM_VF_ADDR; +#else + clear_bit(ATM_VF_ADDR, &vcc->flags); +#endif + } + else + { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1) + vcc->flags |= ATM_VF_READY; +#else + set_bit(ATM_VF_READY, &vcc->flags); +#endif + } + + return err; +} + +static void +he_close(struct atm_vcc *vcc) +{ + unsigned long flags; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,1) + DECLARE_WAITQUEUE(wait, current); +#else + struct wait_queue wait = { current, NULL }; +#endif + struct he_dev *he_dev = HE_DEV(vcc->dev); + struct he_tpd *tpd; + unsigned cid; + struct he_vcc *he_vcc = HE_VCC(vcc); +#define MAX_RETRY 30 + int retry = 0, sleep = 1, tx_inuse; + + HPRINTK("close vcc %p %d.%d\n", vcc, vcc->vpi, vcc->vci); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1) + vcc->flags &= ~ATM_VF_READY; +#else + clear_bit(ATM_VF_READY, &vcc->flags); +#endif + cid = he_mkcid(he_dev, vcc->vpi, vcc->vci); + + if (vcc->qos.rxtp.traffic_class != ATM_NONE) + { + int timeout; + + HPRINTK("close rx cid 0x%x\n", cid); + + /* 2.7.2.2 close receive operation */ + + /* wait for previous close (if any) to finish */ + + HE_SPIN_LOCK(he_dev, flags); + while(he_readl(he_dev, RCC_STAT) & RCC_BUSY) + { + HPRINTK("close cid 0x%x RCC_BUSY\n", cid); + udelay(250); + } + + add_wait_queue(&he_vcc->rx_waitq, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); + + he_writel_rsr0(he_dev, RSR0_CLOSE_CONN, cid); +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl_rsr0(he_dev, cid); +#endif + he_writel_mbox(he_dev, cid, RXCON_CLOSE); + HE_SPIN_UNLOCK(he_dev, flags); + + timeout = schedule_timeout(30*HZ); + + remove_wait_queue(&he_vcc->rx_waitq, &wait); + set_current_state(TASK_RUNNING); + + if (timeout == 0) + hprintk("close rx timeout cid 0x%x\n", cid); + +#ifndef USE_HE_FIND_VCC + HE_LOOKUP_VCC(he_dev, cid) = NULL; +#endif + HPRINTK("close rx cid 0x%x complete\n", cid); + + } + + if (vcc->qos.txtp.traffic_class != ATM_NONE) + { + volatile unsigned tsr4, tsr0; + int timeout; + + HPRINTK("close tx cid 0x%x\n", cid); + + /* 2.1.2 + * + * ... the host must first stop queueing packets to the TPDRQ + * on the connection to be closed, then wait for all outstanding + * packets to be transmitted and their buffers returned to the + * TBRQ. When the last packet on the connection arrives in the + * TBRQ, the host issues the close command to the adapter. + */ + + while (((tx_inuse = atomic_read(&vcc->sk->wmem_alloc)) > 0) + && (retry < MAX_RETRY)) + { + set_current_state(TASK_UNINTERRUPTIBLE); + (void) schedule_timeout(sleep); + set_current_state(TASK_RUNNING); + if (sleep < HZ) sleep = sleep * 2; + + ++retry; + } + + if (tx_inuse) hprintk("close tx cid 0x%x tx_inuse = %d\n", + cid, tx_inuse); + + /* 2.3.1.1 generic close operations with flush */ + + HE_SPIN_LOCK(he_dev, flags); + he_writel_tsr4_upper(he_dev, TSR4_FLUSH_CONN, cid); + /* also clears TSR4_SESSION_ENDED */ +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl_tsr4(he_dev, cid); +#endif + + switch(vcc->qos.txtp.traffic_class) + { + case ATM_UBR: + he_writel_tsr1(he_dev, + TSR1_MCR(rate_to_atmf(200000)) + | TSR1_PCR(0), cid); + break; + case ATM_CBR: + he_writel_tsr14_upper(he_dev, TSR14_DELETE, cid); + break; + } + + + tpd = __alloc_tpd(he_dev); + if (tpd == NULL) + { + hprintk("close tx he_alloc_tpd failed cid 0x%x\n", cid); + goto close_tx_incomplete; + } + tpd->status |= TPD_EOS | TPD_INT; + tpd->skb = NULL; + tpd->vcc = vcc; + wmb(); + + add_wait_queue(&he_vcc->tx_waitq, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); + __enqueue_tpd(he_dev, tpd, cid); + HE_SPIN_UNLOCK(he_dev, flags); + + timeout = schedule_timeout(30*HZ); + + remove_wait_queue(&he_vcc->tx_waitq, &wait); + set_current_state(TASK_RUNNING); + + if (timeout == 0) + { + hprintk("close tx timeout cid 0x%x\n", cid); + goto close_tx_incomplete; + } + + HE_SPIN_LOCK(he_dev, flags); + while (!((tsr4 = he_readl_tsr4(he_dev, cid)) + & TSR4_SESSION_ENDED)) + { + HPRINTK("close tx cid 0x%x !TSR4_SESSION_ENDED (tsr4 = 0x%x)\n", cid, tsr4); + udelay(250); + } + + while (TSR0_CONN_STATE(tsr0 = he_readl_tsr0(he_dev, cid)) != 0) + { + HPRINTK("close tx cid 0x%x TSR0_CONN_STATE != 0 (tsr0 = 0x%x)\n", cid, tsr0); + udelay(250); + } + +close_tx_incomplete: + + if (vcc->qos.txtp.traffic_class == ATM_CBR) + { + int reg = he_vcc->rc_index; + + HPRINTK("cs_stper reg = %d\n", reg); + + if (he_dev->cs_stper[reg].inuse == 0) + hprintk("cs_stper[%d].inuse = 0!\n", reg); + else + --he_dev->cs_stper[reg].inuse; + + he_dev->total_bw -= he_dev->cs_stper[reg].pcr; + } + HE_SPIN_UNLOCK(he_dev, flags); + + HPRINTK("close tx cid 0x%x complete\n", cid); + } + + kfree(he_vcc); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1) + vcc->flags &= ~ATM_VF_ADDR; +#else + clear_bit(ATM_VF_ADDR, &vcc->flags); +#endif +} + +static int +he_sg_send(struct atm_vcc *vcc, unsigned long start, unsigned long size) +{ +#ifdef USE_SCATTERGATHER + return 1; +#else + return 0; +#endif +} + +static int +he_send(struct atm_vcc *vcc, struct sk_buff *skb) +{ + unsigned long flags; + struct he_dev *he_dev = HE_DEV(vcc->dev); + unsigned cid = he_mkcid(he_dev, vcc->vpi, vcc->vci); + struct he_tpd *tpd; +#ifdef USE_SCATTERGATHER + int i, slot = 0; +#endif + +#define HE_TPD_BUFSIZE 0xffff + + HPRINTK("send %d.%d\n", vcc->vpi, vcc->vci); + + if ((skb->len > HE_TPD_BUFSIZE) || + ((vcc->qos.aal == ATM_AAL0) && (skb->len != ATM_AAL0_SDU))) + { + hprintk("buffer too large (or small) -- %d bytes\n", skb->len ); + if (vcc->pop) + vcc->pop(vcc, skb); + else + dev_kfree_skb_any(skb); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99) + ++vcc->stats->tx_err; +#else + atomic_inc(&vcc->stats->tx_err); +#endif + return -EINVAL; + } + +#ifndef USE_SCATTERGATHER + if (skb_shinfo(skb)->nr_frags) + { + hprintk1("no scatter/gather support\n"); + if (vcc->pop) + vcc->pop(vcc, skb); + else + dev_kfree_skb_any(skb); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99) + ++vcc->stats->tx_err; +#else + atomic_inc(&vcc->stats->tx_err); +#endif + return -EINVAL; + } +#endif + HE_SPIN_LOCK(he_dev, flags); + + tpd = __alloc_tpd(he_dev); + if (tpd == NULL) + { + if (vcc->pop) + vcc->pop(vcc, skb); + else + dev_kfree_skb_any(skb); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99) + ++vcc->stats->tx_err; +#else + atomic_inc(&vcc->stats->tx_err); +#endif + HE_SPIN_UNLOCK(he_dev, flags); + return -ENOMEM; + } + + if (vcc->qos.aal == ATM_AAL5) + tpd->status |= TPD_CELLTYPE(TPD_USERCELL); + else + { + char *pti_clp = (void *) (skb->data + 3); + int clp, pti; + + pti = (*pti_clp & ATM_HDR_PTI_MASK) >> ATM_HDR_PTI_SHIFT; + clp = (*pti_clp & ATM_HDR_CLP); + tpd->status |= TPD_CELLTYPE(pti); + if (clp) tpd->status |= TPD_CLP; + + skb_pull(skb, ATM_AAL0_SDU - ATM_CELL_PAYLOAD); + } + +#ifdef USE_SCATTERGATHER + tpd->iovec[slot].addr = pci_map_single(he_dev->pci_dev, skb->data, + skb->len - skb->data_len, PCI_DMA_TODEVICE); + tpd->iovec[slot].len = skb->len - skb->data_len; + ++slot; + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) + { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + if (slot == TPD_MAXIOV) /* send tpd; start new tpd */ + { + tpd->vcc = vcc; + tpd->skb = NULL; /* not the last fragment + so dont ->push() yet */ + wmb(); + + __enqueue_tpd(he_dev, tpd, cid); + tpd = __alloc_tpd(he_dev); + if (tpd == NULL) + { + if (vcc->pop) + vcc->pop(vcc, skb); + else + dev_kfree_skb_any(skb); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99) + ++vcc->stats->tx_err; +#else + atomic_inc(&vcc->stats->tx_err); + HE_SPIN_UNLOCK(he_dev, flags); +#endif + return -ENOMEM; + } + tpd->status |= TPD_USERCELL; + slot = 0; + } + + tpd->iovec[slot].addr = pci_map_single(he_dev->pci_dev, + (void *) page_address(frag->page) + frag->page_offset, + frag->size, PCI_DMA_TODEVICE); + tpd->iovec[slot].len = frag->size; + ++slot; + + } + + tpd->iovec[slot-1].len |= TPD_LST; +#else + tpd->address0 = pci_map_single(he_dev->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE); + tpd->length0 = skb->len | TPD_LST; +#endif + tpd->status |= TPD_INT; + + tpd->vcc = vcc; + tpd->skb = skb; + wmb(); + ATM_SKB(skb)->vcc = vcc; + + __enqueue_tpd(he_dev, tpd, cid); + HE_SPIN_UNLOCK(he_dev, flags); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,99) + ++vcc->stats->tx; +#else + atomic_inc(&vcc->stats->tx); +#endif + + return 0; +} + +static int +he_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void *arg) +{ + unsigned long flags; + struct he_dev *he_dev = HE_DEV(atm_dev); + struct he_ioctl_reg reg; + int err = 0; + + switch (cmd) + { + case HE_GET_REG: + if (!capable(CAP_NET_ADMIN)) return -EPERM; + + copy_from_user(®, (struct he_ioctl_reg *) arg, + sizeof(struct he_ioctl_reg)); + HE_SPIN_LOCK(he_dev, flags); + switch (reg.type) + { + case HE_REGTYPE_PCI: + reg.val = he_readl(he_dev, reg.addr); + break; + case HE_REGTYPE_RCM: + reg.val = + he_readl_rcm(he_dev, reg.addr); + break; + case HE_REGTYPE_TCM: + reg.val = + he_readl_tcm(he_dev, reg.addr); + break; + case HE_REGTYPE_MBOX: + reg.val = + he_readl_mbox(he_dev, reg.addr); + break; + default: + err = -EINVAL; + break; + } + HE_SPIN_UNLOCK(he_dev, flags); + if (err == 0) copy_to_user((struct he_ioctl_reg *) arg, ®, + sizeof(struct he_ioctl_reg)); + break; + default: +#ifdef CONFIG_ATM_HE_USE_SUNI + if (atm_dev->phy && atm_dev->phy->ioctl) + err = atm_dev->phy->ioctl(atm_dev, cmd, arg); +#else /* CONFIG_ATM_HE_USE_SUNI */ + return -EINVAL; +#endif /* CONFIG_ATM_HE_USE_SUNI */ + break; + } + + return err; +} + +static void +he_phy_put(struct atm_dev *atm_dev, unsigned char val, unsigned long addr) +{ + unsigned long flags; + struct he_dev *he_dev = HE_DEV(atm_dev); + + HPRINTK("phy_put(val 0x%x, addr 0x%lx)\n", val, addr); + + HE_SPIN_LOCK(he_dev, flags); + he_writel(he_dev, val, FRAMER + (addr*4)); +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl(he_dev, FRAMER + (addr*4)); +#endif + HE_SPIN_UNLOCK(he_dev, flags); +} + + +static unsigned char +he_phy_get(struct atm_dev *atm_dev, unsigned long addr) +{ + unsigned long flags; + struct he_dev *he_dev = HE_DEV(atm_dev); + unsigned reg; + + HE_SPIN_LOCK(he_dev, flags); + reg = he_readl(he_dev, FRAMER + (addr*4)); + HE_SPIN_UNLOCK(he_dev, flags); + + HPRINTK("phy_get(addr 0x%lx) =0x%x\n", addr, reg); + return reg; +} + +static int +he_proc_read(struct atm_dev *dev, loff_t *pos, char *page) +{ + unsigned long flags; + struct he_dev *he_dev = HE_DEV(dev); + int left, i; +#ifdef notdef + struct he_rbrq *rbrq_tail; + struct he_tpdrq *tpdrq_head; + int rbpl_head, rbpl_tail; +#endif + static long mcc = 0, oec = 0, dcc = 0, cec = 0; + + + left = *pos; + if (!left--) + return sprintf(page, "%s\n", version); + + if (!left--) + return sprintf(page, "%s%s\n\n", + he_dev->prod_id, he_dev->media & 0x40 ? "SM" : "MM"); + + if (!left--) + return sprintf(page, "Mismatched Cells VPI/VCI Not Open Dropped Cells RCM Dropped Cells\n"); + + HE_SPIN_LOCK(he_dev, flags); + mcc += he_readl(he_dev, MCC); + oec += he_readl(he_dev, OEC); + dcc += he_readl(he_dev, DCC); + cec += he_readl(he_dev, CEC); + HE_SPIN_UNLOCK(he_dev, flags); + + if (!left--) + return sprintf(page, "%16ld %16ld %13ld %17ld\n\n", + mcc, oec, dcc, cec); + + if (!left--) + return sprintf(page, "irq_size = %d inuse = ? peak = %d\n", + CONFIG_IRQ_SIZE, he_dev->irq_peak); + + if (!left--) + return sprintf(page, "tpdrq_size = %d inuse = ?\n", + CONFIG_TPDRQ_SIZE); + + if (!left--) + return sprintf(page, "rbrq_size = %d inuse = ? peak = %d\n", + CONFIG_RBRQ_SIZE, he_dev->rbrq_peak); + + if (!left--) + return sprintf(page, "tbrq_size = %d peak = %d\n", + CONFIG_TBRQ_SIZE, he_dev->tbrq_peak); + + +#ifdef notdef + rbpl_head = RBPL_MASK(he_readl(he_dev, G0_RBPL_S)); + rbpl_tail = RBPL_MASK(he_readl(he_dev, G0_RBPL_T)); + + inuse = rbpl_head - rbpl_tail; + if (inuse < 0) inuse += CONFIG_RBPL_SIZE * sizeof(struct he_rbp); + inuse /= sizeof(struct he_rbp); + + if (!left--) + return sprintf(page, "rbpl_size = %d inuse = %d\n\n", + CONFIG_RBPL_SIZE, inuse); +#endif + + if (!left--) + return sprintf(page, "rate controller periods (cbr)\n pcr #vc\n"); + + for (i = 0; i < HE_NUM_CS_STPER; ++i) + if (!left--) + return sprintf(page, "cs_stper%-2d %8ld %3d\n", i, + he_dev->cs_stper[i].pcr, + he_dev->cs_stper[i].inuse); + + if (!left--) + return sprintf(page, "total bw (cbr): %d (limit %d)\n", + he_dev->total_bw, he_dev->atm_dev->link_rate * 10 / 9); + + return 0; +} + +/* eeprom routines -- see 4.7 */ + +u8 +read_prom_byte(struct he_dev *he_dev, int addr) +{ + u32 val = 0, tmp_read = 0; + int i, j = 0; + u8 byte_read = 0; + + val = readl(he_dev->membase + HOST_CNTL); + val &= 0xFFFFE0FF; + + /* Turn on write enable */ + val |= 0x800; + he_writel(he_dev, val, HOST_CNTL); + + /* Send READ instruction */ + for (i=0; i=0; i--) { + he_writel(he_dev, val | clocktab[j++] | (((addr >> i) & 1) << 9), HOST_CNTL); + udelay(EEPROM_DELAY); + he_writel(he_dev, val | clocktab[j++] | (((addr >> i) & 1) << 9), HOST_CNTL); + udelay(EEPROM_DELAY); + } + + j=0; + + val &= 0xFFFFF7FF; /* Turn off write enable */ + he_writel(he_dev, val, HOST_CNTL); + + /* Now, we can read data from the EEPROM by clocking it in */ + for (i=7; i>=0; i--) { + he_writel(he_dev, val | clocktab[j++], HOST_CNTL); + udelay(EEPROM_DELAY); + tmp_read = he_readl(he_dev, HOST_CNTL); + byte_read |= (unsigned char) + ((tmp_read & ID_DOUT) + >> ID_DOFFSET << i); + he_writel(he_dev, val | clocktab[j++], HOST_CNTL); + udelay(EEPROM_DELAY); + } + + he_writel(he_dev, val | ID_CS, HOST_CNTL); + udelay(EEPROM_DELAY); + + return (byte_read); +} + +MODULE_AUTHOR("chas williams "); +MODULE_DESCRIPTION("ForeRunnerHE ATM Adapter driver"); +MODULE_PARM(disable64, "h"); +MODULE_PARM_DESC(disable64, "disable 64-bit pci bus transfers"); +MODULE_PARM(nvpibits, "i"); +MODULE_PARM_DESC(nvpibits, "numbers of bits for vpi (default 0)"); +MODULE_PARM(nvcibits, "i"); +MODULE_PARM_DESC(nvcibits, "numbers of bits for vci (default 12)"); +MODULE_PARM(rx_skb_reserve, "i"); +MODULE_PARM_DESC(rx_skb_reserve, "padding for receive skb (default 16)"); +MODULE_PARM(irq_coalesce, "i"); +MODULE_PARM_DESC(irq_coalesce, "use interrupt coalescing (default 1)"); +MODULE_PARM(sdh, "i"); +MODULE_PARM_DESC(sdh, "use SDH framing (default 0)"); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,1) +static struct pci_device_id he_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_HE, PCI_ANY_ID, PCI_ANY_ID, + 0, 0, 0 }, + { 0, } +}; + +static struct pci_driver he_driver = { + .name = "he", + .probe = he_init_one, +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,9) + .remove = __devexit_p(he_remove_one), +#else + .remove = he_remove_one, +#endif + .id_table = he_pci_tbl, +}; + +static int __init he_init(void) +{ + return pci_module_init(&he_driver); +} + +static void __exit he_cleanup(void) +{ + pci_unregister_driver(&he_driver); +} + +module_init(he_init); +module_exit(he_cleanup); +#else +static int __init +he_init() +{ + if (!pci_present()) + return -EIO; + +#ifdef CONFIG_ATM_HE_USE_SUNI_MODULE + /* request_module("suni"); */ +#endif + + pci_dev = NULL; + while ((pci_dev = pci_find_device(PCI_VENDOR_ID_FORE, + PCI_DEVICE_ID_FORE_HE, pci_dev)) != NULL) + if (he_init_one(pci_dev, NULL) == 0) + ++ndevs; + + return (ndevs ? 0 : -ENODEV); +} + +static void __devexit +he_cleanup(void) +{ + while (he_devs) + { + struct he_dev *next = he_devs->next; + he_stop(he_devs); + atm_dev_deregister(he_devs->atm_dev); + kfree(he_devs); + + he_devs = next; + } + +} + +int init_module(void) +{ + return he_init(); +} + +void cleanup_module(void) +{ + he_cleanup(); +} +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,7) +MODULE_LICENSE("GPL"); +#endif diff -Nru a/drivers/atm/he.h b/drivers/atm/he.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/atm/he.h Thu May 8 00:24:30 2003 @@ -0,0 +1,935 @@ +/* $Id: he.h,v 1.4 2003/05/06 22:48:00 chas Exp $ */ + +/* + + he.h + + ForeRunnerHE ATM Adapter driver for ATM on Linux + Copyright (C) 1999-2001 Naval Research Laboratory + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/* + + he.h + + ForeRunnerHE ATM Adapter driver for ATM on Linux + Copyright (C) 1999-2000 Naval Research Laboratory + + Permission to use, copy, modify and distribute this software and its + documentation is hereby granted, provided that both the copyright + notice and this permission notice appear in all copies of the software, + derivative works or modified versions, and any portions thereof, and + that both notices appear in supporting documentation. + + NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND + DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER + RESULTING FROM THE USE OF THIS SOFTWARE. + + */ + +#ifndef _HE_H_ +#define _HE_H_ + +#define DEV_LABEL "he" + +#define CONFIG_DEFAULT_VCIBITS 12 +#define CONFIG_DEFAULT_VPIBITS 0 + +#define CONFIG_IRQ_SIZE 128 +#define CONFIG_IRQ_THRESH (CONFIG_IRQ_SIZE/2) + +#define CONFIG_NUMTPDS 256 + +#define CONFIG_TPDRQ_SIZE 512 +#define TPDRQ_MASK(x) (((unsigned long)(x))&((CONFIG_TPDRQ_SIZE<<3)-1)) + +#define CONFIG_RBRQ_SIZE 512 +#define CONFIG_RBRQ_THRESH 400 +#define RBRQ_MASK(x) (((unsigned long)(x))&((CONFIG_RBRQ_SIZE<<3)-1)) + +#define CONFIG_TBRQ_SIZE 512 +#define CONFIG_TBRQ_THRESH 400 +#define TBRQ_MASK(x) (((unsigned long)(x))&((CONFIG_TBRQ_SIZE<<2)-1)) + +#define CONFIG_RBPL_SIZE 512 +#define CONFIG_RBPL_THRESH 64 +#define CONFIG_RBPL_BUFSIZE 4096 +#define RBPL_MASK(x) (((unsigned long)(x))&((CONFIG_RBPL_SIZE<<3)-1)) + +#define CONFIG_RBPS_SIZE 1024 +#define CONFIG_RBPS_THRESH 64 +#define CONFIG_RBPS_BUFSIZE 128 +#define RBPS_MASK(x) (((unsigned long)(x))&((CONFIG_RBPS_SIZE<<3)-1)) + +/* 5.1.3 initialize connection memory */ + +#define CONFIG_RSRA 0x00000 +#define CONFIG_RCMLBM 0x08000 +#define CONFIG_RCMABR 0x0d800 +#define CONFIG_RSRB 0x0e000 + +#define CONFIG_TSRA 0x00000 +#define CONFIG_TSRB 0x08000 +#define CONFIG_TSRC 0x0c000 +#define CONFIG_TSRD 0x0e000 +#define CONFIG_TMABR 0x0f000 +#define CONFIG_TPDBA 0x10000 + +#define HE_MAXCIDBITS 12 + +/* 2.9.3.3 interrupt encodings */ + +struct he_irq { + volatile u32 isw; +}; + +#define IRQ_ALIGNMENT 0x1000 + +#define NEXT_ENTRY(base, tail, mask) \ + (((unsigned long)base)|(((unsigned long)(tail+1))&mask)) + +#define ITYPE_INVALID 0xffffffff +#define ITYPE_TBRQ_THRESH (0<<3) +#define ITYPE_TPD_COMPLETE (1<<3) +#define ITYPE_RBPS_THRESH (2<<3) +#define ITYPE_RBPL_THRESH (3<<3) +#define ITYPE_RBRQ_THRESH (4<<3) +#define ITYPE_RBRQ_TIMER (5<<3) +#define ITYPE_PHY (6<<3) +#define ITYPE_OTHER 0x80 +#define ITYPE_PARITY 0x81 +#define ITYPE_ABORT 0x82 + +#define ITYPE_GROUP(x) (x & 0x7) +#define ITYPE_TYPE(x) (x & 0xf8) + +#define HE_NUM_GROUPS 8 + +/* 2.1.4 transmit packet descriptor */ + +struct he_tpd { + + /* read by the adapter */ + + volatile u32 status; + volatile u32 reserved; + +#define TPD_MAXIOV 3 + struct { + u32 addr, len; + } iovec[TPD_MAXIOV]; + +#define address0 iovec[0].addr +#define length0 iovec[0].len + + /* linux-atm extensions */ + + struct sk_buff *skb; + struct atm_vcc *vcc; + +#ifdef USE_TPD_POOL + struct list_head entry; +#else + u32 inuse; + char padding[32 - sizeof(u32) - (2*sizeof(void*))]; +#endif +}; + +#define TPD_ALIGNMENT 64 +#define TPD_LEN_MASK 0xffff + +#define TPD_ADDR_SHIFT 6 +#define TPD_MASK 0xffffffc0 +#define TPD_ADDR(x) ((x) & TPD_MASK) +#define TPD_INDEX(x) (TPD_ADDR(x) >> TPD_ADDR_SHIFT) + + +/* table 2.3 transmit buffer return elements */ + +struct he_tbrq { + volatile u32 tbre; +}; + +#define TBRQ_ALIGNMENT CONFIG_TBRQ_SIZE + +#define TBRQ_TPD(tbrq) ((tbrq)->tbre & 0xffffffc0) +#define TBRQ_EOS(tbrq) ((tbrq)->tbre & (1<<3)) +#define TBRQ_MULTIPLE(tbrq) ((tbrq)->tbre & (1)) + +/* table 2.21 receive buffer return queue element field organization */ + +struct he_rbrq { + volatile u32 addr; + volatile u32 cidlen; +}; + +#define RBRQ_ALIGNMENT CONFIG_RBRQ_SIZE + +#define RBRQ_ADDR(rbrq) ((rbrq)->addr & 0xffffffc0) +#define RBRQ_CRC_ERR(rbrq) ((rbrq)->addr & (1<<5)) +#define RBRQ_LEN_ERR(rbrq) ((rbrq)->addr & (1<<4)) +#define RBRQ_END_PDU(rbrq) ((rbrq)->addr & (1<<3)) +#define RBRQ_AAL5_PROT(rbrq) ((rbrq)->addr & (1<<2)) +#define RBRQ_CON_CLOSED(rbrq) ((rbrq)->addr & (1<<1)) +#define RBRQ_HBUF_ERR(rbrq) ((rbrq)->addr & 1) +#define RBRQ_CID(rbrq) (((rbrq)->cidlen >> 16) & 0x1fff) +#define RBRQ_BUFLEN(rbrq) ((rbrq)->cidlen & 0xffff) + +/* figure 2.3 transmit packet descriptor ready queue */ + +struct he_tpdrq { + volatile u32 tpd; + volatile u32 cid; +}; + +#define TPDRQ_ALIGNMENT CONFIG_TPDRQ_SIZE + +/* table 2.30 host status page detail */ + +#define HSP_ALIGNMENT 0x400 /* must align on 1k boundary */ + +struct he_hsp { + struct he_hsp_entry { + volatile u32 tbrq_tail; + volatile u32 reserved1[15]; + volatile u32 rbrq_tail; + volatile u32 reserved2[15]; + } group[HE_NUM_GROUPS]; +}; + +/* figure 2.9 receive buffer pools */ + +struct he_rbp { + volatile u32 phys; + volatile u32 status; +}; + +/* NOTE: it is suggested that virt be the virtual address of the host + buffer. on a 64-bit machine, this would not work. Instead, we + store the real virtual address in another list, and store an index + (and buffer status) in the virt member. +*/ + +#define RBP_INDEX_OFF 6 +#define RBP_INDEX(x) (((long)(x) >> RBP_INDEX_OFF) & 0xffff) +#define RBP_LOANED 0x80000000 +#define RBP_SMALLBUF 0x40000000 + +struct he_virt { + void *virt; +}; + +#define RBPL_ALIGNMENT CONFIG_RBPL_SIZE +#define RBPS_ALIGNMENT CONFIG_RBPS_SIZE + +#ifdef notyet +struct he_group { + u32 rpbs_size, rpbs_qsize; + struct he_rbp rbps_ba; + + u32 rpbl_size, rpbl_qsize; + struct he_rpb_entry *rbpl_ba; +}; +#endif + +#define HE_LOOKUP_VCC(dev, cid) ((dev)->he_vcc_table[(cid)].vcc) + +struct he_vcc_table +{ + struct atm_vcc *vcc; +}; + +struct he_cs_stper +{ + long pcr; + int inuse; +}; + +#define HE_NUM_CS_STPER 16 + +struct he_dev { + unsigned int number; + unsigned int irq; + unsigned long membase; + + char prod_id[30]; + char mac_addr[6]; + int media; /* + * 0x26 = HE155 MM + * 0x27 = HE622 MM + * 0x46 = HE155 SM + * 0x47 = HE622 SM + */ + + + unsigned int vcibits, vpibits; + unsigned int cells_per_row; + unsigned int bytes_per_row; + unsigned int cells_per_lbuf; + unsigned int r0_numrows, r0_startrow, r0_numbuffs; + unsigned int r1_numrows, r1_startrow, r1_numbuffs; + unsigned int tx_numrows, tx_startrow, tx_numbuffs; + unsigned int buffer_limit; + + struct he_vcc_table *he_vcc_table; + +#ifdef notyet + struct he_group group[HE_NUM_GROUPS]; +#endif + struct he_cs_stper cs_stper[HE_NUM_CS_STPER]; + unsigned total_bw; + + dma_addr_t irq_phys; + struct he_irq *irq_base, *irq_head, *irq_tail; + volatile unsigned *irq_tailoffset; + int irq_peak; + +#ifdef USE_TASKLET + struct tasklet_struct tasklet; +#endif +#ifdef USE_TPD_POOL + struct pci_pool *tpd_pool; + struct list_head outstanding_tpds; +#else + struct he_tpd *tpd_head, *tpd_base, *tpd_end; + dma_addr_t tpd_base_phys; +#endif + + dma_addr_t tpdrq_phys; + struct he_tpdrq *tpdrq_base, *tpdrq_tail, *tpdrq_head; + + spinlock_t global_lock; /* 8.1.5 pci transaction ordering + error problem */ + dma_addr_t rbrq_phys; + struct he_rbrq *rbrq_base, *rbrq_head; + int rbrq_peak; + +#ifdef USE_RBPL_POOL + struct pci_pool *rbpl_pool; +#else + void *rbpl_pages; + dma_addr_t rbpl_pages_phys; +#endif + dma_addr_t rbpl_phys; + struct he_rbp *rbpl_base, *rbpl_tail; + struct he_virt *rbpl_virt; + int rbpl_peak; + +#ifdef USE_RBPS +#ifdef USE_RBPS_POOL + struct pci_pool *rbps_pool; +#else + void *rbps_pages; + dma_addr_t rbps_pages_phys; +#endif +#endif + dma_addr_t rbps_phys; + struct he_rbp *rbps_base, *rbps_tail; + struct he_virt *rbps_virt; + int rbps_peak; + + dma_addr_t tbrq_phys; + struct he_tbrq *tbrq_base, *tbrq_head; + int tbrq_peak; + + dma_addr_t hsp_phys; + struct he_hsp *hsp; + + struct pci_dev *pci_dev; + struct atm_dev *atm_dev; + struct he_dev *next; +}; + +struct he_vcc +{ + struct iovec iov_head[32]; + struct iovec *iov_tail; + int pdu_len; + + int rc_index; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1) + struct wait_queue *rx_waitq; + atruct wait_queue *tx_waitq; +#else + wait_queue_head_t rx_waitq; + wait_queue_head_t tx_waitq; +#endif +}; + +#define HE_VCC(vcc) ((struct he_vcc *)(vcc->dev_data)) + +#define PCI_VENDOR_ID_FORE 0x1127 +#define PCI_DEVICE_ID_FORE_HE 0x400 + +#define HE_DMA_MASK 0xffffffff + +#define GEN_CNTL_0 0x40 +#define INT_PROC_ENBL (1<<25) +#define SLAVE_ENDIAN_MODE (1<<16) +#define MRL_ENB (1<<5) +#define MRM_ENB (1<<4) +#define INIT_ENB (1<<2) +#define IGNORE_TIMEOUT (1<<1) +#define ENBL_64 (1<<0) + +#define MIN_PCI_LATENCY 32 /* errata 8.1.3 */ + +#define HE_DEV(dev) ((struct he_dev *) (dev)->dev_data) + +#define he_is622(dev) ((dev)->media & 0x1) + +#define HE_REGMAP_SIZE 0x100000 + +#define RESET_CNTL 0x80000 +#define BOARD_RST_STATUS (1<<6) + +#define HOST_CNTL 0x80004 +#define PCI_BUS_SIZE64 (1<<27) +#define DESC_RD_STATIC_64 (1<<26) +#define DATA_RD_STATIC_64 (1<<25) +#define DATA_WR_STATIC_64 (1<<24) +#define ID_CS (1<<12) +#define ID_WREN (1<<11) +#define ID_DOUT (1<<10) +#define ID_DOFFSET 10 +#define ID_DIN (1<<9) +#define ID_CLOCK (1<<8) +#define QUICK_RD_RETRY (1<<7) +#define QUICK_WR_RETRY (1<<6) +#define OUTFF_ENB (1<<5) +#define CMDFF_ENB (1<<4) +#define PERR_INT_ENB (1<<2) +#define IGNORE_INTR (1<<0) + +#define LB_SWAP 0x80008 +#define SWAP_RNUM_MAX(x) (x<<27) +#define DATA_WR_SWAP (1<<20) +#define DESC_RD_SWAP (1<<19) +#define DATA_RD_SWAP (1<<18) +#define INTR_SWAP (1<<17) +#define DESC_WR_SWAP (1<<16) +#define SDRAM_INIT (1<<15) +#define BIG_ENDIAN_HOST (1<<14) +#define XFER_SIZE (1<<7) + +#define LB_MEM_ADDR 0x8000c +#define LB_MEM_DATA 0x80010 + +#define LB_MEM_ACCESS 0x80014 +#define LB_MEM_HNDSHK (1<<30) +#define LM_MEM_WRITE (0x7) +#define LM_MEM_READ (0x3) + +#define SDRAM_CTL 0x80018 +#define LB_64_ENB (1<<3) +#define LB_TWR (1<<2) +#define LB_TRP (1<<1) +#define LB_TRAS (1<<0) + +#define INT_FIFO 0x8001c +#define INT_MASK_D (1<<15) +#define INT_MASK_C (1<<14) +#define INT_MASK_B (1<<13) +#define INT_MASK_A (1<<12) +#define INT_CLEAR_D (1<<11) +#define INT_CLEAR_C (1<<10) +#define INT_CLEAR_B (1<<9) +#define INT_CLEAR_A (1<<8) + +#define ABORT_ADDR 0x80020 + +#define IRQ0_BASE 0x80080 +#define IRQ_BASE(x) (x<<12) +#define IRQ_MASK ((CONFIG_IRQ_SIZE<<2)-1) /* was 0x3ff */ +#define IRQ_TAIL(x) (((unsigned long)(x)) & IRQ_MASK) +#define IRQ0_HEAD 0x80084 +#define IRQ_SIZE(x) (x<<22) +#define IRQ_THRESH(x) (x<<12) +#define IRQ_HEAD(x) (x<<2) +/* #define IRQ_PENDING (1) conflict with linux/irq.h */ +#define IRQ0_CNTL 0x80088 +#define IRQ_ADDRSEL(x) (x<<2) +#define IRQ_INT_A (0<<2) +#define IRQ_INT_B (1<<2) +#define IRQ_INT_C (2<<2) +#define IRQ_INT_D (3<<2) +#define IRQ_TYPE_ADDR 0x1 +#define IRQ_TYPE_LINE 0x0 +#define IRQ0_DATA 0x8008c + +#define IRQ1_BASE 0x80090 +#define IRQ1_HEAD 0x80094 +#define IRQ1_CNTL 0x80098 +#define IRQ1_DATA 0x8009c + +#define IRQ2_BASE 0x800a0 +#define IRQ2_HEAD 0x800a4 +#define IRQ2_CNTL 0x800a8 +#define IRQ2_DATA 0x800ac + +#define IRQ3_BASE 0x800b0 +#define IRQ3_HEAD 0x800b4 +#define IRQ3_CNTL 0x800b8 +#define IRQ3_DATA 0x800bc + +#define GRP_10_MAP 0x800c0 +#define GRP_32_MAP 0x800c4 +#define GRP_54_MAP 0x800c8 +#define GRP_76_MAP 0x800cc + +#define G0_RBPS_S 0x80400 +#define G0_RBPS_T 0x80404 +#define RBP_TAIL(x) ((x)<<3) +#define RBP_MASK(x) ((x)|0x1fff) +#define G0_RBPS_QI 0x80408 +#define RBP_QSIZE(x) ((x)<<14) +#define RBP_INT_ENB (1<<13) +#define RBP_THRESH(x) (x) +#define G0_RBPS_BS 0x8040c +#define G0_RBPL_S 0x80410 +#define G0_RBPL_T 0x80414 +#define G0_RBPL_QI 0x80418 +#define G0_RBPL_BS 0x8041c + +#define G1_RBPS_S 0x80420 +#define G1_RBPS_T 0x80424 +#define G1_RBPS_QI 0x80428 +#define G1_RBPS_BS 0x8042c +#define G1_RBPL_S 0x80430 +#define G1_RBPL_T 0x80434 +#define G1_RBPL_QI 0x80438 +#define G1_RBPL_BS 0x8043c + +#define G2_RBPS_S 0x80440 +#define G2_RBPS_T 0x80444 +#define G2_RBPS_QI 0x80448 +#define G2_RBPS_BS 0x8044c +#define G2_RBPL_S 0x80450 +#define G2_RBPL_T 0x80454 +#define G2_RBPL_QI 0x80458 +#define G2_RBPL_BS 0x8045c + +#define G3_RBPS_S 0x80460 +#define G3_RBPS_T 0x80464 +#define G3_RBPS_QI 0x80468 +#define G3_RBPS_BS 0x8046c +#define G3_RBPL_S 0x80470 +#define G3_RBPL_T 0x80474 +#define G3_RBPL_QI 0x80478 +#define G3_RBPL_BS 0x8047c + +#define G4_RBPS_S 0x80480 +#define G4_RBPS_T 0x80484 +#define G4_RBPS_QI 0x80488 +#define G4_RBPS_BS 0x8048c +#define G4_RBPL_S 0x80490 +#define G4_RBPL_T 0x80494 +#define G4_RBPL_QI 0x80498 +#define G4_RBPL_BS 0x8049c + +#define G5_RBPS_S 0x804a0 +#define G5_RBPS_T 0x804a4 +#define G5_RBPS_QI 0x804a8 +#define G5_RBPS_BS 0x804ac +#define G5_RBPL_S 0x804b0 +#define G5_RBPL_T 0x804b4 +#define G5_RBPL_QI 0x804b8 +#define G5_RBPL_BS 0x804bc + +#define G6_RBPS_S 0x804c0 +#define G6_RBPS_T 0x804c4 +#define G6_RBPS_QI 0x804c8 +#define G6_RBPS_BS 0x804cc +#define G6_RBPL_S 0x804d0 +#define G6_RBPL_T 0x804d4 +#define G6_RBPL_QI 0x804d8 +#define G6_RBPL_BS 0x804dc + +#define G7_RBPS_S 0x804e0 +#define G7_RBPS_T 0x804e4 +#define G7_RBPS_QI 0x804e8 +#define G7_RBPS_BS 0x804ec + +#define G7_RBPL_S 0x804f0 +#define G7_RBPL_T 0x804f4 +#define G7_RBPL_QI 0x804f8 +#define G7_RBPL_BS 0x804fc + +#define G0_RBRQ_ST 0x80500 +#define G0_RBRQ_H 0x80504 +#define G0_RBRQ_Q 0x80508 +#define RBRQ_THRESH(x) ((x)<<13) +#define RBRQ_SIZE(x) (x) +#define G0_RBRQ_I 0x8050c +#define RBRQ_TIME(x) ((x)<<8) +#define RBRQ_COUNT(x) (x) + +/* fill in 1 ... 7 later */ + +#define G0_TBRQ_B_T 0x80600 +#define G0_TBRQ_H 0x80604 +#define G0_TBRQ_S 0x80608 +#define G0_TBRQ_THRESH 0x8060c +#define TBRQ_THRESH(x) (x) + +/* fill in 1 ... 7 later */ + +#define RH_CONFIG 0x805c0 +#define PHY_INT_ENB (1<<10) +#define OAM_GID(x) (x<<7) +#define PTMR_PRE(x) (x) + +#define G0_INMQ_S 0x80580 +#define G0_INMQ_L 0x80584 +#define G1_INMQ_S 0x80588 +#define G1_INMQ_L 0x8058c +#define G2_INMQ_S 0x80590 +#define G2_INMQ_L 0x80594 +#define G3_INMQ_S 0x80598 +#define G3_INMQ_L 0x8059c +#define G4_INMQ_S 0x805a0 +#define G4_INMQ_L 0x805a4 +#define G5_INMQ_S 0x805a8 +#define G5_INMQ_L 0x805ac +#define G6_INMQ_S 0x805b0 +#define G6_INMQ_L 0x805b4 +#define G7_INMQ_S 0x805b8 +#define G7_INMQ_L 0x805bc + +#define TPDRQ_B_H 0x80680 +#define TPDRQ_T 0x80684 +#define TPDRQ_S 0x80688 + +#define UBUFF_BA 0x8068c + +#define RLBF0_H 0x806c0 +#define RLBF0_T 0x806c4 +#define RLBF1_H 0x806c8 +#define RLBF1_T 0x806cc +#define RLBC_H 0x806d0 +#define RLBC_T 0x806d4 +#define RLBC_H2 0x806d8 +#define TLBF_H 0x806e0 +#define TLBF_T 0x806e4 +#define RLBF0_C 0x806e8 +#define RLBF1_C 0x806ec +#define RXTHRSH 0x806f0 +#define LITHRSH 0x806f4 + +#define LBARB 0x80700 +#define SLICE_X(x) (x<<28) +#define ARB_RNUM_MAX(x) (x<<23) +#define TH_PRTY(x) (x<<21) +#define RH_PRTY(x) (x<<19) +#define TL_PRTY(x) (x<<17) +#define RL_PRTY(x) (x<<15) +#define BUS_MULTI(x) (x<<8) +#define NET_PREF(x) (x) + +#define SDRAMCON 0x80704 +#define BANK_ON (1<<14) +#define WIDE_DATA (1<<13) +#define TWR_WAIT (1<<12) +#define TRP_WAIT (1<<11) +#define TRAS_WAIT (1<<10) +#define REF_RATE(x) (x) + +#define LBSTAT 0x80708 + +#define RCC_STAT 0x8070c +#define RCC_BUSY (1) + +#define TCMCONFIG 0x80740 +#define TM_DESL2 (1<<10) +#define TM_BANK_WAIT(x) (x<<6) +#define TM_ADD_BANK4(x) (x<<4) +#define TM_PAR_CHECK(x) (x<<3) +#define TM_RW_WAIT(x) (x<<2) +#define TM_SRAM_TYPE(x) (x) + +#define TSRB_BA 0x80744 +#define TSRC_BA 0x80748 +#define TMABR_BA 0x8074c +#define TPD_BA 0x80750 +#define TSRD_BA 0x80758 + +#define TX_CONFIG 0x80760 +#define DRF_THRESH(x) (x<<22) +#define TX_UT_MODE(x) (x<<21) +#define TX_VCI_MASK(x) (x<<17) +#define LBFREE_CNT(x) (x) + +#define TXAAL5_PROTO 0x80764 +#define CPCS_UU(x) (x<<8) +#define CPI(x) (x) + +#define RCMCONFIG 0x80780 +#define RM_DESL2(x) (x<<10) +#define RM_BANK_WAIT(x) (x<<6) +#define RM_ADD_BANK(x) (x<<4) +#define RM_PAR_CHECK(x) (x<<3) +#define RM_RW_WAIT(x) (x<<2) +#define RM_SRAM_TYPE(x) (x) + +#define RCMRSRB_BA 0x80784 +#define RCMLBM_BA 0x80788 +#define RCMABR_BA 0x8078c + +#define RC_CONFIG 0x807c0 +#define UT_RD_DELAY(x) (x<<11) +#define WRAP_MODE(x) (x<<10) +#define RC_UT_MODE(x) (x<<9) +#define RX_ENABLE (1<<8) +#define RX_VALVP(x) (x<<4) +#define RX_VALVC(x) (x) + +#define MCC 0x807c4 +#define OEC 0x807c8 +#define DCC 0x807cc +#define CEC 0x807d0 + +#define HSP_BA 0x807f0 + +#define LB_CONFIG 0x807f4 +#define LB_SIZE(x) (x) + +#define CON_DAT 0x807f8 +#define CON_CTL 0x807fc +#define CON_CTL_MBOX (2<<30) +#define CON_CTL_TCM (1<<30) +#define CON_CTL_RCM (0<<30) +#define CON_CTL_WRITE (1<<29) +#define CON_CTL_READ (0<<29) +#define CON_CTL_BUSY (1<<28) +#define CON_BYTE_DISABLE_3 (1<<22) /* 24..31 */ +#define CON_BYTE_DISABLE_2 (1<<21) /* 16..23 */ +#define CON_BYTE_DISABLE_1 (1<<20) /* 8..15 */ +#define CON_BYTE_DISABLE_0 (1<<19) /* 0..7 */ +#define CON_CTL_ADDR(x) (x) + +#define FRAMER 0x80800 /* to 0x80bfc */ + +/* 3.3 network controller (internal) mailbox registers */ + +#define CS_STPER0 0x0 + /* ... */ +#define CS_STPER31 0x01f + +#define CS_STTIM0 0x020 + /* ... */ +#define CS_STTIM31 0x03f + +#define CS_TGRLD0 0x040 + /* ... */ +#define CS_TGRLD15 0x04f + +#define CS_ERTHR0 0x050 +#define CS_ERTHR1 0x051 +#define CS_ERTHR2 0x052 +#define CS_ERTHR3 0x053 +#define CS_ERTHR4 0x054 +#define CS_ERCTL0 0x055 +#define TX_ENABLE (1<<28) +#define ER_ENABLE (1<<27) +#define CS_ERCTL1 0x056 +#define CS_ERCTL2 0x057 +#define CS_ERSTAT0 0x058 +#define CS_ERSTAT1 0x059 + +#define CS_RTCCT 0x060 +#define CS_RTFWC 0x061 +#define CS_RTFWR 0x062 +#define CS_RTFTC 0x063 +#define CS_RTATR 0x064 + +#define CS_TFBSET 0x070 +#define CS_TFBADD 0x071 +#define CS_TFBSUB 0x072 +#define CS_WCRMAX 0x073 +#define CS_WCRMIN 0x074 +#define CS_WCRINC 0x075 +#define CS_WCRDEC 0x076 +#define CS_WCRCEIL 0x077 +#define CS_BWDCNT 0x078 + +#define CS_OTPPER 0x080 +#define CS_OTWPER 0x081 +#define CS_OTTLIM 0x082 +#define CS_OTTCNT 0x083 + +#define CS_HGRRT0 0x090 + /* ... */ +#define CS_HGRRT7 0x097 + +#define CS_ORPTRS 0x0a0 + +#define RXCON_CLOSE 0x100 + + +#define RCM_MEM_SIZE 0x10000 /* 1M of 32-bit registers */ +#define TCM_MEM_SIZE 0x20000 /* 2M of 32-bit registers */ + +/* 2.5 transmit connection memory registers */ + +#define TSR0_CONN_STATE(x) ((x>>28) & 0x7) +#define TSR0_USE_WMIN (1<<23) +#define TSR0_GROUP(x) ((x & 0x7)<<18) +#define TSR0_ABR (2<<16) +#define TSR0_UBR (1<<16) +#define TSR0_CBR (0<<16) +#define TSR0_PROT (1<<15) +#define TSR0_AAL0_SDU (2<<12) +#define TSR0_AAL0 (1<<12) +#define TSR0_AAL5 (0<<12) +#define TSR0_HALT_ER (1<<11) +#define TSR0_MARK_CI (1<<10) +#define TSR0_MARK_ER (1<<9) +#define TSR0_UPDATE_GER (1<<8) +#define TSR0_RC_INDEX(x) (x & 0x1F) + +#define TSR1_PCR(x) ((x & 0x7FFF)<<16) +#define TSR1_MCR(x) (x & 0x7FFF) + +#define TSR2_ACR(x) ((x & 0x7FFF)<<16) + +#define TSR3_NRM_CNT(x) ((x & 0xFF)<<24) +#define TSR3_CRM_CNT(x) (x & 0xFFFF) + +#define TSR4_FLUSH_CONN (1<<31) +#define TSR4_SESSION_ENDED (1<<30) +#define TSR4_CRC10 (1<<28) +#define TSR4_NULL_CRC10 (1<<27) +#define TSR4_PROT (1<<26) +#define TSR4_AAL0_SDU (2<<23) +#define TSR4_AAL0 (1<<23) +#define TSR4_AAL5 (0<<23) + +#define TSR9_OPEN_CONN (1<<20) + +#define TSR11_ICR(x) ((x & 0x7FFF)<<16) +#define TSR11_TRM(x) ((x & 0x7)<<13) +#define TSR11_NRM(x) ((x & 0x7)<<10) +#define TSR11_ADTF(x) (x & 0x3FF) + +#define TSR13_RDF(x) ((x & 0xF)<<23) +#define TSR13_RIF(x) ((x & 0xF)<<19) +#define TSR13_CDF(x) ((x & 0x7)<<16) +#define TSR13_CRM(x) (x & 0xFFFF) + +#define TSR14_DELETE (1<<31) +#define TSR14_ABR_CLOSE (1<<16) + +/* 2.7.1 per connection receieve state registers */ + +#define RSR0_START_PDU (1<<10) +#define RSR0_OPEN_CONN (1<<6) +#define RSR0_CLOSE_CONN (0<<6) +#define RSR0_PPD_ENABLE (1<<5) +#define RSR0_EPD_ENABLE (1<<4) +#define RSR0_TCP_CKSUM (1<<3) +#define RSR0_AAL5 (0) +#define RSR0_AAL0 (1) +#define RSR0_AAL0_SDU (2) +#define RSR0_RAWCELL (3) +#define RSR0_RAWCELL_CRC10 (4) + +#define RSR1_AQI_ENABLE (1<<20) +#define RSR1_RBPL_ONLY (1<<19) +#define RSR1_GROUP(x) ((x)<<16) + +#define RSR4_AQI_ENABLE (1<<30) +#define RSR4_GROUP(x) ((x)<<27) +#define RSR4_RBPL_ONLY (1<<26) + +/* 2.1.4 transmit packet descriptor */ + +#define TPD_USERCELL 0x0 +#define TPD_SEGMENT_OAMF5 0x4 +#define TPD_END2END_OAMF5 0x5 +#define TPD_RMCELL 0x6 +#define TPD_CELLTYPE(x) (x<<3) +#define TPD_EOS (1<<2) +#define TPD_CLP (1<<1) +#define TPD_INT (1<<0) +#define TPD_LST (1<<31) + +/* table 4.3 serial eeprom information */ + +#define PROD_ID 0x08 /* char[] */ +#define PROD_ID_LEN 30 +#define HW_REV 0x26 /* char[] */ +#define M_SN 0x3a /* integer */ +#define MEDIA 0x3e /* integer */ +#define HE155MM 0x26 +#define HE155SM 0x27 +#define HE622MM 0x46 +#define HE622SM 0x47 +#define MAC_ADDR 0x42 /* char[] */ + +#define CS_LOW 0x0 +#define CS_HIGH ID_CS /* HOST_CNTL_ID_PROM_SEL */ +#define CLK_LOW 0x0 +#define CLK_HIGH ID_CLOCK /* HOST_CNTL_ID_PROM_CLOCK */ +#define SI_HIGH ID_DIN /* HOST_CNTL_ID_PROM_DATA_IN */ +#define EEPROM_DELAY 400 /* microseconds */ + +/* Read from EEPROM = 0000 0011b */ +unsigned int readtab[] = { + CS_HIGH | CLK_HIGH, + CS_LOW | CLK_LOW, + CLK_HIGH, /* 0 */ + CLK_LOW, + CLK_HIGH, /* 0 */ + CLK_LOW, + CLK_HIGH, /* 0 */ + CLK_LOW, + CLK_HIGH, /* 0 */ + CLK_LOW, + CLK_HIGH, /* 0 */ + CLK_LOW, + CLK_HIGH, /* 0 */ + CLK_LOW | SI_HIGH, + CLK_HIGH | SI_HIGH, /* 1 */ + CLK_LOW | SI_HIGH, + CLK_HIGH | SI_HIGH /* 1 */ +}; + +/* Clock to read from/write to the EEPROM */ +unsigned int clocktab[] = { + CLK_LOW, + CLK_HIGH, + CLK_LOW, + CLK_HIGH, + CLK_LOW, + CLK_HIGH, + CLK_LOW, + CLK_HIGH, + CLK_LOW, + CLK_HIGH, + CLK_LOW, + CLK_HIGH, + CLK_LOW, + CLK_HIGH, + CLK_LOW, + CLK_HIGH, + CLK_LOW +}; + + +#endif /* _HE_H_ */ diff -Nru a/drivers/atm/iphase.c b/drivers/atm/iphase.c --- a/drivers/atm/iphase.c Thu May 8 00:24:30 2003 +++ b/drivers/atm/iphase.c Thu May 8 00:24:30 2003 @@ -2792,11 +2792,15 @@ break; case MEMDUMP_FFL: { - ia_regs_t regs_local; - ffredn_t *ffL = ®s_local.ffredn; - rfredn_t *rfL = ®s_local.rfredn; + ia_regs_t *regs_local; + ffredn_t *ffL; + rfredn_t *rfL; if (!capable(CAP_NET_ADMIN)) return -EPERM; + regs_local = kmalloc(sizeof(*regs_local), GFP_KERNEL); + if (!regs_local) return -ENOMEM; + ffL = ®s_local->ffredn; + rfL = ®s_local->rfredn; /* Copy real rfred registers into the local copy */ for (i=0; i<(sizeof (rfredn_t))/4; i++) ((u_int *)rfL)[i] = ((u_int *)iadev->reass_reg)[i] & 0xffff; @@ -2804,8 +2808,11 @@ for (i=0; i<(sizeof (ffredn_t))/4; i++) ((u_int *)ffL)[i] = ((u_int *)iadev->seg_reg)[i] & 0xffff; - if (copy_to_user(ia_cmds.buf, ®s_local,sizeof(ia_regs_t))) + if (copy_to_user(ia_cmds.buf, regs_local,sizeof(ia_regs_t))) { + kfree(regs_local); return -EFAULT; + } + kfree(regs_local); printk("Board %d registers dumped\n", board); ia_cmds.status = 0; } diff -Nru a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c --- a/drivers/block/acsi_slm.c Thu May 8 00:24:27 2003 +++ b/drivers/block/acsi_slm.c Thu May 8 00:24:27 2003 @@ -1008,11 +1008,8 @@ devfs_mk_dir("slm"); for (i = 0; i < MAX_SLM; i++) { - char name[16]; - sprintf(name, "slm/%d", i); - devfs_register(NULL, name, DEVFS_FL_DEFAULT, - ACSI_MAJOR, i, S_IFCHR | S_IRUSR | S_IWUSR, - &slm_fops, NULL); + devfs_mk_cdev(MKDEV(ACSI_MAJOR, i), + S_IFCHR|S_IRUSR|S_IWUSR, "slm/%d", i); } return 0; } diff -Nru a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c --- a/drivers/block/paride/pg.c Thu May 8 00:24:29 2003 +++ b/drivers/block/paride/pg.c Thu May 8 00:24:30 2003 @@ -652,11 +652,8 @@ devfs_mk_dir ("pg"); for (unit=0; unitudev, husb->bulk_out_ep->desc.bEndpointAddress); usb_fill_bulk_urb(urb, husb->udev, pipe, skb->data, skb->len, hci_usb_tx_complete, husb); - urb->transfer_flags = USB_ZERO_PACKET; + urb->transfer_flags = URB_ZERO_PACKET; BT_DBG("%s skb %p len %d", husb->hdev.name, skb, skb->len); diff -Nru a/drivers/char/amiserial.c b/drivers/char/amiserial.c --- a/drivers/char/amiserial.c Thu May 8 00:24:30 2003 +++ b/drivers/char/amiserial.c Thu May 8 00:24:30 2003 @@ -1528,7 +1528,6 @@ if (tty_hung_up_p(filp)) { DBG_CNT("before DEC-hung"); - MOD_DEC_USE_COUNT; local_irq_restore(flags); return; } @@ -1555,7 +1554,6 @@ } if (state->count) { DBG_CNT("before DEC-2"); - MOD_DEC_USE_COUNT; local_irq_restore(flags); return; } @@ -1615,7 +1613,6 @@ info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE| ASYNC_CLOSING); wake_up_interruptible(&info->close_wait); - MOD_DEC_USE_COUNT; local_irq_restore(flags); } @@ -1894,15 +1891,12 @@ int retval, line; unsigned long page; - MOD_INC_USE_COUNT; line = tty->index; if ((line < 0) || (line >= NR_PORTS)) { - MOD_DEC_USE_COUNT; return -ENODEV; } retval = get_async_struct(line, &info); if (retval) { - MOD_DEC_USE_COUNT; return retval; } tty->driver_data = info; @@ -2116,6 +2110,7 @@ memset(&serial_driver, 0, sizeof(struct tty_driver)); serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.owner = THIS_MODULE; serial_driver.driver_name = "amiserial"; serial_driver.name = "ttyS"; serial_driver.major = TTY_MAJOR; diff -Nru a/drivers/char/cyclades.c b/drivers/char/cyclades.c --- a/drivers/char/cyclades.c Thu May 8 00:24:28 2003 +++ b/drivers/char/cyclades.c Thu May 8 00:24:28 2003 @@ -2579,15 +2579,12 @@ int retval, line; unsigned long page; - MOD_INC_USE_COUNT; line = tty->index; if ((line < 0) || (NR_PORTS <= line)){ - MOD_DEC_USE_COUNT; return -ENODEV; } info = &cy_port[line]; if (info->line < 0){ - MOD_DEC_USE_COUNT; return -ENODEV; } @@ -2607,7 +2604,6 @@ } else { printk("cyc:Cyclades-Z firmware not yet loaded\n"); } - MOD_DEC_USE_COUNT; return -ENODEV; } #ifdef CONFIG_CYZ_INTR @@ -2803,7 +2799,6 @@ CY_LOCK(info, flags); /* If the TTY is being hung up, nothing to do */ if (tty_hung_up_p(filp)) { - MOD_DEC_USE_COUNT; CY_UNLOCK(info, flags); return; } @@ -2834,7 +2829,6 @@ info->count = 0; } if (info->count) { - MOD_DEC_USE_COUNT; CY_UNLOCK(info, flags); return; } @@ -2931,7 +2925,6 @@ printk(" cyc:cy_close done\n"); #endif - MOD_DEC_USE_COUNT; CY_UNLOCK(info, flags); return; } /* cy_close */ @@ -5494,6 +5487,7 @@ memset(&cy_serial_driver, 0, sizeof(struct tty_driver)); cy_serial_driver.magic = TTY_DRIVER_MAGIC; + cy_serial_driver.owner = THIS_MODULE; cy_serial_driver.driver_name = "cyclades"; cy_serial_driver.name = "ttyC"; cy_serial_driver.major = CYCLADES_MAJOR; diff -Nru a/drivers/char/drm/drm_drv.h b/drivers/char/drm/drm_drv.h --- a/drivers/char/drm/drm_drv.h Thu May 8 00:24:29 2003 +++ b/drivers/char/drm/drm_drv.h Thu May 8 00:24:29 2003 @@ -334,7 +334,6 @@ dev->last_context = 0; dev->last_switch = 0; dev->last_checked = 0; - init_timer( &dev->timer ); init_waitqueue_head( &dev->context_wait ); dev->ctx_start = 0; @@ -590,6 +589,7 @@ dev = &(DRM(device)[i]); memset( (void *)dev, 0, sizeof(*dev) ); dev->count_lock = SPIN_LOCK_UNLOCKED; + init_timer( &dev->timer ); sema_init( &dev->struct_sem, 1 ); if ((DRM(minor)[i] = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0) diff -Nru a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c --- a/drivers/char/drm/radeon_cp.c Thu May 8 00:24:28 2003 +++ b/drivers/char/drm/radeon_cp.c Thu May 8 00:24:28 2003 @@ -903,8 +903,8 @@ RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR, entry->busaddr[page_ofs]); - DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n", - entry->busaddr[page_ofs], + DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n", + (unsigned long) entry->busaddr[page_ofs], entry->handle + tmp_ofs ); } diff -Nru a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c --- a/drivers/char/dsp56k.c Thu May 8 00:24:29 2003 +++ b/drivers/char/dsp56k.c Thu May 8 00:24:29 2003 @@ -512,10 +512,9 @@ printk("DSP56k driver: Unable to register driver\n"); return -ENODEV; } - devfs_register(NULL, "dsp56k", DEVFS_FL_DEFAULT, - DSP56K_MAJOR, 0, - S_IFCHR | S_IRUSR | S_IWUSR, - &dsp56k_fops, NULL); + + devfs_mk_cdev(MKDEV(DSP56K_MAJOR, 0), + S_IFCHR | S_IRUSR | S_IWUSR, "dsp56k"); printk(banner); return 0; diff -Nru a/drivers/char/dtlk.c b/drivers/char/dtlk.c --- a/drivers/char/dtlk.c Thu May 8 00:24:28 2003 +++ b/drivers/char/dtlk.c Thu May 8 00:24:28 2003 @@ -345,10 +345,9 @@ } if (dtlk_dev_probe() == 0) printk(", MAJOR %d\n", dtlk_major); - devfs_register(NULL, "dtlk", DEVFS_FL_DEFAULT, - dtlk_major, DTLK_MINOR, - S_IFCHR | S_IRUSR | S_IWUSR, - &dtlk_fops, NULL); + + devfs_mk_cdev(MKDEV(dtlk_major, DTLK_MINOR), + S_IFCHR | S_IRUSR | S_IWUSR, "dtlk"); init_timer(&dtlk_timer); dtlk_timer.function = dtlk_timer_tick; diff -Nru a/drivers/char/dz.c b/drivers/char/dz.c --- a/drivers/char/dz.c Thu May 8 00:24:27 2003 +++ b/drivers/char/dz.c Thu May 8 00:24:27 2003 @@ -1332,6 +1332,7 @@ memset(&serial_driver, 0, sizeof(struct tty_driver)); serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.owner = THIS_MODULE; #if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS)) serial_driver.name = "ttyS"; #else @@ -1425,8 +1426,8 @@ printk("ttyS%02d at 0x%08x (irq = %d)\n", info->line, info->port, SERIAL); - tty_register_device(&serial_driver, info->line); - tty_register_device(&callout_driver, info->line); + tty_register_device(&serial_driver, info->line, NULL); + tty_register_device(&callout_driver, info->line, NULL); } /* Reset the chip */ diff -Nru a/drivers/char/esp.c b/drivers/char/esp.c --- a/drivers/char/esp.c Thu May 8 00:24:27 2003 +++ b/drivers/char/esp.c Thu May 8 00:24:27 2003 @@ -643,9 +643,7 @@ #ifdef SERIAL_DEBUG_OPEN printk("scheduling hangup..."); #endif - MOD_INC_USE_COUNT; - if (schedule_task(&info->tqueue_hangup) == 0) - MOD_DEC_USE_COUNT; + schedule_task(&info->tqueue_hangup); } } } @@ -811,7 +809,6 @@ tty = info->tty; if (tty) tty_hangup(tty); - MOD_DEC_USE_COUNT; } /* @@ -2132,7 +2129,7 @@ info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE| ASYNC_CLOSING); wake_up_interruptible(&info->close_wait); -out: MOD_DEC_USE_COUNT; +out: restore_flags(flags); } @@ -2375,7 +2372,6 @@ #ifdef SERIAL_DEBUG_OPEN printk("esp_open %s, count = %d\n", tty->name, info->count); #endif - MOD_INC_USE_COUNT; info->count++; tty->driver_data = info; info->tty = tty; @@ -2551,6 +2547,7 @@ memset(&esp_driver, 0, sizeof(struct tty_driver)); esp_driver.magic = TTY_DRIVER_MAGIC; + esp_driver.owner = THIS_MODULE; esp_driver.name = "ttyP"; esp_driver.major = ESP_IN_MAJOR; esp_driver.minor_start = 0; diff -Nru a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c --- a/drivers/char/ftape/zftape/zftape-init.c Thu May 8 00:24:28 2003 +++ b/drivers/char/ftape/zftape/zftape-init.c Thu May 8 00:24:28 2003 @@ -342,38 +342,24 @@ TRACE_CATCH(register_chrdev(QIC117_TAPE_MAJOR, "zft", &zft_cdev),); for (i = 0; i < 4; i++) { - char devname[9]; - - sprintf (devname, "qft%i", i); - devfs_register (NULL, devname, DEVFS_FL_DEFAULT, - QIC117_TAPE_MAJOR, i, - S_IFCHR | S_IRUSR | S_IWUSR, - &zft_cdev, NULL); - sprintf (devname, "nqft%i", i); - devfs_register (NULL, devname, DEVFS_FL_DEFAULT, - QIC117_TAPE_MAJOR, i + 4, - S_IFCHR | S_IRUSR | S_IWUSR, - &zft_cdev, NULL); - sprintf (devname, "zqft%i", i); - devfs_register (NULL, devname, DEVFS_FL_DEFAULT, - QIC117_TAPE_MAJOR, i + 16, - S_IFCHR | S_IRUSR | S_IWUSR, - &zft_cdev, NULL); - sprintf (devname, "nzqft%i", i); - devfs_register (NULL, devname, DEVFS_FL_DEFAULT, - QIC117_TAPE_MAJOR, i + 20, - S_IFCHR | S_IRUSR | S_IWUSR, - &zft_cdev, NULL); - sprintf (devname, "rawqft%i", i); - devfs_register (NULL, devname, DEVFS_FL_DEFAULT, - QIC117_TAPE_MAJOR, i + 32, - S_IFCHR | S_IRUSR | S_IWUSR, - &zft_cdev, NULL); - sprintf (devname, "nrawqft%i", i); - devfs_register (NULL, devname, DEVFS_FL_DEFAULT, - QIC117_TAPE_MAJOR, i + 36, + devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i), S_IFCHR | S_IRUSR | S_IWUSR, - &zft_cdev, NULL); + "qft%i", i); + devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 4), + S_IFCHR | S_IRUSR | S_IWUSR, + "nqft%i", i); + devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 16), + S_IFCHR | S_IRUSR | S_IWUSR, + "zqft%i", i); + devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 20), + S_IFCHR | S_IRUSR | S_IWUSR, + "nzqft%i", i); + devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 32), + S_IFCHR | S_IRUSR | S_IWUSR, + "rawqft%i", i); + devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 36), + S_IFCHR | S_IRUSR | S_IWUSR, + "nrawqft%i", i); } #ifdef CONFIG_ZFT_COMPRESSOR diff -Nru a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c --- a/drivers/char/hvc_console.c Thu May 8 00:24:30 2003 +++ b/drivers/char/hvc_console.c Thu May 8 00:24:30 2003 @@ -227,7 +227,12 @@ spin_unlock_irqrestore(&hp->lock, flags); } +#if defined (CONFIG_XMON) extern unsigned long cpus_in_xmon; +#else +unsigned long cpus_in_xmon=0; +#endif + int khvcd(void *unused) { @@ -252,6 +257,7 @@ memset(&hvc_driver, 0, sizeof(struct tty_driver)); hvc_driver.magic = TTY_DRIVER_MAGIC; + hvc_driver.owner = THIS_MODULE; hvc_driver.driver_name = "hvc"; hvc_driver.name = "hvc/"; hvc_driver.major = HVC_MAJOR; @@ -277,7 +283,7 @@ for (i = 0; i < hvc_driver.num; i++) { hvc_struct[i].lock = SPIN_LOCK_UNLOCKED; hvc_struct[i].index = i; - tty_register_device(&hvc_driver, i); + tty_register_device(&hvc_driver, i, NULL); } if (tty_register_driver(&hvc_driver)) diff -Nru a/drivers/char/ip2main.c b/drivers/char/ip2main.c --- a/drivers/char/ip2main.c Thu May 8 00:24:30 2003 +++ b/drivers/char/ip2main.c Thu May 8 00:24:30 2003 @@ -793,6 +793,7 @@ /* Initialise the relevant fields. */ ip2_tty_driver.magic = TTY_DRIVER_MAGIC; + ip2_tty_driver.owner = THIS_MODULE; ip2_tty_driver.name = pcTty; #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0) ip2_tty_driver.driver_name = pcDriver_name; @@ -869,29 +870,19 @@ */ for( i = 0; i < IP2_MAX_BOARDS; ++i ) { -#ifdef CONFIG_DEVFS_FS - char name[16]; -#endif - if ( 0 == ip2config.addr[i] ) { continue; } #ifdef CONFIG_DEVFS_FS if ( NULL != ( pB = i2BoardPtrTable[i] ) ) { - sprintf( name, "ip2/ipl%d", i ); - devfs_register(NULL, name, - DEVFS_FL_DEFAULT, - IP2_IPL_MAJOR, 4 * i, + devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i), S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR, - &ip2_ipl, NULL); + "ip2/ipl%d", i); - sprintf( name, "ip2/stat%d", i ); - devfs_register(NULL, name, - DEVFS_FL_DEFAULT, - IP2_IPL_MAJOR, 4 * i + 1, + devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i + 1), S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR, - &ip2_ipl, NULL); + "ip2/stat%d", i); for ( box = 0; box < ABS_MAX_BOXES; ++box ) { @@ -901,10 +892,10 @@ { tty_register_device(&ip2_tty_driver, j + ABS_BIGGEST_BOX * - (box+i*ABS_MAX_BOXES)); + (box+i*ABS_MAX_BOXES), NULL); tty_register_device(&ip2_callout_driver, j + ABS_BIGGEST_BOX * - (box+i*ABS_MAX_BOXES)); + (box+i*ABS_MAX_BOXES), NULL); } } } @@ -1577,7 +1568,6 @@ /* Setup pointer links in device and tty structures */ pCh->pTTY = tty; tty->driver_data = pCh; - MOD_INC_USE_COUNT; #ifdef IP2DEBUG_OPEN printk(KERN_DEBUG \ @@ -1777,14 +1767,12 @@ #endif if ( tty_hung_up_p ( pFile ) ) { - MOD_DEC_USE_COUNT; ip2trace (CHANN, ITRC_CLOSE, 2, 1, 2 ); return; } if ( tty->count > 1 ) { /* not the last close */ - MOD_DEC_USE_COUNT; ip2trace (CHANN, ITRC_CLOSE, 2, 1, 3 ); @@ -1852,7 +1840,6 @@ DBG_CNT("ip2_close: after wakeups--"); #endif - MOD_DEC_USE_COUNT; ip2trace (CHANN, ITRC_CLOSE, ITRC_RETURN, 1, 1 ); diff -Nru a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c --- a/drivers/char/ipmi/ipmi_devintf.c Thu May 8 00:24:29 2003 +++ b/drivers/char/ipmi/ipmi_devintf.c Thu May 8 00:24:29 2003 @@ -441,24 +441,17 @@ static void ipmi_new_smi(int if_num) { - char name[10]; - - if (if_num > MAX_DEVICES) - return; - - snprintf(name, sizeof(name), "ipmidev/%d", if_num); - - devfs_register(NULL, name, 0, ipmi_major, if_num, - S_IFCHR | S_IRUSR | S_IWUSR, - &ipmi_fops, NULL); + if (if_num <= MAX_DEVICES) { + devfs_mk_cdev(MKDEV(ipmi_major, if_num), + S_IFCHR | S_IRUSR | S_IWUSR, + "ipmidev/%d", if_num); + } } static void ipmi_smi_gone(int if_num) { - if (if_num > MAX_DEVICES) - return; - - devfs_remove("ipmidev/%d", if_num); + if (if_num <= MAX_DEVICES) + devfs_remove("ipmidev/%d", if_num); } static struct ipmi_smi_watcher smi_watcher = diff -Nru a/drivers/char/isicom.c b/drivers/char/isicom.c --- a/drivers/char/isicom.c Thu May 8 00:24:27 2003 +++ b/drivers/char/isicom.c Thu May 8 00:24:27 2003 @@ -590,9 +590,7 @@ port->status &= ~ISI_DCD; if (!((port->flags & ASYNC_CALLOUT_ACTIVE) && (port->flags & ASYNC_CALLOUT_NOHUP))) { - MOD_INC_USE_COUNT; - if (schedule_task(&port->hangup_tq) == 0) - MOD_DEC_USE_COUNT; + schedule_task(&port->hangup_tq); } } } @@ -846,7 +844,6 @@ #endif bp->status |= BOARD_ACTIVE; - MOD_INC_USE_COUNT; return; } @@ -1104,7 +1101,6 @@ for(channel = 0; channel < bp->port_count; channel++, port++) { drop_dtr_rts(port); } - MOD_DEC_USE_COUNT; } static void isicom_shutdown_port(struct isi_port * port) @@ -1644,7 +1640,6 @@ tty = port->tty; if (tty) tty_hangup(tty); /* FIXME: module removal race here - AKPM */ - MOD_DEC_USE_COUNT; } static void isicom_hangup(struct tty_struct * tty) @@ -1715,6 +1710,7 @@ /* tty driver structure initialization */ memset(&isicom_normal, 0, sizeof(struct tty_driver)); isicom_normal.magic = TTY_DRIVER_MAGIC; + isicom_normal.owner = THIS_MODULE; isicom_normal.name = "ttyM"; isicom_normal.major = ISICOM_NMAJOR; isicom_normal.minor_start = 0; diff -Nru a/drivers/char/istallion.c b/drivers/char/istallion.c --- a/drivers/char/istallion.c Thu May 8 00:24:29 2003 +++ b/drivers/char/istallion.c Thu May 8 00:24:29 2003 @@ -1054,7 +1054,6 @@ if (portp->devnr < 1) return(-ENODEV); - MOD_INC_USE_COUNT; /* * Check if this port is in the middle of closing. If so then wait @@ -1170,14 +1169,12 @@ save_flags(flags); cli(); if (tty_hung_up_p(filp)) { - MOD_DEC_USE_COUNT; restore_flags(flags); return; } if ((tty->count == 1) && (portp->refcount != 1)) portp->refcount = 1; if (portp->refcount-- > 1) { - MOD_DEC_USE_COUNT; restore_flags(flags); return; } @@ -1232,7 +1229,6 @@ portp->flags &= ~(ASYNC_CALLOUT_ACTIVE | ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); wake_up_interruptible(&portp->close_wait); - MOD_DEC_USE_COUNT; restore_flags(flags); } @@ -2369,7 +2365,6 @@ tty_hangup(portp->tty); } } - MOD_DEC_USE_COUNT; } /*****************************************************************************/ @@ -3004,9 +2999,7 @@ if (! ((portp->flags & ASYNC_CALLOUT_ACTIVE) && (portp->flags & ASYNC_CALLOUT_NOHUP))) { if (tty != (struct tty_struct *) NULL) { - MOD_INC_USE_COUNT; - if (schedule_task(&portp->tqhangup) == 0) - MOD_DEC_USE_COUNT; + schedule_task(&portp->tqhangup); } } } @@ -5336,12 +5329,9 @@ devfs_mk_dir("staliomem"); for (i = 0; i < 4; i++) { - char name[16]; - sprintf(name, "staliomem/%d", i); - devfs_register(NULL, name, DEVFS_FL_DEFAULT, - STL_SIOMEMMAJOR, i, + devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i), S_IFCHR | S_IRUSR | S_IWUSR, - &stli_fsiomem, NULL); + "staliomem/%d", i); } /* @@ -5350,6 +5340,7 @@ */ memset(&stli_serial, 0, sizeof(struct tty_driver)); stli_serial.magic = TTY_DRIVER_MAGIC; + stli_serial.owner = THIS_MODULE; stli_serial.driver_name = stli_drvname; stli_serial.name = stli_serialname; stli_serial.major = STL_SERIALMAJOR; diff -Nru a/drivers/char/keyboard.c b/drivers/char/keyboard.c --- a/drivers/char/keyboard.c Thu May 8 00:24:28 2003 +++ b/drivers/char/keyboard.c Thu May 8 00:24:28 2003 @@ -1047,8 +1047,8 @@ printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode); #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ - if (keycode == KEY_SYSRQ && !rep) { - sysrq_down = sysrq_alt && down; + if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) { + sysrq_down = down; return; } if (sysrq_down && down && !rep) { diff -Nru a/drivers/char/lp.c b/drivers/char/lp.c --- a/drivers/char/lp.c Thu May 8 00:24:27 2003 +++ b/drivers/char/lp.c Thu May 8 00:24:27 2003 @@ -784,8 +784,6 @@ static int lp_register(int nr, struct parport *port) { - char name[16]; - lp_table[nr].dev = parport_register_device(port, "lp", lp_preempt, NULL, NULL, 0, (void *) &lp_table[nr]); @@ -796,11 +794,8 @@ if (reset) lp_reset(nr); - sprintf (name, "printers/%d", nr); - devfs_register (NULL, name, - DEVFS_FL_DEFAULT, LP_MAJOR, nr, - S_IFCHR | S_IRUGO | S_IWUGO, - &lp_fops, NULL); + devfs_mk_cdev(MKDEV(LP_MAJOR, nr), S_IFCHR | S_IRUGO | S_IWUGO, + "printers/%d", nr); printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, (port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven"); diff -Nru a/drivers/char/mem.c b/drivers/char/mem.c --- a/drivers/char/mem.c Thu May 8 00:24:29 2003 +++ b/drivers/char/mem.c Thu May 8 00:24:29 2003 @@ -660,15 +660,16 @@ return 0; } -void __init memory_devfs_register (void) -{ - /* These are never unregistered */ - static const struct { - unsigned short minor; - char *name; - umode_t mode; - struct file_operations *fops; - } list[] = { /* list of minor devices */ +static struct file_operations memory_fops = { + .open = memory_open, /* just a selector for the real open */ +}; + +static const struct { + unsigned int minor; + char *name; + umode_t mode; + struct file_operations *fops; +} devlist[] = { /* list of minor devices */ {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, {3, "null", S_IRUGO | S_IWUGO, &null_fops}, @@ -680,25 +681,20 @@ {8, "random", S_IRUGO | S_IWUSR, &random_fops}, {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops}, {11,"kmsg", S_IRUGO | S_IWUSR, &kmsg_fops}, - }; - int i; - - for (i=0; i<(sizeof(list)/sizeof(*list)); i++) - devfs_register (NULL, list[i].name, DEVFS_FL_NONE, - MEM_MAJOR, list[i].minor, - list[i].mode | S_IFCHR, - list[i].fops, NULL); -} - -static struct file_operations memory_fops = { - .open = memory_open, /* just a selector for the real open */ }; -int __init chr_dev_init(void) +static int __init chr_dev_init(void) { + int i; + if (register_chrdev(MEM_MAJOR,"mem",&memory_fops)) printk("unable to get major %d for memory devs\n", MEM_MAJOR); - memory_devfs_register(); + + for (i = 0; i < ARRAY_SIZE(devlist); i++) { + devfs_mk_cdev(MKDEV(MEM_MAJOR, devlist[i].minor), + S_IFCHR | devlist[i].mode, devlist[i].name); + } + rand_initialize(); #if defined (CONFIG_FB) fbmem_init(); diff -Nru a/drivers/char/misc.c b/drivers/char/misc.c --- a/drivers/char/misc.c Thu May 8 00:24:30 2003 +++ b/drivers/char/misc.c Thu May 8 00:24:30 2003 @@ -200,8 +200,8 @@ "misc/%s", misc->name); } - devfs_register(NULL, misc->devfs_name, 0, MISC_MAJOR, misc->minor, - S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, misc->fops, NULL); + devfs_mk_cdev(MKDEV(MISC_MAJOR, misc->minor), + S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, misc->devfs_name); /* * Add it to the front, so that later devices can "override" diff -Nru a/drivers/char/moxa.c b/drivers/char/moxa.c --- a/drivers/char/moxa.c Thu May 8 00:24:30 2003 +++ b/drivers/char/moxa.c Thu May 8 00:24:30 2003 @@ -341,6 +341,7 @@ memset(&moxaDriver, 0, sizeof(struct tty_driver)); memset(&moxaCallout, 0, sizeof(struct tty_driver)); moxaDriver.magic = TTY_DRIVER_MAGIC; + moxaDriver.owner = THIS_MODULE; moxaDriver.name = "ttya"; moxaDriver.major = ttymajor; moxaDriver.minor_start = 0; @@ -544,7 +545,6 @@ ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE); } } - MOD_DEC_USE_COUNT; } static int moxa_open(struct tty_struct *tty, struct file *filp) @@ -556,7 +556,6 @@ port = PORTNO(tty); if (port == MAX_PORTS) { - MOD_INC_USE_COUNT; return (0); } if (!MoxaPortIsValid(port)) { @@ -579,7 +578,6 @@ } up(&moxaBuffSem); - MOD_INC_USE_COUNT; ch = &moxaChannels[port]; ch->count++; tty->driver_data = ch; @@ -619,7 +617,6 @@ port = PORTNO(tty); if (port == MAX_PORTS) { - MOD_DEC_USE_COUNT; return; } if (!MoxaPortIsValid(port)) { @@ -633,7 +630,6 @@ return; } if (tty_hung_up_p(filp)) { - MOD_DEC_USE_COUNT; return; } ch = (struct moxa_str *) tty->driver_data; @@ -649,7 +645,6 @@ ch->count = 0; } if (ch->count) { - MOD_DEC_USE_COUNT; return; } ch->asyncflags |= ASYNC_CLOSING; @@ -688,7 +683,6 @@ ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE | ASYNC_CLOSING); wake_up_interruptible(&ch->close_wait); - MOD_DEC_USE_COUNT; } static int moxa_write(struct tty_struct *tty, int from_user, @@ -1024,9 +1018,7 @@ wake_up_interruptible(&ch->open_wait); else { set_bit(MOXA_EVENT_HANGUP, &ch->event); - MOD_DEC_USE_COUNT; - if (schedule_work(&ch->tqueue) == 0) - MOD_INC_USE_COUNT; + schedule_work(&ch->tqueue); } } } diff -Nru a/drivers/char/mwave/mwavedd.h b/drivers/char/mwave/mwavedd.h --- a/drivers/char/mwave/mwavedd.h Thu May 8 00:24:29 2003 +++ b/drivers/char/mwave/mwavedd.h Thu May 8 00:24:29 2003 @@ -50,9 +50,11 @@ #define _LINUX_MWAVEDD_H #include "3780i.h" #include "tp3780i.h" +#include "smapi.h" #include "mwavepub.h" #include #include +#include extern int mwave_debug; extern int mwave_3780i_irq; diff -Nru a/drivers/char/mxser.c b/drivers/char/mxser.c --- a/drivers/char/mxser.c Thu May 8 00:24:29 2003 +++ b/drivers/char/mxser.c Thu May 8 00:24:29 2003 @@ -501,6 +501,7 @@ memset(&mxvar_sdriver, 0, sizeof(struct tty_driver)); mxvar_sdriver.magic = TTY_DRIVER_MAGIC; + mxvar_sdriver.owner = THIS_MODULE; mxvar_sdriver.name = "ttyM"; mxvar_sdriver.major = ttymajor; mxvar_sdriver.minor_start = 0; @@ -708,7 +709,6 @@ tty_hangup(tty); /* FIXME: module removal race here - AKPM */ } } - MOD_DEC_USE_COUNT; } /* @@ -767,8 +767,6 @@ info->session = current->session; info->pgrp = current->pgrp; - MOD_INC_USE_COUNT; - return (0); } @@ -795,7 +793,6 @@ if (tty_hung_up_p(filp)) { restore_flags(flags); - MOD_DEC_USE_COUNT; return; } if ((tty->count == 1) && (info->count != 1)) { @@ -817,7 +814,6 @@ } if (info->count) { restore_flags(flags); - MOD_DEC_USE_COUNT; return; } info->flags |= ASYNC_CLOSING; @@ -881,7 +877,6 @@ wake_up_interruptible(&info->close_wait); restore_flags(flags); - MOD_DEC_USE_COUNT; } static int mxser_write(struct tty_struct *tty, int from_user, @@ -1492,9 +1487,7 @@ if (info->xmit_cnt < WAKEUP_CHARS) { set_bit(MXSER_EVENT_TXLOW, &info->event); - MOD_INC_USE_COUNT; - if (schedule_work(&info->tqueue) == 0) - MOD_DEC_USE_COUNT; + schedule_work(&info->tqueue); } if (info->xmit_cnt <= 0) { info->IER &= ~UART_IER_THRI; @@ -1523,9 +1516,7 @@ else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) && (info->flags & ASYNC_CALLOUT_NOHUP))) set_bit(MXSER_EVENT_HANGUP, &info->event); - MOD_INC_USE_COUNT; - if (schedule_work(&info->tqueue) == 0) - MOD_DEC_USE_COUNT; + schedule_work(&info->tqueue); } if (info->flags & ASYNC_CTS_FLOW) { if (info->tty->hw_stopped) { @@ -1535,9 +1526,7 @@ outb(info->IER, info->base + UART_IER); set_bit(MXSER_EVENT_TXLOW, &info->event); - MOD_INC_USE_COUNT; - if (schedule_work(&info->tqueue) == 0) - MOD_DEC_USE_COUNT; + schedule_work(&info->tqueue); } } else { if (!(status & UART_MSR_CTS)) { diff -Nru a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c --- a/drivers/char/n_hdlc.c Thu May 8 00:24:28 2003 +++ b/drivers/char/n_hdlc.c Thu May 8 00:24:28 2003 @@ -9,7 +9,7 @@ * Al Longyear , Paul Mackerras * * Original release 01/11/99 - * $Id: n_hdlc.c,v 4.6 2003/04/21 19:14:07 paulkf Exp $ + * $Id: n_hdlc.c,v 4.8 2003/05/06 21:18:51 paulkf Exp $ * * This code is released under the GNU General Public License (GPL) * @@ -78,7 +78,7 @@ */ #define HDLC_MAGIC 0x239e -#define HDLC_VERSION "$Revision: 4.6 $" +#define HDLC_VERSION "$Revision: 4.8 $" #include #include @@ -215,6 +215,21 @@ /* Define this string only once for all macro invocations */ static char szVersion[] = HDLC_VERSION; +static struct tty_ldisc n_hdlc_ldisc = { + .owner = THIS_MODULE, + .magic = TTY_LDISC_MAGIC, + .name = "hdlc", + .open = n_hdlc_tty_open, + .close = n_hdlc_tty_close, + .read = n_hdlc_tty_read, + .write = n_hdlc_tty_write, + .ioctl = n_hdlc_tty_ioctl, + .poll = n_hdlc_tty_poll, + .receive_buf = n_hdlc_tty_receive, + .receive_room = n_hdlc_tty_room, + .write_wakeup = n_hdlc_tty_wakeup, +}; + /* n_hdlc_release() * * release an n_hdlc per device line discipline info structure @@ -968,25 +983,6 @@ static int __init n_hdlc_init(void) { - static struct tty_ldisc n_hdlc_ldisc = { - TTY_LDISC_MAGIC, /* magic */ - "hdlc", /* name */ - 0, /* num */ - 0, /* flags */ - n_hdlc_tty_open, /* open */ - n_hdlc_tty_close, /* close */ - 0, /* flush_buffer */ - 0, /* chars_in_buffer */ - n_hdlc_tty_read, /* read */ - n_hdlc_tty_write, /* write */ - n_hdlc_tty_ioctl, /* ioctl */ - 0, /* set_termios */ - n_hdlc_tty_poll, /* poll */ - n_hdlc_tty_receive, /* receive_buf */ - n_hdlc_tty_room, /* receive_room */ - n_hdlc_tty_wakeup, /* write_wakeup */ - THIS_MODULE /* owner */ - }; int status; /* range check maxframe arg */ diff -Nru a/drivers/char/pcxx.c b/drivers/char/pcxx.c --- a/drivers/char/pcxx.c Thu May 8 00:24:29 2003 +++ b/drivers/char/pcxx.c Thu May 8 00:24:29 2003 @@ -431,8 +431,6 @@ return(-ENODEV); } - /* flag the kernel that there is somebody using this guy */ - MOD_INC_USE_COUNT; /* * If the device is in the middle of being closed, then block * until it's done, and then try again. @@ -576,7 +574,6 @@ if(tty_hung_up_p(filp)) { /* flag that somebody is done with this module */ - MOD_DEC_USE_COUNT; restore_flags(flags); return; } @@ -594,7 +591,6 @@ } if (info->count-- > 1) { restore_flags(flags); - MOD_DEC_USE_COUNT; return; } if (info->count < 0) { @@ -651,7 +647,6 @@ info->asyncflags &= ~(ASYNC_NORMAL_ACTIVE| ASYNC_CALLOUT_ACTIVE|ASYNC_CLOSING); wake_up_interruptible(&info->close_wait); - MOD_DEC_USE_COUNT; restore_flags(flags); } } @@ -1228,6 +1223,7 @@ memset(&pcxe_driver, 0, sizeof(struct tty_driver)); pcxe_driver.magic = TTY_DRIVER_MAGIC; + pcxe_driver.owner = THIS_MODULE; pcxe_driver.name = "ttyD"; pcxe_driver.major = DIGI_MAJOR; pcxe_driver.minor_start = 0; diff -Nru a/drivers/char/ppdev.c b/drivers/char/ppdev.c --- a/drivers/char/ppdev.c Thu May 8 00:24:30 2003 +++ b/drivers/char/ppdev.c Thu May 8 00:24:30 2003 @@ -760,10 +760,8 @@ } devfs_mk_dir("parports"); for (i = 0; i < PARPORT_MAX; i++) { - char name[16]; - sprintf(name, "parports/%d", i); - devfs_register(NULL, name, DEVFS_FL_DEFAULT, PP_MAJOR, i, - S_IFCHR | S_IRUGO | S_IWUGO, &pp_fops, NULL); + devfs_mk_cdev(MKDEV(PP_MAJOR, i), + S_IFCHR | S_IRUGO | S_IWUGO, "parports/%d", i); } printk (KERN_INFO PP_VERSION "\n"); diff -Nru a/drivers/char/random.c b/drivers/char/random.c --- a/drivers/char/random.c Thu May 8 00:24:27 2003 +++ b/drivers/char/random.c Thu May 8 00:24:27 2003 @@ -1527,7 +1527,7 @@ * If we gave the user some bytes, update the access time. */ if (count != 0) { - UPDATE_ATIME(file->f_dentry->d_inode); + update_atime(file->f_dentry->d_inode); } return (count ? count : retval); diff -Nru a/drivers/char/raw.c b/drivers/char/raw.c --- a/drivers/char/raw.c Thu May 8 00:24:29 2003 +++ b/drivers/char/raw.c Thu May 8 00:24:29 2003 @@ -181,7 +181,7 @@ } if (rawdev->binding) { bdput(rawdev->binding); - MOD_DEC_USE_COUNT; + module_put(THIS_MODULE); } if (rq.block_major == 0 && rq.block_minor == 0) { /* unbind */ @@ -191,7 +191,7 @@ if (rawdev->binding == NULL) err = -ENOMEM; else - try_module_get(THIS_MODULE); + __module_get(THIS_MODULE); } up(&raw_mutex); } else { diff -Nru a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c --- a/drivers/char/rio/rio_linux.c Thu May 8 00:24:29 2003 +++ b/drivers/char/rio/rio_linux.c Thu May 8 00:24:29 2003 @@ -389,29 +389,6 @@ udelay (usecs); } - -void rio_inc_mod_count (void) -{ -#ifdef MODULE - func_enter (); - rio_dprintk (RIO_DEBUG_MOD_COUNT, "rio_inc_mod_count\n"); - MOD_INC_USE_COUNT; - func_exit (); -#endif -} - - -void rio_dec_mod_count (void) -{ -#ifdef MODULE - func_enter (); - rio_dprintk (RIO_DEBUG_MOD_COUNT, "rio_dec_mod_count\n"); - MOD_DEC_USE_COUNT; - func_exit (); -#endif -} - - static int rio_set_real_termios (void *ptr) { int rv, modem; @@ -660,7 +637,6 @@ PortP = (struct Port *)ptr; PortP->gs.tty = NULL; - rio_dec_mod_count (); func_exit (); } @@ -686,7 +662,6 @@ } PortP->gs.tty = NULL; - rio_dec_mod_count (); func_exit (); } @@ -908,6 +883,7 @@ memset(&rio_driver, 0, sizeof(rio_driver)); rio_driver.magic = TTY_DRIVER_MAGIC; + rio_driver.owner = THIS_MODULE; rio_driver.driver_name = "specialix_rio"; rio_driver.name = "ttySR"; rio_driver.major = RIO_NORMAL_MAJOR0; diff -Nru a/drivers/char/rio/rio_linux.h b/drivers/char/rio/rio_linux.h --- a/drivers/char/rio/rio_linux.h Thu May 8 00:24:29 2003 +++ b/drivers/char/rio/rio_linux.h Thu May 8 00:24:29 2003 @@ -87,9 +87,6 @@ #endif -void rio_dec_mod_count (void); -void rio_inc_mod_count (void); - /* Allow us to debug "in the field" without requiring clients to recompile.... */ #if 1 diff -Nru a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c --- a/drivers/char/rio/riotty.c Thu May 8 00:24:28 2003 +++ b/drivers/char/rio/riotty.c Thu May 8 00:24:28 2003 @@ -139,7 +139,6 @@ extern struct rio_info *p; -extern void rio_inc_mod_count (void); int @@ -205,8 +204,6 @@ tty->driver_data = PortP; PortP->gs.tty = tty; - if (!PortP->gs.count) - rio_inc_mod_count (); PortP->gs.count++; rio_dprintk (RIO_DEBUG_TTY, "%d bytes in tx buffer\n", @@ -215,8 +212,6 @@ retval = gs_init_port (&PortP->gs); if (retval) { PortP->gs.count--; - if (PortP->gs.count) - rio_dec_mod_count (); return -ENXIO; } /* diff -Nru a/drivers/char/riscom8.c b/drivers/char/riscom8.c --- a/drivers/char/riscom8.c Thu May 8 00:24:28 2003 +++ b/drivers/char/riscom8.c Thu May 8 00:24:28 2003 @@ -552,9 +552,7 @@ wake_up_interruptible(&port->open_wait); else if (!((port->flags & ASYNC_CALLOUT_ACTIVE) && (port->flags & ASYNC_CALLOUT_NOHUP))) { - MOD_INC_USE_COUNT; - if (schedule_task(&port->tqueue_hangup) == 0) - MOD_DEC_USE_COUNT; + schedule_task(&port->tqueue_hangup); } } @@ -676,7 +674,6 @@ IRQ_to_board[bp->irq] = bp; bp->flags |= RC_BOARD_ACTIVE; - MOD_INC_USE_COUNT; return 0; } @@ -694,7 +691,6 @@ bp->DTR = ~0; rc_out(bp, RC_DTR, bp->DTR); /* Drop DTR on all ports */ - MOD_DEC_USE_COUNT; } /* @@ -1678,7 +1674,6 @@ tty = port->tty; if (tty) tty_hangup(tty); /* FIXME: module removal race still here */ - MOD_DEC_USE_COUNT; } static void rc_hangup(struct tty_struct * tty) @@ -1757,6 +1752,7 @@ memset(IRQ_to_board, 0, sizeof(IRQ_to_board)); memset(&riscom_driver, 0, sizeof(riscom_driver)); riscom_driver.magic = TTY_DRIVER_MAGIC; + riscom_driver.owner = THIS_MODULE; riscom_driver.name = "ttyL"; riscom_driver.major = RISCOM8_NORMAL_MAJOR; riscom_driver.num = RC_NBOARD * RC_NPORT; diff -Nru a/drivers/char/rocket.c b/drivers/char/rocket.c --- a/drivers/char/rocket.c Thu May 8 00:24:29 2003 +++ b/drivers/char/rocket.c Thu May 8 00:24:29 2003 @@ -874,9 +874,6 @@ } if (info->count++ == 0) { -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif rp_num_ports_open++; #ifdef ROCKET_DEBUG_OPEN printk("rocket mod++ = %d...", rp_num_ports_open); @@ -1071,9 +1068,6 @@ tty->closing = 0; wake_up_interruptible(&info->close_wait); -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif rp_num_ports_open--; #ifdef ROCKET_DEBUG_OPEN printk("rocket mod-- = %d...", rp_num_ports_open); @@ -1504,9 +1498,6 @@ return; } if (info->count) { -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif rp_num_ports_open--; } @@ -2012,6 +2003,7 @@ */ memset(&rocket_driver, 0, sizeof(struct tty_driver)); rocket_driver.magic = TTY_DRIVER_MAGIC; + rocket_driver.owner = THIS_MODULE; #ifdef CONFIG_DEVFS_FS rocket_driver.name = "tts/R"; #else diff -Nru a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c --- a/drivers/char/ser_a2232.c Thu May 8 00:24:28 2003 +++ b/drivers/char/ser_a2232.c Thu May 8 00:24:28 2003 @@ -272,7 +272,6 @@ not in "a2232_close()". See the comment in "sx.c", too. If you run into problems, compile this driver into the kernel instead of compiling it as a module. */ - MOD_DEC_USE_COUNT; } static int a2232_set_real_termios(void *ptr) @@ -414,7 +413,6 @@ a2232_disable_tx_interrupts(ptr); a2232_disable_rx_interrupts(ptr); /* see the comment in a2232_shutdown_port above. */ - /* MOD_DEC_USE_COUNT; */ } static void a2232_hungup(void *ptr) @@ -468,13 +466,9 @@ return retval; } port->gs.flags |= GS_ACTIVE; - if (port->gs.count == 1) { - MOD_INC_USE_COUNT; - } retval = gs_block_til_ready(port, filp); if (retval) { - MOD_DEC_USE_COUNT; port->gs.count--; return retval; } @@ -711,6 +705,7 @@ memset(&a2232_driver, 0, sizeof(a2232_driver)); a2232_driver.magic = TTY_DRIVER_MAGIC; + a2232_driver.owner = THIS_MODULE; a2232_driver.driver_name = "commodore_a2232"; a2232_driver.name = "ttyY"; a2232_driver.major = A2232_NORMAL_MAJOR; diff -Nru a/drivers/char/serial167.c b/drivers/char/serial167.c --- a/drivers/char/serial167.c Thu May 8 00:24:28 2003 +++ b/drivers/char/serial167.c Thu May 8 00:24:28 2003 @@ -2395,6 +2395,7 @@ memset(&cy_serial_driver, 0, sizeof(struct tty_driver)); cy_serial_driver.magic = TTY_DRIVER_MAGIC; + cy_serial_driver.owner = THIS_MODULE; #ifdef CONFIG_DEVFS_FS cy_serial_driver.name = "tts/"; #else diff -Nru a/drivers/char/serial_tx3912.c b/drivers/char/serial_tx3912.c --- a/drivers/char/serial_tx3912.c Thu May 8 00:24:29 2003 +++ b/drivers/char/serial_tx3912.c Thu May 8 00:24:29 2003 @@ -41,8 +41,6 @@ static void rs_shutdown_port (void * ptr); static int rs_set_real_termios (void *ptr); static int rs_chars_in_buffer (void * ptr); -static void rs_hungup (void *ptr); -static void rs_close (void *ptr); /* * Used by generic serial driver to access hardware @@ -56,8 +54,6 @@ .shutdown_port = rs_shutdown_port, .set_real_termios = rs_set_real_termios, .chars_in_buffer = rs_chars_in_buffer, - .close = rs_close, - .hungup = rs_hungup, }; /* @@ -579,9 +575,6 @@ rs_dprintk (TX3912_UART_DEBUG_OPEN, "before inc_use_count (count=%d.\n", port->gs.count); - if (port->gs.count == 1) { - MOD_INC_USE_COUNT; - } rs_dprintk (TX3912_UART_DEBUG_OPEN, "after inc_use_count\n"); /* Jim: Initialize port hardware here */ @@ -595,7 +588,6 @@ retval, port->gs.count); if (retval) { - MOD_DEC_USE_COUNT; port->gs.count--; return retval; } @@ -621,32 +613,6 @@ } - -static void rs_close (void *ptr) -{ - func_enter (); - - /* Anything to do here? */ - - MOD_DEC_USE_COUNT; - func_exit (); -} - - -/* I haven't the foggiest why the decrement use count has to happen - here. The whole linux serial drivers stuff needs to be redesigned. - My guess is that this is a hack to minimize the impact of a bug - elsewhere. Thinking about it some more. (try it sometime) Try - running minicom on a serial port that is driven by a modularized - driver. Have the modem hangup. Then remove the driver module. Then - exit minicom. I expect an "oops". -- REW */ -static void rs_hungup (void *ptr) -{ - func_enter (); - MOD_DEC_USE_COUNT; - func_exit (); -} - static int rs_ioctl (struct tty_struct * tty, struct file * filp, unsigned int cmd, unsigned long arg) { @@ -839,6 +805,7 @@ memset(&rs_driver, 0, sizeof(rs_driver)); rs_driver.magic = TTY_DRIVER_MAGIC; + rs_driver.owner = THIS_MODULE; rs_driver.driver_name = "serial"; rs_driver.name = "ttyS"; rs_driver.major = TTY_MAJOR; diff -Nru a/drivers/char/sh-sci.c b/drivers/char/sh-sci.c --- a/drivers/char/sh-sci.c Thu May 8 00:24:30 2003 +++ b/drivers/char/sh-sci.c Thu May 8 00:24:30 2003 @@ -71,8 +71,6 @@ static int sci_get_CD(void *ptr); static void sci_shutdown_port(void *ptr); static int sci_set_real_termios(void *ptr); -static void sci_hungup(void *ptr); -static void sci_close(void *ptr); static int sci_chars_in_buffer(void *ptr); static int sci_request_irq(struct sci_port *port); static void sci_free_irq(struct sci_port *port); @@ -216,8 +214,6 @@ sci_shutdown_port, sci_set_real_termios, sci_chars_in_buffer, - sci_close, - sci_hungup, NULL }; @@ -838,12 +834,7 @@ sci_setsignals(port, 1,1); if (port->gs.count == 1) { - MOD_INC_USE_COUNT; - retval = sci_request_irq(port); - if (retval) { - goto failed_2; - } } retval = gs_block_til_ready(port, filp); @@ -878,23 +869,11 @@ failed_3: sci_free_irq(port); -failed_2: - MOD_DEC_USE_COUNT; failed_1: port->gs.count--; return retval; } -static void sci_hungup(void *ptr) -{ - MOD_DEC_USE_COUNT; -} - -static void sci_close(void *ptr) -{ - MOD_DEC_USE_COUNT; -} - static int sci_ioctl(struct tty_struct * tty, struct file * filp, unsigned int cmd, unsigned long arg) { @@ -1019,6 +998,7 @@ memset(&sci_driver, 0, sizeof(sci_driver)); sci_driver.magic = TTY_DRIVER_MAGIC; + sci_driver.owner = THIS_MODULE; sci_driver.driver_name = "sci"; #ifdef CONFIG_DEVFS_FS sci_driver.name = "ttsc/"; diff -Nru a/drivers/char/specialix.c b/drivers/char/specialix.c --- a/drivers/char/specialix.c Thu May 8 00:24:30 2003 +++ b/drivers/char/specialix.c Thu May 8 00:24:30 2003 @@ -833,9 +833,7 @@ #ifdef SPECIALIX_DEBUG printk ( "Sending HUP.\n"); #endif - MOD_INC_USE_COUNT; - if (schedule_task(&port->tqueue_hangup) == 0) - MOD_DEC_USE_COUNT; + schedule_task(&port->tqueue_hangup); } else { #ifdef SPECIALIX_DEBUG printk ( "Don't need to send HUP.\n"); @@ -980,7 +978,6 @@ turn_ints_on (bp); bp->flags |= SX_BOARD_ACTIVE; - MOD_INC_USE_COUNT; return 0; } @@ -1000,7 +997,6 @@ turn_ints_off (bp); - MOD_DEC_USE_COUNT; } @@ -2150,7 +2146,6 @@ tty = port->tty; if (tty) tty_hangup(tty); /* FIXME: module removal race here */ - MOD_DEC_USE_COUNT; } @@ -2233,6 +2228,7 @@ init_bh(SPECIALIX_BH, do_specialix_bh); memset(&specialix_driver, 0, sizeof(specialix_driver)); specialix_driver.magic = TTY_DRIVER_MAGIC; + specialix_driver.owner = THIS_MODULE; specialix_driver.name = "ttyW"; specialix_driver.major = SPECIALIX_NORMAL_MAJOR; specialix_driver.num = SX_NBOARD * SX_NPORT; diff -Nru a/drivers/char/stallion.c b/drivers/char/stallion.c --- a/drivers/char/stallion.c Thu May 8 00:24:29 2003 +++ b/drivers/char/stallion.c Thu May 8 00:24:29 2003 @@ -1044,8 +1044,6 @@ if (portp == (stlport_t *) NULL) return(-ENODEV); - MOD_INC_USE_COUNT; - /* * On the first open of the device setup the port hardware, and * initialize the per port data structure. @@ -1207,14 +1205,12 @@ save_flags(flags); cli(); if (tty_hung_up_p(filp)) { - MOD_DEC_USE_COUNT; restore_flags(flags); return; } if ((tty->count == 1) && (portp->refcount != 1)) portp->refcount = 1; if (portp->refcount-- > 1) { - MOD_DEC_USE_COUNT; restore_flags(flags); return; } @@ -1267,7 +1263,6 @@ portp->flags &= ~(ASYNC_CALLOUT_ACTIVE | ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); wake_up_interruptible(&portp->close_wait); - MOD_DEC_USE_COUNT; restore_flags(flags); } @@ -2241,11 +2236,11 @@ #endif if (portp == (stlport_t *) NULL) - goto out; + return; tty = portp->tty; if (tty == (struct tty_struct *) NULL) - goto out; + return; lock_kernel(); if (test_bit(ASYI_TXLOW, &portp->istate)) { @@ -2270,8 +2265,6 @@ } } unlock_kernel(); -out: - MOD_DEC_USE_COUNT; } /*****************************************************************************/ @@ -3216,13 +3209,11 @@ if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem)) printk("STALLION: failed to register serial board device\n"); devfs_mk_dir("staliomem"); + for (i = 0; i < 4; i++) { - char name[16]; - sprintf(name, "staliomem/%d", i); - devfs_register(NULL, name, DEVFS_FL_DEFAULT, - STL_SIOMEMMAJOR, i, - S_IFCHR | S_IRUSR | S_IWUSR, - &stl_fsiomem, NULL); + devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i), + S_IFCHR|S_IRUSR|S_IWUSR, + &stl_fsiomem, NULL, "staliomem/%d", i); } /* @@ -3231,6 +3222,7 @@ */ memset(&stl_serial, 0, sizeof(struct tty_driver)); stl_serial.magic = TTY_DRIVER_MAGIC; + stl_serial.owner = THIS_MODULE; stl_serial.driver_name = stl_drvname; stl_serial.name = stl_serialname; stl_serial.major = STL_SERIALMAJOR; @@ -4136,9 +4128,7 @@ if ((len == 0) || ((len < STL_TXBUFLOW) && (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { set_bit(ASYI_TXLOW, &portp->istate); - MOD_INC_USE_COUNT; - if (schedule_work(&portp->tqueue) == 0) - MOD_DEC_USE_COUNT; + schedule_work(&portp->tqueue); } if (len == 0) { @@ -4318,9 +4308,7 @@ misr = inb(ioaddr + EREG_DATA); if (misr & MISR_DCD) { set_bit(ASYI_DCDCHANGE, &portp->istate); - MOD_INC_USE_COUNT; - if (schedule_task(&portp->tqueue) == 0) - MOD_DEC_USE_COUNT; + schedule_task(&portp->tqueue); portp->stats.modem++; } @@ -5117,9 +5105,7 @@ if ((len == 0) || ((len < STL_TXBUFLOW) && (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { set_bit(ASYI_TXLOW, &portp->istate); - MOD_INC_USE_COUNT; - if (schedule_task(&portp->tqueue) == 0) - MOD_DEC_USE_COUNT; + schedule_task(&portp->tqueue); } if (len == 0) { @@ -5336,9 +5322,7 @@ ipr = stl_sc26198getreg(portp, IPR); if (ipr & IPR_DCDCHANGE) { set_bit(ASYI_DCDCHANGE, &portp->istate); - MOD_INC_USE_COUNT; - if (schedule_task(&portp->tqueue) == 0) - MOD_DEC_USE_COUNT; + schedule_task(&portp->tqueue); portp->stats.modem++; } break; diff -Nru a/drivers/char/synclink.c b/drivers/char/synclink.c --- a/drivers/char/synclink.c Thu May 8 00:24:28 2003 +++ b/drivers/char/synclink.c Thu May 8 00:24:28 2003 @@ -1,7 +1,7 @@ /* * linux/drivers/char/synclink.c * - * $Id: synclink.c,v 4.6 2003/04/21 17:46:54 paulkf Exp $ + * $Id: synclink.c,v 4.9 2003/05/06 21:18:51 paulkf Exp $ * * Device driver for Microgate SyncLink ISA and PCI * high speed multiprotocol serial adapters. @@ -193,6 +193,7 @@ int flags; int count; /* count of opens */ int line; + int hw_version; unsigned short close_delay; unsigned short closing_wait; /* time to wait before closing */ @@ -917,7 +918,7 @@ MODULE_PARM(txholdbufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i"); static char *driver_name = "SyncLink serial driver"; -static char *driver_version = "$Revision: 4.6 $"; +static char *driver_version = "$Revision: 4.9 $"; static int synclink_init_one (struct pci_dev *dev, const struct pci_device_id *ent); @@ -925,6 +926,7 @@ static struct pci_device_id synclink_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_MICROGATE, PCI_DEVICE_ID_MICROGATE_USC, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_MICROGATE, 0x0210, PCI_ANY_ID, PCI_ANY_ID, }, { 0, }, /* terminate list */ }; MODULE_DEVICE_TABLE(pci, synclink_pci_tbl); @@ -4216,9 +4218,7 @@ info->get_tx_holding_index=0; /* restart transmit timer */ - del_timer(&info->tx_timer); - info->tx_timer.expires = jiffies + jiffies_from_ms(5000); - add_timer(&info->tx_timer); + mod_timer(&info->tx_timer, jiffies + jiffies_from_ms(5000)); ret = 1; } @@ -4436,12 +4436,12 @@ info->max_frame_size = 65535; if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - printk( "SyncLink device %s added:PCI bus IO=%04X IRQ=%d Mem=%08X LCR=%08X MaxFrameSize=%u\n", - info->device_name, info->io_base, info->irq_level, + printk( "SyncLink PCI v%d %s: IO=%04X IRQ=%d Mem=%08X,%08X MaxFrameSize=%u\n", + info->hw_version + 1, info->device_name, info->io_base, info->irq_level, info->phys_memory_base, info->phys_lcr_base, info->max_frame_size ); } else { - printk( "SyncLink device %s added:ISA bus IO=%04X IRQ=%d DMA=%d MaxFrameSize=%u\n", + printk( "SyncLink ISA %s: IO=%04X IRQ=%d DMA=%d MaxFrameSize=%u\n", info->device_name, info->io_base, info->irq_level, info->dma_level, info->max_frame_size ); } @@ -5296,10 +5296,11 @@ info->mbre_bit = BIT8; outw( BIT8, info->io_base ); /* set Master Bus Enable (DCAR) */ - /* Enable DMAEN (Port 7, Bit 14) */ - /* This connects the DMA request signal to the ISA bus */ - /* on the ISA adapter. This has no effect for the PCI adapter */ - usc_OutReg( info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) & ~BIT14) ); + if (info->bus_type == MGSL_BUS_TYPE_ISA) { + /* Enable DMAEN (Port 7, Bit 14) */ + /* This connects the DMA request signal to the ISA bus */ + usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) & ~BIT14)); + } /* DMA Control Register (DCR) * @@ -6276,10 +6277,11 @@ usc_EnableMasterIrqBit( info ); - /* Enable INTEN (Port 6, Bit12) */ - /* This connects the IRQ request signal to the ISA bus */ - /* on the ISA adapter. This has no effect for the PCI adapter */ - usc_OutReg( info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12) ); + if (info->bus_type == MGSL_BUS_TYPE_ISA) { + /* Enable INTEN (Port 6, Bit12) */ + /* This connects the IRQ request signal to the ISA bus */ + usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12)); + } } /* end of usc_set_async_mode() */ @@ -6370,10 +6372,11 @@ usc_loopback_frame( info ); usc_set_sdlc_mode( info ); - /* Enable INTEN (Port 6, Bit12) */ - /* This connects the IRQ request signal to the ISA bus */ - /* on the ISA adapter. This has no effect for the PCI adapter */ - usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12)); + if (info->bus_type == MGSL_BUS_TYPE_ISA) { + /* Enable INTEN (Port 6, Bit12) */ + /* This connects the IRQ request signal to the ISA bus */ + usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12)); + } usc_enable_aux_clock(info, info->params.clock_speed); @@ -8115,17 +8118,20 @@ info->bus_type = MGSL_BUS_TYPE_PCI; info->io_addr_size = 8; info->irq_flags = SA_SHIRQ; - - /* Store the PCI9050 misc control register value because a flaw - * in the PCI9050 prevents LCR registers from being read if - * BIOS assigns an LCR base address with bit 7 set. - * - * Only the misc control register is accessed for which only - * write access is needed, so set an initial value and change - * bits to the device instance data as we write the value - * to the actual misc control register. - */ - info->misc_ctrl_value = 0x087e4546; + + if (dev->device == 0x0210) { + /* Version 1 PCI9030 based universal PCI adapter */ + info->misc_ctrl_value = 0x007c4080; + info->hw_version = 1; + } else { + /* Version 0 PCI9050 based 5V PCI adapter + * A PCI9050 bug prevents reading LCR registers if + * LCR base address bit 7 is set. Maintain shadow + * value so we can write to LCR misc control reg. + */ + info->misc_ctrl_value = 0x087e4546; + info->hw_version = 0; + } mgsl_add_device(info); diff -Nru a/drivers/char/sysrq.c b/drivers/char/sysrq.c --- a/drivers/char/sysrq.c Thu May 8 00:24:30 2003 +++ b/drivers/char/sysrq.c Thu May 8 00:24:30 2003 @@ -101,131 +101,19 @@ { machine_restart(NULL); } + static struct sysrq_key_op sysrq_reboot_op = { .handler = sysrq_handle_reboot, .help_msg = "reBoot", .action_msg = "Resetting", }; - - -/* SYNC SYSRQ HANDLERS BLOCK */ - -/* do_emergency_sync helper function */ -/* Guesses if the device is a local hard drive */ -static int is_local_disk(struct block_device *bdev) -{ - switch (MAJOR(bdev->bd_dev)) { - case IDE0_MAJOR: - case IDE1_MAJOR: - case IDE2_MAJOR: - case IDE3_MAJOR: - case IDE4_MAJOR: - case IDE5_MAJOR: - case IDE6_MAJOR: - case IDE7_MAJOR: - case IDE8_MAJOR: - case IDE9_MAJOR: - case SCSI_DISK0_MAJOR: - case SCSI_DISK1_MAJOR: - case SCSI_DISK2_MAJOR: - case SCSI_DISK3_MAJOR: - case SCSI_DISK4_MAJOR: - case SCSI_DISK5_MAJOR: - case SCSI_DISK6_MAJOR: - case SCSI_DISK7_MAJOR: - case XT_DISK_MAJOR: - return 1; - default: - return 0; - } -} - -/* do_emergency_sync helper function */ -static void go_sync(struct super_block *sb, int remount_flag) -{ - int orig_loglevel; - orig_loglevel = console_loglevel; - console_loglevel = 7; - printk(KERN_INFO "%sing device %s ... ", - remount_flag ? "Remount" : "Sync", - sb->s_id); - - if (remount_flag) { /* Remount R/O */ - int ret, flags; - struct file *file; - - if (sb->s_flags & MS_RDONLY) { - printk("R/O\n"); - return; - } - - file_list_lock(); - list_for_each_entry(file, &sb->s_files, f_list) { - if (file->f_dentry && file_count(file) - && S_ISREG(file->f_dentry->d_inode->i_mode)) - file->f_mode &= ~2; - } - file_list_unlock(); - DQUOT_OFF(sb); - fsync_bdev(sb->s_bdev); - flags = MS_RDONLY; - if (sb->s_op && sb->s_op->remount_fs) { - ret = sb->s_op->remount_fs(sb, &flags, NULL); - if (ret) - printk("error %d\n", ret); - else { - sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); - printk("OK\n"); - } - } else - printk("nothing to do\n"); - } else { /* Sync only */ - fsync_bdev(sb->s_bdev); - printk("OK\n"); - } - console_loglevel = orig_loglevel; -} -/* - * Emergency Sync or Unmount. We cannot do it directly, so we set a special - * flag and wake up the bdflush kernel thread which immediately calls this function. - * We process all mounted hard drives first to recover from crashed experimental - * block devices and malfunctional network filesystems. - */ - -int emergency_sync_scheduled; - -void do_emergency_sync(void) { - struct super_block *sb; - int remount_flag; - int orig_loglevel; - - lock_kernel(); - remount_flag = (emergency_sync_scheduled == EMERG_REMOUNT); - emergency_sync_scheduled = 0; - - list_for_each_entry(sb, &super_blocks, s_list) - if (sb->s_bdev && is_local_disk(sb->s_bdev)) - go_sync(sb, remount_flag); - - list_for_each_entry(sb, &super_blocks, s_list) - if (sb->s_bdev && !is_local_disk(sb->s_bdev)) - go_sync(sb, remount_flag); - - unlock_kernel(); - - orig_loglevel = console_loglevel; - console_loglevel = 7; - printk(KERN_INFO "Done.\n"); - console_loglevel = orig_loglevel; -} - static void sysrq_handle_sync(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { - emergency_sync_scheduled = EMERG_SYNC; - wakeup_bdflush(0); + emergency_sync(); } + static struct sysrq_key_op sysrq_sync_op = { .handler = sysrq_handle_sync, .help_msg = "Sync", @@ -235,9 +123,9 @@ static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { - emergency_sync_scheduled = EMERG_REMOUNT; - wakeup_bdflush(0); + emergency_remount(); } + static struct sysrq_key_op sysrq_mountro_op = { .handler = sysrq_handle_mountro, .help_msg = "Unmount", diff -Nru a/drivers/char/tipar.c b/drivers/char/tipar.c --- a/drivers/char/tipar.c Thu May 8 00:24:29 2003 +++ b/drivers/char/tipar.c Thu May 8 00:24:29 2003 @@ -421,8 +421,6 @@ static int tipar_register(int nr, struct parport *port) { - char name[32]; - /* Register our module into parport */ table[nr].dev = parport_register_device(port, "tipar", NULL, NULL, NULL, 0, @@ -432,13 +430,9 @@ return 1; /* Use devfs, tree: /dev/ticables/par/[0..2] */ - sprintf(name, "ticables/par/%d", nr); - printk - ("tipar: registering to devfs : major = %d, minor = %d, node = %s\n", - TISER_MAJOR, (TIPAR_MINOR + nr), name); - devfs_register(NULL, name, DEVFS_FL_DEFAULT, TIPAR_MAJOR, - TIPAR_MINOR + nr, S_IFCHR | S_IRUGO | S_IWUGO, - &tipar_fops, NULL); + devfs_mk_cdev(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr), + S_IFCHR | S_IRUGO | S_IWUGO, + "ticables/par/%d", nr); /* Display informations */ printk(KERN_INFO "tipar%d: using %s (%s).\n", nr, port->name, diff -Nru a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c --- a/drivers/char/tpqic02.c Thu May 8 00:24:28 2003 +++ b/drivers/char/tpqic02.c Thu May 8 00:24:28 2003 @@ -2694,38 +2694,27 @@ #endif return -ENODEV; } - devfs_register(NULL, "ntpqic11", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 2, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - devfs_register(NULL, "tpqic11", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 3, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - devfs_register(NULL, "ntpqic24", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 4, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - devfs_register(NULL, "tpqic24", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 5, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - devfs_register(NULL, "ntpqic120", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 6, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - devfs_register(NULL, "tpqic120", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 7, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - devfs_register(NULL, "ntpqic150", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 8, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - devfs_register(NULL, "tpqic150", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 9, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); + + devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 2), + S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic11"); + devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 3), + S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic11"); + + devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 4), + S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic24"); + devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 5), + S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic24"); + + devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 6), + S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic120"); + devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 7), + S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic120"); + + devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 8), + S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic150"); + devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 9), + S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic150"); + init_waitqueue_head(&qic02_tape_transfer); /* prepare timer */ TIMEROFF; diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c --- a/drivers/char/tty_io.c Thu May 8 00:24:29 2003 +++ b/drivers/char/tty_io.c Thu May 8 00:24:29 2003 @@ -2088,22 +2088,6 @@ } #ifdef CONFIG_DEVFS_FS -static void tty_register_devfs(struct tty_driver *driver, unsigned index) -{ - dev_t dev = MKDEV(driver->major, driver->minor_start) + index; - char buf[32]; - - if (index >= driver->num) { - printk(KERN_ERR "Attempt to register invalid tty line number " - "with devfs (%d).\n", index); - return; - } - - tty_line_name(driver, index, buf); - devfs_register(NULL, buf, 0, MAJOR(dev), MINOR(dev), - S_IFCHR | S_IRUSR | S_IWUSR, &tty_fops, NULL); -} - static void tty_unregister_devfs(struct tty_driver *driver, int index) { char path[64]; @@ -2111,21 +2095,131 @@ devfs_remove(path); } #else -# define tty_register_devfs(driver, index) do { } while (0) # define tty_unregister_devfs(driver, index) do { } while (0) #endif /* CONFIG_DEVFS_FS */ -/* - * Register a tty device described by , with minor number . +static struct class tty_class = { + .name = "tty", +}; + +struct tty_dev { + struct list_head node; + dev_t dev; + struct class_device class_dev; +}; +#define to_tty_dev(d) container_of(d, struct tty_dev, class_dev) + +static LIST_HEAD(tty_dev_list); + +static ssize_t show_dev(struct class_device *class_dev, char *buf) +{ + struct tty_dev *tty_dev = to_tty_dev(class_dev); + return sprintf(buf, "%04x\n", tty_dev->dev); +} +static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL); + +static void tty_add_class_device(char *name, dev_t dev, struct device *device) +{ + struct tty_dev *tty_dev = NULL; + char *temp; + int retval; + + tty_dev = kmalloc(sizeof(*tty_dev), GFP_KERNEL); + if (!tty_dev) + return; + memset(tty_dev, 0x00, sizeof(*tty_dev)); + + /* stupid '/' in tty name strings... */ + temp = strchr(name, '/'); + if (temp && (temp[1] != 0x00)) + ++temp; + else + temp = name; + + tty_dev->class_dev.dev = device; + tty_dev->class_dev.class = &tty_class; + snprintf(tty_dev->class_dev.class_id, BUS_ID_SIZE, "%s", temp); + retval = class_device_register(&tty_dev->class_dev); + if (retval) + goto error; + class_device_create_file (&tty_dev->class_dev, &class_device_attr_dev); + tty_dev->dev = dev; + list_add(&tty_dev->node, &tty_dev_list); + return; +error: + kfree(tty_dev); +} + +void tty_remove_class_device(dev_t dev) +{ + struct tty_dev *tty_dev = NULL; + struct list_head *tmp; + int found = 0; + + list_for_each (tmp, &tty_dev_list) { + tty_dev = list_entry(tmp, struct tty_dev, node); + if ((MAJOR(tty_dev->dev) == MAJOR(dev)) && + (MINOR(tty_dev->dev) == MINOR(dev))) { + found = 1; + break; + } + } + if (found) { + list_del(&tty_dev->node); + class_device_unregister(&tty_dev->class_dev); + kfree(tty_dev); + } +} + +/** + * tty_register_device - register a tty device + * @driver: the tty driver that describes the tty device + * @index: the index in the tty driver for this tty device + * @device: a struct device that is associated with this tty device. + * This field is optional, if there is no known struct device for this + * tty device it can be set to NULL safely. + * + * This call is required to be made to register an individual tty device if + * the tty driver's flags have the TTY_DRIVER_NO_DEVFS bit set. If that + * bit is not set, this function should not be called. */ -void tty_register_device(struct tty_driver *driver, unsigned index) +void tty_register_device(struct tty_driver *driver, unsigned index, + struct device *device) { - tty_register_devfs(driver, index); + dev_t dev = MKDEV(driver->major, driver->minor_start) + index; + char name[64]; + + if (index >= driver->num) { + printk(KERN_ERR "Attempt to register invalid tty line number " + " (%d).\n", index); + return; + } + + tty_line_name(driver, index, name); + devfs_register(NULL, name, 0, MAJOR(dev), MINOR(dev), + S_IFCHR | S_IRUSR | S_IWUSR, &tty_fops, NULL); + + /* stupid console driver devfs names... change vc/X into ttyX */ + if (driver->type == TTY_DRIVER_TYPE_CONSOLE) + sprintf(name, "tty%d", MINOR(dev)); + + /* we don't care about the ptys */ + if (driver->type != TTY_DRIVER_TYPE_PTY) + tty_add_class_device (name, dev, device); } +/** + * tty_unregister_device - unregister a tty device + * @driver: the tty driver that describes the tty device + * @index: the index in the tty driver for this tty device + * + * If a tty device is registered with a call to tty_register_device() then + * this function must be made when the tty device is gone. + */ void tty_unregister_device(struct tty_driver *driver, unsigned index) { tty_unregister_devfs(driver, index); + tty_remove_class_device(MKDEV(driver->major, driver->minor_start) + index); } EXPORT_SYMBOL(tty_register_device); @@ -2207,7 +2301,7 @@ if ( !(driver->flags & TTY_DRIVER_NO_DEVFS) ) { for(i = 0; i < driver->num; i++) - tty_register_device(driver, i); + tty_register_device(driver, i, NULL); } proc_tty_register_driver(driver); return error; @@ -2288,10 +2382,6 @@ extern int vty_init(void); #endif -static struct class tty_class = { - .name = "tty", -}; - static int __init tty_class_init(void) { return class_register(&tty_class); @@ -2308,33 +2398,29 @@ if (register_chrdev_region(TTYAUX_MAJOR, 0, 1, "/dev/tty", &tty_fops) < 0) panic("Couldn't register /dev/tty driver\n"); - - devfs_register (NULL, "tty", 0, TTYAUX_MAJOR, 0, - S_IFCHR | S_IRUGO | S_IWUGO, &tty_fops, NULL); + devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty"); + tty_add_class_device ("tty", MKDEV(TTYAUX_MAJOR, 0), NULL); if (register_chrdev_region(TTYAUX_MAJOR, 1, 1, "/dev/console", &tty_fops) < 0) panic("Couldn't register /dev/console driver\n"); - - devfs_register (NULL, "console", 0, TTYAUX_MAJOR, 1, - S_IFCHR | S_IRUSR | S_IWUSR, &tty_fops, NULL); + devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console"); + tty_add_class_device ("console", MKDEV(TTYAUX_MAJOR, 1), NULL); #ifdef CONFIG_UNIX98_PTYS if (register_chrdev_region(TTYAUX_MAJOR, 2, 1, "/dev/ptmx", &tty_fops) < 0) panic("Couldn't register /dev/ptmx driver\n"); - - devfs_register (NULL, "ptmx", 0, TTYAUX_MAJOR, 2, - S_IFCHR | S_IRUGO | S_IWUGO, &tty_fops, NULL); + devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx"); + tty_add_class_device ("ptmx", MKDEV(TTYAUX_MAJOR, 2), NULL); #endif #ifdef CONFIG_VT if (register_chrdev_region(TTY_MAJOR, 0, 1, "/dev/vc/0", &tty_fops) < 0) panic("Couldn't register /dev/tty0 driver\n"); - - devfs_register (NULL, "vc/0", 0, TTY_MAJOR, 0, - S_IFCHR | S_IRUSR | S_IWUSR, &tty_fops, NULL); + devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0"); + tty_add_class_device ("tty0", MKDEV(TTY_MAJOR, 0), NULL); vty_init(); #endif diff -Nru a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c --- a/drivers/char/vc_screen.c Thu May 8 00:24:28 2003 +++ b/drivers/char/vc_screen.c Thu May 8 00:24:28 2003 @@ -469,40 +469,27 @@ .open = vcs_open, }; -void vcs_make_devfs (unsigned int index, int unregister) +void vcs_make_devfs(struct tty_struct *tty) { -#ifdef CONFIG_DEVFS_FS - - if (unregister) { - devfs_remove("vcc/%u", index + 1); - devfs_remove("vcc/a%u", index + 1); - } else { - char name[16]; - sprintf(name, "vcc/%u", index + 1); - devfs_register(NULL, name, DEVFS_FL_DEFAULT, - VCS_MAJOR, index + 1, - S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL); - sprintf(name, "vcc/a%u", index + 1); - devfs_register(NULL, name, DEVFS_FL_DEFAULT, - VCS_MAJOR, index + 129, - S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL); - } -#endif /* CONFIG_DEVFS_FS */ + devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 1), + S_IFCHR|S_IRUSR|S_IWUSR, + "vcc/%u", tty->index + 1); + devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 129), + S_IFCHR|S_IRUSR|S_IWUSR, + "vcc/a%u", tty->index + 1); +} +void vcs_remove_devfs(struct tty_struct *tty) +{ + devfs_remove("vcc/%u", tty->index + 1); + devfs_remove("vcc/a%u", tty->index + 1); } int __init vcs_init(void) { - int error; - - error = register_chrdev(VCS_MAJOR, "vcs", &vcs_fops); - - if (error) - printk("unable to get major %d for vcs device", VCS_MAJOR); - - devfs_register(NULL, "vcc/0", DEVFS_FL_DEFAULT, VCS_MAJOR, 0, - S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL); - devfs_register(NULL, "vcc/a", DEVFS_FL_DEFAULT, VCS_MAJOR, 128, - S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL); + if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops)) + panic("unable to get major %d for vcs device", VCS_MAJOR); - return error; + devfs_mk_cdev(MKDEV(VCS_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/0"); + devfs_mk_cdev(MKDEV(VCS_MAJOR, 128), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/a0"); + return 0; } diff -Nru a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c --- a/drivers/char/vme_scc.c Thu May 8 00:24:27 2003 +++ b/drivers/char/vme_scc.c Thu May 8 00:24:27 2003 @@ -129,6 +129,7 @@ memset(&scc_driver, 0, sizeof(scc_driver)); scc_driver.magic = TTY_DRIVER_MAGIC; + scc_driver.owner = THIS_MODULE; scc_driver.driver_name = "scc"; #ifdef CONFIG_DEVFS_FS scc_driver.name = "tts/"; @@ -795,7 +796,6 @@ { scc_disable_tx_interrupts(ptr); scc_disable_rx_interrupts(ptr); - MOD_DEC_USE_COUNT; } @@ -803,7 +803,6 @@ { scc_disable_tx_interrupts(ptr); scc_disable_rx_interrupts(ptr); - MOD_DEC_USE_COUNT; } @@ -938,13 +937,9 @@ return retval; } port->gs.flags |= GS_ACTIVE; - if (port->gs.count == 1) { - MOD_INC_USE_COUNT; - } retval = gs_block_til_ready(port, filp); if (retval) { - MOD_DEC_USE_COUNT; port->gs.count--; return retval; } diff -Nru a/drivers/char/vt.c b/drivers/char/vt.c --- a/drivers/char/vt.c Thu May 8 00:24:30 2003 +++ b/drivers/char/vt.c Thu May 8 00:24:30 2003 @@ -124,7 +124,9 @@ #define DEFAULT_BELL_PITCH 750 #define DEFAULT_BELL_DURATION (HZ/8) -extern void vcs_make_devfs (unsigned int index, int unregister); +extern void vcs_make_devfs(struct tty_struct *tty); +extern void vcs_remove_devfs(struct tty_struct *tty); + extern void console_map_init(void); #ifdef CONFIG_PROM_CONSOLE extern void prom_con_init(void); @@ -158,7 +160,6 @@ static void hide_cursor(int currcons); static void unblank_screen_t(unsigned long dummy); static void console_callback(void *ignored); -static void __init con_init_devfs (void); static int printable; /* Is console ready for printing? */ @@ -2410,7 +2411,7 @@ tty->winsize.ws_col = video_num_columns; } if (tty->count == 1) - vcs_make_devfs (currcons, 0); + vcs_make_devfs(tty); return 0; } @@ -2418,10 +2419,10 @@ { struct vt_struct *vt; - if (!tty) + if (!tty || tty->count != 1) return; - if (tty->count != 1) return; - vcs_make_devfs (tty->index, 1); + + vcs_remove_devfs(tty); vt = (struct vt_struct*)tty->driver_data; if (vt) vc_cons[vt->vc_num].d->vc_tty = NULL; @@ -2525,11 +2526,6 @@ console_driver.type = TTY_DRIVER_TYPE_CONSOLE; console_driver.init_termios = tty_std_termios; console_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS; - /* Tell tty_register_driver() to skip consoles because they are - * registered before kmalloc() is ready. We'll patch them in later. - * See comments at console_init(); see also con_init_devfs(). - */ - console_driver.flags |= TTY_DRIVER_NO_DEVFS; console_driver.refcount = &console_refcount; console_driver.table = console_table; console_driver.termios = console_termios; @@ -2562,7 +2558,6 @@ #ifdef CONFIG_FRAMEBUFFER_CONSOLE fb_console_init(); #endif - con_init_devfs(); vcs_init(); return 0; } @@ -2655,18 +2650,6 @@ unsigned int mode; get_user(mode, argp); vesa_blank_mode = (mode < 4) ? mode : 0; -} - -/* We can't register the console with devfs during con_init(), because it - * is called before kmalloc() works. This function is called later to - * do the registration. - */ -static void __init con_init_devfs (void) -{ - int i; - - for (i = 0; i < console_driver.num; i++) - tty_register_device (&console_driver, i); } /* diff -Nru a/drivers/hotplug/Kconfig b/drivers/hotplug/Kconfig --- a/drivers/hotplug/Kconfig Thu May 8 00:24:28 2003 +++ b/drivers/hotplug/Kconfig Thu May 8 00:24:28 2003 @@ -61,7 +61,7 @@ config HOTPLUG_PCI_ACPI tristate "ACPI PCI Hotplug driver" - depends on ACPI && HOTPLUG_PCI + depends on ACPI_BUS && HOTPLUG_PCI help Say Y here if you have a system that supports PCI Hotplug using ACPI. diff -Nru a/drivers/hotplug/acpiphp_glue.c b/drivers/hotplug/acpiphp_glue.c --- a/drivers/hotplug/acpiphp_glue.c Thu May 8 00:24:28 2003 +++ b/drivers/hotplug/acpiphp_glue.c Thu May 8 00:24:28 2003 @@ -806,6 +806,7 @@ struct list_head *l; struct acpiphp_func *func; int retval = 0; + int num; if (slot->flags & SLOT_ENABLED) goto err_exit; @@ -825,7 +826,10 @@ goto err_exit; /* returned `dev' is the *first function* only! */ - dev = pci_scan_slot(slot->bridge->pci_bus, PCI_DEVFN(slot->device, 0)); + num = pci_scan_slot(slot->bridge->pci_bus, PCI_DEVFN(slot->device, 0)); + if (num) + pci_bus_add_devices(slot->bridge->pci_bus); + dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0)); if (!dev) { err("No new device found\n"); diff -Nru a/drivers/hotplug/cpqphp.h b/drivers/hotplug/cpqphp.h --- a/drivers/hotplug/cpqphp.h Thu May 8 00:24:29 2003 +++ b/drivers/hotplug/cpqphp.h Thu May 8 00:24:29 2003 @@ -31,7 +31,7 @@ #include "pci_hotplug.h" #include #include /* for read? and write? functions */ - +#include /* for delays */ #if !defined(CONFIG_HOTPLUG_PCI_COMPAQ_MODULE) #define MY_NAME "cpqphp.o" @@ -146,6 +146,10 @@ u8 reserved11; /* 0x2b */ u8 slot_SERR; /* 0x2c */ u8 slot_power; /* 0x2d */ + u8 reserved12; /* 0x2e */ + u8 reserved13; /* 0x2f */ + u8 next_curr_freq; /* 0x30 */ + u8 reset_freq_mode; /* 0x31 */ } __attribute__ ((packed)); /* offsets to the controller registers based on the above structure layout */ @@ -173,6 +177,8 @@ CTRL_RESERVED11 = offsetof(struct ctrl_reg, reserved11), SLOT_SERR = offsetof(struct ctrl_reg, slot_SERR), SLOT_POWER = offsetof(struct ctrl_reg, slot_power), + NEXT_CURR_FREQ = offsetof(struct ctrl_reg, next_curr_freq), + RESET_FREQ_MODE = offsetof(struct ctrl_reg, reset_freq_mode), }; struct hrt { @@ -294,12 +300,11 @@ struct pci_resource *bus_head; struct pci_dev *pci_dev; struct pci_bus *pci_bus; - struct proc_dir_entry* proc_entry; - struct proc_dir_entry* proc_entry2; struct event_info event_queue[10]; struct slot *slot; u8 next_event; u8 interrupt; + u8 cfgspc_irq; u8 bus; /* bus number for the pci hotplug controller */ u8 rev; u8 slot_device_offset; @@ -316,8 +321,6 @@ u8 pcix_speed_capability; /* PCI-X */ u8 pcix_support; /* PCI-X */ u16 vendor_id; - char proc_name[20]; - char proc_name2[20]; struct work_struct int_task_event; wait_queue_head_t queue; /* sleep & wake process */ }; @@ -344,6 +347,7 @@ #define PCI_SUB_HPC_ID2 0xA2F8 #define PCI_SUB_HPC_ID3 0xA2F9 #define PCI_SUB_HPC_ID_INTC 0xA2FA +#define PCI_SUB_HPC_ID4 0xA2FD #define INT_BUTTON_IGNORE 0 #define INT_PRESENCE_ON 1 @@ -436,7 +440,7 @@ extern void cpqhp_destroy_resource_list (struct resource_lists * resources); extern int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func); extern int cpqhp_unconfigure_device (struct pci_func* func); - +extern struct slot *cpqhp_find_slot (struct controller *ctrl, u8 device); /* Global variables */ extern int cpqhp_debug; @@ -564,6 +568,7 @@ u32 led_control; led_control = readl(ctrl->hpc_reg + LED_CONTROL); + led_control &= ~(0x0101L << slot); led_control |= (0x0001L << slot); writel(led_control, ctrl->hpc_reg + LED_CONTROL); } @@ -605,14 +610,63 @@ } +/* + * get_controller_speed - find the current frequency/mode of controller. + * + * @ctrl: controller to get frequency/mode for. + * + * Returns controller speed. + * + */ static inline u8 get_controller_speed (struct controller *ctrl) { - u16 misc; - - misc = readw(ctrl->hpc_reg + MISC); - return (misc & 0x0800) ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; + u8 curr_freq; + u16 misc; + + if (ctrl->pcix_support) { + curr_freq = readb(ctrl->hpc_reg + NEXT_CURR_FREQ); + if ((curr_freq & 0xB0) == 0xB0) + return PCI_SPEED_133MHz_PCIX; + if ((curr_freq & 0xA0) == 0xA0) + return PCI_SPEED_100MHz_PCIX; + if ((curr_freq & 0x90) == 0x90) + return PCI_SPEED_66MHz_PCIX; + if (curr_freq & 0x10) + return PCI_SPEED_66MHz; + + return PCI_SPEED_33MHz; + } + + misc = readw(ctrl->hpc_reg + MISC); + return (misc & 0x0800) ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; } + + +/* + * get_adapter_speed - find the max supported frequency/mode of adapter. + * + * @ctrl: hotplug controller. + * @hp_slot: hotplug slot where adapter is installed. + * + * Returns adapter speed. + * + */ +static inline u8 get_adapter_speed (struct controller *ctrl, u8 hp_slot) +{ + u32 temp_dword = readl(ctrl->hpc_reg + NON_INT_INPUT); + dbg("slot: %d, PCIXCAP: %8x\n", hp_slot, temp_dword); + if (ctrl->pcix_support) { + if (temp_dword & (0x10000 << hp_slot)) + return PCI_SPEED_133MHz_PCIX; + if (temp_dword & (0x100 << hp_slot)) + return PCI_SPEED_66MHz_PCIX; + } + if (temp_dword & (0x01 << hp_slot)) + return PCI_SPEED_66MHz; + + return PCI_SPEED_33MHz; +} static inline void enable_slot_power (struct controller *ctrl, u8 slot) { @@ -719,6 +773,139 @@ dbg("%s - end\n", __FUNCTION__); return retval; +} + + +/** + * set_controller_speed - set the frequency and/or mode of a specific + * controller segment. + * + * @ctrl: controller to change frequency/mode for. + * @adapter_speed: the speed of the adapter we want to match. + * @hp_slot: the slot number where the adapter is installed. + * + * Returns 0 if we successfully change frequency and/or mode to match the + * adapter speed. + * + */ +static inline u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot) +{ + struct slot *slot; + u8 reg; + u8 slot_power = readb(ctrl->hpc_reg + SLOT_POWER); + u16 reg16; + u32 leds = readl(ctrl->hpc_reg + LED_CONTROL); + + if (ctrl->speed == adapter_speed) + return 0; + + /* We don't allow freq/mode changes if we find another adapter running + * in another slot on this controller */ + for(slot = ctrl->slot; slot; slot = slot->next) { + if (slot->device == (hp_slot + ctrl->slot_device_offset)) + continue; + if (!slot->hotplug_slot && !slot->hotplug_slot->info) + continue; + if (slot->hotplug_slot->info->adapter_status == 0) + continue; + /* If another adapter is running on the same segment but at a + * lower speed/mode, we allow the new adapter to function at + * this rate if supported */ + if (ctrl->speed < adapter_speed) + return 0; + + return 1; + } + + /* If the controller doesn't support freq/mode changes and the + * controller is running at a higher mode, we bail */ + if ((ctrl->speed > adapter_speed) && (!ctrl->pcix_speed_capability)) + return 1; + + /* But we allow the adapter to run at a lower rate if possible */ + if ((ctrl->speed < adapter_speed) && (!ctrl->pcix_speed_capability)) + return 0; + + /* We try to set the max speed supported by both the adapter and + * controller */ + if (ctrl->speed_capability < adapter_speed) { + if (ctrl->speed == ctrl->speed_capability) + return 0; + adapter_speed = ctrl->speed_capability; + } + + writel(0x0L, ctrl->hpc_reg + LED_CONTROL); + writeb(0x00, ctrl->hpc_reg + SLOT_ENABLE); + + set_SOGO(ctrl); + wait_for_ctrl_irq(ctrl); + + if (adapter_speed != PCI_SPEED_133MHz_PCIX) + reg = 0xF5; + else + reg = 0xF4; + pci_write_config_byte(ctrl->pci_dev, 0x41, reg); + + reg16 = readw(ctrl->hpc_reg + NEXT_CURR_FREQ); + reg16 &= ~0x000F; + switch(adapter_speed) { + case(PCI_SPEED_133MHz_PCIX): + reg = 0x75; + reg16 |= 0xB; + break; + case(PCI_SPEED_100MHz_PCIX): + reg = 0x74; + reg16 |= 0xA; + break; + case(PCI_SPEED_66MHz_PCIX): + reg = 0x73; + reg16 |= 0x9; + break; + case(PCI_SPEED_66MHz): + reg = 0x73; + reg16 |= 0x1; + break; + default: /* 33MHz PCI 2.2 */ + reg = 0x71; + break; + + } + reg16 |= 0xB << 12; + writew(reg16, ctrl->hpc_reg + NEXT_CURR_FREQ); + + mdelay(5); + + /* Reenable interrupts */ + writel(0, ctrl->hpc_reg + INT_MASK); + + pci_write_config_byte(ctrl->pci_dev, 0x41, reg); + + /* Restart state machine */ + reg = ~0xF; + pci_read_config_byte(ctrl->pci_dev, 0x43, ®); + pci_write_config_byte(ctrl->pci_dev, 0x43, reg); + + /* Only if mode change...*/ + if (((ctrl->speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) || + ((ctrl->speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz))) + set_SOGO(ctrl); + + wait_for_ctrl_irq(ctrl); + mdelay(1100); + + /* Restore LED/Slot state */ + writel(leds, ctrl->hpc_reg + LED_CONTROL); + writeb(slot_power, ctrl->hpc_reg + SLOT_ENABLE); + + set_SOGO(ctrl); + wait_for_ctrl_irq(ctrl); + + ctrl->speed = adapter_speed; + slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + + info("Successfully changed frequency/mode for adapter in slot %d\n", + slot->number); + return 0; } #endif diff -Nru a/drivers/hotplug/cpqphp_core.c b/drivers/hotplug/cpqphp_core.c --- a/drivers/hotplug/cpqphp_core.c Thu May 8 00:24:27 2003 +++ b/drivers/hotplug/cpqphp_core.c Thu May 8 00:24:27 2003 @@ -24,6 +24,9 @@ * * Send feedback to * + * Jan 12, 2003 - Added 66/100/133MHz PCI-X support, + * Torben Mathiasen + * */ #include @@ -57,7 +60,7 @@ static u8 power_mode; static int debug; -#define DRIVER_VERSION "0.9.6" +#define DRIVER_VERSION "0.9.7" #define DRIVER_AUTHOR "Dan Zink , Greg Kroah-Hartman " #define DRIVER_DESC "Compaq Hot Plug PCI Controller Driver" @@ -835,6 +838,7 @@ u8 hp_slot = 0; u8 device; u8 rev; + u8 bus_cap; u16 temp_word; u16 vendor_id; u16 subsystem_vid; @@ -896,6 +900,39 @@ switch (subsystem_vid) { case PCI_VENDOR_ID_COMPAQ: + if (rev >= 0x13) { /* CIOBX */ + ctrl->push_flag = 1; + ctrl->slot_switch_type = 1; // Switch is present + ctrl->push_button = 1; // Pushbutton is present + ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported + ctrl->defeature_PHP = 1; // PHP is supported + ctrl->pcix_support = 1; // PCI-X supported + ctrl->pcix_speed_capability = 1; + pci_read_config_byte(pdev, 0x41, &bus_cap); + if (bus_cap & 0x80) { + dbg("bus max supports 133MHz PCI-X\n"); + ctrl->speed_capability = PCI_SPEED_133MHz_PCIX; + break; + } + if (bus_cap & 0x40) { + dbg("bus max supports 100MHz PCI-X\n"); + ctrl->speed_capability = PCI_SPEED_100MHz_PCIX; + break; + } + if (bus_cap & 20) { + dbg("bus max supports 66MHz PCI-X\n"); + ctrl->speed_capability = PCI_SPEED_66MHz_PCIX; + break; + } + if (bus_cap & 10) { + dbg("bus max supports 66MHz PCI\n"); + ctrl->speed_capability = PCI_SPEED_66MHz; + break; + } + + break; + } + switch (subsystem_deviceid) { case PCI_SUB_HPC_ID: /* Original 6500/7000 implementation */ @@ -939,8 +976,18 @@ ctrl->pcix_support = 0; // PCI-X not supported ctrl->pcix_speed_capability = 0; // N/A since PCI-X not supported break; + case PCI_SUB_HPC_ID4: + /* First PCI-X implementation, 100MHz */ + ctrl->push_flag = 1; + ctrl->slot_switch_type = 1; // Switch is present + ctrl->speed_capability = PCI_SPEED_100MHz_PCIX; + ctrl->push_button = 1; // Pushbutton is present + ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported + ctrl->defeature_PHP = 1; // PHP is supported + ctrl->pcix_support = 1; // PCI-X supported + ctrl->pcix_speed_capability = 0; + break; default: - // TODO: Add SSIDs for CPQ systems that support PCI-X err(msg_HPC_not_supported); rc = -ENODEV; goto err_free_ctrl; @@ -1029,7 +1076,7 @@ info("Initializing the PCI hot plug controller residing on PCI bus %d\n", pdev->bus->number); dbg ("Hotplug controller capabilities:\n"); - dbg (" speed_capability %s\n", ctrl->speed_capability == PCI_SPEED_33MHz ? "33MHz" : "66Mhz"); + dbg (" speed_capability %d\n", ctrl->speed_capability); dbg (" slot_switch_type %s\n", ctrl->slot_switch_type == 0 ? "no switch" : "switch present"); dbg (" defeature_PHP %s\n", ctrl->defeature_PHP == 0 ? "PHP not supported" : "PHP supported"); dbg (" alternate_base_address %s\n", ctrl->alternate_base_address == 0 ? "not supported" : "supported"); @@ -1082,7 +1129,6 @@ } // Check for 66Mhz operation - // TODO: Add PCI-X support ctrl->speed = get_controller_speed(ctrl); @@ -1118,6 +1164,9 @@ */ // The next line is required for cpqhp_find_available_resources ctrl->interrupt = pdev->irq; + + ctrl->cfgspc_irq = 0; + pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &ctrl->cfgspc_irq); rc = cpqhp_find_available_resources(ctrl, cpqhp_rom_start); ctrl->add_support = !rc; diff -Nru a/drivers/hotplug/cpqphp_ctrl.c b/drivers/hotplug/cpqphp_ctrl.c --- a/drivers/hotplug/cpqphp_ctrl.c Thu May 8 00:24:28 2003 +++ b/drivers/hotplug/cpqphp_ctrl.c Thu May 8 00:24:28 2003 @@ -136,9 +136,9 @@ /* - * find_slot + * cpqhp_find_slot */ -static inline struct slot *find_slot (struct controller * ctrl, u8 device) +struct slot *cpqhp_find_slot (struct controller * ctrl, u8 device) { struct slot *slot; @@ -187,7 +187,7 @@ rc++; - p_slot = find_slot(ctrl, hp_slot + (readb(ctrl->hpc_reg + SLOT_MASK) >> 4)); + p_slot = cpqhp_find_slot(ctrl, hp_slot + (readb(ctrl->hpc_reg + SLOT_MASK) >> 4)); if (!p_slot) return 0; @@ -920,6 +920,7 @@ { struct controller *ctrl = data; u8 schedule_flag = 0; + u8 reset; u16 misc; u32 Diff; u32 temp_dword; @@ -971,6 +972,15 @@ schedule_flag += handle_power_fault((u8)((Diff & 0xFF00L) >> 8), ctrl); } + reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE); + if (reset & 0x40) { + /* Bus reset has completed */ + reset &= 0xCF; + writeb(reset, ctrl->hpc_reg + RESET_FREQ_MODE); + reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE); + wake_up_interruptible(&ctrl->queue); + } + if (schedule_flag) { up(&event_semaphore); dbg("Signal event_semaphore\n"); @@ -1172,6 +1182,7 @@ { u8 hp_slot; u8 temp_byte; + u8 adapter_speed; u32 index; u32 rc = 0; u32 src = 8; @@ -1189,46 +1200,46 @@ //********************************* rc = CARD_FUNCTIONING; } else { - if (ctrl->speed == PCI_SPEED_66MHz) { - // Wait for exclusive access to hardware - down(&ctrl->crit_sect); - - // turn on board without attaching to the bus - enable_slot_power (ctrl, hp_slot); + // Wait for exclusive access to hardware + down(&ctrl->crit_sect); - set_SOGO(ctrl); + // turn on board without attaching to the bus + enable_slot_power (ctrl, hp_slot); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + set_SOGO(ctrl); - // Change bits in slot power register to force another shift out - // NOTE: this is to work around the timer bug - temp_byte = readb(ctrl->hpc_reg + SLOT_POWER); - writeb(0x00, ctrl->hpc_reg + SLOT_POWER); - writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER); + // Wait for SOBS to be unset + wait_for_ctrl_irq (ctrl); - set_SOGO(ctrl); + // Change bits in slot power register to force another shift out + // NOTE: this is to work around the timer bug + temp_byte = readb(ctrl->hpc_reg + SLOT_POWER); + writeb(0x00, ctrl->hpc_reg + SLOT_POWER); + writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + set_SOGO(ctrl); - if (!(readl(ctrl->hpc_reg + NON_INT_INPUT) & (0x01 << hp_slot))) { + // Wait for SOBS to be unset + wait_for_ctrl_irq (ctrl); + + adapter_speed = get_adapter_speed(ctrl, hp_slot); + if (ctrl->speed != adapter_speed) + if (set_controller_speed(ctrl, adapter_speed, hp_slot)) rc = WRONG_BUS_FREQUENCY; - } - // turn off board without attaching to the bus - disable_slot_power (ctrl, hp_slot); - set_SOGO(ctrl); + // turn off board without attaching to the bus + disable_slot_power (ctrl, hp_slot); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + set_SOGO(ctrl); - // Done with exclusive hardware access - up(&ctrl->crit_sect); + // Wait for SOBS to be unset + wait_for_ctrl_irq (ctrl); - if (rc) - return(rc); - } + // Done with exclusive hardware access + up(&ctrl->crit_sect); + + if (rc) + return(rc); // Wait for exclusive access to hardware down(&ctrl->crit_sect); @@ -1376,6 +1387,7 @@ { u8 hp_slot; u8 temp_byte; + u8 adapter_speed; int index; u32 temp_register = 0xFFFFFFFF; u32 rc = 0; @@ -1387,47 +1399,48 @@ dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot); - if (ctrl->speed == PCI_SPEED_66MHz) { - // Wait for exclusive access to hardware - down(&ctrl->crit_sect); - - // turn on board without attaching to the bus - enable_slot_power (ctrl, hp_slot); + // Wait for exclusive access to hardware + down(&ctrl->crit_sect); - set_SOGO(ctrl); + // turn on board without attaching to the bus + enable_slot_power (ctrl, hp_slot); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + set_SOGO(ctrl); - // Change bits in slot power register to force another shift out - // NOTE: this is to work around the timer bug - temp_byte = readb(ctrl->hpc_reg + SLOT_POWER); - writeb(0x00, ctrl->hpc_reg + SLOT_POWER); - writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER); + // Wait for SOBS to be unset + wait_for_ctrl_irq (ctrl); - set_SOGO(ctrl); + // Change bits in slot power register to force another shift out + // NOTE: this is to work around the timer bug + temp_byte = readb(ctrl->hpc_reg + SLOT_POWER); + writeb(0x00, ctrl->hpc_reg + SLOT_POWER); + writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + set_SOGO(ctrl); - if (!(readl(ctrl->hpc_reg + NON_INT_INPUT) & (0x01 << hp_slot))) { + // Wait for SOBS to be unset + wait_for_ctrl_irq (ctrl); + + adapter_speed = get_adapter_speed(ctrl, hp_slot); + if (ctrl->speed != adapter_speed) + if (set_controller_speed(ctrl, adapter_speed, hp_slot)) rc = WRONG_BUS_FREQUENCY; - } - // turn off board without attaching to the bus - disable_slot_power (ctrl, hp_slot); + + // turn off board without attaching to the bus + disable_slot_power (ctrl, hp_slot); - set_SOGO(ctrl); + set_SOGO(ctrl); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + // Wait for SOBS to be unset + wait_for_ctrl_irq (ctrl); - // Done with exclusive hardware access - up(&ctrl->crit_sect); + // Done with exclusive hardware access + up(&ctrl->crit_sect); - if (rc) - return(rc); - } - p_slot = find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + if (rc) + return(rc); + + p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); // turn on board and blink green LED @@ -1800,7 +1813,7 @@ if (!func) return; - p_slot = find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); if (!p_slot) return; @@ -1860,11 +1873,12 @@ } // Wait for exclusive access to hardware down(&ctrl->crit_sect); - + dbg("blink green LED and turn off amber\n"); + amber_LED_off (ctrl, hp_slot); green_LED_blink (ctrl, hp_slot); - + set_SOGO(ctrl); // Wait for SOBS to be unset @@ -1992,7 +2006,7 @@ device = func->device; hp_slot = device - ctrl->slot_device_offset; - p_slot = find_slot(ctrl, device); + p_slot = cpqhp_find_slot(ctrl, device); if (p_slot) { physical_slot = p_slot->number; } @@ -2091,7 +2105,7 @@ device = func->device; func = cpqhp_slot_find(ctrl->bus, device, index++); - p_slot = find_slot(ctrl, device); + p_slot = cpqhp_find_slot(ctrl, device); if (p_slot) { physical_slot = p_slot->number; } diff -Nru a/drivers/hotplug/cpqphp_pci.c b/drivers/hotplug/cpqphp_pci.c --- a/drivers/hotplug/cpqphp_pci.c Thu May 8 00:24:30 2003 +++ b/drivers/hotplug/cpqphp_pci.c Thu May 8 00:24:30 2003 @@ -85,18 +85,20 @@ { unsigned char bus; struct pci_bus *child; - int rc = 0; + int num; if (func->pci_dev == NULL) - func->pci_dev = pci_find_slot(func->bus, (func->device << 3) | (func->function & 0x7)); + func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function)); - //Still NULL ? Well then scan for it ! + /* No pci device, we need to create it then */ if (func->pci_dev == NULL) { dbg("INFO: pci_dev still null\n"); - //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(ctrl->pci_dev->bus, - (func->device << 3) + (func->function & 0x7)); + num = pci_scan_slot(ctrl->pci_dev->bus, PCI_DEVFN(func->device, func->function)); + if (num) + pci_bus_add_devices(ctrl->pci_dev->bus); + + func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function)); if (func->pci_dev == NULL) { dbg("ERROR: pci_dev still null\n"); return 0; @@ -107,10 +109,9 @@ pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus); child = (struct pci_bus*) pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus); pci_do_scan_bus(child); - } - return rc; + return 0; } @@ -1209,11 +1210,11 @@ temp = 0; if (!cpqhp_nic_irq) { - cpqhp_nic_irq = ctrl->interrupt; + cpqhp_nic_irq = ctrl->cfgspc_irq; } if (!cpqhp_disk_irq) { - cpqhp_disk_irq = ctrl->interrupt; + cpqhp_disk_irq = ctrl->cfgspc_irq; } dbg("cpqhp_disk_irq, cpqhp_nic_irq= %d, %d\n", cpqhp_disk_irq, cpqhp_nic_irq); diff -Nru a/drivers/hotplug/ibmphp_core.c b/drivers/hotplug/ibmphp_core.c --- a/drivers/hotplug/ibmphp_core.c Thu May 8 00:24:30 2003 +++ b/drivers/hotplug/ibmphp_core.c Thu May 8 00:24:30 2003 @@ -846,22 +846,24 @@ { unsigned char bus; struct pci_bus *child; - int rc = 0; + int num; int flag = 0; /* this is to make sure we don't double scan the bus, for bridged devices primarily */ 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)); + func->dev = pci_find_slot (func->busno, PCI_DEVFN(func->device, func->function)); if (func->dev == NULL) { struct pci_bus *bus = ibmphp_find_bus (func->busno); if (!bus) return 0; - func->dev = pci_scan_slot(bus, - (func->device << 3) + (func->function & 0x7)); + num = pci_scan_slot(bus, PCI_DEVFN(func->device, func->function)); + if (num) + pci_bus_add_devices(bus); + func->dev = pci_find_slot(func->busno, PCI_DEVFN(func->device, func->function)); if (func->dev == NULL) { err ("ERROR... : pci_dev still NULL \n"); return 0; @@ -873,7 +875,7 @@ pci_do_scan_bus (child); } - return rc; + return 0; } /******************************************************* @@ -1415,7 +1417,7 @@ /* lock ourselves into memory with a module * count of -1 so that no one can unload us. */ - MOD_DEC_USE_COUNT; + module_put(THIS_MODULE); exit: return rc; diff -Nru a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c --- a/drivers/i2c/busses/i2c-ali15x3.c Thu May 8 00:24:29 2003 +++ b/drivers/i2c/busses/i2c-ali15x3.c Thu May 8 00:24:29 2003 @@ -475,6 +475,7 @@ static struct i2c_adapter ali15x3_adapter = { .owner = THIS_MODULE, .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI15X3, + .class = I2C_ADAP_CLASS_SMBUS, .algo = &smbus_algorithm, .dev = { .name = "unset", diff -Nru a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c --- a/drivers/i2c/busses/i2c-amd756.c Thu May 8 00:24:30 2003 +++ b/drivers/i2c/busses/i2c-amd756.c Thu May 8 00:24:30 2003 @@ -313,6 +313,7 @@ static struct i2c_adapter amd756_adapter = { .owner = THIS_MODULE, .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD756, + .class = I2C_ADAP_CLASS_SMBUS, .algo = &smbus_algorithm, .dev = { .name = "unset", diff -Nru a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c --- a/drivers/i2c/busses/i2c-amd8111.c Thu May 8 00:24:29 2003 +++ b/drivers/i2c/busses/i2c-amd8111.c Thu May 8 00:24:29 2003 @@ -360,6 +360,7 @@ snprintf(smbus->adapter.dev.name, DEVICE_NAME_SIZE, "SMBus2 AMD8111 adapter at %04x", smbus->base); smbus->adapter.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD8111; + smbus->adapter.class = I2C_ADAP_CLASS_SMBUS; smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo_data = smbus; diff -Nru a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c --- a/drivers/i2c/busses/i2c-i801.c Thu May 8 00:24:28 2003 +++ b/drivers/i2c/busses/i2c-i801.c Thu May 8 00:24:28 2003 @@ -547,6 +547,7 @@ static struct i2c_adapter i801_adapter = { .owner = THIS_MODULE, .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_I801, + .class = I2C_ADAP_CLASS_SMBUS, .algo = &smbus_algorithm, .dev = { .name = "unset", diff -Nru a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c --- a/drivers/i2c/busses/i2c-isa.c Thu May 8 00:24:29 2003 +++ b/drivers/i2c/busses/i2c-isa.c Thu May 8 00:24:29 2003 @@ -40,6 +40,7 @@ static struct i2c_adapter isa_adapter = { .owner = THIS_MODULE, .id = I2C_ALGO_ISA | I2C_HW_ISA, + .class = I2C_ADAP_CLASS_SMBUS, .algo = &isa_algorithm, .dev = { .name = "ISA main adapter", diff -Nru a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c --- a/drivers/i2c/busses/i2c-piix4.c Thu May 8 00:24:28 2003 +++ b/drivers/i2c/busses/i2c-piix4.c Thu May 8 00:24:28 2003 @@ -395,6 +395,7 @@ static struct i2c_adapter piix4_adapter = { .owner = THIS_MODULE, .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_PIIX4, + .class = I2C_ADAP_CLASS_SMBUS, .algo = &smbus_algorithm, .dev = { .name = "unset", diff -Nru a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c --- a/drivers/i2c/busses/i2c-viapro.c Thu May 8 00:24:29 2003 +++ b/drivers/i2c/busses/i2c-viapro.c Thu May 8 00:24:29 2003 @@ -295,6 +295,7 @@ static struct i2c_adapter vt596_adapter = { .owner = THIS_MODULE, .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_VIA2, + .class = I2C_ADAP_CLASS_SMBUS, .algo = &smbus_algorithm, .dev = { .name = "unset", diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c --- a/drivers/i2c/chips/adm1021.c Thu May 8 00:24:27 2003 +++ b/drivers/i2c/chips/adm1021.c Thu May 8 00:24:27 2003 @@ -203,6 +203,8 @@ static int adm1021_attach_adapter(struct i2c_adapter *adapter) { + if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + return 0; return i2c_detect(adapter, &addr_data, adm1021_detect); } diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c --- a/drivers/i2c/chips/it87.c Thu May 8 00:24:29 2003 +++ b/drivers/i2c/chips/it87.c Thu May 8 00:24:29 2003 @@ -3,7 +3,7 @@ monitoring. Supports: IT8705F Super I/O chip w/LPC interface - IT8712F Super I/O chup w/LPC interface & SMbus + IT8712F Super I/O chip w/LPC interface & SMbus Sis950 A clone of the IT8705F Copyright (c) 2001 Chris Gauthron @@ -238,6 +238,7 @@ u8 temp[3]; /* Register value */ u8 temp_high[3]; /* Register value */ u8 temp_low[3]; /* Register value */ + u8 sensor; /* Register value */ u8 fan_div[3]; /* Register encoding, shifted right */ u8 vid; /* Register encoding, combined */ u32 alarms; /* Register encoding, combined */ @@ -252,7 +253,7 @@ static int it87_write_value(struct i2c_client *client, u8 register, u8 value); static void it87_update_client(struct i2c_client *client); -static void it87_init_client(struct i2c_client *client); +static void it87_init_client(struct i2c_client *client, struct it87_data *data); static struct i2c_driver it87_driver = { @@ -350,6 +351,10 @@ show_in_offset(2); show_in_offset(3); show_in_offset(4); +show_in_offset(5); +show_in_offset(6); +show_in_offset(7); +show_in_offset(8); /* 3 temperatures */ static ssize_t show_temp(struct device *dev, char *buf, int nr) @@ -430,7 +435,52 @@ show_temp_offset(2); show_temp_offset(3); -/* 2 Fans */ +/* more like overshoot temperature */ +static ssize_t show_sensor(struct device *dev, char *buf, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + struct it87_data *data = i2c_get_clientdata(client); + it87_update_client(client); + if (data->sensor & (1 << nr)) + return sprintf(buf, "1\n"); + if (data->sensor & (8 << nr)) + return sprintf(buf, "2\n"); + return sprintf(buf, "0\n"); +} +static ssize_t set_sensor(struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + struct it87_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + + data->sensor &= ~(1 << nr); + data->sensor &= ~(8 << nr); + if (val == 1) + data->sensor |= 1 << nr; + else if (val == 2) + data->sensor |= 8 << nr; + it87_write_value(client, IT87_REG_TEMP_ENABLE, data->sensor); + return count; +} +#define show_sensor_offset(offset) \ +static ssize_t show_sensor_##offset (struct device *dev, char *buf) \ +{ \ + return show_sensor(dev, buf, 0x##offset - 1); \ +} \ +static ssize_t set_sensor_##offset (struct device *dev, \ + const char *buf, size_t count) \ +{ \ + return set_sensor(dev, buf, count, 0x##offset - 1); \ +} \ +static DEVICE_ATTR(sensor##offset, S_IRUGO | S_IWUSR, \ + show_sensor_##offset, set_sensor_##offset) + +show_sensor_offset(1); +show_sensor_offset(2); +show_sensor_offset(3); + +/* 3 Fans */ static ssize_t show_fan(struct device *dev, char *buf, int nr) { struct i2c_client *client = to_i2c_client(dev); @@ -508,6 +558,7 @@ show_fan_offset(1); show_fan_offset(2); +show_fan_offset(3); /* Alarm */ static ssize_t show_alarm(struct device *dev, char *buf) @@ -525,6 +576,8 @@ * when a new adapter is inserted (and it87_driver is still present) */ static int it87_attach_adapter(struct i2c_adapter *adapter) { + if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + return 0; return i2c_detect(adapter, &addr_data, it87_detect); } @@ -574,6 +627,7 @@ } } } + memset (new_client, 0x00, sizeof(struct i2c_client) + sizeof(struct it87_data)); /* OK. For now, we presume we have a valid client. We now create the client structure, even though we cannot fill it completely yet. @@ -585,6 +639,8 @@ err = -ENOMEM; goto ERROR1; } + memset(new_client, 0x00, sizeof(struct i2c_client) + + sizeof(struct it87_data)); data = (struct it87_data *) (new_client + 1); if (is_isa) @@ -652,16 +708,28 @@ device_create_file(&new_client->dev, &dev_attr_in_input2); device_create_file(&new_client->dev, &dev_attr_in_input3); device_create_file(&new_client->dev, &dev_attr_in_input4); + device_create_file(&new_client->dev, &dev_attr_in_input5); + device_create_file(&new_client->dev, &dev_attr_in_input6); + device_create_file(&new_client->dev, &dev_attr_in_input7); + device_create_file(&new_client->dev, &dev_attr_in_input8); device_create_file(&new_client->dev, &dev_attr_in_min0); device_create_file(&new_client->dev, &dev_attr_in_min1); device_create_file(&new_client->dev, &dev_attr_in_min2); device_create_file(&new_client->dev, &dev_attr_in_min3); device_create_file(&new_client->dev, &dev_attr_in_min4); + device_create_file(&new_client->dev, &dev_attr_in_min5); + device_create_file(&new_client->dev, &dev_attr_in_min6); + device_create_file(&new_client->dev, &dev_attr_in_min7); + device_create_file(&new_client->dev, &dev_attr_in_min8); device_create_file(&new_client->dev, &dev_attr_in_max0); device_create_file(&new_client->dev, &dev_attr_in_max1); device_create_file(&new_client->dev, &dev_attr_in_max2); device_create_file(&new_client->dev, &dev_attr_in_max3); device_create_file(&new_client->dev, &dev_attr_in_max4); + device_create_file(&new_client->dev, &dev_attr_in_max5); + device_create_file(&new_client->dev, &dev_attr_in_max6); + device_create_file(&new_client->dev, &dev_attr_in_max7); + device_create_file(&new_client->dev, &dev_attr_in_max8); device_create_file(&new_client->dev, &dev_attr_temp_input1); device_create_file(&new_client->dev, &dev_attr_temp_input2); device_create_file(&new_client->dev, &dev_attr_temp_input3); @@ -671,16 +739,22 @@ device_create_file(&new_client->dev, &dev_attr_temp_min1); device_create_file(&new_client->dev, &dev_attr_temp_min2); device_create_file(&new_client->dev, &dev_attr_temp_min3); + device_create_file(&new_client->dev, &dev_attr_sensor1); + device_create_file(&new_client->dev, &dev_attr_sensor2); + device_create_file(&new_client->dev, &dev_attr_sensor3); device_create_file(&new_client->dev, &dev_attr_fan_input1); device_create_file(&new_client->dev, &dev_attr_fan_input2); + device_create_file(&new_client->dev, &dev_attr_fan_input3); device_create_file(&new_client->dev, &dev_attr_fan_min1); device_create_file(&new_client->dev, &dev_attr_fan_min2); + device_create_file(&new_client->dev, &dev_attr_fan_min3); device_create_file(&new_client->dev, &dev_attr_fan_div1); device_create_file(&new_client->dev, &dev_attr_fan_div2); + device_create_file(&new_client->dev, &dev_attr_fan_div3); device_create_file(&new_client->dev, &dev_attr_alarm); /* Initialize the IT87 chip */ - it87_init_client(new_client); + it87_init_client(new_client, data); return 0; ERROR1: @@ -753,7 +827,7 @@ } /* Called when we have found a new IT87. It should set limits, etc. */ -static void it87_init_client(struct i2c_client *client) +static void it87_init_client(struct i2c_client *client, struct it87_data *data) { /* Reset all except Watchdog values and last conversion values This sets fan-divs to 2, among others */ @@ -814,9 +888,9 @@ it87_write_value(client, IT87_REG_VIN_ENABLE, 0xff); /* Enable Temp1-Temp3 */ - it87_write_value(client, IT87_REG_TEMP_ENABLE, - (it87_read_value(client, IT87_REG_TEMP_ENABLE) & 0xc0) - | (temp_type & 0x3f)); + data->sensor = (it87_read_value(client, IT87_REG_TEMP_ENABLE) & 0xc0); + data->sensor |= temp_type & 0x3f; + it87_write_value(client, IT87_REG_TEMP_ENABLE, data->sensor); /* Enable fans */ it87_write_value(client, IT87_REG_FAN_CTRL, diff -Nru a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c --- a/drivers/i2c/chips/lm75.c Thu May 8 00:24:27 2003 +++ b/drivers/i2c/chips/lm75.c Thu May 8 00:24:27 2003 @@ -121,6 +121,8 @@ static int lm75_attach_adapter(struct i2c_adapter *adapter) { + if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + return 0; return i2c_detect(adapter, &addr_data, lm75_detect); } diff -Nru a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c --- a/drivers/i2c/chips/via686a.c Thu May 8 00:24:27 2003 +++ b/drivers/i2c/chips/via686a.c Thu May 8 00:24:27 2003 @@ -661,6 +661,8 @@ /* This is called when the module is loaded */ static int via686a_attach_adapter(struct i2c_adapter *adapter) { + if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + return 0; return i2c_detect(adapter, &addr_data, via686a_detect); } diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c --- a/drivers/i2c/chips/w83781d.c Thu May 8 00:24:27 2003 +++ b/drivers/i2c/chips/w83781d.c Thu May 8 00:24:27 2003 @@ -1026,6 +1026,8 @@ static int w83781d_attach_adapter(struct i2c_adapter *adapter) { + if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + return 0; return i2c_detect(adapter, &addr_data, w83781d_detect); } diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c --- a/drivers/i2c/i2c-core.c Thu May 8 00:24:27 2003 +++ b/drivers/i2c/i2c-core.c Thu May 8 00:24:27 2003 @@ -38,8 +38,8 @@ #define DEB(x) if (i2c_debug>=1) x; #define DEB2(x) if (i2c_debug>=2) x; -static struct i2c_adapter *adapters[I2C_ADAP_MAX]; -static struct i2c_driver *drivers[I2C_DRIVER_MAX]; +static LIST_HEAD(adapters); +static LIST_HEAD(drivers); static DECLARE_MUTEX(core_lists); /**** debug level */ @@ -75,23 +75,17 @@ */ int i2c_add_adapter(struct i2c_adapter *adap) { - int res = 0, i, j; + static int nr = 0; + struct list_head *item; + struct i2c_driver *driver; down(&core_lists); - for (i = 0; i < I2C_ADAP_MAX; i++) - if (NULL == adapters[i]) - break; - if (I2C_ADAP_MAX == i) { - dev_warn(&adap->dev, - "register_adapter - enlarge I2C_ADAP_MAX.\n"); - res = -ENOMEM; - goto out_unlock; - } - adapters[i] = adap; - - init_MUTEX(&adap->bus); - init_MUTEX(&adap->list); + adap->nr = nr++; + init_MUTEX(&adap->bus_lock); + init_MUTEX(&adap->clist_lock); + list_add_tail(&adap->list,&adapters); + INIT_LIST_HEAD(&adap->clients); /* Add the adapter to the driver core. * If the parent pointer is not set up, @@ -99,77 +93,65 @@ */ if (adap->dev.parent == NULL) adap->dev.parent = &legacy_bus; - sprintf(adap->dev.bus_id, "i2c-%d", i); + sprintf(adap->dev.bus_id, "i2c-%d", adap->nr); adap->dev.driver = &i2c_generic_driver; device_register(&adap->dev); /* inform drivers of new adapters */ - for (j=0;jflags&(I2C_DF_NOTIFY|I2C_DF_DUMMY))) + list_for_each(item,&drivers) { + driver = list_entry(item, struct i2c_driver, list); + if (driver->flags & I2C_DF_NOTIFY) /* We ignore the return code; if it fails, too bad */ - drivers[j]->attach_adapter(adap); + driver->attach_adapter(adap); + } up(&core_lists); - - DEB(dev_dbg(&adap->dev, "registered as adapter %d.\n", i)); - out_unlock: - up(&core_lists); - return res;; + DEB(dev_dbg(&adap->dev, "registered as adapter #%d\n", adap->nr)); + return 0; } int i2c_del_adapter(struct i2c_adapter *adap) { - int res = 0, i, j; + struct list_head *item; + struct i2c_driver *driver; + struct i2c_client *client; + int res = 0; down(&core_lists); - for (i = 0; i < I2C_ADAP_MAX; i++) - if (adap == adapters[i]) - break; - if (I2C_ADAP_MAX == i) { - dev_warn(&adap->dev, "unregister_adapter adap not found.\n"); - res = -ENODEV; - goto out_unlock; - } - /* DUMMY drivers do not register their clients, so we have to - * use a trick here: we call driver->attach_adapter to - * *detach* it! Of course, each dummy driver should know about - * this or hell will break loose... - */ - for (j = 0; j < I2C_DRIVER_MAX; j++) - if (drivers[j] && (drivers[j]->flags & I2C_DF_DUMMY)) - if ((res = drivers[j]->attach_adapter(adap))) { + list_for_each(item,&drivers) { + driver = list_entry(item, struct i2c_driver, list); + if (driver->detach_adapter) + if ((res = driver->detach_adapter(adap))) { dev_warn(&adap->dev, "can't detach adapter" - "while detaching driver %s: driver not " - "detached!", drivers[j]->name); + "while detaching driver %s: driver not " + "detached!", driver->name); goto out_unlock; } + } /* detach any active clients. This must be done first, because * it can fail; in which case we give upp. */ - for (j=0;jclients[j]; - if (client!=NULL) { - /* detaching devices is unconditional of the set notify - * flag, as _all_ clients that reside on the adapter - * must be deleted, as this would cause invalid states. - */ - if ((res=client->driver->detach_client(client))) { - dev_err(&adap->dev, "adapter not " - "unregistered, because client at " - "address %02x can't be detached. ", - client->addr); - goto out_unlock; - } + list_for_each(item,&adap->clients) { + client = list_entry(item, struct i2c_client, list); + + /* detaching devices is unconditional of the set notify + * flag, as _all_ clients that reside on the adapter + * must be deleted, as this would cause invalid states. + */ + if ((res=client->driver->detach_client(client))) { + dev_err(&adap->dev, "adapter not " + "unregistered, because client at " + "address %02x can't be detached. ", + client->addr); + goto out_unlock; } } /* clean up the sysfs representation */ device_unregister(&adap->dev); - - adapters[i] = NULL; + list_del(&adap->list); DEB(dev_dbg(&adap->dev, "adapter unregistered\n")); @@ -187,24 +169,11 @@ int i2c_add_driver(struct i2c_driver *driver) { - int res = 0, i; + struct list_head *item; + struct i2c_adapter *adapter; + int res = 0; down(&core_lists); - for (i = 0; i < I2C_DRIVER_MAX; i++) - if (NULL == drivers[i]) - break; - if (I2C_DRIVER_MAX == i) { - printk(KERN_WARNING - " i2c-core.o: register_driver(%s) " - "- enlarge I2C_DRIVER_MAX.\n", - driver->name); - res = -ENOMEM; - goto out_unlock; - } - - drivers[i] = driver; - - DEB(printk(KERN_DEBUG "i2c-core.o: driver %s registered.\n",driver->name)); /* add the driver to the list of i2c drivers in the driver core */ driver->driver.name = driver->name; @@ -216,13 +185,14 @@ if (res) goto out_unlock; - /* now look for instances of driver on our adapters - */ - if (driver->flags& (I2C_DF_NOTIFY|I2C_DF_DUMMY)) { - for (i=0;iattach_adapter(adapters[i]); + list_add_tail(&driver->list,&drivers); + DEB(printk(KERN_DEBUG "i2c-core.o: driver %s registered.\n",driver->name)); + + /* now look for instances of driver on our adapters */ + if (driver->flags & I2C_DF_NOTIFY) { + list_for_each(item,&adapters) { + adapter = list_entry(item, struct i2c_adapter, list); + driver->attach_adapter(adapter); } } @@ -233,44 +203,29 @@ int i2c_del_driver(struct i2c_driver *driver) { - int res = 0, i, j, k; + struct list_head *item1; + struct list_head *item2; + struct i2c_client *client; + struct i2c_adapter *adap; + + int res = 0; down(&core_lists); - for (i = 0; i < I2C_DRIVER_MAX; i++) - if (driver == drivers[i]) - break; - if (I2C_DRIVER_MAX == i) { - printk(KERN_WARNING " i2c-core.o: unregister_driver: " - "[%s] not found\n", - driver->name); - res = -ENODEV; - goto out_unlock; - } - - driver_unregister(&driver->driver); /* Have a look at each adapter, if clients of this driver are still * attached. If so, detach them to be able to kill the driver * afterwards. */ DEB2(printk(KERN_DEBUG "i2c-core.o: unregister_driver - looking for clients.\n")); - /* removing clients does not depend on the notify flag, else * invalid operation might (will!) result, when using stale client * pointers. */ - for (k=0;kdev, "examining adapter\n")); - if (driver->flags & I2C_DF_DUMMY) { - /* DUMMY drivers do not register their clients, so we have to - * use a trick here: we call driver->attach_adapter to - * *detach* it! Of course, each dummy driver should know about - * this or hell will break loose... - */ - if ((res = driver->attach_adapter(adap))) { + if (driver->detach_adapter) { + if ((res = driver->detach_adapter(adap))) { dev_warn(&adap->dev, "while unregistering " "dummy driver %s, adapter could " "not be detached properly; driver " @@ -278,31 +233,31 @@ goto out_unlock; } } else { - for (j=0;jclients[j]; - if (client != NULL && - client->driver == driver) { - DEB2(printk(KERN_DEBUG "i2c-core.o: " - "detaching client %s:\n", - client->dev.name)); - if ((res = driver->detach_client(client))) { - dev_err(&adap->dev, "while " - "unregistering driver " - "`%s', the client at " - "address %02x of " - "adapter could not " - "be detached; driver " - "not unloaded!", - driver->name, - client->addr); - goto out_unlock; - } + list_for_each(item2,&adap->clients) { + client = list_entry(item2, struct i2c_client, list); + if (client->driver != driver) + continue; + DEB2(printk(KERN_DEBUG "i2c-core.o: " + "detaching client %s:\n", + client->dev.name)); + if ((res = driver->detach_client(client))) { + dev_err(&adap->dev, "while " + "unregistering driver " + "`%s', the client at " + "address %02x of " + "adapter could not " + "be detached; driver " + "not unloaded!", + driver->name, + client->addr); + goto out_unlock; } } } } - drivers[i] = NULL; - + + driver_unregister(&driver->driver); + list_del(&driver->list); DEB(printk(KERN_DEBUG "i2c-core.o: driver unregistered: %s\n",driver->name)); out_unlock: @@ -310,14 +265,16 @@ return 0; } -static int __i2c_check_addr(struct i2c_adapter *adapter, int addr) +static int __i2c_check_addr(struct i2c_adapter *adapter, unsigned int addr) { - int i; + struct list_head *item; + struct i2c_client *client; - for (i = 0; i < I2C_CLIENT_MAX ; i++) - if (adapter->clients[i] && (adapter->clients[i]->addr == addr)) + list_for_each(item,&adapter->clients) { + client = list_entry(item, struct i2c_client, list); + if (client->addr == addr) return -EBUSY; - + } return 0; } @@ -325,9 +282,9 @@ { int rval; - down(&adapter->list); + down(&adapter->clist_lock); rval = __i2c_check_addr(adapter, addr); - up(&adapter->list); + up(&adapter->clist_lock); return rval; } @@ -335,28 +292,14 @@ int i2c_attach_client(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; - int i; - - down(&adapter->list); - if (__i2c_check_addr(client->adapter, client->addr)) - goto out_unlock_list; - for (i = 0; i < I2C_CLIENT_MAX; i++) { - if (!adapter->clients[i]) - goto free_slot; + down(&adapter->clist_lock); + if (__i2c_check_addr(client->adapter, client->addr)) { + up(&adapter->clist_lock); + return -EBUSY; } - - printk(KERN_WARNING - " i2c-core.o: attach_client(%s) - enlarge I2C_CLIENT_MAX.\n", - client->dev.name); - - out_unlock_list: - up(&adapter->list); - return -EBUSY; - - free_slot: - adapter->clients[i] = client; - up(&adapter->list); + list_add_tail(&client->list,&adapter->clients); + up(&adapter->clist_lock); if (adapter->client_register) { if (adapter->client_register(client)) { @@ -366,8 +309,8 @@ } } - DEB(dev_dbg(&adapter->dev, "client [%s] registered to adapter " - "(pos. %d).\n", client->dev.name, i)); + DEB(dev_dbg(&adapter->dev, "client [%s] registered to adapter\n", + client->dev.name)); if (client->flags & I2C_CLIENT_ALLOW_USE) client->usage_count = 0; @@ -388,7 +331,7 @@ int i2c_detach_client(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; - int res = 0, i; + int res = 0; if ((client->flags & I2C_CLIENT_ALLOW_USE) && (client->usage_count > 0)) return -EBUSY; @@ -403,22 +346,11 @@ } } - down(&adapter->list); - for (i = 0; i < I2C_CLIENT_MAX; i++) { - if (client == adapter->clients[i]) { - adapter->clients[i] = NULL; - goto out_unlock; - } - } - - printk(KERN_WARNING - " i2c-core.o: unregister_client [%s] not found\n", - client->dev.name); - res = -ENODEV; - - out_unlock: + down(&adapter->clist_lock); + list_del(&client->list); device_unregister(&client->dev); - up(&adapter->list); + up(&adapter->clist_lock); + out: return res; } @@ -479,6 +411,27 @@ return 0; } +void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg) +{ + struct list_head *item; + struct i2c_client *client; + + down(&adap->clist_lock); + list_for_each(item,&adap->clients) { + client = list_entry(item, struct i2c_client, list); + if (!try_module_get(client->driver->owner)) + continue; + if (NULL != client->driver->command) { + up(&adap->clist_lock); + client->driver->command(client,cmd,arg); + down(&adap->clist_lock); + } + module_put(client->driver->owner); + } + up(&adap->clist_lock); +} + + /* match always succeeds, as we want the probe() to tell if we really accept this match */ static int i2c_device_match(struct device *dev, struct device_driver *drv) { @@ -516,9 +469,9 @@ if (adap->algo->master_xfer) { DEB2(dev_dbg(&adap->dev, "master_xfer: with %d msgs.\n", num)); - down(&adap->bus); + down(&adap->bus_lock); ret = adap->algo->master_xfer(adap,msgs,num); - up(&adap->bus); + up(&adap->bus_lock); return ret; } else { @@ -542,9 +495,9 @@ DEB2(dev_dbg(&client->adapter->dev, "master_send: writing %d bytes.\n", count)); - down(&adap->bus); + down(&adap->bus_lock); ret = adap->algo->master_xfer(adap,&msg,1); - up(&adap->bus); + up(&adap->bus_lock); /* if everything went ok (i.e. 1 msg transmitted), return #bytes * transmitted, else error code. @@ -572,9 +525,9 @@ DEB2(dev_dbg(&client->adapter->dev, "master_recv: reading %d bytes.\n", count)); - down(&adap->bus); + down(&adap->bus_lock); ret = adap->algo->master_xfer(adap,&msg,1); - up(&adap->bus); + up(&adap->bus_lock); DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: return:%d (count:%d, addr:0x%02x)\n", ret, count, client->addr)); @@ -743,11 +696,30 @@ */ int i2c_adapter_id(struct i2c_adapter *adap) { - int i; - for (i = 0; i < I2C_ADAP_MAX; i++) - if (adap == adapters[i]) - return i; - return -1; + return adap->nr; +} + +struct i2c_adapter* i2c_get_adapter(int id) +{ + struct list_head *item; + struct i2c_adapter *adapter; + + down(&core_lists); + list_for_each(item,&adapters) { + adapter = list_entry(item, struct i2c_adapter, list); + if (id == adapter->nr && + try_module_get(adapter->owner)) { + up(&core_lists); + return adapter; + } + } + up(&core_lists); + return NULL; +} + +void i2c_put_adapter(struct i2c_adapter *adap) +{ + module_put(adap->owner); } /* The SMBus parts */ @@ -1189,10 +1161,10 @@ } if (adapter->algo->smbus_xfer) { - down(&adapter->bus); + down(&adapter->bus_lock); res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, command,size,data); - up(&adapter->bus); + up(&adapter->bus_lock); } else res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, command,size,data); @@ -1232,6 +1204,7 @@ EXPORT_SYMBOL(i2c_detach_client); EXPORT_SYMBOL(i2c_use_client); EXPORT_SYMBOL(i2c_release_client); +EXPORT_SYMBOL(i2c_clients_command); EXPORT_SYMBOL(i2c_check_addr); EXPORT_SYMBOL(i2c_master_send); @@ -1239,6 +1212,8 @@ EXPORT_SYMBOL(i2c_control); EXPORT_SYMBOL(i2c_transfer); EXPORT_SYMBOL(i2c_adapter_id); +EXPORT_SYMBOL(i2c_get_adapter); +EXPORT_SYMBOL(i2c_put_adapter); EXPORT_SYMBOL(i2c_probe); EXPORT_SYMBOL(i2c_smbus_xfer); diff -Nru a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c --- a/drivers/i2c/i2c-dev.c Thu May 8 00:24:29 2003 +++ b/drivers/i2c/i2c-dev.c Thu May 8 00:24:29 2003 @@ -58,6 +58,7 @@ static int i2cdev_release (struct inode *inode, struct file *file); static int i2cdev_attach_adapter(struct i2c_adapter *adap); +static int i2cdev_detach_adapter(struct i2c_adapter *adap); static int i2cdev_detach_client(struct i2c_client *client); static int i2cdev_command(struct i2c_client *client, unsigned int cmd, void *arg); @@ -72,15 +73,13 @@ .release = i2cdev_release, }; -#define I2CDEV_ADAPS_MAX I2C_ADAP_MAX -static struct i2c_adapter *i2cdev_adaps[I2CDEV_ADAPS_MAX]; - static struct i2c_driver i2cdev_driver = { .owner = THIS_MODULE, .name = "dev driver", .id = I2C_DRIVERID_I2CDEV, - .flags = I2C_DF_DUMMY, + .flags = I2C_DF_NOTIFY, .attach_adapter = i2cdev_attach_adapter, + .detach_adapter = i2cdev_detach_adapter, .detach_client = i2cdev_detach_client, .command = i2cdev_command, }; @@ -340,35 +339,31 @@ { unsigned int minor = minor(inode->i_rdev); struct i2c_client *client; + struct i2c_adapter *adap; - if ((minor >= I2CDEV_ADAPS_MAX) || !(i2cdev_adaps[minor])) + adap = i2c_get_adapter(minor); + if (NULL == adap) return -ENODEV; client = kmalloc(sizeof(*client), GFP_KERNEL); - if (!client) + if (!client) { + i2c_put_adapter(adap); return -ENOMEM; + } memcpy(client, &i2cdev_client_template, sizeof(*client)); /* registered with adapter, passed as client to user */ - client->adapter = i2cdev_adaps[minor]; + client->adapter = adap; file->private_data = client; - /* use adapter module, i2c-dev handled with fops */ - if (!try_module_get(client->adapter->owner)) - goto out_kfree; - return 0; - -out_kfree: - kfree(client); - return -ENODEV; } static int i2cdev_release(struct inode *inode, struct file *file) { struct i2c_client *client = file->private_data; - module_put(client->adapter->owner); + i2c_put_adapter(client->adapter); kfree(client); file->private_data = NULL; @@ -378,32 +373,22 @@ int i2cdev_attach_adapter(struct i2c_adapter *adap) { int i; - char name[12]; - if ((i = i2c_adapter_id(adap)) < 0) { - dev_dbg(&adap->dev, "Unknown adapter ?!?\n"); - return -ENODEV; - } - if (i >= I2CDEV_ADAPS_MAX) { - dev_dbg(&adap->dev, "Adapter number too large?!? (%d)\n",i); - return -ENODEV; - } + i = i2c_adapter_id(adap); + devfs_mk_cdev(MKDEV(I2C_MAJOR, i), + S_IFCHR|S_IRUSR|S_IWUSR, "i2c/%d", i); + dev_dbg(&adap->dev, "Registered as minor %d\n", i); + return 0; +} - sprintf (name, "i2c/%d", i); - if (! i2cdev_adaps[i]) { - i2cdev_adaps[i] = adap; - devfs_register (NULL, name, - DEVFS_FL_DEFAULT, I2C_MAJOR, i, - S_IFCHR | S_IRUSR | S_IWUSR, - &i2cdev_fops, NULL); - dev_dbg(&adap->dev, "Registered as minor %d\n", i); - } else { - /* This is actually a detach_adapter call! */ - devfs_remove("i2c/%d", i); - i2cdev_adaps[i] = NULL; - dev_dbg(&adap->dev, "Adapter unregistered\n"); - } +int i2cdev_detach_adapter(struct i2c_adapter *adap) +{ + int i; + + i = i2c_adapter_id(adap); + devfs_remove("i2c/%d", i); + dev_dbg(&adap->dev, "Adapter unregistered\n"); return 0; } diff -Nru a/drivers/i2c/i2c-keywest.c b/drivers/i2c/i2c-keywest.c --- a/drivers/i2c/i2c-keywest.c Thu May 8 00:24:29 2003 +++ b/drivers/i2c/i2c-keywest.c Thu May 8 00:24:29 2003 @@ -212,7 +212,7 @@ #ifndef POLLED_MODE /* Interrupt handler */ -static void +static irqreturn_t keywest_irq(int irq, void *dev_id, struct pt_regs *regs) { struct keywest_iface *iface = (struct keywest_iface *)dev_id; @@ -225,6 +225,7 @@ add_timer(&iface->timeout_timer); } spin_unlock(&iface->lock); + return IRQ_HANDLED; } static void diff -Nru a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c --- a/drivers/ide/ide-tape.c Thu May 8 00:24:28 2003 +++ b/drivers/ide/ide-tape.c Thu May 8 00:24:28 2003 @@ -6292,11 +6292,9 @@ devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor) S_IFCHR | S_IRUGO | S_IWUGO, - &idetape_fops, NULL, "%s/mt", drive->devfs_name); devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor + 128), S_IFCHR | S_IRUGO | S_IWUGO, - &idetape_fops, NULL, "%s/mtn", drive->devfs_name); drive->disk->number = devfs_register_tape(drive->devfs_name); diff -Nru a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c --- a/drivers/ieee1394/amdtp.c Thu May 8 00:24:29 2003 +++ b/drivers/ieee1394/amdtp.c Thu May 8 00:24:29 2003 @@ -1205,7 +1205,6 @@ { struct amdtp_host *ah; int minor; - char name[16]; if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME) != 0) return; @@ -1223,13 +1222,11 @@ minor = IEEE1394_MINOR_BLOCK_AMDTP * 16 + ah->ohci->id; - sprintf(name, "amdtp/%d", ah->ohci->id); - INIT_LIST_HEAD(&ah->stream_list); spin_lock_init(&ah->stream_list_lock); - devfs_register(NULL, name, 0, IEEE1394_MAJOR, minor, - S_IFCHR | S_IRUSR | S_IWUSR, &amdtp_fops, NULL); + devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor), + S_IFCHR|S_IRUSR|S_IWUSR, "amdtp/%d", ah->ohci->id); } static void amdtp_remove_host(struct hpsb_host *host) diff -Nru a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c --- a/drivers/ieee1394/dv1394.c Thu May 8 00:24:29 2003 +++ b/drivers/ieee1394/dv1394.c Thu May 8 00:24:29 2003 @@ -2420,24 +2420,6 @@ }; -#ifdef CONFIG_DEVFS_FS -static int dv1394_devfs_add_entry(struct video_card *video) -{ - char buf[64]; - - snprintf(buf, sizeof(buf), "ieee1394/dv/host%d/%s/%s", - (video->id>>2), - (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"), - (video->mode == MODE_RECEIVE ? "in" : "out")); - - devfs_register(NULL, buf, 0, IEEE1394_MAJOR, - IEEE1394_MINOR_BLOCK_DV1394*16 + video->id, - S_IFCHR | S_IRUGO | S_IWUGO, &dv1394_fops, video); - return 0; -} -#endif /* CONFIG_DEVFS_FS */ - - /*** HOTPLUG STUFF **********************************************************/ /* * Export information about protocols/devices supported by this driver. @@ -2536,10 +2518,14 @@ list_add_tail(&video->list, &dv1394_cards); spin_unlock_irqrestore(&dv1394_cards_lock, flags); -#ifdef CONFIG_DEVFS_FS - if (dv1394_devfs_add_entry(video) < 0) + if (devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, + IEEE1394_MINOR_BLOCK_DV1394*16 + video->id), + S_IFCHR|S_IRUGO|S_IWUGO, + "ieee1394/dv/host%d/%s/%s", + (video->id>>2), + (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"), + (video->mode == MODE_RECEIVE ? "in" : "out")) < 0) goto err_free; -#endif debug_printk("dv1394: dv1394_init() OK on ID %d\n", video->id); @@ -2562,9 +2548,7 @@ (video->mode == MODE_RECEIVE ? "in" : "out") ); -#ifdef CONFIG_DEVFS_FS devfs_remove("ieee1394/%s", buf); -#endif #ifdef CONFIG_PROC_FS dv1394_procfs_del(buf); #endif @@ -2602,11 +2586,9 @@ n = (video->id >> 2); -#ifdef CONFIG_DEVFS_FS devfs_remove("ieee1394/dv/host%d/NTSC", n); devfs_remove("ieee1394/dv/host%d/PAL", n); devfs_remove("ieee1394/dv/host%d", n); -#endif #ifdef CONFIG_PROC_FS snprintf(buf, sizeof(buf), "dv/host%d/NTSC", n); @@ -2642,11 +2624,9 @@ } #endif -#ifdef CONFIG_DEVFS_FS devfs_mk_dir("ieee1394/dv/host%d", ohci->id); devfs_mk_dir("ieee1394/dv/host%d/NTSC", ohci->id); devfs_mk_dir("ieee1394/dv/host%d/PAL", ohci->id); -#endif dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE); dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT); @@ -2901,9 +2881,7 @@ hpsb_unregister_highlevel(&dv1394_highlevel); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394); -#ifdef CONFIG_DEVFS_FS devfs_remove("ieee1394/dv"); -#endif #ifdef CONFIG_PROC_FS dv1394_procfs_del("dv"); #endif @@ -2920,18 +2898,14 @@ return -EIO; } -#ifdef CONFIG_DEVFS_FS devfs_mk_dir("ieee1394/dv"); -#endif #ifdef CONFIG_PROC_FS ret = dv1394_procfs_add_dir("dv",NULL,NULL); if (ret < 0) { printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/dv\n"); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394); -#ifdef CONFIG_DEVFS_FS devfs_remove("ieee1394/dv"); -#endif return -ENOMEM; } #endif diff -Nru a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c --- a/drivers/ieee1394/raw1394.c Thu May 8 00:24:27 2003 +++ b/drivers/ieee1394/raw1394.c Thu May 8 00:24:27 2003 @@ -2531,9 +2531,8 @@ { hpsb_register_highlevel(&raw1394_highlevel); - devfs_register(NULL, RAW1394_DEVICE_NAME, 0, - IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16, - S_IFCHR | S_IRUSR | S_IWUSR, &file_ops, NULL); + devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), + S_IFCHR | S_IRUSR | S_IWUSR, RAW1394_DEVICE_NAME); if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_RAW1394, THIS_MODULE, &file_ops)) { diff -Nru a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c --- a/drivers/ieee1394/video1394.c Thu May 8 00:24:27 2003 +++ b/drivers/ieee1394/video1394.c Thu May 8 00:24:27 2003 @@ -1257,7 +1257,6 @@ static void video1394_add_host (struct hpsb_host *host) { struct ti_ohci *ohci; - char name[16]; int minor; /* We only work with the OHCI-1394 driver */ @@ -1274,12 +1273,10 @@ hpsb_set_hostinfo(&video1394_highlevel, host, ohci); hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->id); - sprintf(name, "%s/%d", VIDEO1394_DRIVER_NAME, ohci->id); - minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->id; - devfs_register(NULL, name, 0, IEEE1394_MAJOR, minor, - S_IFCHR | S_IRUSR | S_IWUSR, &video1394_fops, NULL); - - return; + minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->id; + devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor), + S_IFCHR | S_IRUSR | S_IWUSR, + "%s/%d", VIDEO1394_DRIVER_NAME, ohci->id); } diff -Nru a/drivers/input/evdev.c b/drivers/input/evdev.c --- a/drivers/input/evdev.c Thu May 8 00:24:29 2003 +++ b/drivers/input/evdev.c Thu May 8 00:24:29 2003 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -400,7 +401,9 @@ sprintf(evdev->name, "event%d", minor); evdev_table[minor] = evdev; - input_register_minor("input/event%d", minor, EVDEV_MINOR_BASE); + + devfs_mk_cdev(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor), + S_IFCHR|S_IRUGO|S_IWUSR, "input/event%d", minor); return &evdev->handle; } diff -Nru a/drivers/input/input.c b/drivers/input/input.c --- a/drivers/input/input.c Thu May 8 00:24:29 2003 +++ b/drivers/input/input.c Thu May 8 00:24:29 2003 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -32,7 +33,6 @@ EXPORT_SYMBOL(input_unregister_device); EXPORT_SYMBOL(input_register_handler); EXPORT_SYMBOL(input_unregister_handler); -EXPORT_SYMBOL(input_register_minor); EXPORT_SYMBOL(input_open_device); EXPORT_SYMBOL(input_close_device); EXPORT_SYMBOL(input_accept_process); @@ -40,7 +40,6 @@ EXPORT_SYMBOL(input_event); EXPORT_SYMBOL(input_class); -#define INPUT_MAJOR 13 #define INPUT_DEVICES 256 static LIST_HEAD(input_dev_list); @@ -540,15 +539,6 @@ .owner = THIS_MODULE, .open = input_open_file, }; - -void input_register_minor(char *name, int minor, int minor_base) -{ - char devfs_name[16]; - - sprintf(devfs_name, name, minor); - devfs_register(NULL, devfs_name, 0, INPUT_MAJOR, minor_base + minor, - S_IFCHR|S_IRUGO|S_IWUSR, &input_fops, NULL); -} #ifdef CONFIG_PROC_FS diff -Nru a/drivers/input/joydev.c b/drivers/input/joydev.c --- a/drivers/input/joydev.c Thu May 8 00:24:28 2003 +++ b/drivers/input/joydev.c Thu May 8 00:24:28 2003 @@ -445,7 +445,9 @@ } joydev_table[minor] = joydev; - input_register_minor("js%d", minor, JOYDEV_MINOR_BASE); + + devfs_mk_cdev(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor), + S_IFCHR|S_IRUGO|S_IWUSR, "js%d", minor); return &joydev->handle; } diff -Nru a/drivers/input/mousedev.c b/drivers/input/mousedev.c --- a/drivers/input/mousedev.c Thu May 8 00:24:30 2003 +++ b/drivers/input/mousedev.c Thu May 8 00:24:30 2003 @@ -432,7 +432,9 @@ input_open_device(&mousedev->handle); mousedev_table[minor] = mousedev; - input_register_minor("input/mouse%d", minor, MOUSEDEV_MINOR_BASE); + + devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor), + S_IFCHR|S_IRUGO|S_IWUSR, "input/mouse%d", minor); return &mousedev->handle; } @@ -502,7 +504,10 @@ mousedev_table[MOUSEDEV_MIX] = &mousedev_mix; mousedev_mix.exist = 1; mousedev_mix.minor = MOUSEDEV_MIX; - input_register_minor("input/mice", MOUSEDEV_MIX, MOUSEDEV_MINOR_BASE); + + devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), + S_IFCHR|S_IRUGO|S_IWUSR, "input/mice"); + #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX if (!(mousedev_mix.misc = !misc_register(&psaux_mouse))) diff -Nru a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c --- a/drivers/input/serio/i8042.c Thu May 8 00:24:27 2003 +++ b/drivers/input/serio/i8042.c Thu May 8 00:24:27 2003 @@ -62,6 +62,12 @@ static unsigned char i8042_mux_open; struct timer_list i8042_timer; +/* + * Shared IRQ's require a device pointer, but this driver doesn't support + * multiple devices + */ +#define i8042_request_irq_cookie (&i8042_timer) + static unsigned long i8042_unxlate_seen[256 / BITS_PER_LONG]; static unsigned char i8042_unxlate_table[128] = { 0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13, @@ -235,7 +241,8 @@ if (i8042_mux_open++) return 0; - if (request_irq(values->irq, i8042_interrupt, 0, "i8042", NULL)) { + if (request_irq(values->irq, i8042_interrupt, + SA_SHIRQ, "i8042", i8042_request_irq_cookie)) { printk(KERN_ERR "i8042.c: Can't get irq %d for %s, unregistering the port.\n", values->irq, values->name); values->exists = 0; serio_unregister_port(port); @@ -275,7 +282,7 @@ return; } - free_irq(values->irq, NULL); + free_irq(values->irq, i8042_request_irq_cookie); i8042_flush(); } @@ -572,9 +579,10 @@ * Check if AUX irq is available. */ - if (request_irq(values->irq, i8042_interrupt, 0, "i8042", NULL)) + if (request_irq(values->irq, i8042_interrupt, SA_SHIRQ, + "i8042", i8042_request_irq_cookie)) return -1; - free_irq(values->irq, NULL); + free_irq(values->irq, i8042_request_irq_cookie); /* * Get rid of bytes in the queue. @@ -643,9 +651,10 @@ * in trying to detect AUX presence. */ - if (request_irq(values->irq, i8042_interrupt, 0, "i8042", NULL)) + if (request_irq(values->irq, i8042_interrupt, SA_SHIRQ, + "i8042", i8042_request_irq_cookie)) return -1; - free_irq(values->irq, NULL); + free_irq(values->irq, i8042_request_irq_cookie); /* * Get rid of bytes in the queue. diff -Nru a/drivers/input/tsdev.c b/drivers/input/tsdev.c --- a/drivers/input/tsdev.c Thu May 8 00:24:30 2003 +++ b/drivers/input/tsdev.c Thu May 8 00:24:30 2003 @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -329,8 +330,9 @@ tsdev->handle.private = tsdev; tsdev_table[minor] = tsdev; - input_register_minor("input/ts%d", minor, TSDEV_MINOR_BASE); - + + devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor), + S_IFCHR|S_IRUGO|S_IWUSR, "input/ts%d", minor); return &tsdev->handle; } diff -Nru a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c --- a/drivers/isdn/capi/capi.c Thu May 8 00:24:30 2003 +++ b/drivers/isdn/capi/capi.c Thu May 8 00:24:30 2003 @@ -200,10 +200,8 @@ unsigned int minor = 0; unsigned long flags; - MOD_INC_USE_COUNT; mp = kmalloc(sizeof(*mp), GFP_ATOMIC); if (!mp) { - MOD_DEC_USE_COUNT; printk(KERN_ERR "capi: can't alloc capiminor\n"); return 0; } @@ -249,7 +247,6 @@ skb_queue_purge(&mp->outqueue); capiminor_del_all_ack(mp); kfree(mp); - MOD_DEC_USE_COUNT; } struct capiminor *capiminor_find(unsigned int minor) @@ -1280,6 +1277,7 @@ memset(drv, 0, sizeof(struct tty_driver)); drv->magic = TTY_DRIVER_MAGIC; + drv->owner = THIS_MODULE; drv->driver_name = "capi_nc"; drv->name = "capi/"; drv->major = capi_ttymajor; @@ -1460,7 +1458,6 @@ char *p; char *compileinfo; - MOD_INC_USE_COUNT; if ((p = strchr(revision, ':')) != 0 && p[1]) { strncpy(rev, p + 2, sizeof(rev)); @@ -1472,19 +1469,17 @@ if (register_chrdev(capi_major, "capi20", &capi_fops)) { printk(KERN_ERR "capi20: unable to get major %d\n", capi_major); - MOD_DEC_USE_COUNT; return -EIO; } - devfs_register (NULL, "isdn/capi20", DEVFS_FL_DEFAULT, - capi_major, 0, S_IFCHR | S_IRUSR | S_IWUSR, - &capi_fops, NULL); + devfs_mk_cdev(MKDEV(capi_major, 0), S_IFCHR | S_IRUSR | S_IWUSR, + "isdn/capi20"); + printk(KERN_NOTICE "capi20: started up with major %d\n", capi_major); #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE if (capinc_tty_init() < 0) { unregister_chrdev(capi_major, "capi20"); - MOD_DEC_USE_COUNT; return -ENOMEM; } #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ @@ -1503,7 +1498,6 @@ printk(KERN_NOTICE "capi20: Rev %s: started up with major %d%s\n", rev, capi_major, compileinfo); - MOD_DEC_USE_COUNT; return 0; } diff -Nru a/drivers/isdn/hardware/eicon/divamnt.c b/drivers/isdn/hardware/eicon/divamnt.c --- a/drivers/isdn/hardware/eicon/divamnt.c Thu May 8 00:24:29 2003 +++ b/drivers/isdn/hardware/eicon/divamnt.c Thu May 8 00:24:29 2003 @@ -420,10 +420,8 @@ DRIVERLNAME); return (0); } - devfs_register(NULL, "DivasMAINT", DEVFS_FL_DEFAULT, major, 0, - S_IFCHR | S_IRUSR | S_IWUSR, &divas_maint_fops, - NULL); + devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, DivasMAINT); return (1); } diff -Nru a/drivers/isdn/hardware/eicon/divasi.c b/drivers/isdn/hardware/eicon/divasi.c --- a/drivers/isdn/hardware/eicon/divasi.c Thu May 8 00:24:28 2003 +++ b/drivers/isdn/hardware/eicon/divasi.c Thu May 8 00:24:28 2003 @@ -179,10 +179,8 @@ DRIVERLNAME); return (0); } - devfs_register(NULL, "DivasIDI", DEVFS_FL_DEFAULT, major, 0, - S_IFCHR | S_IRUSR | S_IWUSR, &divas_idi_fops, - NULL); + devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, "DivasIDI"); return (1); } diff -Nru a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c --- a/drivers/isdn/hardware/eicon/divasmain.c Thu May 8 00:24:27 2003 +++ b/drivers/isdn/hardware/eicon/divasmain.c Thu May 8 00:24:27 2003 @@ -788,9 +788,8 @@ DRIVERLNAME); return (0); } - devfs_register(NULL, "Divas", DEVFS_FL_DEFAULT, major, 0, - S_IFCHR | S_IRUSR | S_IWUSR, &divas_fops, NULL); + devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, "Divas"); return (1); } diff -Nru a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c --- a/drivers/isdn/i4l/isdn_common.c Thu May 8 00:24:28 2003 +++ b/drivers/isdn/i4l/isdn_common.c Thu May 8 00:24:28 2003 @@ -37,9 +37,6 @@ static void isdn_lock_driver(struct isdn_driver *drv); static void isdn_unlock_driver(struct isdn_driver *drv); -static void isdn_register_devfs(int); -static void isdn_unregister_devfs(int); - /* ====================================================================== */ /* Description of hardware-level-driver */ @@ -2157,85 +2154,37 @@ return max; } -/* - ***************************************************************************** - * And now the modules code. - ***************************************************************************** - */ - -#ifdef CONFIG_DEVFS_FS - -static void isdn_register_devfs(int k) -{ - char buf[16]; - - sprintf (buf, "isdn/isdnctrl%d", k); - devfs_register(NULL, buf, DEVFS_FL_DEFAULT, - ISDN_MAJOR, ISDN_MINOR_CTRL + k, 0600 | S_IFCHR, - &isdn_fops, NULL); -} - -static void isdn_unregister_devfs(int k) +static void isdn_init_devfs(void) { - devfs_remove("isdn/isdnctrl%d", k); -} + devfs_mk_dir("isdn"); -static void isdn_init_devfs(void) +#ifdef CONFIG_ISDN_PPP { -# ifdef CONFIG_ISDN_PPP int i; -# endif - devfs_mk_dir("isdn"); -# ifdef CONFIG_ISDN_PPP - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - char buf[16]; + for (i = 0; i < ISDN_MAX_CHANNELS; i++) + devfs_mk_cdev(MKDEV(ISDN_MAJOR, ISDN_MINOR_PPP + i), + 0600 | S_IFCHR, "isdn/ippp%d", i); +} +#endif - sprintf (buf, "isdn/ippp%d", i); - devfs_register(NULL, buf, DEVFS_FL_DEFAULT, - ISDN_MAJOR, ISDN_MINOR_PPP + i, - 0600 | S_IFCHR, &isdn_fops, NULL); - } -# endif - - devfs_register(NULL, "isdn/isdninfo", DEVFS_FL_DEFAULT, - ISDN_MAJOR, ISDN_MINOR_STATUS, 0600 | S_IFCHR, - &isdn_fops, NULL); - devfs_register(NULL, "isdn/isdnctrl", DEVFS_FL_DEFAULT, - ISDN_MAJOR, ISDN_MINOR_CTRL, 0600 | S_IFCHR, - &isdn_fops, NULL); + devfs_mk_cdev(MKDEV(ISDN_MAJOR, ISDN_MINOR_STATUS), + 0600 | S_IFCHR, "isdn/isdninfo"); + devfs_mk_cdev(MKDEV(ISDN_MAJOR, ISDN_MINOR_CTRL), + 0600 | S_IFCHR, "isdn/isdnctrl"); } static void isdn_cleanup_devfs(void) { -# ifdef CONFIG_ISDN_PPP +#ifdef CONFIG_ISDN_PPP int i; for (i = 0; i < ISDN_MAX_CHANNELS; i++) devfs_remove("isdn/ippp%d", i); -# endif +#endif devfs_remove("isdn/isdninfo"); devfs_remove("isdn/isdnctrl"); devfs_remove("isdn"); } - -#else /* CONFIG_DEVFS_FS */ -static void isdn_register_devfs(int dummy) -{ -} - -static void isdn_unregister_devfs(int dummy) -{ -} - -static void isdn_init_devfs(void) -{ -} - -static void isdn_cleanup_devfs(void) -{ -} - -#endif /* CONFIG_DEVFS_FS */ /* * Allocate and initialize all data, register modem-devices diff -Nru a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c --- a/drivers/macintosh/adb.c Thu May 8 00:24:30 2003 +++ b/drivers/macintosh/adb.c Thu May 8 00:24:30 2003 @@ -896,8 +896,6 @@ if (register_chrdev(ADB_MAJOR, "adb", &adb_fops)) printk(KERN_ERR "adb: unable to get major %d\n", ADB_MAJOR); else - devfs_register (NULL, "adb", DEVFS_FL_DEFAULT, - ADB_MAJOR, 0, - S_IFCHR | S_IRUSR | S_IWUSR, - &adb_fops, NULL); + devfs_mk_cdev(MKDEV(ADB_MAJOR, 0), + S_IFCHR | S_IRUSR | S_IWUSR, "adb"); } diff -Nru a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c --- a/drivers/macintosh/macserial.c Thu May 8 00:24:30 2003 +++ b/drivers/macintosh/macserial.c Thu May 8 00:24:30 2003 @@ -1932,7 +1932,6 @@ spin_lock_irqsave(&info->lock, flags); if (tty_hung_up_p(filp)) { - MOD_DEC_USE_COUNT; spin_unlock_irqrestore(&info->lock, flags); return; } @@ -1956,7 +1955,6 @@ info->count = 0; } if (info->count) { - MOD_DEC_USE_COUNT; spin_unlock_irqrestore(&info->lock, flags); return; } @@ -2026,7 +2024,6 @@ info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CALLOUT_ACTIVE| ZILOG_CLOSING); wake_up_interruptible(&info->close_wait); - MOD_DEC_USE_COUNT; } /* @@ -2233,17 +2230,14 @@ int retval, line; unsigned long page; - MOD_INC_USE_COUNT; line = tty->index; if ((line < 0) || (line >= zs_channels_found)) { - MOD_DEC_USE_COUNT; return -ENODEV; } info = zs_soft + line; #ifdef CONFIG_KGDB if (info->kgdb_channel) { - MOD_DEC_USE_COUNT; return -ENODEV; } #endif @@ -2610,6 +2604,7 @@ memset(&serial_driver, 0, sizeof(struct tty_driver)); serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.owner = THIS_MODULE; serial_driver.driver_name = "macserial"; #ifdef CONFIG_DEVFS_FS serial_driver.name = "tts/"; diff -Nru a/drivers/md/md.c b/drivers/md/md.c --- a/drivers/md/md.c Thu May 8 00:24:28 2003 +++ b/drivers/md/md.c Thu May 8 00:24:28 2003 @@ -1111,8 +1111,10 @@ static void print_desc(mdp_disk_t *desc) { + char b[BDEVNAME_SIZE]; + printk(" DISK\n", desc->number, - partition_name(MKDEV(desc->major,desc->minor)), + __bdevname(MKDEV(desc->major, desc->minor), b), desc->major,desc->minor,desc->raid_disk,desc->state); } @@ -1294,6 +1296,7 @@ */ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_minor) { + char b[BDEVNAME_SIZE]; int err; mdk_rdev_t *rdev; sector_t size; @@ -1301,7 +1304,7 @@ rdev = (mdk_rdev_t *) kmalloc(sizeof(*rdev), GFP_KERNEL); if (!rdev) { printk(KERN_ERR "md: could not alloc mem for %s!\n", - partition_name(newdev)); + __bdevname(newdev, b)); return ERR_PTR(-ENOMEM); } memset(rdev, 0, sizeof(*rdev)); @@ -1312,7 +1315,7 @@ err = lock_rdev(rdev, newdev); if (err) { printk(KERN_ERR "md: could not lock %s.\n", - partition_name(newdev)); + __bdevname(newdev, b)); goto abort_free; } rdev->desc_nr = -1; @@ -1840,6 +1843,7 @@ static int autostart_array(dev_t startdev) { + char b[BDEVNAME_SIZE]; int err = -EINVAL, i; mdp_super_t *sb = NULL; mdk_rdev_t *start_rdev = NULL, *rdev; @@ -1847,7 +1851,7 @@ start_rdev = md_import_device(startdev, 0, 0); if (IS_ERR(start_rdev)) { printk(KERN_WARNING "md: could not import %s!\n", - partition_name(startdev)); + __bdevname(startdev, b)); return err; } @@ -1884,7 +1888,7 @@ if (IS_ERR(rdev)) { printk(KERN_WARNING "md: could not import %s," " trying to run array nevertheless.\n", - partition_name(dev)); + __bdevname(dev, b)); continue; } list_add(&rdev->same_set, &pending_raid_disks); @@ -2116,6 +2120,7 @@ static int hot_generate_error(mddev_t * mddev, dev_t dev) { + char b[BDEVNAME_SIZE]; struct request_queue *q; mdk_rdev_t *rdev; @@ -2123,7 +2128,7 @@ return -ENODEV; printk(KERN_INFO "md: trying to generate %s error in md%d ... \n", - partition_name(dev), mdidx(mddev)); + __bdevname(dev, b), mdidx(mddev)); rdev = find_rdev(mddev, dev); if (!rdev) { @@ -2151,13 +2156,14 @@ static int hot_remove_disk(mddev_t * mddev, dev_t dev) { + char b[BDEVNAME_SIZE]; mdk_rdev_t *rdev; if (!mddev->pers) return -ENODEV; printk(KERN_INFO "md: trying to remove %s from md%d ... \n", - partition_name(dev), mdidx(mddev)); + __bdevname(dev, b), mdidx(mddev)); rdev = find_rdev(mddev, dev); if (!rdev) @@ -2178,6 +2184,7 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) { + char b[BDEVNAME_SIZE]; int err; unsigned int size; mdk_rdev_t *rdev; @@ -2186,7 +2193,7 @@ return -ENODEV; printk(KERN_INFO "md: trying to hot-add %s to md%d ... \n", - partition_name(dev), mdidx(mddev)); + __bdevname(dev, b), mdidx(mddev)); if (mddev->major_version != 0) { printk(KERN_WARNING "md%d: HOT_ADD may only be used with" @@ -2344,6 +2351,7 @@ static int md_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + char b[BDEVNAME_SIZE]; unsigned int minor; int err = 0; struct hd_geometry *loc = (struct hd_geometry *) arg; @@ -2403,7 +2411,7 @@ err = autostart_array(arg); if (err) { printk(KERN_WARNING "md: autostart %s failed!\n", - partition_name(arg)); + __bdevname(arg, b)); goto abort; } goto done; @@ -3516,6 +3524,7 @@ static void autostart_arrays(void) { + char b[BDEVNAME_SIZE]; mdk_rdev_t *rdev; int i; @@ -3527,7 +3536,7 @@ rdev = md_import_device(dev,0, 0); if (IS_ERR(rdev)) { printk(KERN_ALERT "md: could not import %s!\n", - partition_name(dev)); + __bdevname(dev, b)); continue; } if (rdev->faulty) { diff -Nru a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c --- a/drivers/media/dvb/dvb-core/dvbdev.c Thu May 8 00:24:28 2003 +++ b/drivers/media/dvb/dvb-core/dvbdev.c Thu May 8 00:24:28 2003 @@ -189,7 +189,6 @@ const struct dvb_device *template, void *priv, int type) { u32 id; - char name [20]; struct dvb_device *dvbdev; if (down_interruptible (&dvbdev_register_lock)) @@ -219,12 +218,12 @@ list_add_tail (&dvbdev->list_head, &adap->device_list); - sprintf(name, "dvb/adapter%d%s%d", adap->num, dnames[type], id); - devfs_register(NULL, name, 0, DVB_MAJOR, nums2minor(adap->num, type, id), - S_IFCHR | S_IRUSR | S_IWUSR, dvbdev->fops, dvbdev); + devfs_mk_cdev(MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)), + S_IFCHR | S_IRUSR | S_IWUSR, + "dvb/adapter%d/%s%d", adap->num, dnames[type], id); - dprintk("DVB: register adapter%d/%s @ minor: %i (0x%02x)\n", - adap->num, name, nums2minor(adap->num, type, id), + dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", + adap->num, dnames[type], id, nums2minor(adap->num, type, id), nums2minor(adap->num, type, id)); return 0; @@ -234,7 +233,7 @@ void dvb_unregister_device(struct dvb_device *dvbdev) { if (dvbdev) { - devfs_remove("dvb/adapter%d%s%d", dvbdev->adapter->num, + devfs_remove("dvb/adapter%d/%s%d", dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id); list_del(&dvbdev->list_head); kfree(dvbdev); @@ -322,12 +321,12 @@ int __init init_dvbdev(void) { devfs_mk_dir("dvb"); -#ifndef CONFIG_DVB_DEVFS_ONLY + if(register_chrdev(DVB_MAJOR,"DVB", &dvb_device_fops)) { printk("video_dev: unable to get major %d\n", DVB_MAJOR); return -EIO; } -#endif + return 0; } @@ -335,9 +334,7 @@ static void __exit exit_dvbdev(void) { -#ifndef CONFIG_DVB_DEVFS_ONLY unregister_chrdev(DVB_MAJOR, "DVB"); -#endif devfs_remove("dvb"); } diff -Nru a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c --- a/drivers/media/video/bt832.c Thu May 8 00:24:29 2003 +++ b/drivers/media/video/bt832.c Thu May 8 00:24:29 2003 @@ -198,25 +198,9 @@ static int bt832_probe(struct i2c_adapter *adap) { - int rc; - - printk("bt832_probe\n"); - - switch (adap->id) { - case I2C_ALGO_BIT | I2C_HW_B_BT848: - case I2C_ALGO_BIT | I2C_HW_B_RIVA: - case I2C_ALGO_SAA7134: - printk("bt832: probing %s i2c adapter [id=0x%x]\n", - adap->name,adap->id); - rc = i2c_probe(adap, &addr_data, bt832_attach); - break; - default: - printk("bt832: ignoring %s i2c adapter [id=0x%x]\n", - adap->name,adap->id); - rc = 0; - /* nothing */ - } - return rc; + if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) + return i2c_probe(adap, &addr_data, bt832_attach); + return 0; } static int bt832_detach(struct i2c_client *client) diff -Nru a/drivers/media/video/bttv-if.c b/drivers/media/video/bttv-if.c --- a/drivers/media/video/bttv-if.c Thu May 8 00:24:27 2003 +++ b/drivers/media/video/bttv-if.c Thu May 8 00:24:27 2003 @@ -7,7 +7,7 @@ Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) & Marcus Metzler (mocm@thp.uni-koeln.de) - (c) 1999,2000 Gerd Knorr + (c) 1999-2003 Gerd Knorr This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -195,51 +195,21 @@ static int attach_inform(struct i2c_client *client) { struct bttv *btv = i2c_get_adapdata(client->adapter); - int i; - for (i = 0; i < I2C_CLIENTS_MAX; i++) { - if (btv->i2c_clients[i] == NULL) { - btv->i2c_clients[i] = client; - break; - } - } - if (btv->tuner_type != -1) + if (btv->tuner_type != UNSET) bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type); - if (bttv_verbose) - printk("bttv%d: i2c attach [client=%s,%s]\n",btv->nr, - client->dev.name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed"); - return 0; -} - -static int detach_inform(struct i2c_client *client) -{ - struct bttv *btv = i2c_get_adapdata(client->adapter); - int i; - for (i = 0; i < I2C_CLIENTS_MAX; i++) { - if (btv->i2c_clients[i] == client) { - btv->i2c_clients[i] = NULL; - break; - } - } - if (bttv_verbose) - printk("bttv%d: i2c detach [client=%s,%s]\n",btv->nr, - client->dev.name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed"); + if (bttv_debug) + printk("bttv%d: i2c attach [client=%s]\n", + btv->nr, i2c_clientname(client)); return 0; } void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg) { - int i; - - for (i = 0; i < I2C_CLIENTS_MAX; i++) { - if (NULL == btv->i2c_clients[i]) - continue; - if (NULL == btv->i2c_clients[i]->driver->command) - continue; - btv->i2c_clients[i]->driver->command( - btv->i2c_clients[i],cmd,arg); - } + if (0 != btv->i2c_rc) + return; + i2c_clients_command(&btv->i2c_adap, cmd, arg); } void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg) @@ -260,20 +230,16 @@ }; static struct i2c_adapter bttv_i2c_adap_template = { - .owner = THIS_MODULE, + .owner = THIS_MODULE, + I2C_DEVNAME("bt848"), .id = I2C_HW_B_BT848, + .class = I2C_ADAP_CLASS_TV_ANALOG, .client_register = attach_inform, - .client_unregister = detach_inform, - .dev = { - .name = "bt848", - }, }; static struct i2c_client bttv_i2c_client_template = { - .id = -1, - .dev = { - .name = "bttv internal", - }, + I2C_DEVNAME("bttv internal"), + .id = -1, }; @@ -347,8 +313,8 @@ memcpy(&btv->i2c_client, &bttv_i2c_client_template, sizeof(struct i2c_client)); - sprintf(btv->i2c_adap.dev.name+strlen(btv->i2c_adap.dev.name), - " #%d", btv->nr); + sprintf(btv->i2c_adap.dev.name, "bt848 #%d", btv->nr); + btv->i2c_algo.data = btv; i2c_set_adapdata(&btv->i2c_adap, btv); btv->i2c_adap.algo_data = &btv->i2c_algo; diff -Nru a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h --- a/drivers/media/video/bttv.h Thu May 8 00:24:27 2003 +++ b/drivers/media/video/bttv.h Thu May 8 00:24:27 2003 @@ -243,7 +243,6 @@ /* i2c */ -#define I2C_CLIENTS_MAX 16 extern void bttv_bit_setscl(void *data, int state); extern void bttv_bit_setsda(void *data, int state); extern void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg); diff -Nru a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h --- a/drivers/media/video/bttvp.h Thu May 8 00:24:28 2003 +++ b/drivers/media/video/bttvp.h Thu May 8 00:24:28 2003 @@ -62,6 +62,8 @@ #define RAW_LINES 640 #define RAW_BPL 1024 +#define UNSET (-1U) + /* ---------------------------------------------------------- */ struct bttv_tvnorm @@ -276,7 +278,6 @@ struct i2c_algo_bit_data i2c_algo; struct i2c_client i2c_client; int i2c_state, i2c_rc; - struct i2c_client *i2c_clients[I2C_CLIENTS_MAX]; /* video4linux (1) */ struct video_device video_dev; diff -Nru a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c --- a/drivers/media/video/cpia.c Thu May 8 00:24:29 2003 +++ b/drivers/media/video/cpia.c Thu May 8 00:24:29 2003 @@ -1409,12 +1409,10 @@ LOG("Unable to initialise /proc/cpia\n"); } -#ifdef MODULE -static void proc_cpia_destroy(void) +static void __exit proc_cpia_destroy(void) { remove_proc_entry("cpia", 0); } -#endif /*MODULE*/ #endif /* CONFIG_PROC_FS */ /* ----------------------- debug functions ---------------------- */ diff -Nru a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c --- a/drivers/media/video/dpc7146.c Thu May 8 00:24:28 2003 +++ b/drivers/media/video/dpc7146.c Thu May 8 00:24:28 2003 @@ -96,7 +96,8 @@ static int dpc_probe(struct saa7146_dev* dev) { struct dpc* dpc = 0; - int i = 0; + struct i2c_client *client; + struct list_head *item; dpc = (struct dpc*)kmalloc(sizeof(struct dpc), GFP_KERNEL); if( NULL == dpc ) { @@ -117,12 +118,10 @@ } /* loop through all i2c-devices on the bus and look who is there */ - for(i = 0; i < I2C_CLIENT_MAX; i++) { - if( NULL == dpc->i2c_adapter.clients[i] ) { - continue; - } - if( I2C_SAA7111A == dpc->i2c_adapter.clients[i]->addr ) - dpc->saa7111a = dpc->i2c_adapter.clients[i]; + list_for_each(item,&dpc->i2c_adapter.clients) { + client = list_entry(item, struct i2c_client, list); + if( I2C_SAA7111A == client->addr ) + dpc->saa7111a = client; } /* check if all devices are present */ diff -Nru a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c --- a/drivers/media/video/msp3400.c Thu May 8 00:24:29 2003 +++ b/drivers/media/video/msp3400.c Thu May 8 00:24:29 2003 @@ -1372,7 +1372,7 @@ static int msp_probe(struct i2c_adapter *adap) { - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) + if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, msp_attach); return 0; } diff -Nru a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c --- a/drivers/media/video/mxb.c Thu May 8 00:24:27 2003 +++ b/drivers/media/video/mxb.c Thu May 8 00:24:27 2003 @@ -208,7 +208,8 @@ static int mxb_probe(struct saa7146_dev* dev) { struct mxb* mxb = 0; - int i = 0; + struct i2c_client *client; + struct list_head *item; request_module("tuner"); request_module("tea6420"); @@ -235,22 +236,20 @@ } /* loop through all i2c-devices on the bus and look who is there */ - for(i = 0; i < I2C_CLIENT_MAX; i++) { - if( NULL == mxb->i2c_adapter.clients[i] ) { - continue; - } - if( I2C_TEA6420_1 == mxb->i2c_adapter.clients[i]->addr ) - mxb->tea6420_1 = mxb->i2c_adapter.clients[i]; - if( I2C_TEA6420_2 == mxb->i2c_adapter.clients[i]->addr ) - mxb->tea6420_2 = mxb->i2c_adapter.clients[i]; - if( I2C_TEA6415C_2 == mxb->i2c_adapter.clients[i]->addr ) - mxb->tea6415c = mxb->i2c_adapter.clients[i]; - if( I2C_TDA9840 == mxb->i2c_adapter.clients[i]->addr ) - mxb->tda9840 = mxb->i2c_adapter.clients[i]; - if( I2C_SAA7111A == mxb->i2c_adapter.clients[i]->addr ) - mxb->saa7111a = mxb->i2c_adapter.clients[i]; - if( 0x60 == mxb->i2c_adapter.clients[i]->addr ) - mxb->tuner = mxb->i2c_adapter.clients[i]; + list_for_each(item,&mxb->i2c_adapter.clients) { + client = list_entry(item, struct i2c_client, list); + if( I2C_TEA6420_1 == client->addr ) + mxb->tea6420_1 = client; + if( I2C_TEA6420_2 == client->addr ) + mxb->tea6420_2 = client; + if( I2C_TEA6415C_2 == client->addr ) + mxb->tea6415c = client; + if( I2C_TDA9840 == client->addr ) + mxb->tda9840 = client; + if( I2C_SAA7111A == client->addr ) + mxb->saa7111a = client; + if( 0x60 == client->addr ) + mxb->tuner = client; } /* check if all devices are present */ diff -Nru a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c --- a/drivers/media/video/saa5249.c Thu May 8 00:24:29 2003 +++ b/drivers/media/video/saa5249.c Thu May 8 00:24:29 2003 @@ -224,12 +224,8 @@ static int saa5249_probe(struct i2c_adapter *adap) { - /* Only attach these chips to the BT848 bus for now */ - - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) - { + if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, saa5249_attach); - } return 0; } diff -Nru a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c --- a/drivers/media/video/saa7134/saa7134-i2c.c Thu May 8 00:24:28 2003 +++ b/drivers/media/video/saa7134/saa7134-i2c.c Thu May 8 00:24:28 2003 @@ -334,19 +334,16 @@ static struct i2c_adapter saa7134_adap_template = { .owner = THIS_MODULE, + I2C_DEVNAME("saa7134"), .id = I2C_ALGO_SAA7134, + .class = I2C_ADAP_CLASS_TV_ANALOG, .algo = &saa7134_algo, .client_register = attach_inform, - .dev = { - .name = "saa7134", - }, }; static struct i2c_client saa7134_client_template = { - .id = -1, - .dev = { - .name = "saa7134 internal", - }, + I2C_DEVNAME("saa7134 internal"), + .id = -1, }; /* ----------------------------------------------------------- */ @@ -399,22 +396,13 @@ void saa7134_i2c_call_clients(struct saa7134_dev *dev, unsigned int cmd, void *arg) { - int i; - - for (i = 0; i < I2C_CLIENT_MAX; i++) { - if (NULL == dev->i2c_adap.clients[i]) - continue; - if (NULL == dev->i2c_adap.clients[i]->driver->command) - continue; - dev->i2c_adap.clients[i]->driver->command - (dev->i2c_adap.clients[i],cmd,arg); - } + i2c_clients_command(&dev->i2c_adap, cmd, arg); } int saa7134_i2c_register(struct saa7134_dev *dev) { dev->i2c_adap = saa7134_adap_template; - strncpy(dev->i2c_adap.dev.name, dev->name, DEVICE_NAME_SIZE); + strcpy(dev->i2c_adap.dev.name,dev->name); dev->i2c_adap.algo_data = dev; i2c_add_adapter(&dev->i2c_adap); diff -Nru a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c --- a/drivers/media/video/tda7432.c Thu May 8 00:24:29 2003 +++ b/drivers/media/video/tda7432.c Thu May 8 00:24:29 2003 @@ -340,7 +340,7 @@ static int tda7432_probe(struct i2c_adapter *adap) { - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) + if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, tda7432_attach); return 0; } diff -Nru a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c --- a/drivers/media/video/tda9875.c Thu May 8 00:24:28 2003 +++ b/drivers/media/video/tda9875.c Thu May 8 00:24:28 2003 @@ -273,7 +273,7 @@ static int tda9875_probe(struct i2c_adapter *adap) { - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) + if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, tda9875_attach); return 0; } diff -Nru a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c --- a/drivers/media/video/tda9887.c Thu May 8 00:24:27 2003 +++ b/drivers/media/video/tda9887.c Thu May 8 00:24:27 2003 @@ -368,23 +368,9 @@ static int tda9887_probe(struct i2c_adapter *adap) { - int rc; - - switch (adap->id) { - case I2C_ALGO_BIT | I2C_HW_B_BT848: - case I2C_ALGO_BIT | I2C_HW_B_RIVA: - case I2C_ALGO_SAA7134: - printk("tda9887: probing %s i2c adapter [id=0x%x]\n", - adap->dev.name,adap->id); - rc = i2c_probe(adap, &addr_data, tda9887_attach); - break; - default: - printk("tda9887: ignoring %s i2c adapter [id=0x%x]\n", - adap->dev.name,adap->id); - rc = 0; - /* nothing */ - } - return rc; + if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) + return i2c_probe(adap, &addr_data, tda9887_attach); + return 0; } static int tda9887_detach(struct i2c_client *client) diff -Nru a/drivers/media/video/tuner.c b/drivers/media/video/tuner.c --- a/drivers/media/video/tuner.c Thu May 8 00:24:29 2003 +++ b/drivers/media/video/tuner.c Thu May 8 00:24:29 2003 @@ -817,29 +817,15 @@ static int tuner_probe(struct i2c_adapter *adap) { - int rc; - if (0 != addr) { normal_i2c_range[0] = addr; normal_i2c_range[1] = addr; } this_adap = 0; - switch (adap->id) { - case I2C_ALGO_BIT | I2C_HW_B_BT848: - case I2C_ALGO_BIT | I2C_HW_B_RIVA: - case I2C_ALGO_SAA7134: - case I2C_ALGO_SAA7146: - printk("tuner: probing %s i2c adapter [id=0x%x]\n", - adap->dev.name,adap->id); - rc = i2c_probe(adap, &addr_data, tuner_attach); - break; - default: - printk("tuner: ignoring %s i2c adapter [id=0x%x]\n", - adap->dev.name,adap->id); - rc = 0; - /* nothing */ - } - return rc; + + if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) + return i2c_probe(adap, &addr_data, tuner_attach); + return 0; } static int tuner_detach(struct i2c_client *client) diff -Nru a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c --- a/drivers/media/video/tvaudio.c Thu May 8 00:24:28 2003 +++ b/drivers/media/video/tvaudio.c Thu May 8 00:24:28 2003 @@ -1408,14 +1408,9 @@ static int chip_probe(struct i2c_adapter *adap) { - switch (adap->id) { - case I2C_ALGO_BIT | I2C_HW_B_BT848: - case I2C_ALGO_BIT | I2C_HW_B_RIVA: + if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, chip_attach); - default: - /* ignore this i2c bus */ - return 0; - } + return 0; } static int chip_detach(struct i2c_client *client) diff -Nru a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c --- a/drivers/media/video/tvmixer.c Thu May 8 00:24:30 2003 +++ b/drivers/media/video/tvmixer.c Thu May 8 00:24:30 2003 @@ -217,8 +217,9 @@ .owner = THIS_MODULE, .name = "tv card mixer driver", .id = I2C_DRIVERID_TVMIXER, - .flags = I2C_DF_DUMMY, + .flags = I2C_DF_NOTIFY, .attach_adapter = tvmixer_adapters, + .detach_adapter = tvmixer_adapters, .detach_client = tvmixer_clients, }; @@ -234,14 +235,15 @@ static int tvmixer_adapters(struct i2c_adapter *adap) { - int i; + struct list_head *item; + struct i2c_client *client; if (debug) printk("tvmixer: adapter %s\n",adap->dev.name); - for (i=0; iclients[i]) - continue; - tvmixer_clients(adap->clients[i]); + + list_for_each(item,&adap->clients) { + client = list_entry(item, struct i2c_client, list); + tvmixer_clients(client); } return 0; } @@ -252,19 +254,15 @@ int i,minor; /* TV card ??? */ - switch (client->adapter->id) { - case I2C_ALGO_BIT | I2C_HW_B_BT848: - case I2C_ALGO_BIT | I2C_HW_B_RIVA: - /* ok, have a look ... */ - break; - default: + if (!(client->adapter->class & I2C_ADAP_CLASS_TV_ANALOG)) { /* ignore that one */ if (debug) printk("tvmixer: %s is not a tv card\n", client->adapter->dev.name); return -1; } - printk("tvmixer: debug: %s\n",client->dev.name); + if (debug) + printk("tvmixer: debug: %s\n",client->dev.name); /* unregister ?? */ for (i = 0; i < DEV_MAX; i++) { diff -Nru a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c --- a/drivers/media/video/videodev.c Thu May 8 00:24:27 2003 +++ b/drivers/media/video/videodev.c Thu May 8 00:24:27 2003 @@ -427,8 +427,8 @@ up(&videodev_lock); sprintf(vfd->devfs_name, "v4l/%s%d", name_base, i - base); - devfs_register(NULL, vfd->devfs_name, 0, VIDEO_MAJOR, vfd->minor, - S_IFCHR | S_IRUSR | S_IWUSR, &video_fops, NULL); + devfs_mk_cdev(MKDEV(VIDEO_MAJOR, vfd->minor), + S_IFCHR | S_IRUSR | S_IWUSR, vfd->devfs_name); init_MUTEX(&vfd->lock); #ifdef CONFIG_VIDEO_PROC_FS diff -Nru a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c --- a/drivers/mtd/mtdchar.c Thu May 8 00:24:29 2003 +++ b/drivers/mtd/mtdchar.c Thu May 8 00:24:29 2003 @@ -461,22 +461,12 @@ static void mtd_notify_add(struct mtd_info* mtd) { - char name[16]; - if (!mtd) return; - - sprintf(name, "mtd/%d", mtd->index); - devfs_register(NULL, name, - DEVFS_FL_DEFAULT, MTD_CHAR_MAJOR, mtd->index*2, - S_IFCHR | S_IRUGO | S_IWUGO, - &mtd_fops, NULL); - - sprintf(name, "mtd/%dro", mtd->index); - devfs_register(NULL, name, - DEVFS_FL_DEFAULT, MTD_CHAR_MAJOR, mtd->index*2+1, - S_IFCHR | S_IRUGO | S_IWUGO, - &mtd_fops, NULL); + devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2), + S_IFCHR | S_IRUGO | S_IWUGO, "mtd/%d", mtd->index); + devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1), + S_IFCHR | S_IRUGO | S_IWUGO, "mtd/%dro", mtd->index); } static void mtd_notify_remove(struct mtd_info* mtd) diff -Nru a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c --- a/drivers/net/pcmcia/3c589_cs.c Thu May 8 00:24:30 2003 +++ b/drivers/net/pcmcia/3c589_cs.c Thu May 8 00:24:30 2003 @@ -159,7 +159,7 @@ static int el3_config(struct net_device *dev, struct ifmap *map); static int el3_open(struct net_device *dev); static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev); -static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void update_stats(struct net_device *dev); static struct net_device_stats *el3_get_stats(struct net_device *dev); static int el3_rx(struct net_device *dev); @@ -816,15 +816,16 @@ } /* The EL3 interrupt handler. */ -static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct el3_private *lp = dev_id; struct net_device *dev = &lp->dev; ioaddr_t ioaddr, status; - int i = 0; + int i = 0, handled = 1; if (!netif_device_present(dev)) - return; + return IRQ_NONE; + ioaddr = dev->base_addr; DEBUG(3, "%s: interrupt, status %4.4x.\n", @@ -833,9 +834,9 @@ spin_lock(&lp->lock); while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete | StatsFull)) { - if (!netif_device_present(dev) || - ((status & 0xe000) != 0x2000)) { + if ((status & 0xe000) != 0x2000) { DEBUG(1, "%s: interrupt from dead card\n", dev->name); + handled = 0; break; } @@ -897,7 +898,7 @@ spin_unlock(&lp->lock); DEBUG(3, "%s: exiting interrupt, status %4.4x.\n", dev->name, inw(ioaddr + EL3_STATUS)); - return; + return IRQ_RETVAL(handled); } static void media_check(unsigned long arg) diff -Nru a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c --- a/drivers/net/pcmcia/fmvj18x_cs.c Thu May 8 00:24:29 2003 +++ b/drivers/net/pcmcia/fmvj18x_cs.c Thu May 8 00:24:29 2003 @@ -107,7 +107,7 @@ static int fjn_open(struct net_device *dev); static int fjn_close(struct net_device *dev); static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev); -static void fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void fjn_rx(struct net_device *dev); static void fjn_reset(struct net_device *dev); static struct net_device_stats *fjn_get_stats(struct net_device *dev); @@ -845,7 +845,7 @@ /*====================================================================*/ -static void fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs) { local_info_t *lp = dev_id; struct net_device *dev = &lp->dev; @@ -855,7 +855,7 @@ if (lp == NULL) { printk(KERN_NOTICE "fjn_interrupt(): irq %d for " "unknown device.\n", irq); - return; + return IRQ_NONE; } ioaddr = dev->base_addr; @@ -899,6 +899,7 @@ outb(D_TX_INTR, ioaddr + TX_INTR); outb(D_RX_INTR, ioaddr + RX_INTR); + return IRQ_HANDLED; } /* fjn_interrupt */ diff -Nru a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c --- a/drivers/net/pcmcia/ibmtr_cs.c Thu May 8 00:24:29 2003 +++ b/drivers/net/pcmcia/ibmtr_cs.c Thu May 8 00:24:29 2003 @@ -127,7 +127,7 @@ extern int ibmtr_probe(struct net_device *dev); extern int trdev_init(struct net_device *dev); -extern void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs); +extern irqreturn_t tok_interrupt (int irq, void *dev_id, struct pt_regs *regs); /*====================================================================*/ diff -Nru a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c --- a/drivers/net/pcmcia/nmclan_cs.c Thu May 8 00:24:27 2003 +++ b/drivers/net/pcmcia/nmclan_cs.c Thu May 8 00:24:27 2003 @@ -431,7 +431,7 @@ static int mace_close(struct net_device *dev); static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev); static void mace_tx_timeout(struct net_device *dev); -static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs); static struct net_device_stats *mace_get_stats(struct net_device *dev); static int mace_rx(struct net_device *dev, unsigned char RxCnt); static void restore_multicast_list(struct net_device *dev); @@ -1143,7 +1143,7 @@ mace_interrupt The interrupt handler. ---------------------------------------------------------------------------- */ -static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs) { mace_private *lp = (mace_private *)dev_id; struct net_device *dev = &lp->dev; @@ -1154,7 +1154,7 @@ if (dev == NULL) { DEBUG(2, "mace_interrupt(): irq 0x%X for unknown device.\n", irq); - return; + return IRQ_NONE; } if (lp->tx_irq_disabled) { @@ -1169,12 +1169,12 @@ inb(ioaddr + AM2150_MACE_BASE + MACE_IMR) ); /* WARNING: MACE_IR has been read! */ - return; + return IRQ_NONE; } if (!netif_device_present(dev)) { DEBUG(2, "%s: interrupt from dead card\n", dev->name); - goto exception; + return IRQ_NONE; } do { @@ -1279,8 +1279,7 @@ } while ((status & ~MACE_IMR_DEFAULT) && (--IntrCnt)); -exception: - return; + return IRQ_HANDLED; } /* mace_interrupt */ /* ---------------------------------------------------------------------------- diff -Nru a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c --- a/drivers/net/pcmcia/smc91c92_cs.c Thu May 8 00:24:29 2003 +++ b/drivers/net/pcmcia/smc91c92_cs.c Thu May 8 00:24:29 2003 @@ -293,7 +293,7 @@ static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static void smc_tx_timeout(struct net_device *dev); static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev); -static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void smc_rx(struct net_device *dev); static struct net_device_stats *smc_get_stats(struct net_device *dev); static void set_rx_mode(struct net_device *dev); @@ -1574,16 +1574,18 @@ /*====================================================================*/ -static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct smc_private *smc = dev_id; struct net_device *dev = &smc->dev; ioaddr_t ioaddr; u_short saved_bank, saved_pointer, mask, status; + unsigned int handled = 1; char bogus_cnt = INTR_WORK; /* Work we are willing to do. */ if (!netif_device_present(dev)) - return; + return IRQ_NONE; + ioaddr = dev->base_addr; DEBUG(3, "%s: SMC91c92 interrupt %d at %#x.\n", dev->name, @@ -1596,6 +1598,7 @@ maybe it has been ejected. */ DEBUG(1, "%s: SMC91c92 interrupt %d for non-existent" "/ejected device.\n", dev->name, irq); + handled = 0; goto irq_done; } @@ -1609,9 +1612,11 @@ status = inw(ioaddr + INTERRUPT) & 0xff; DEBUG(3, "%s: Status is %#2.2x (mask %#2.2x).\n", dev->name, status, mask); - if ((status & mask) == 0) + if ((status & mask) == 0) { + if (bogus_cnt == INTR_WORK) + handled = 0; break; - + } if (status & IM_RCV_INT) { /* Got a packet(s). */ smc_rx(dev); @@ -1683,6 +1688,7 @@ readb(smc->base+MEGAHERTZ_ISR); } #endif + return IRQ_RETVAL(handled); } /*====================================================================*/ diff -Nru a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c --- a/drivers/net/pcmcia/xirc2ps_cs.c Thu May 8 00:24:28 2003 +++ b/drivers/net/pcmcia/xirc2ps_cs.c Thu May 8 00:24:28 2003 @@ -317,7 +317,7 @@ * less on other parts of the kernel. */ -static void xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs); /* * The dev_info variable is the "key" that is used to match up this @@ -1296,7 +1296,7 @@ /**************** * This is the Interrupt service route. */ -static void +static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *)dev_id; @@ -1305,14 +1305,14 @@ u_char saved_page; unsigned bytes_rcvd; unsigned int_status, eth_status, rx_status, tx_status; - unsigned rsr, pktlen; + unsigned rsr, pktlen, handled = 1; ulong start_ticks = jiffies; /* fixme: jiffies rollover every 497 days * is this something to worry about? * -- on a laptop? */ if (!netif_device_present(dev)) - return; + return IRQ_NONE; ioaddr = dev->base_addr; if (lp->mohawk) { /* must disable the interrupt */ @@ -1330,6 +1330,7 @@ loop_entry: if (int_status == 0xff) { /* card may be ejected */ DEBUG(3, "%s: interrupt %d for dead card\n", dev->name, irq); + handled = 0; goto leave; } eth_status = GetByte(XIRCREG_ESR); @@ -1514,6 +1515,7 @@ * force an interrupt with this command: * PutByte(XIRCREG_CR, EnableIntr|ForceIntr); */ + return IRQ_RETVAL(handled); } /* xirc2ps_interrupt */ /*====================================================================*/ diff -Nru a/drivers/net/ppp_deflate.c b/drivers/net/ppp_deflate.c --- a/drivers/net/ppp_deflate.c Thu May 8 00:24:30 2003 +++ b/drivers/net/ppp_deflate.c Thu May 8 00:24:30 2003 @@ -88,7 +88,6 @@ if (state->strm.workspace) vfree(state->strm.workspace); kfree(state); - MOD_DEC_USE_COUNT; } } @@ -118,7 +117,6 @@ if (state == NULL) return NULL; - MOD_INC_USE_COUNT; memset (state, 0, sizeof (struct ppp_deflate_state)); state->strm.next_in = NULL; state->w_size = w_size; @@ -274,7 +272,6 @@ if (state->strm.workspace) kfree(state->strm.workspace); kfree(state); - MOD_DEC_USE_COUNT; } } @@ -303,7 +300,6 @@ if (state == NULL) return NULL; - MOD_INC_USE_COUNT; memset (state, 0, sizeof (struct ppp_deflate_state)); state->w_size = w_size; state->strm.next_out = NULL; diff -Nru a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c --- a/drivers/net/ppp_generic.c Thu May 8 00:24:30 2003 +++ b/drivers/net/ppp_generic.c Thu May 8 00:24:30 2003 @@ -784,11 +784,14 @@ printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n"); err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops); - if (err) + if (!err) { + err = devfs_mk_cdev(MKDEV(PPP_MAJOR, 0), + S_IFCHR|S_IRUSR|S_IWUSR, "ppp"); + } + + if (!err) printk(KERN_ERR "failed to register PPP device (%d)\n", err); - devfs_register(NULL, "ppp", DEVFS_FL_DEFAULT, PPP_MAJOR, 0, - S_IFCHR | S_IRUSR | S_IWUSR, &ppp_device_fops, NULL); - return 0; + return err; } /* diff -Nru a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c --- a/drivers/net/wan/cosa.c Thu May 8 00:24:27 2003 +++ b/drivers/net/wan/cosa.c Thu May 8 00:24:27 2003 @@ -392,12 +392,9 @@ } devfs_mk_dir("cosa"); for (i=0; iminor), + S_IFCHR|S_IRUSR|S_IWUSR, "3270/tub%.4x"); TUBUNLOCK(tubp->irq, flags); return minor; @@ -492,9 +491,7 @@ for (i = 0; i < TUBMAXMINS; i++) { tubpp = &(*tubminors)[i]; if ((tubp = *tubpp)) { -#ifdef CONFIG_DEVFS_FS - fs3270_devfs_unregister(tubp); -#endif + devfs_remove("3270/tub%.4x", tubp->devno); tubdelbyirq(tubp, tubp->irq); tty3270_rcl_fini(tubp); kfree(tubp->tty_bcb.bc_buf); diff -Nru a/drivers/s390/char/tubfs.c b/drivers/s390/char/tubfs.c --- a/drivers/s390/char/tubfs.c Thu May 8 00:24:29 2003 +++ b/drivers/s390/char/tubfs.c Thu May 8 00:24:29 2003 @@ -23,9 +23,7 @@ extern void tty3270_refresh(tub_t *); static struct file_operations fs3270_fops = { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)) .owner = THIS_MODULE, /* owner */ -#endif .read = fs3270_read, /* read */ .write = fs3270_write, /* write */ .ioctl = fs3270_ioctl, /* ioctl */ @@ -33,27 +31,6 @@ .release = fs3270_close, /* release */ }; -#ifdef CONFIG_DEVFS_FS -void fs3270_devfs_register(tub_t *tubp) -{ - char name[16]; - - sprintf(name, "3270/tub%.4x", tubp->devno); - devfs_register(NULL, name, DEVFS_FL_DEFAULT, - IBM_FS3270_MAJOR, tubp->minor, - S_IFCHR | S_IRUSR | S_IWUSR, &fs3270_fops, NULL); - sprintf(name, "tty%.4x", tubp->devno); - tty_register_devfs_name(&tty3270_driver, 0, tubp->minor, - NULL, name); -} - -void fs3270_devfs_unregister(tub_t *tubp) -{ - devfs_remove("3270/tub%.4x", tubp->devno); - devfs_remove("3270/tty%.4x", tubp->devno); -} -#endif - /* * fs3270_init() -- Initialize fullscreen tubes */ @@ -69,10 +46,8 @@ return -1; } devfs_mk_dir("3270"); - devfs_register(NULL, "3270/tub", 0, - IBM_FS3270_MAJOR, 0, - S_IFCHR | S_IRUGO | S_IWUGO, - &fs3270_fops, NULL); + devfs_mk_cdev(MKDEV(IBM_FS3270_MAJOR, 0), + S_IFCHR|S_IRUGO|S_IWUGO, "3270/tub"); fs3270_major = IBM_FS3270_MAJOR; return 0; } diff -Nru a/drivers/s390/char/tubio.h b/drivers/s390/char/tubio.h --- a/drivers/s390/char/tubio.h Thu May 8 00:24:29 2003 +++ b/drivers/s390/char/tubio.h Thu May 8 00:24:29 2003 @@ -337,10 +337,6 @@ extern int tty3270_proc_misc; extern enum tubwhat tty3270_proc_what; extern struct tty_driver tty3270_driver; -#ifdef CONFIG_DEVFS_FS -extern void fs3270_devfs_register(tub_t *); -extern void fs3270_devfs_unregister(tub_t *); -#endif #ifndef spin_trylock_irqsave #define spin_trylock_irqsave(lock, flags) \ diff -Nru a/drivers/s390/char/tubtty.c b/drivers/s390/char/tubtty.c --- a/drivers/s390/char/tubtty.c Thu May 8 00:24:29 2003 +++ b/drivers/s390/char/tubtty.c Thu May 8 00:24:29 2003 @@ -90,9 +90,7 @@ td->subtype = SYSTEM_TYPE_TTY; td->init_termios = tty_std_termios; td->flags = TTY_DRIVER_RESET_TERMIOS; -#ifdef CONFIG_DEVFS_FS td->flags |= TTY_DRIVER_NO_DEVFS; -#endif td->refcount = &tty3270_refcount; td->table = tty3270_table; td->termios = tty3270_termios; diff -Nru a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c --- a/drivers/sbus/char/bpp.c Thu May 8 00:24:27 2003 +++ b/drivers/sbus/char/bpp.c Thu May 8 00:24:27 2003 @@ -1051,11 +1051,8 @@ } devfs_mk_dir("bpp"); for (idx = 0; idx < BPP_NO; idx++) { - char name[16]; - sprintf(name, "bpp/%d", idx); - devfs_register(NULL, name, DEVFS_FL_DEFAULT, - BPP_MAJOR, idx, S_IFCHR | S_IRUSR | S_IWUSR, - &bpp_fops, NULL); + devfs_mk_cdev(MKDEV(BPP_MAJOR, idx), + S_IFCHR | S_IRUSR | S_IWUSR, "bpp/%d", idx); } return 0; diff -Nru a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c --- a/drivers/sbus/char/vfc_dev.c Thu May 8 00:24:29 2003 +++ b/drivers/sbus/char/vfc_dev.c Thu May 8 00:24:29 2003 @@ -143,8 +143,6 @@ int init_vfc_device(struct sbus_dev *sdev,struct vfc_dev *dev, int instance) { - char devname[16]; - if(dev == NULL) { printk(KERN_ERR "VFC: Bogus pointer passed\n"); return -ENOMEM; @@ -167,11 +165,9 @@ if (init_vfc_hw(dev)) return -EIO; - sprintf (devname, "vfc/%d", instance); - dev->de = devfs_register (NULL, devname, DEVFS_FL_DEFAULT, - VFC_MAJOR, instance, - S_IFCHR | S_IRUSR | S_IWUSR, - &vfc_fops, NULL); + devfs_mk_cdev(MKDEV(VFC_MAJOR, instance), + S_IFCHR | S_IRUSR | S_IWUSR, + "vfc/%d", instance); return 0; } diff -Nru a/drivers/scsi/osst.c b/drivers/scsi/osst.c --- a/drivers/scsi/osst.c Thu May 8 00:24:28 2003 +++ b/drivers/scsi/osst.c Thu May 8 00:24:28 2003 @@ -5527,11 +5527,10 @@ write_unlock(&os_scsi_tapes_lock); for (mode = 0; mode < ST_NBR_MODES; ++mode) { - char name[8], devfs_name[64]; + char name[8]; /* Rewind entry */ sprintf(name, "ot%s", osst_formats[mode]); - sprintf(devfs_name, "%s/ot%s", SDp->devfs_name, osst_formats[mode]); sprintf(tpnt->driverfs_dev_r[mode].bus_id, "%s:%s", SDp->sdev_driverfs_dev.bus_id, name); @@ -5545,13 +5544,13 @@ device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_type); device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_kdev); - devfs_register(NULL, devfs_name, 0, - OSST_MAJOR, dev_num + (mode << 5), - S_IFCHR | S_IRUGO | S_IWUGO, - &osst_fops, NULL); + + devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5)), + S_IFCHR | S_IRUGO | S_IWUGO, + "%s/ot%s", SDp->devfs_name, osst_formats[mode]); + /* No-rewind entry */ sprintf (name, "ot%sn", osst_formats[mode]); - sprintf(devfs_name, "%s/ot%sn", SDp->devfs_name, osst_formats[mode]); sprintf(tpnt->driverfs_dev_n[mode].bus_id, "%s:%s", SDp->sdev_driverfs_dev.bus_id, name); @@ -5566,10 +5565,10 @@ &dev_attr_type); device_create_file(&tpnt->driverfs_dev_n[mode], &dev_attr_kdev); - devfs_register(NULL, devfs_name, 0, - OSST_MAJOR, dev_num + (mode << 5) + 128, - S_IFCHR | S_IRUGO | S_IWUGO, - &osst_fops, NULL); + + devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5) + 128), + S_IFCHR | S_IRUGO | S_IWUGO, + "%s/ot%sn", SDp->devfs_name, osst_formats[mode]); } drive->number = devfs_register_tape(SDp->devfs_name); diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c --- a/drivers/scsi/sg.c Thu May 8 00:24:28 2003 +++ b/drivers/scsi/sg.c Thu May 8 00:24:28 2003 @@ -1350,7 +1350,6 @@ struct gendisk *disk; Sg_device *sdp = NULL; unsigned long iflags; - char devfs_name[64]; int k, error; disk = alloc_disk(1); @@ -1449,11 +1448,9 @@ device_create_file(&sdp->sg_driverfs_dev, &dev_attr_type); device_create_file(&sdp->sg_driverfs_dev, &dev_attr_kdev); - sprintf(devfs_name, "%s/generic", scsidp->devfs_name); - devfs_register(NULL, devfs_name, 0, - SCSI_GENERIC_MAJOR, k, + devfs_mk_cdev(MKDEV(SCSI_GENERIC_MAJOR, k), S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, - &sg_fops, sdp); + "%s/generic", scsidp->devfs_name); switch (scsidp->type) { case TYPE_DISK: diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c --- a/drivers/scsi/st.c Thu May 8 00:24:29 2003 +++ b/drivers/scsi/st.c Thu May 8 00:24:29 2003 @@ -3865,11 +3865,10 @@ write_unlock(&st_dev_arr_lock); for (mode = 0; mode < ST_NBR_MODES; ++mode) { - char name[8], devfs_name[64]; + char name[8]; /* Rewind entry */ sprintf(name, "mt%s", st_formats[mode]); - sprintf(devfs_name, "%s/mt%s", SDp->devfs_name, st_formats[mode]); sprintf(tpnt->driverfs_dev_r[mode].bus_id, "%s:%s", SDp->sdev_driverfs_dev.bus_id, name); @@ -3883,13 +3882,12 @@ device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_type); device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_kdev); - devfs_register(NULL, devfs_name, 0, - SCSI_TAPE_MAJOR, dev_num + (mode << 5), + devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, dev_num + (mode << 5)), S_IFCHR | S_IRUGO | S_IWUGO, - &st_fops, NULL); + "%s/mt%s", SDp->devfs_name, st_formats[mode]); + /* No-rewind entry */ sprintf (name, "mt%sn", st_formats[mode]); - sprintf(devfs_name, "%s/mt%sn", SDp->devfs_name, st_formats[mode]); sprintf(tpnt->driverfs_dev_n[mode].bus_id, "%s:%s", SDp->sdev_driverfs_dev.bus_id, name); @@ -3904,10 +3902,9 @@ &dev_attr_type); device_create_file(&tpnt->driverfs_dev_n[mode], &dev_attr_kdev); - devfs_register(NULL, devfs_name, 0, - SCSI_TAPE_MAJOR, dev_num + (mode << 5) + 128, + devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, dev_num + (mode << 5) + 128), S_IFCHR | S_IRUGO | S_IWUGO, - &st_fops, NULL); + "%s/mt%sn", SDp->devfs_name, st_formats[mode]); } disk->number = devfs_register_tape(SDp->devfs_name); diff -Nru a/drivers/serial/core.c b/drivers/serial/core.c --- a/drivers/serial/core.c Thu May 8 00:24:28 2003 +++ b/drivers/serial/core.c Thu May 8 00:24:28 2003 @@ -2242,7 +2242,7 @@ * Register the port whether it's detected or not. This allows * setserial to be used to alter this ports parameters. */ - tty_register_device(drv->tty_driver, port->line); + tty_register_device(drv->tty_driver, port->line, NULL); out: up(&port_sem); diff -Nru a/drivers/sgi/char/sgiserial.c b/drivers/sgi/char/sgiserial.c --- a/drivers/sgi/char/sgiserial.c Thu May 8 00:24:28 2003 +++ b/drivers/sgi/char/sgiserial.c Thu May 8 00:24:28 2003 @@ -1867,6 +1867,7 @@ memset(&serial_driver, 0, sizeof(struct tty_driver)); serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.owner = THIS_MODULE; serial_driver.name = "ttyS"; serial_driver.major = TTY_MAJOR; serial_driver.minor_start = 64; diff -Nru a/drivers/sgi/char/shmiq.c b/drivers/sgi/char/shmiq.c --- a/drivers/sgi/char/shmiq.c Thu May 8 00:24:29 2003 +++ b/drivers/sgi/char/shmiq.c Thu May 8 00:24:29 2003 @@ -470,9 +470,8 @@ printk ("SHMIQ setup\n"); register_chrdev(SHMIQ_MAJOR, "shmiq", &shmiq_fops); for (i = 0; i < 3; i++) { - devfs_register (NULL, names[i], DEVFS_FL_DEFAULT, - SHMIQ_MAJOR, i, S_IFCHR | S_IRUSR | S_IWUSR, - &shmiq_fops, NULL); + devfs_mk_cdev(MKDEV(SHMIQ_MAJOR, i), + S_IFCHR | S_IRUSR | S_IWUSR, names[i]); } } diff -Nru a/drivers/tc/zs.c b/drivers/tc/zs.c --- a/drivers/tc/zs.c Thu May 8 00:24:29 2003 +++ b/drivers/tc/zs.c Thu May 8 00:24:29 2003 @@ -1872,6 +1872,7 @@ memset(&serial_driver, 0, sizeof(struct tty_driver)); serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.owner = THIS_MODULE; #if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS)) serial_driver.name = "tts/"; #else @@ -1970,8 +1971,8 @@ printk("ttyS%02d at 0x%08x (irq = %d)", info->line, info->port, info->irq); printk(" is a Z85C30 SCC\n"); - tty_register_device(&serial_driver, info->line); - tty_register_device(&callout_driver, info->line); + tty_register_device(&serial_driver, info->line, NULL); + tty_register_device(&callout_driver, info->line, NULL); } diff -Nru a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c --- a/drivers/usb/class/bluetty.c Thu May 8 00:24:29 2003 +++ b/drivers/usb/class/bluetty.c Thu May 8 00:24:29 2003 @@ -1198,7 +1198,7 @@ bluetooth, endpoint->bInterval); /* initialize the devfs nodes for this device and let the user know what bluetooths we are bound to */ - tty_register_device (&bluetooth_tty_driver, minor); + tty_register_device (&bluetooth_tty_driver, minor, &intf->dev); info("Bluetooth converter now attached to ttyUB%d (or usb/ttub/%d for devfs)", minor, minor); bluetooth_table[minor] = bluetooth; diff -Nru a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c --- a/drivers/usb/class/cdc-acm.c Thu May 8 00:24:29 2003 +++ b/drivers/usb/class/cdc-acm.c Thu May 8 00:24:29 2003 @@ -653,7 +653,7 @@ usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm); usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm); - tty_register_device(&acm_tty_driver, minor); + tty_register_device(&acm_tty_driver, minor, &intf->dev); acm_table[minor] = acm; usb_set_intfdata (intf, acm); diff -Nru a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c --- a/drivers/usb/class/usblp.c Thu May 8 00:24:28 2003 +++ b/drivers/usb/class/usblp.c Thu May 8 00:24:28 2003 @@ -54,7 +54,6 @@ #include #include #include -#include #undef DEBUG #include @@ -109,11 +108,7 @@ #define USBLP_REQ_RESET 0x02 #define USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST 0x00 /* HP Vendor-specific */ -#ifdef CONFIG_USB_DYNAMIC_MINORS -#define USBLP_MINORS 256 -#else #define USBLP_MINORS 16 -#endif #define USBLP_MINOR_BASE 0 #define USBLP_WRITE_TIMEOUT (5*HZ) /* 5 seconds */ @@ -324,13 +319,13 @@ struct usb_interface *intf; int retval; - if (minor < 0 || minor >= USBLP_MINORS) + if (minor < 0) return -ENODEV; lock_kernel(); retval = -ENODEV; - intf = usb_find_interface(&usblp_driver, mk_kdev(USB_MAJOR,minor)); + intf = usb_find_interface(&usblp_driver, minor); if (!intf) { goto out; } @@ -380,8 +375,6 @@ static void usblp_cleanup (struct usblp *usblp) { - devfs_remove ("usb/lp%d", usblp->minor); - usb_deregister_dev (1, usblp->minor); info("usblp%d: removed", usblp->minor); usb_buffer_free (usblp->dev, USBLP_BUF_SIZE, @@ -809,6 +802,13 @@ .release = usblp_release, }; +static struct usb_class_driver usblp_class = { + .name = "usb/lp%d", + .fops = &usblp_fops, + .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, + .minor_base = USBLP_MINOR_BASE, +}; + static int usblp_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -816,7 +816,6 @@ struct usblp *usblp = 0; int protocol; int retval; - char name[10]; /* Malloc and start initializing usblp structure so we can use it * directly. */ @@ -830,11 +829,12 @@ init_waitqueue_head(&usblp->wait); usblp->ifnum = intf->altsetting->desc.bInterfaceNumber; - retval = usb_register_dev(&usblp_fops, USBLP_MINOR_BASE, 1, &usblp->minor); + retval = usb_register_dev(intf, &usblp_class); if (retval) { err("Not able to get a minor for this device."); goto abort; } + usblp->minor = intf->minor; usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL); if (!usblp->writeurb) { @@ -904,13 +904,6 @@ usblp_check_status(usblp, 0); #endif - /* If we have devfs, create with perms=660. */ - sprintf(name, "usb/lp%d", usblp->minor); - devfs_register(NULL, name, 0, USB_MAJOR, - usblp->minor, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | - S_IWGRP, &usblp_fops, NULL); - info("usblp%d: USB %sdirectional printer dev %d " "if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X", usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum, @@ -921,13 +914,10 @@ usb_set_intfdata (intf, usblp); - /* add device id so the device works when advertised */ - intf->kdev = mk_kdev(USB_MAJOR,usblp->minor); - return 0; abort_minor: - usb_deregister_dev (1, usblp->minor); + usb_deregister_dev(intf, &usblp_class); abort: if (usblp) { if (usblp->writebuf) @@ -1108,8 +1098,7 @@ { struct usblp *usblp = usb_get_intfdata (intf); - /* remove device id to disable open() */ - intf->kdev = NODEV; + usb_deregister_dev(intf, &usblp_class); if (!usblp || !usblp->dev) { err("bogus disconnect"); diff -Nru a/drivers/usb/core/file.c b/drivers/usb/core/file.c --- a/drivers/usb/core/file.c Thu May 8 00:24:30 2003 +++ b/drivers/usb/core/file.c Thu May 8 00:24:30 2003 @@ -66,6 +66,10 @@ .open = usb_open, }; +static struct class usb_class = { + .name = "usb", +}; + int usb_major_init(void) { if (register_chrdev(USB_MAJOR, "usb", &usb_fops)) { @@ -74,41 +78,53 @@ } devfs_mk_dir("usb"); + class_register(&usb_class); return 0; } void usb_major_cleanup(void) { + class_unregister(&usb_class); devfs_remove("usb"); unregister_chrdev(USB_MAJOR, "usb"); } +static ssize_t show_dev(struct class_device *class_dev, char *buf) +{ + struct usb_interface *intf = class_dev_to_usb_interface(class_dev); + dev_t dev = MKDEV(USB_MAJOR, intf->minor); + return sprintf(buf, "%04x\n", dev); +} +static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL); + /** * usb_register_dev - register a USB device, and ask for a minor number - * @fops: the file operations for this USB device - * @minor: the requested starting minor for this device. - * @num_minors: number of minor numbers requested for this device - * @start_minor: place to put the new starting minor number + * @intf: pointer to the usb_interface that is being registered + * @class_driver: pointer to the usb_class_driver for this device * * This should be called by all USB drivers that use the USB major number. * If CONFIG_USB_DYNAMIC_MINORS is enabled, the minor number will be * dynamically allocated out of the list of available ones. If it is not * enabled, the minor number will be based on the next available free minor, - * starting at the requested @minor. + * starting at the class_driver->minor_base. + * + * This function also creates the devfs file for the usb device, if devfs + * is enabled, and creates a usb class device in the sysfs tree. * * usb_deregister_dev() must be called when the driver is done with * the minor numbers given out by this function. * * Returns -EINVAL if something bad happens with trying to register a - * device, and 0 on success, alone with a value that the driver should - * use in start_minor. + * device, and 0 on success. */ -int usb_register_dev (struct file_operations *fops, int minor, int num_minors, int *start_minor) +int usb_register_dev(struct usb_interface *intf, + struct usb_class_driver *class_driver) { - int i; - int j; - int good_spot; int retval = -EINVAL; + int minor_base = class_driver->minor_base; + int minor = 0; + char name[DEVICE_ID_SIZE]; + char *temp; #ifdef CONFIG_USB_DYNAMIC_MINORS /* @@ -116,65 +132,94 @@ * at zero to pack the devices into the smallest available space with * no holes in the minor range. */ - minor = 0; + minor_base = 0; #endif + intf->minor = -1; - dbg ("asking for %d minors, starting at %d", num_minors, minor); + dbg ("looking for a minor, starting at %d", minor_base); - if (fops == NULL) + if (class_driver->fops == NULL) goto exit; - *start_minor = 0; spin_lock (&minor_lock); - for (i = minor; i < MAX_USB_MINORS; ++i) { - if (usb_minors[i]) + for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) { + if (usb_minors[minor]) continue; - good_spot = 1; - for (j = 1; j <= num_minors-1; ++j) - if (usb_minors[i+j]) { - good_spot = 0; - break; - } - if (good_spot == 0) - continue; - - *start_minor = i; - dbg("found a minor chunk free, starting at %d", i); - for (i = *start_minor; i < (*start_minor + num_minors); ++i) - usb_minors[i] = fops; + usb_minors[minor] = class_driver->fops; retval = 0; - goto exit; + break; } -exit: spin_unlock (&minor_lock); + + if (retval) + goto exit; + + intf->minor = minor; + + /* handle the devfs registration */ + snprintf(name, DEVICE_ID_SIZE, class_driver->name, minor - minor_base); + devfs_register(NULL, name, 0, USB_MAJOR, minor, class_driver->mode, + class_driver->fops, NULL); + + /* create a usb class device for this usb interface */ + memset(&intf->class_dev, 0x00, sizeof(struct class_device)); + intf->class_dev.class = &usb_class; + intf->class_dev.dev = &intf->dev; + + temp = strrchr(name, '/'); + if (temp && (temp[1] != 0x00)) + ++temp; + else + temp = name; + snprintf(intf->class_dev.class_id, BUS_ID_SIZE, "%s", temp); + class_device_register(&intf->class_dev); + class_device_create_file (&intf->class_dev, &class_device_attr_dev); +exit: return retval; } EXPORT_SYMBOL(usb_register_dev); /** * usb_deregister_dev - deregister a USB device's dynamic minor. - * @num_minors: number of minor numbers to put back. - * @start_minor: the starting minor number + * @intf: pointer to the usb_interface that is being deregistered + * @class_driver: pointer to the usb_class_driver for this device * * Used in conjunction with usb_register_dev(). This function is called * when the USB driver is finished with the minor numbers gotten from a * call to usb_register_dev() (usually when the device is disconnected * from the system.) + * + * This function also cleans up the devfs file for the usb device, if devfs + * is enabled, and removes the usb class device from the sysfs tree. * * This should be called by all drivers that use the USB major number. */ -void usb_deregister_dev (int num_minors, int start_minor) +void usb_deregister_dev(struct usb_interface *intf, + struct usb_class_driver *class_driver) { - int i; + int minor_base = class_driver->minor_base; + char name[DEVICE_ID_SIZE]; + +#ifdef CONFIG_USB_DYNAMIC_MINORS + minor_base = 0; +#endif + + if (intf->minor == -1) + return; - dbg ("removing %d minors starting at %d", num_minors, start_minor); + dbg ("removing %d minor", intf->minor); spin_lock (&minor_lock); - for (i = start_minor; i < (start_minor + num_minors); ++i) - usb_minors[i] = NULL; + usb_minors[intf->minor] = NULL; spin_unlock (&minor_lock); + + snprintf(name, DEVICE_ID_SIZE, class_driver->name, intf->minor - minor_base); + devfs_remove (name); + + class_device_unregister(&intf->class_dev); + intf->minor = -1; } EXPORT_SYMBOL(usb_deregister_dev); diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c --- a/drivers/usb/core/usb.c Thu May 8 00:24:29 2003 +++ b/drivers/usb/core/usb.c Thu May 8 00:24:29 2003 @@ -457,12 +457,13 @@ /** * usb_find_interface - find usb_interface pointer for driver and device * @drv: the driver whose current configuration is considered - * @kdev: the desired device + * @minor: the minor number of the desired device * * This walks the driver device list and returns a pointer to the interface - * with the matching kdev_t. + * with the matching minor. Note, this only works for devices that share the + * USB major number. */ -struct usb_interface *usb_find_interface(struct usb_driver *drv, kdev_t kdev) +struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor) { struct list_head *entry; struct device *dev; @@ -476,9 +477,10 @@ continue; intf = to_usb_interface(dev); - if (kdev_same(intf->kdev,kdev)) { + if (intf->minor == -1) + continue; + if (intf->minor == minor) return intf; - } } /* no device found that matches */ diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c --- a/drivers/usb/host/ehci-hcd.c Thu May 8 00:24:29 2003 +++ b/drivers/usb/host/ehci-hcd.c Thu May 8 00:24:29 2003 @@ -116,8 +116,10 @@ #define EHCI_TUNE_MULT_TT 1 #define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ -#define EHCI_WATCHDOG_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ +#define EHCI_IAA_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ +#define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ +#define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ /* Initial IRQ latency: lower than default */ static int log2_irq_thresh = 0; // 0 to 6 @@ -266,16 +268,13 @@ } } + /* stop async processing after it's idled a bit */ + if (test_bit (TIMER_ASYNC_OFF, &ehci->actions)) + start_unlink_async (ehci, ehci->async); + + /* ehci could run by timer, without IRQs ... */ ehci_work (ehci, NULL); - if (ehci->reclaim && !timer_pending (&ehci->watchdog)) - mod_timer (&ehci->watchdog, - jiffies + EHCI_WATCHDOG_JIFFIES); - /* stop async processing after it's idled a while */ - else if (ehci->async_idle) { - start_unlink_async (ehci, ehci->async); - ehci->async_idle = 0; - } spin_unlock_irqrestore (&ehci->lock, flags); } @@ -658,11 +657,18 @@ */ static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs) { + timer_action_done (ehci, TIMER_IO_WATCHDOG); if (ehci->reclaim_ready) end_unlink_async (ehci, regs); scan_async (ehci, regs); if (ehci->next_uframe != -1) scan_periodic (ehci, regs); + + /* the IO watchdog guards against hardware or driver bugs that + * misplace IRQs, and should let us run completely without IRQs. + */ + if ((ehci->async->qh_next.ptr != 0) || (ehci->periodic_sched != 0)) + timer_action (ehci, TIMER_IO_WATCHDOG); } /*-------------------------------------------------------------------------*/ diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c --- a/drivers/usb/host/ehci-q.c Thu May 8 00:24:29 2003 +++ b/drivers/usb/host/ehci-q.c Thu May 8 00:24:29 2003 @@ -706,8 +706,7 @@ /* (re)start the async schedule? */ head = ehci->async; - if (ehci->async_idle) - del_timer (&ehci->watchdog); + timer_action_done (ehci, TIMER_ASYNC_OFF); if (!head->qh_next.qh) { u32 cmd = readl (&ehci->regs->command); @@ -733,8 +732,6 @@ qh->qh_state = QH_STATE_LINKED; /* qtd completions reported later by interrupt */ - - ehci->async_idle = 0; } /*-------------------------------------------------------------------------*/ @@ -915,7 +912,7 @@ struct ehci_qh *qh = ehci->reclaim; struct ehci_qh *next; - del_timer (&ehci->watchdog); + timer_action_done (ehci, TIMER_IAA_WATCHDOG); // qh->hw_next = cpu_to_le32 (qh->qh_dma); qh->qh_state = QH_STATE_IDLE; @@ -940,12 +937,8 @@ * active but idle for a while once it empties. */ if (HCD_IS_RUNNING (ehci->hcd.state) - && ehci->async->qh_next.qh == 0 - && !timer_pending (&ehci->watchdog)) { - ehci->async_idle = 1; - mod_timer (&ehci->watchdog, - jiffies + EHCI_ASYNC_JIFFIES); - } + && ehci->async->qh_next.qh == 0) + timer_action (ehci, TIMER_ASYNC_OFF); } if (next) @@ -980,6 +973,7 @@ wmb (); // handshake later, if we need to } + timer_action_done (ehci, TIMER_ASYNC_OFF); return; } @@ -1005,9 +999,8 @@ ehci->reclaim_ready = 0; cmd |= CMD_IAAD; writel (cmd, &ehci->regs->command); - /* posted write need not be known to HC yet ... */ - - mod_timer (&ehci->watchdog, jiffies + EHCI_WATCHDOG_JIFFIES); + (void) readl (&ehci->regs->command); + timer_action (ehci, TIMER_IAA_WATCHDOG); } /*-------------------------------------------------------------------------*/ @@ -1016,10 +1009,11 @@ scan_async (struct ehci_hcd *ehci, struct pt_regs *regs) { struct ehci_qh *qh; - int unlink_delay = 0; + enum ehci_timer_action action = TIMER_IO_WATCHDOG; if (!++(ehci->stamp)) ehci->stamp++; + timer_action_done (ehci, TIMER_ASYNC_SHRINK); rescan: qh = ehci->async->qh_next.qh; if (likely (qh != 0)) { @@ -1051,17 +1045,14 @@ */ if (list_empty (&qh->qtd_list)) { if (qh->stamp == ehci->stamp) - unlink_delay = 1; - else if (!ehci->reclaim) { + action = TIMER_ASYNC_SHRINK; + else if (!ehci->reclaim) start_unlink_async (ehci, qh); - unlink_delay = 0; - } } qh = qh->qh_next.qh; } while (qh); } - - if (unlink_delay && !timer_pending (&ehci->watchdog)) - mod_timer (&ehci->watchdog, jiffies + EHCI_WATCHDOG_JIFFIES/2); + if (action == TIMER_ASYNC_SHRINK) + timer_action (ehci, TIMER_ASYNC_SHRINK); } diff -Nru a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h --- a/drivers/usb/host/ehci.h Thu May 8 00:24:30 2003 +++ b/drivers/usb/host/ehci.h Thu May 8 00:24:30 2003 @@ -52,8 +52,7 @@ /* async schedule support */ struct ehci_qh *async; struct ehci_qh *reclaim; - int reclaim_ready : 1, - async_idle : 1; + int reclaim_ready : 1; /* periodic schedule support */ #define DEFAULT_I_TDPS 1024 /* some HCs can do less */ @@ -83,6 +82,7 @@ struct timer_list watchdog; struct notifier_block reboot_notifier; + unsigned long actions; unsigned stamp; /* irq statistics */ @@ -99,6 +99,53 @@ /* NOTE: urb->transfer_flags expected to not use this bit !!! */ #define EHCI_STATE_UNLINK 0x8000 /* urb being unlinked */ + +enum ehci_timer_action { + TIMER_IO_WATCHDOG, + TIMER_IAA_WATCHDOG, + TIMER_ASYNC_SHRINK, + TIMER_ASYNC_OFF, +}; + +static inline void +timer_action_done (struct ehci_hcd *ehci, enum ehci_timer_action action) +{ + clear_bit (action, &ehci->actions); +} + +static inline void +timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) +{ + if (!test_and_set_bit (action, &ehci->actions)) { + unsigned long t; + + switch (action) { + case TIMER_IAA_WATCHDOG: + t = EHCI_IAA_JIFFIES; + break; + case TIMER_IO_WATCHDOG: + t = EHCI_IO_JIFFIES; + break; + case TIMER_ASYNC_OFF: + t = EHCI_ASYNC_JIFFIES; + break; + // case TIMER_ASYNC_SHRINK: + default: + t = EHCI_SHRINK_JIFFIES; + break; + } + t += jiffies; + // all timings except IAA watchdog can be overridden. + // async queue SHRINK often precedes IAA. while it's ready + // to go OFF neither can matter, and afterwards the IO + // watchdog stops unless there's still periodic traffic. + if (action != TIMER_IAA_WATCHDOG + && t > ehci->watchdog.expires + && timer_pending (&ehci->watchdog)) + return; + mod_timer (&ehci->watchdog, t); + } +} /*-------------------------------------------------------------------------*/ diff -Nru a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c --- a/drivers/usb/image/mdc800.c Thu May 8 00:24:29 2003 +++ b/drivers/usb/image/mdc800.c Thu May 8 00:24:29 2003 @@ -118,12 +118,8 @@ #define TO_READ_FROM_IRQ TO_DEFAULT_COMMAND #define TO_GET_READY TO_DEFAULT_COMMAND -#ifdef CONFIG_USB_DYNAMIC_MINORS -#define MDC800_DEVICE_MINOR_BASE 0 -#else /* Minor Number of the device (create with mknod /dev/mustek c 180 32) */ #define MDC800_DEVICE_MINOR_BASE 32 -#endif /************************************************************************** @@ -401,6 +397,13 @@ static struct usb_driver mdc800_usb_driver; static struct file_operations mdc800_device_ops; +static struct usb_class_driver mdc800_class = { + .name = "usb/mdc800%d", + .fops = &mdc800_device_ops, + .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, + .minor_base = MDC800_DEVICE_MINOR_BASE, +}; + /* * Callback to search the Mustek MDC800 on the USB Bus @@ -477,8 +480,8 @@ down (&mdc800->io_lock); - retval = usb_register_dev (&mdc800_device_ops, MDC800_DEVICE_MINOR_BASE, 1, &mdc800->minor); - if (retval && (retval != -ENODEV)) { + retval = usb_register_dev(intf, &mdc800_class); + if (retval) { err ("Not able to get a minor for this device."); return -ENODEV; } @@ -540,7 +543,7 @@ if (mdc800->state == NOT_CONNECTED) return; - usb_deregister_dev (1, mdc800->minor); + usb_deregister_dev(intf, &mdc800_class); mdc800->state=NOT_CONNECTED; diff -Nru a/drivers/usb/image/scanner.c b/drivers/usb/image/scanner.c --- a/drivers/usb/image/scanner.c Thu May 8 00:24:28 2003 +++ b/drivers/usb/image/scanner.c Thu May 8 00:24:28 2003 @@ -397,7 +397,6 @@ */ -#include #include /* @@ -464,7 +463,7 @@ dbg("open_scanner: scn_minor:%d", scn_minor); - intf = usb_find_interface(&scanner_driver, mk_kdev(USB_MAJOR,scn_minor)); + intf = usb_find_interface(&scanner_driver, scn_minor); if (!intf) { up(&scn_mutex); err("open_scanner(%d): Unable to access minor data", scn_minor); @@ -843,9 +842,6 @@ kfree(scn->ibuf); kfree(scn->obuf); - dbg("%s: De-allocating minor:%d", __FUNCTION__, scn->scn_minor); - devfs_remove("usb/scanner%d", scn->scn_minor - SCN_BASE_MNR); - usb_deregister_dev(1, scn->scn_minor); usb_free_urb(scn->scn_irq); usb_put_dev(scn->scn_dev); up (&(scn->sem)); @@ -867,6 +863,13 @@ .release = close_scanner, }; +static struct usb_class_driver scanner_class = { + .name = "usb/scanner%d", + .fops = &usb_scanner_fops, + .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, + .minor_base = SCN_BASE_MNR, +}; + static int probe_scanner(struct usb_interface *intf, const struct usb_device_id *id) @@ -878,7 +881,6 @@ int ep_cnt; int ix; - int scn_minor; int retval; char valid_device = 0; @@ -1011,14 +1013,14 @@ down(&scn_mutex); - retval = usb_register_dev(&usb_scanner_fops, SCN_BASE_MNR, 1, &scn_minor); + retval = usb_register_dev(intf, &scanner_class); if (retval) { err ("Not able to get a minor for this device."); up(&scn_mutex); return -ENOMEM; } - dbg("probe_scanner: Allocated minor:%d", scn_minor); + dbg("probe_scanner: Allocated minor:%d", intf->minor); if (!(scn = kmalloc (sizeof (struct scn_usb_data), GFP_KERNEL))) { err("probe_scanner: Out of memory."); @@ -1038,11 +1040,11 @@ init_MUTEX(&(scn->sem)); /* Initializes to unlocked */ - dbg ("probe_scanner(%d): Address of scn:%p", scn_minor, scn); + dbg ("probe_scanner(%d): Address of scn:%p", intf->minor, scn); /* Ok, if we detected an interrupt EP, setup a handler for it */ if (have_intr) { - dbg("probe_scanner(%d): Configuring IRQ handler for intr EP:%d", scn_minor, have_intr); + dbg("probe_scanner(%d): Configuring IRQ handler for intr EP:%d", intf->minor, have_intr); usb_fill_int_urb(scn->scn_irq, dev, usb_rcvintpipe(dev, have_intr), &scn->button, 1, irq_scanner, scn, @@ -1050,7 +1052,7 @@ 250); if (usb_submit_urb(scn->scn_irq, GFP_KERNEL)) { - err("probe_scanner(%d): Unable to allocate INT URB.", scn_minor); + err("probe_scanner(%d): Unable to allocate INT URB.", intf->minor); kfree(scn); up(&scn_mutex); return -ENOMEM; @@ -1060,21 +1062,21 @@ /* Ok, now initialize all the relevant values */ if (!(scn->obuf = (char *)kmalloc(OBUF_SIZE, GFP_KERNEL))) { - err("probe_scanner(%d): Not enough memory for the output buffer.", scn_minor); + err("probe_scanner(%d): Not enough memory for the output buffer.", intf->minor); kfree(scn); up(&scn_mutex); return -ENOMEM; } - dbg("probe_scanner(%d): obuf address:%p", scn_minor, scn->obuf); + dbg("probe_scanner(%d): obuf address:%p", intf->minor, scn->obuf); if (!(scn->ibuf = (char *)kmalloc(IBUF_SIZE, GFP_KERNEL))) { - err("probe_scanner(%d): Not enough memory for the input buffer.", scn_minor); + err("probe_scanner(%d): Not enough memory for the input buffer.", intf->minor); kfree(scn->obuf); kfree(scn); up(&scn_mutex); return -ENOMEM; } - dbg("probe_scanner(%d): ibuf address:%p", scn_minor, scn->ibuf); + dbg("probe_scanner(%d): ibuf address:%p", intf->minor, scn->ibuf); switch (dev->descriptor.idVendor) { /* Scanner specific read timeout parameters */ @@ -1101,17 +1103,9 @@ scn->intr_ep = have_intr; scn->present = 1; scn->scn_dev = dev; - scn->scn_minor = scn_minor; + scn->scn_minor = intf->minor; scn->isopen = 0; - sprintf(name, "usb/scanner%d", scn->scn_minor - SCN_BASE_MNR); - - devfs_register(NULL, name, - DEVFS_FL_DEFAULT, USB_MAJOR, - scn->scn_minor, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | - S_IWGRP | S_IROTH | S_IWOTH, &usb_scanner_fops, NULL); - info ("USB scanner device (0x%04x/0x%04x) now attached to %s", dev->descriptor.idVendor, dev->descriptor.idProduct, name); @@ -1119,9 +1113,6 @@ usb_set_intfdata(intf, scn); - /* add device id so the device works when advertised */ - intf->kdev = mk_kdev(USB_MAJOR,scn->scn_minor); - return 0; } @@ -1130,8 +1121,9 @@ { struct scn_usb_data *scn = usb_get_intfdata(intf); - /* remove device id to disable open() */ - intf->kdev = NODEV; + /* disable open() */ + dbg("%s: De-allocating minor:%d", __FUNCTION__, scn->scn_minor); + usb_deregister_dev(intf, &scanner_class); usb_set_intfdata(intf, NULL); if(scn->intr_ep) { diff -Nru a/drivers/usb/image/scanner.h b/drivers/usb/image/scanner.h --- a/drivers/usb/image/scanner.h Thu May 8 00:24:28 2003 +++ b/drivers/usb/image/scanner.h Thu May 8 00:24:28 2003 @@ -323,13 +323,7 @@ USB - Vivid III */ #define SCN_CLASS_SCANJET 16 -#ifdef CONFIG_USB_DYNAMIC_MINORS -#define SCN_MAX_MNR 256 -#define SCN_BASE_MNR 0 -#else -#define SCN_MAX_MNR 16 /* We're allocated 16 minors */ #define SCN_BASE_MNR 48 /* USB Scanners start at minor 48 */ -#endif static DECLARE_MUTEX (scn_mutex); /* Initializes to unlocked */ diff -Nru a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c --- a/drivers/usb/input/hiddev.c Thu May 8 00:24:28 2003 +++ b/drivers/usb/input/hiddev.c Thu May 8 00:24:28 2003 @@ -53,6 +53,7 @@ wait_queue_head_t wait; struct hid_device *hid; struct hiddev_list *list; + struct usb_interface intf; }; struct hiddev_list { @@ -226,10 +227,10 @@ /* * De-allocate a hiddev structure */ +static struct usb_class_driver hiddev_class; static void hiddev_cleanup(struct hiddev *hiddev) { - devfs_remove("usb/hid/hiddev%d", hiddev->minor); - usb_deregister_dev(1, hiddev->minor); + usb_deregister_dev(&hiddev->intf, &hiddev_class); hiddev_table[hiddev->minor] = NULL; kfree(hiddev); } @@ -675,15 +676,21 @@ .fasync = hiddev_fasync, }; +static struct usb_class_driver hiddev_class = { + .name = "usb/hid/hiddev%d", + .fops = &hiddev_fops, + .mode = S_IFCHR | S_IRUGO | S_IWUSR, + .minor_base = HIDDEV_MINOR_BASE, +}; + /* * This is where hid.c calls us to connect a hid device to the hiddev driver */ int hiddev_connect(struct hid_device *hid) { struct hiddev *hiddev; - int minor, i; + int i; int retval; - char devfs_name[24]; for (i = 0; i < hid->maxcollection; i++) if (hid->collection[i].type == @@ -694,31 +701,25 @@ if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDDEV) == 0) return -1; - retval = usb_register_dev(&hiddev_fops, HIDDEV_MINOR_BASE, 1, &minor); - if (retval) { - err("Not able to get a minor for this device."); + if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL))) return -1; - } + memset(hiddev, 0, sizeof(struct hiddev)); - if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL))) { - usb_deregister_dev (1, minor); + retval = usb_register_dev(&hiddev->intf, &hiddev_class); + if (retval) { + err("Not able to get a minor for this device."); return -1; } - memset(hiddev, 0, sizeof(struct hiddev)); init_waitqueue_head(&hiddev->wait); - hiddev->minor = minor; - hiddev_table[minor - HIDDEV_MINOR_BASE] = hiddev; + hiddev->minor = hiddev->intf.minor; + hiddev_table[hiddev->intf.minor - HIDDEV_MINOR_BASE] = hiddev; hiddev->hid = hid; hiddev->exist = 1; - sprintf(devfs_name, "usb/hid/hiddev%d", minor); - devfs_register(NULL, devfs_name, 0, - USB_MAJOR, minor + HIDDEV_MINOR_BASE, - S_IFCHR | S_IRUGO | S_IWUSR, &hiddev_fops, NULL); - hid->minor = minor; + hid->minor = hiddev->intf.minor; hid->hiddev = hiddev; return 0; diff -Nru a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c --- a/drivers/usb/input/xpad.c Thu May 8 00:24:28 2003 +++ b/drivers/usb/input/xpad.c Thu May 8 00:24:28 2003 @@ -61,7 +61,6 @@ #include #include #include -#include #include #define DRIVER_VERSION "v0.0.5" diff -Nru a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c --- a/drivers/usb/media/dabusb.c Thu May 8 00:24:29 2003 +++ b/drivers/usb/media/dabusb.c Thu May 8 00:24:29 2003 @@ -712,12 +712,19 @@ .release = dabusb_release, }; +static struct usb_class_driver dabusb_class = { + .name = "usb/dabusb%d", + .fops = &dabusb_fops, + .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, + .minor_base = DABUSB_MINOR, +}; + + /* --------------------------------------------------------------------- */ static int dabusb_probe (struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *usbdev = interface_to_usbdev(intf); - int devnum; int retval; pdabusb_t s; @@ -731,16 +738,16 @@ if (intf->altsetting->desc.bInterfaceNumber != _DABUSB_IF && usbdev->descriptor.idProduct == 0x9999) return -ENODEV; - retval = usb_register_dev (&dabusb_fops, DABUSB_MINOR, 1, &devnum); + retval = usb_register_dev(intf, &dabusb_class); if (retval) return -ENOMEM; - s = &dabusb[devnum]; + s = &dabusb[intf->minor]; down (&s->mutex); s->remove_pending = 0; s->usbdev = usbdev; - s->devnum = devnum; + s->devnum = intf->minor; if (usb_set_configuration (usbdev, usbdev->config[0].desc.bConfigurationValue) < 0) { err("set_configuration failed"); @@ -778,7 +785,7 @@ usb_set_intfdata (intf, NULL); if (s) { - usb_deregister_dev (1, s->devnum); + usb_deregister_dev (intf, &dabusb_class); s->remove_pending = 1; wake_up (&s->wait); if (s->state == _started) diff -Nru a/drivers/usb/media/dabusb.h b/drivers/usb/media/dabusb.h --- a/drivers/usb/media/dabusb.h Thu May 8 00:24:27 2003 +++ b/drivers/usb/media/dabusb.h Thu May 8 00:24:27 2003 @@ -6,11 +6,7 @@ unsigned int pipe; }bulk_transfer_t,*pbulk_transfer_t; -#ifdef CONFIG_USB_DYNAMIC_MINORS -#define DABUSB_MINOR 0 -#else #define DABUSB_MINOR 240 /* some unassigned USB minor */ -#endif #define DABUSB_VERSION 0x1000 #define IOCTL_DAB_BULK _IOWR('d', 0x30, bulk_transfer_t) #define IOCTL_DAB_OVERRUNS _IOR('d', 0x15, int) diff -Nru a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c --- a/drivers/usb/media/vicam.c Thu May 8 00:24:28 2003 +++ b/drivers/usb/media/vicam.c Thu May 8 00:24:28 2003 @@ -1101,28 +1101,6 @@ ((struct vicam_camera *)data)->gain); } -static int vicam_write_proc_shutter(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - struct vicam_camera *cam = (struct vicam_camera *)data; - - cam->shutter_speed = simple_strtoul(buffer, NULL, 10); - - return count; -} - -static int vicam_write_proc_gain(struct file *file, const char *buffer, - unsigned long count, void *data) -{ - struct vicam_camera *cam = (struct vicam_camera *)data; - - cam->gain = simple_strtoul(buffer, NULL, 10); - - return count; -} - - - static void vicam_create_proc_root(void) { @@ -1164,21 +1142,17 @@ if ( !cam->proc_dir ) return; // We should probably return an error here ent = - create_proc_entry("shutter", S_IFREG | S_IRUGO | S_IWUSR, - cam->proc_dir); + create_proc_entry("shutter", S_IFREG | S_IRUGO, cam->proc_dir); if (ent) { ent->data = cam; ent->read_proc = vicam_read_proc_shutter; - ent->write_proc = vicam_write_proc_shutter; ent->size = 64; } - ent = create_proc_entry("gain", S_IFREG | S_IRUGO | S_IWUSR, - cam->proc_dir); + ent = create_proc_entry("gain", S_IFREG | S_IRUGO , cam->proc_dir); if ( ent ) { ent->data = cam; ent->read_proc = vicam_read_proc_gain; - ent->write_proc = vicam_write_proc_gain; ent->size = 64; } } diff -Nru a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c --- a/drivers/usb/misc/auerswald.c Thu May 8 00:24:28 2003 +++ b/drivers/usb/misc/auerswald.c Thu May 8 00:24:28 2003 @@ -29,7 +29,6 @@ #include #include #include -#include #undef DEBUG /* include debug macros until it's done */ #include @@ -60,16 +59,10 @@ /* Auerswald Vendor ID */ #define ID_AUERSWALD 0x09BF -#ifdef CONFIG_USB_DYNAMIC_MINORS -/* we can have up to 256 devices at once */ -#define AUER_MINOR_BASE 0 -#define AUER_MAX_DEVICES 256 -#else #define AUER_MINOR_BASE 112 /* auerswald driver minor number */ /* we can have up to this number of device plugged in at once */ #define AUER_MAX_DEVICES 16 -#endif /* Number of read buffers for each device */ @@ -256,12 +249,6 @@ wait_queue_head_t bufferwait; /* wait for a control buffer */ } auerswald_t,*pauerswald_t; -/* array of pointers to our devices that are currently connected */ -static pauerswald_t dev_table[AUER_MAX_DEVICES]; - -/* lock to protect the dev_table structure */ -static struct semaphore dev_table_mutex; - /* ................................................................... */ /* character device context */ typedef struct @@ -1384,29 +1371,29 @@ /* Open a new character device */ static int auerchar_open (struct inode *inode, struct file *file) { - int dtindex = minor(inode->i_rdev) - AUER_MINOR_BASE; + int dtindex = minor(inode->i_rdev); pauerswald_t cp = NULL; pauerchar_t ccp = NULL; + struct usb_interface *intf; int ret; /* minor number in range? */ - if ((dtindex < 0) || (dtindex >= AUER_MAX_DEVICES)) { + if (dtindex < 0) { return -ENODEV; } - /* usb device available? */ - if (down_interruptible (&dev_table_mutex)) { - return -ERESTARTSYS; + intf = usb_find_interface(&auerswald_driver, dtindex); + if (!intf) { + return -ENODEV; } - cp = dev_table[dtindex]; + + /* usb device available? */ + cp = usb_get_intfdata (intf); if (cp == NULL) { - up (&dev_table_mutex); return -ENODEV; } if (down_interruptible (&cp->mutex)) { - up (&dev_table_mutex); return -ERESTARTSYS; } - up (&dev_table_mutex); /* we have access to the device. Now lets allocate memory */ ccp = (pauerchar_t) kmalloc(sizeof(auerchar_t), GFP_KERNEL); @@ -1895,6 +1882,13 @@ .release = auerchar_release, }; +static struct usb_class_driver auerswald_class = { + .name = "usb/auer%d", + .fops = &auerswald_fops, + .mode = S_IFCHR | S_IRUGO | S_IWUGO, + .minor_base = AUER_MINOR_BASE, +}; + /* --------------------------------------------------------------------- */ /* Special USB driver functions */ @@ -1923,7 +1917,6 @@ struct usb_device *usbdev = interface_to_usbdev(intf); pauerswald_t cp = NULL; DECLARE_WAIT_QUEUE_HEAD (wqh); - unsigned int dtindex; unsigned int u = 0; char *pbuf; int ret; @@ -1954,27 +1947,17 @@ auerbuf_init (&cp->bufctl); init_waitqueue_head (&cp->bufferwait); - down (&dev_table_mutex); - ret = usb_register_dev (&auerswald_fops, AUER_MINOR_BASE, 1, &dtindex); + ret = usb_register_dev(intf, &auerswald_class); if (ret) { err ("Not able to get a minor for this device."); - up (&dev_table_mutex); goto pfail; } /* Give the device a name */ - sprintf (cp->name, "usb/auer%d", dtindex); + sprintf (cp->name, "usb/auer%d", intf->minor); /* Store the index */ - cp->dtindex = dtindex; - dev_table[dtindex] = cp; - up (&dev_table_mutex); - - /* initialize the devfs node for this device and register it */ - devfs_register(NULL, cp->name, 0, USB_MAJOR, - AUER_MINOR_BASE + dtindex, - S_IFCHR | S_IRUGO | S_IWUGO, - &auerswald_fops, NULL); + cp->dtindex = intf->minor; /* Get the usb version of the device */ cp->version = cp->usbdev->descriptor.bcdDevice; @@ -2083,18 +2066,8 @@ down (&cp->mutex); info ("device /dev/%s now disconnecting", cp->name); - /* remove from device table */ - /* Nobody can open() this device any more */ - down (&dev_table_mutex); - dev_table[cp->dtindex] = NULL; - up (&dev_table_mutex); - - /* remove our devfs node */ - /* Nobody can see this device any more */ - devfs_remove(cp->name); - /* give back our USB minor number */ - usb_deregister_dev (1, cp->dtindex); + usb_deregister_dev(intf, &auerswald_class); /* Stop the interrupt endpoint */ auerswald_int_release (cp); @@ -2162,10 +2135,6 @@ { int result; dbg ("init"); - - /* initialize the device table */ - memset (&dev_table, 0, sizeof(dev_table)); - init_MUTEX (&dev_table_mutex); /* register driver at the USB subsystem */ result = usb_register (&auerswald_driver); diff -Nru a/drivers/usb/misc/brlvger.c b/drivers/usb/misc/brlvger.c --- a/drivers/usb/misc/brlvger.c Thu May 8 00:24:29 2003 +++ b/drivers/usb/misc/brlvger.c Thu May 8 00:24:29 2003 @@ -50,7 +50,6 @@ #include #include #include -#include #include MODULE_AUTHOR( DRIVER_AUTHOR ); @@ -180,12 +179,6 @@ /* Globals */ -/* Table of connected devices, a different minor for each. */ -static struct brlvger_priv *display_table[ MAX_NR_BRLVGER_DEVS ]; - -/* Mutex for the operation of removing a device from display_table */ -static DECLARE_MUTEX(disconnect_sem); - /* For blocking open */ static DECLARE_WAIT_QUEUE_HEAD(open_wait); @@ -237,6 +230,13 @@ .poll = brlvger_poll, }; +static struct usb_class_driver brlvger_class = { + .name = "usb/brlvger%d", + .fops = &brlvger_fops, + .mode = S_IFCHR | S_IRUSR |S_IWUSR | S_IRGRP | S_IWGRP, + .minor_base = BRLVGER_MINOR, +}; + static struct usb_driver brlvger_driver = { .owner = THIS_MODULE, @@ -254,8 +254,6 @@ if(stall_tries < 1 || write_repeats < 1) return -EINVAL; - memset(display_table, 0, sizeof(display_table)); - if (usb_register(&brlvger_driver)) { err("USB registration failed"); return -ENOSYS; @@ -284,14 +282,12 @@ { struct usb_device *dev = interface_to_usbdev(intf); struct brlvger_priv *priv = NULL; - int i; int retval; struct usb_endpoint_descriptor *endpoint; struct usb_host_interface *actifsettings; /* protects against reentrance: once we've found a free slot we reserve it.*/ static DECLARE_MUTEX(reserve_sem); - char devfs_name[20]; actifsettings = dev->actconfig->interface->altsetting; @@ -311,7 +307,7 @@ down(&reserve_sem); - retval = usb_register_dev(&brlvger_fops, BRLVGER_MINOR, 1, &i); + retval = usb_register_dev(intf, &brlvger_class); if (retval) { err("Not able to get a minor for this device."); goto error; @@ -331,7 +327,7 @@ init_MUTEX(&priv->open_sem); init_MUTEX(&priv->dev_sem); - priv->subminor = i; + priv->subminor = intf->minor; /* we found a interrupt in endpoint */ priv->in_interrupt = endpoint; @@ -372,17 +368,9 @@ }; dbg("Display length: %d", priv->plength); - sprintf(devfs_name, "usb/brlvger%d", priv->subminor); - devfs_register(NULL, devfs_name, - DEVFS_FL_DEFAULT, USB_MAJOR, - BRLVGER_MINOR+priv->subminor, - S_IFCHR |S_IRUSR|S_IWUSR |S_IRGRP|S_IWGRP, - &brlvger_fops, NULL); - - display_table[i] = priv; - + usb_set_intfdata (intf, priv); info( "Braille display %d is device major %d minor %d", - i, USB_MAJOR, BRLVGER_MINOR + i); + intf->minor, USB_MAJOR, BRLVGER_MINOR + intf->minor); /* Tell anyone waiting on a blocking open */ wake_up_interruptible(&open_wait); @@ -414,12 +402,7 @@ if(priv){ info("Display %d disconnecting", priv->subminor); - devfs_remove("usb/brlvger%d", priv->subminor); - usb_deregister_dev(1, priv->subminor); - - down(&disconnect_sem); - display_table[priv->subminor] = NULL; - up(&disconnect_sem); + usb_deregister_dev(intf, &brlvger_class); down(&priv->open_sem); down(&priv->dev_sem); @@ -450,21 +433,18 @@ brlvger_open(struct inode *inode, struct file *file) { int devnum = minor (inode->i_rdev); - struct brlvger_priv *priv; + struct usb_interface *intf = NULL; + struct brlvger_priv *priv = NULL; int n, ret; - if (devnum < BRLVGER_MINOR - || devnum >= (BRLVGER_MINOR + MAX_NR_BRLVGER_DEVS)) + if (devnum < 0) return -ENXIO; n = devnum - BRLVGER_MINOR; do { - down(&disconnect_sem); - priv = display_table[n]; - - if(!priv) { - up(&disconnect_sem); + intf = usb_find_interface(&brlvger_driver, devnum); + if (!intf) { if (file->f_flags & O_NONBLOCK) { dbg3("Failing non-blocking open: " "device %d not connected", n); @@ -475,19 +455,18 @@ minor is connected. */ dbg2("Waiting for device %d to be connected", n); ret = wait_event_interruptible(open_wait, - display_table[n] - != NULL); - if(ret) { + (intf = usb_find_interface(&brlvger_driver, devnum))); + if (ret) { dbg2("Interrupted wait for device %d", n); return ret; } } - } while(!priv); - /* We grabbed an existing device. */ + } while(!intf); + priv = usb_get_intfdata(intf); + /* We grabbed an existing device. */ if(down_interruptible(&priv->open_sem)) return -ERESTARTSYS; - up(&disconnect_sem); /* Only one process can open each device, no sharing. */ ret = -EBUSY; diff -Nru a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c --- a/drivers/usb/misc/rio500.c Thu May 8 00:24:29 2003 +++ b/drivers/usb/misc/rio500.c Thu May 8 00:24:29 2003 @@ -38,7 +38,6 @@ #include #include #include -#include #include "rio500_usb.h" @@ -49,11 +48,7 @@ #define DRIVER_AUTHOR "Cesar Miquel " #define DRIVER_DESC "USB Rio 500 driver" -#ifdef CONFIG_USB_DYNAMIC_MINORS - #define RIO_MINOR 0 -#else - #define RIO_MINOR 64 -#endif +#define RIO_MINOR 64 /* stall/wait timeout for rio */ #define NAK_TIMEOUT (HZ) @@ -68,7 +63,6 @@ unsigned int ifnum; /* Interface number of the USB device */ int isopen; /* nz if open */ int present; /* Device is present on the bus */ - int minor; /* minor number assigned to us */ char *obuf, *ibuf; /* transfer buffers */ char bulk_in_ep, bulk_out_ep; /* Endpoint assignments */ wait_queue_head_t wait_q; /* for timeouts */ @@ -444,6 +438,13 @@ .release = close_rio, }; +static struct usb_class_driver usb_rio_class = { + .name = "usb/rio500%d", + .fops = &usb_rio_fops, + .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, + .minor_base = RIO_MINOR, +}; + static int probe_rio(struct usb_interface *intf, const struct usb_device_id *id) { @@ -453,7 +454,7 @@ info("USB Rio found at address %d", dev->devnum); - retval = usb_register_dev(&usb_rio_fops, RIO_MINOR, 1, &rio->minor); + retval = usb_register_dev(intf, &usb_rio_class); if (retval) { err("Not able to get a minor for this device."); return -ENOMEM; @@ -464,23 +465,19 @@ if (!(rio->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) { err("probe_rio: Not enough memory for the output buffer"); + usb_deregister_dev(intf, &usb_rio_class); return -ENOMEM; } dbg("probe_rio: obuf address:%p", rio->obuf); if (!(rio->ibuf = (char *) kmalloc(IBUF_SIZE, GFP_KERNEL))) { err("probe_rio: Not enough memory for the input buffer"); + usb_deregister_dev(intf, &usb_rio_class); kfree(rio->obuf); return -ENOMEM; } dbg("probe_rio: ibuf address:%p", rio->ibuf); - devfs_register(NULL, "usb/rio500", - DEVFS_FL_DEFAULT, USB_MAJOR, - RIO_MINOR, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | - S_IWGRP, &usb_rio_fops, NULL); - init_MUTEX(&(rio->lock)); usb_set_intfdata (intf, rio); @@ -493,8 +490,7 @@ usb_set_intfdata (intf, NULL); if (rio) { - devfs_remove("usb/rio500"); - usb_deregister_dev(1, rio->minor); + usb_deregister_dev(intf, &usb_rio_class); down(&(rio->lock)); if (rio->isopen) { diff -Nru a/drivers/usb/misc/speedtch.c b/drivers/usb/misc/speedtch.c --- a/drivers/usb/misc/speedtch.c Thu May 8 00:24:30 2003 +++ b/drivers/usb/misc/speedtch.c Thu May 8 00:24:30 2003 @@ -74,6 +74,7 @@ #include #include #include +#include /* #define DEBUG 1 diff -Nru a/drivers/usb/misc/tiglusb.c b/drivers/usb/misc/tiglusb.c --- a/drivers/usb/misc/tiglusb.c Thu May 8 00:24:27 2003 +++ b/drivers/usb/misc/tiglusb.c Thu May 8 00:24:27 2003 @@ -327,7 +327,6 @@ int minor = -1; int i; ptiglusb_t s; - char name[32]; dbg ("probing vendor id 0x%x, device id 0x%x", dev->descriptor.idVendor, dev->descriptor.idProduct); @@ -371,12 +370,9 @@ up (&s->mutex); dbg ("bound to interface"); - sprintf (name, "ticables/usb/%d", s->minor); - dbg ("registering to devfs : major = %d, minor = %d, node = %s", - TIUSB_MAJOR, (TIUSB_MINOR + s->minor), name); - devfs_register(NULL, name, DEVFS_FL_DEFAULT, TIUSB_MAJOR, - TIUSB_MINOR + s->minor, S_IFCHR | S_IRUGO | S_IWUGO, - &tiglusb_fops, NULL); + devfs_mk_cdev(MAJOR(TIUSB_MAJOR, TIUSB_MINOR + s->minor), + S_IFCHR | S_IRUGO | S_IWUGO, + "ticables/usb/%d", s->minor); /* Display firmware version */ info ("firmware revision %i.%02x", @@ -390,8 +386,6 @@ static void tiglusb_disconnect (struct usb_interface *intf) { - char name[32]; - ptiglusb_t s = usb_get_intfdata (intf); usb_set_intfdata (intf, NULL); @@ -408,7 +402,7 @@ s->dev = NULL; s->opened = 0; - devfs_remove (name, "ticables/usb/%d", s->minor); + devfs_remove("ticables/usb/%d", s->minor); info ("device %d removed", s->minor); diff -Nru a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c --- a/drivers/usb/misc/usblcd.c Thu May 8 00:24:27 2003 +++ b/drivers/usb/misc/usblcd.c Thu May 8 00:24:27 2003 @@ -34,7 +34,6 @@ struct lcd_usb_data { struct usb_device *lcd_dev; /* init: probe_lcd */ unsigned int ifnum; /* Interface number of the USB device */ - int minor; /* minor number for this device */ int isopen; /* nz if open */ int present; /* Device is present on the bus */ char *obuf, *ibuf; /* transfer buffers */ @@ -245,6 +244,13 @@ .release = close_lcd, }; +static struct usb_class_driver usb_lcd_class = { + .name = "usb/lcd%d", + .fops = &usb_lcd_fops, + .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, + .minor_base = USBLCD_MINOR, +}; + static int probe_lcd(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(intf); @@ -268,23 +274,25 @@ (i & 0xF000)>>12,(i & 0xF00)>>8,(i & 0xF0)>>4,(i & 0xF), dev->devnum); - retval = usb_register_dev(&usb_lcd_fops, USBLCD_MINOR, 1, &lcd->minor); + retval = usb_register_dev(intf, &usb_lcd_class); if (retval) { err("Not able to get a minor for this device."); return -ENOMEM; } - + lcd->present = 1; lcd->lcd_dev = dev; if (!(lcd->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) { err("probe_lcd: Not enough memory for the output buffer"); + usb_deregister_dev(intf, &usb_lcd_class); return -ENOMEM; } dbg("probe_lcd: obuf address:%p", lcd->obuf); if (!(lcd->ibuf = (char *) kmalloc(IBUF_SIZE, GFP_KERNEL))) { err("probe_lcd: Not enough memory for the input buffer"); + usb_deregister_dev(intf, &usb_lcd_class); kfree(lcd->obuf); return -ENOMEM; } @@ -300,7 +308,7 @@ usb_set_intfdata (intf, NULL); if (lcd) { - usb_deregister_dev(1, lcd->minor); + usb_deregister_dev(intf, &usb_lcd_class); if (lcd->isopen) { lcd->isopen = 0; diff -Nru a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c --- a/drivers/usb/net/rtl8150.c Thu May 8 00:24:29 2003 +++ b/drivers/usb/net/rtl8150.c Thu May 8 00:24:29 2003 @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -106,7 +105,6 @@ typedef struct rtl8150 rtl8150_t; -/* the global usb devfs handle */ unsigned long multicast_filter_limit = 32; static void fill_skb_pool(rtl8150_t *); @@ -160,7 +158,7 @@ clear_bit(RX_REG_SET, &dev->flags); } -static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data) +static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size) { int ret; @@ -537,7 +535,8 @@ warn("%s - device reset failed", __FUNCTION__); } /* RCR bit7=1 attach Rx info at the end; =0 HW CRC (which is broken) */ - dev->rx_creg = rcr = 0x9e; + rcr = 0x9e; /* bit7=1 attach Rx info at the end */ + dev->rx_creg = cpu_to_le16(rcr); tcr = 0xd8; cr = 0x0c; if (!(rcr & 0x80)) @@ -584,18 +583,18 @@ dev = netdev->priv; netif_stop_queue(netdev); if (netdev->flags & IFF_PROMISC) { - dev->rx_creg |= 0x0001; + dev->rx_creg |= cpu_to_le16(0x0001); info("%s: promiscuous mode", netdev->name); } else if ((netdev->mc_count > multicast_filter_limit) || (netdev->flags & IFF_ALLMULTI)) { - dev->rx_creg &= 0xfffe; - dev->rx_creg |= 0x0002; + dev->rx_creg &= cpu_to_le16(0xfffe); + dev->rx_creg |= cpu_to_le16(0x0002); info("%s: allmulti set", netdev->name); } else { /* ~RX_MULTICAST, ~RX_PROMISCUOUS */ - dev->rx_creg &= 0x00fc; + dev->rx_creg &= cpu_to_le16(0x00fc); } - async_set_registers(dev, RCR, 2, &dev->rx_creg); + async_set_registers(dev, RCR, 2); netif_wake_queue(netdev); } diff -Nru a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c --- a/drivers/usb/serial/bus.c Thu May 8 00:24:30 2003 +++ b/drivers/usb/serial/bus.c Thu May 8 00:24:30 2003 @@ -23,18 +23,6 @@ #include "usb-serial.h" -static ssize_t show_dev (struct device *dev, char *buf) -{ - struct usb_serial_port *port= to_usb_serial_port(dev); - dev_t base; - - port = to_usb_serial_port(dev); - - base = MKDEV(SERIAL_TTY_MAJOR, port->number); - return sprintf(buf, "%04x\n", base); -} -static DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL); - static int usb_serial_device_match (struct device *dev, struct device_driver *drv) { struct usb_serial_device_type *driver; @@ -88,10 +76,7 @@ } minor = port->number; - - tty_register_device (&usb_serial_tty_driver, minor); - device_create_file (dev, &dev_attr_dev); - + tty_register_device (&usb_serial_tty_driver, minor, dev); dev_info(&port->serial->dev->dev, "%s converter now attached to ttyUSB%d (or usb/tts/%d for devfs)\n", driver->name, minor, minor); diff -Nru a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c --- a/drivers/usb/serial/console.c Thu May 8 00:24:29 2003 +++ b/drivers/usb/serial/console.c Thu May 8 00:24:29 2003 @@ -133,7 +133,7 @@ co->cflag = cflag; /* grab the first serial port that happens to be connected */ - serial = usb_serial_get_by_minor (0); + serial = usb_serial_get_by_index(0); if (serial_paranoia_check (serial, __FUNCTION__)) { /* no device is connected yet, sorry :( */ err ("No USB device connected to ttyUSB0"); diff -Nru a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h --- a/drivers/usb/serial/usb-serial.h Thu May 8 00:24:30 2003 +++ b/drivers/usb/serial/usb-serial.h Thu May 8 00:24:30 2003 @@ -280,7 +280,7 @@ #endif /* Functions needed by other parts of the usbserial core */ -extern struct usb_serial *usb_serial_get_by_minor (unsigned int minor); +extern struct usb_serial *usb_serial_get_by_index (unsigned int minor); extern int usb_serial_generic_open (struct usb_serial_port *port, struct file *filp); extern int usb_serial_generic_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); extern void usb_serial_generic_close (struct usb_serial_port *port, struct file *filp); diff -Nru a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h --- a/drivers/usb/storage/unusual_devs.h Thu May 8 00:24:29 2003 +++ b/drivers/usb/storage/unusual_devs.h Thu May 8 00:24:29 2003 @@ -98,6 +98,18 @@ "Nex II Digital", US_SC_SCSI, US_PR_BULK, NULL, US_FL_START_STOP), +/* Patch submitted by Philipp Friedrich */ +UNUSUAL_DEV( 0x0482, 0x0100, 0x0100, 0x0100, + "Kyocera", + "Finecam S3x", + US_SC_8070, US_PR_CB, NULL, US_FL_FIX_INQUIRY), + +/* Patch submitted by Philipp Friedrich */ +UNUSUAL_DEV( 0x0482, 0x0101, 0x0100, 0x0100, + "Kyocera", + "Finecam S4", + US_SC_8070, US_PR_CB, NULL, US_FL_FIX_INQUIRY), + /* Reported by Paul Stewart * This entry is needed because the device reports Sub=ff */ UNUSUAL_DEV( 0x04a4, 0x0004, 0x0001, 0x0001, @@ -237,14 +249,6 @@ US_SC_8070, US_PR_BULK, NULL, US_FL_FIX_INQUIRY | US_FL_START_STOP ), -/* Submitted by Lars Gemeinhardt - * Needed for START_STOP flag */ -UNUSUAL_DEV( 0x0547, 0x2810, 0x0001, 0x0001, - "Mello", - "MP3 Player", - US_SC_SCSI, US_PR_BULK, NULL, - US_FL_START_STOP), - /* This entry is needed because the device reports Sub=ff */ UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450, "Sony", @@ -626,6 +630,26 @@ US_SC_SCSI, US_PR_BULK, NULL, US_FL_MODE_XLATE | US_FL_START_STOP | US_FL_FIX_INQUIRY ), +/* This Pentax still camera is not conformant + * to the USB storage specification: - + * - It does not like the INQUIRY command. So we must handle this command + * of the SCSI layer ourselves. + * Tested on Rev. 10.00 (0x1000) + * Submitted by James Courtier-Dutton + */ +UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000, + "Pentax", + "Optio 2/3/400", + US_SC_8070, US_PR_CBI, NULL, + US_FL_FIX_INQUIRY ), + +/* Submitted by Per Winkvist */ +UNUSUAL_DEV( 0x0a17, 0x006, 0x1000, 0x9009, + "Pentax", + "Optio S", + US_SC_8070, US_PR_CBI, NULL, + US_FL_FIX_INQUIRY ), + /* Submitted by Brian Hall * Needed for START_STOP flag */ UNUSUAL_DEV( 0x0c76, 0x0003, 0x0100, 0x0100, @@ -657,3 +681,13 @@ US_SC_SCSI, US_PR_SDDR55, NULL, US_FL_SINGLE_LUN), #endif + +/* Aiptek PocketCAM 3Mega + * Nicolas DUPEUX + */ +UNUSUAL_DEV( 0x08ca, 0x2011, 0x0000, 0x9999, + "AIPTEK", + "PocketCAM 3Mega", + US_SC_SCSI, US_PR_BULK, NULL, + US_FL_MODE_XLATE | US_FL_START_STOP), + diff -Nru a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c --- a/drivers/usb/usb-skeleton.c Thu May 8 00:24:28 2003 +++ b/drivers/usb/usb-skeleton.c Thu May 8 00:24:28 2003 @@ -1,5 +1,5 @@ /* - * USB Skeleton driver - 1.0 + * USB Skeleton driver - 1.1 * * Copyright (c) 2001-2002 Greg Kroah-Hartman (greg@kroah.com) * @@ -18,6 +18,7 @@ * * History: * + * 2003-05-06 - 1.1 - changes due to usb core changes with usb_register_dev() * 2003-02-25 - 1.0 - fix races involving urb->status, unlink_urb(), and * disconnect. Fix transfer amount in read(). Use * macros instead of magic numbers in probe(). Change @@ -47,7 +48,6 @@ #include #include #include -#include #include #include @@ -87,12 +87,8 @@ MODULE_DEVICE_TABLE (usb, skel_table); -#ifdef CONFIG_USB_DYNAMIC_MINORS -#define USB_SKEL_MINOR_BASE 0 -#else /* Get a minor range for your devices from the usb maintainer */ #define USB_SKEL_MINOR_BASE 192 -#endif /* Structure to hold all of our device specific stuff */ struct usb_skel { @@ -153,16 +149,6 @@ * This also means that the kernel can decrement * the use-counter again before calling release() * or should the open() function fail. - * - * Not all device structures have an "owner" field - * yet. "struct file_operations" and "struct net_device" - * do, while "struct tty_driver" does not. If the struct - * has an "owner" field, then initialize it to the value - * THIS_MODULE and the kernel will handle all module - * locking for you automatically. Otherwise, you must - * increment the use-counter in the open() function - * and decrement it again in the release() function - * yourself. */ .owner = THIS_MODULE, @@ -173,6 +159,16 @@ .release = skel_release, }; +/* + * usb class driver info in order to get a minor number from the usb core, + * and to have the device registered with devfs and the driver core + */ +static struct usb_class_driver skell_class = { + .name = "usb/skel%d", + .fops = &skel_fops, + .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, + .minor_base = USB_SKEL_MINOR_BASE, +}; /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver skel_driver = { @@ -236,8 +232,7 @@ /* prevent disconnects */ down (&disconnect_sem); - interface = usb_find_interface (&skel_driver, - mk_kdev(USB_MAJOR, subminor)); + interface = usb_find_interface (&skel_driver, subminor); if (!interface) { err ("%s - error, can't find device for minor %d", __FUNCTION__, subminor); @@ -508,7 +503,6 @@ struct usb_skel *dev = NULL; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; - int minor; size_t buffer_size; int i; int retval; @@ -521,7 +515,7 @@ return -ENODEV; } - retval = usb_register_dev (&skel_fops, USB_SKEL_MINOR_BASE, 1, &minor); + retval = usb_register_dev (intf, &skel_class); if (retval) { /* something prevented us from registering this driver */ err ("Not able to get a minor for this device."); @@ -539,7 +533,7 @@ init_MUTEX (&dev->sem); dev->udev = udev; dev->interface = interface; - dev->minor = minor; + dev->minor = intf->minor; /* set up the endpoint information */ /* check out the endpoints */ @@ -606,22 +600,9 @@ goto error; } - /* initialize the devfs node for this device and register it */ - sprintf(name, "usb/skel%d", dev->minor); - - devfs = devfs_register(NULL, name, - DEVFS_FL_DEFAULT, USB_MAJOR, - dev->minor, - S_IFCHR | S_IRUSR | S_IWUSR | - S_IRGRP | S_IWGRP | S_IROTH, - &skel_fops, NULL); - /* let the user know what node this device is now attached to */ info ("USB Skeleton device now attached to USBSkel-%d", dev->minor); - /* add device id so the device works when advertised */ - interface->kdev = mk_kdev(USB_MAJOR, dev->minor); - goto exit; error: @@ -629,7 +610,7 @@ dev = NULL; exit_minor: - usb_deregister_dev (1, minor); + usb_deregister_dev (intf, &skel_class); exit: if (dev) { @@ -667,16 +648,13 @@ down (&dev->sem); - /* remove device id to disable open() */ - interface->kdev = NODEV; + /* disable open() */ + interface->minor = -1; minor = dev->minor; - /* remove our devfs node */ - devfs_remove("usb/skel%d", dev->minor); - - /* give back our dynamic minor */ - usb_deregister_dev (1, minor); + /* give back our minor */ + usb_deregister_dev (intf, &skel_class); /* terminate an ongoing write */ if (atomic_read (&dev->write_busy)) { diff -Nru a/drivers/video/fbmem.c b/drivers/video/fbmem.c --- a/drivers/video/fbmem.c Thu May 8 00:24:27 2003 +++ b/drivers/video/fbmem.c Thu May 8 00:24:27 2003 @@ -1214,7 +1214,6 @@ int register_framebuffer(struct fb_info *fb_info) { - char name_buf[12]; int i; if (num_registered_fb == FB_MAX) @@ -1242,10 +1241,9 @@ spin_lock_init(&fb_info->pixmap.lock); registered_fb[i] = fb_info; - sprintf(name_buf, "fb/%d", i); - devfs_register(NULL, name_buf, DEVFS_FL_DEFAULT, - FB_MAJOR, i, S_IFCHR | S_IRUGO | S_IWUGO, - &fb_fops, NULL); + + devfs_mk_cdev(MKDEV(FB_MAJOR, i), + S_IFCHR | S_IRUGO | S_IWUGO, "fb/%d", i); return 0; } diff -Nru a/fs/Kconfig b/fs/Kconfig --- a/fs/Kconfig Thu May 8 00:24:29 2003 +++ b/fs/Kconfig Thu May 8 00:24:29 2003 @@ -73,6 +73,18 @@ If you don't know what Access Control Lists are, say N +config EXT2_FS_SECURITY + bool "Ext2 Security Labels" + depends on EXT2_FS_XATTR + help + Security labels support alternative access control models + implemented by security modules like SELinux. This option + enables an extended attribute handler for file security + labels in the ext2 filesystem. + + If you are not using a security module that requires using + extended attributes for file security labels, say N. + config EXT3_FS tristate "Ext3 journalling file system support" help @@ -130,6 +142,18 @@ Linux website . If you don't know what Access Control Lists are, say N + +config EXT3_FS_SECURITY + bool "Ext3 Security Labels" + depends on EXT3_FS_XATTR + help + Security labels support alternative access control models + implemented by security modules like SELinux. This option + enables an extended attribute handler for file security + labels in the ext3 filesystem. + + If you are not using a security module that requires using + extended attributes for file security labels, say N. config JBD # CONFIG_JBD could be its own option (even modular), but until there are diff -Nru a/fs/bfs/dir.c b/fs/bfs/dir.c --- a/fs/bfs/dir.c Thu May 8 00:24:30 2003 +++ b/fs/bfs/dir.c Thu May 8 00:24:30 2003 @@ -65,7 +65,7 @@ brelse(bh); } - UPDATE_ATIME(dir); + update_atime(dir); unlock_kernel(); return 0; } diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c --- a/fs/binfmt_elf.c Thu May 8 00:24:28 2003 +++ b/fs/binfmt_elf.c Thu May 8 00:24:28 2003 @@ -1105,7 +1105,7 @@ i = p->state ? ffz(~p->state) + 1 : 0; psinfo->pr_state = i; - psinfo->pr_sname = (i < 0 || i > 5) ? '.' : "RSDZTD"[i]; + psinfo->pr_sname = (i < 0 || i > 5) ? '.' : "RSDTZW"[i]; psinfo->pr_zomb = psinfo->pr_sname == 'Z'; psinfo->pr_nice = task_nice(p); psinfo->pr_flag = p->flags; diff -Nru a/fs/buffer.c b/fs/buffer.c --- a/fs/buffer.c Thu May 8 00:24:29 2003 +++ b/fs/buffer.c Thu May 8 00:24:29 2003 @@ -244,16 +244,26 @@ * sync everything. Start out by waking pdflush, because that writes back * all queues in parallel. */ -asmlinkage long sys_sync(void) +static void do_sync(unsigned long wait) { wakeup_bdflush(0); sync_inodes(0); /* All mappings, inodes and their blockdevs */ DQUOT_SYNC(NULL); sync_supers(); /* Write the superblocks */ sync_filesystems(0); /* Start syncing the filesystems */ - sync_filesystems(1); /* Waitingly sync the filesystems */ - sync_inodes(1); /* Mappings, inodes and blockdevs, again. */ + sync_filesystems(wait); /* Waitingly sync the filesystems */ + sync_inodes(wait); /* Mappings, inodes and blockdevs, again. */ +} + +asmlinkage long sys_sync(void) +{ + do_sync(1); return 0; +} + +void emergency_sync(void) +{ + pdflush_operation(do_sync, 0); } /* diff -Nru a/fs/coda/psdev.c b/fs/coda/psdev.c --- a/fs/coda/psdev.c Thu May 8 00:24:29 2003 +++ b/fs/coda/psdev.c Thu May 8 00:24:29 2003 @@ -373,16 +373,10 @@ } devfs_mk_dir ("coda"); for (i = 0; i < MAX_CODADEVS; i++) { - char name[16]; - sprintf(name, "coda/%d", i); - devfs_register(NULL, name, DEVFS_FL_NONE, - CODA_PSDEV_MAJOR, i, - S_IFCHR | S_IRUSR | S_IWUSR, - &coda_psdev_fops, NULL); + devfs_mk_cdev(MKDEV(CODA_PSDEV_MAJOR, i), + S_IFCHR|S_IRUSR|S_IWUSR, "coda/%d", i); } - coda_sysctl_init(); - return 0; } diff -Nru a/fs/dcache.c b/fs/dcache.c --- a/fs/dcache.c Thu May 8 00:24:27 2003 +++ b/fs/dcache.c Thu May 8 00:24:27 2003 @@ -770,12 +770,12 @@ void d_instantiate(struct dentry *entry, struct inode * inode) { if (!list_empty(&entry->d_alias)) BUG(); - security_d_instantiate(entry, inode); spin_lock(&dcache_lock); if (inode) list_add(&entry->d_alias, &inode->i_dentry); entry->d_inode = inode; spin_unlock(&dcache_lock); + security_d_instantiate(entry, inode); } /** @@ -903,12 +903,12 @@ struct dentry *new = NULL; if (inode && S_ISDIR(inode->i_mode)) { - security_d_instantiate(dentry, inode); spin_lock(&dcache_lock); if (!list_empty(&inode->i_dentry)) { new = list_entry(inode->i_dentry.next, struct dentry, d_alias); __dget_locked(new); spin_unlock(&dcache_lock); + security_d_instantiate(dentry, inode); d_rehash(dentry); d_move(new, dentry); iput(inode); @@ -917,6 +917,7 @@ list_add(&dentry->d_alias, &inode->i_dentry); dentry->d_inode = inode; spin_unlock(&dcache_lock); + security_d_instantiate(dentry, inode); d_rehash(dentry); } } else diff -Nru a/fs/devfs/base.c b/fs/devfs/base.c --- a/fs/devfs/base.c Thu May 8 00:24:28 2003 +++ b/fs/devfs/base.c Thu May 8 00:24:28 2003 @@ -1562,6 +1562,52 @@ EXPORT_SYMBOL(devfs_mk_bdev); +int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...) +{ + struct devfs_entry *dir = NULL, *de; + char buf[64]; + va_list args; + int error, n; + + if (!S_ISCHR(mode)) { + printk(KERN_WARNING "%s: invalide mode (%u) for %s\n", + __FUNCTION__, mode, buf); + return -EINVAL; + } + + va_start(args, fmt); + n = vsnprintf(buf, 64, fmt, args); + if (n >= 64 || !buf[0]) { + printk(KERN_WARNING "%s: invalid format string\n", + __FUNCTION__); + return -EINVAL; + } + + de = _devfs_prepare_leaf(&dir, buf, mode); + if (!de) { + printk(KERN_WARNING "%s: could not prepare leaf for %s\n", + __FUNCTION__, buf); + return -ENOMEM; /* could be more accurate... */ + } + + de->u.cdev.dev = dev; + + error = _devfs_append_entry(dir, de, NULL); + if (error) { + printk(KERN_WARNING "%s: could not append to parent for %s\n", + __FUNCTION__, buf); + goto out; + } + + devfsd_notify(de, DEVFSD_NOTIFY_REGISTERED); + out: + devfs_put(dir); + return error; +} + +EXPORT_SYMBOL(devfs_mk_cdev); + + /** * _devfs_unhook - Unhook a device entry from its parents list * @de: The entry to unhook. diff -Nru a/fs/ext2/Makefile b/fs/ext2/Makefile --- a/fs/ext2/Makefile Thu May 8 00:24:29 2003 +++ b/fs/ext2/Makefile Thu May 8 00:24:29 2003 @@ -14,3 +14,7 @@ ifeq ($(CONFIG_EXT2_FS_POSIX_ACL),y) ext2-objs += acl.o endif + +ifeq ($(CONFIG_EXT2_FS_SECURITY),y) +ext2-objs += xattr_security.o +endif diff -Nru a/fs/ext2/dir.c b/fs/ext2/dir.c --- a/fs/ext2/dir.c Thu May 8 00:24:29 2003 +++ b/fs/ext2/dir.c Thu May 8 00:24:29 2003 @@ -310,7 +310,7 @@ done: filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset; filp->f_version = inode->i_version; - UPDATE_ATIME(inode); + update_atime(inode); return 0; } diff -Nru a/fs/ext2/xattr.c b/fs/ext2/xattr.c --- a/fs/ext2/xattr.c Thu May 8 00:24:29 2003 +++ b/fs/ext2/xattr.c Thu May 8 00:24:29 2003 @@ -1102,22 +1102,33 @@ &ext2_xattr_trusted_handler); if (err) goto out; +#ifdef CONFIG_EXT2_FS_SECURITY + err = ext2_xattr_register(EXT2_XATTR_INDEX_SECURITY, + &ext2_xattr_security_handler); + if (err) + goto out1; +#endif #ifdef CONFIG_EXT2_FS_POSIX_ACL err = init_ext2_acl(); if (err) - goto out1; + goto out2; #endif ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL, sizeof(struct mb_cache_entry) + sizeof(struct mb_cache_entry_index), 1, 6); if (!ext2_xattr_cache) { err = -ENOMEM; - goto out2; + goto out3; } return 0; -out2: +out3: #ifdef CONFIG_EXT2_FS_POSIX_ACL exit_ext2_acl(); +out2: +#endif +#ifdef CONFIG_EXT2_FS_SECURITY + ext2_xattr_unregister(EXT2_XATTR_INDEX_SECURITY, + &ext2_xattr_security_handler); out1: #endif ext2_xattr_unregister(EXT2_XATTR_INDEX_TRUSTED, @@ -1134,6 +1145,10 @@ mb_cache_destroy(ext2_xattr_cache); #ifdef CONFIG_EXT2_FS_POSIX_ACL exit_ext2_acl(); +#endif +#ifdef CONFIG_EXT2_FS_SECURITY + ext2_xattr_unregister(EXT2_XATTR_INDEX_SECURITY, + &ext2_xattr_security_handler); #endif ext2_xattr_unregister(EXT2_XATTR_INDEX_TRUSTED, &ext2_xattr_trusted_handler); diff -Nru a/fs/ext2/xattr.h b/fs/ext2/xattr.h --- a/fs/ext2/xattr.h Thu May 8 00:24:29 2003 +++ b/fs/ext2/xattr.h Thu May 8 00:24:29 2003 @@ -22,6 +22,7 @@ #define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS 2 #define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT 3 #define EXT2_XATTR_INDEX_TRUSTED 4 +#define EXT2_XATTR_INDEX_SECURITY 6 struct ext2_xattr_header { __u32 h_magic; /* magic number for identification */ @@ -134,4 +135,5 @@ extern struct ext2_xattr_handler ext2_xattr_user_handler; extern struct ext2_xattr_handler ext2_xattr_trusted_handler; +extern struct ext2_xattr_handler ext2_xattr_security_handler; diff -Nru a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/ext2/xattr_security.c Thu May 8 00:24:30 2003 @@ -0,0 +1,54 @@ +/* + * linux/fs/ext2/xattr_security.c + * Handler for storing security labels as extended attributes. + */ + +#include +#include +#include +#include +#include +#include "xattr.h" + +#define XATTR_SECURITY_PREFIX "security." + +static size_t +ext2_xattr_security_list(char *list, struct inode *inode, + const char *name, int name_len) +{ + const int prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1; + + if (list) { + memcpy(list, XATTR_SECURITY_PREFIX, prefix_len); + memcpy(list+prefix_len, name, name_len); + list[prefix_len + name_len] = '\0'; + } + return prefix_len + name_len + 1; +} + +static int +ext2_xattr_security_get(struct inode *inode, const char *name, + void *buffer, size_t size) +{ + if (strcmp(name, "") == 0) + return -EINVAL; + return ext2_xattr_get(inode, EXT2_XATTR_INDEX_SECURITY, name, + buffer, size); +} + +static int +ext2_xattr_security_set(struct inode *inode, const char *name, + const void *value, size_t size, int flags) +{ + if (strcmp(name, "") == 0) + return -EINVAL; + return ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY, name, + value, size, flags); +} + +struct ext2_xattr_handler ext2_xattr_security_handler = { + .prefix = XATTR_SECURITY_PREFIX, + .list = ext2_xattr_security_list, + .get = ext2_xattr_security_get, + .set = ext2_xattr_security_set, +}; diff -Nru a/fs/ext3/Makefile b/fs/ext3/Makefile --- a/fs/ext3/Makefile Thu May 8 00:24:27 2003 +++ b/fs/ext3/Makefile Thu May 8 00:24:27 2003 @@ -14,3 +14,7 @@ ifeq ($(CONFIG_EXT3_FS_POSIX_ACL),y) ext3-objs += acl.o endif + +ifeq ($(CONFIG_EXT3_FS_SECURITY),y) +ext3-objs += xattr_security.o +endif diff -Nru a/fs/ext3/dir.c b/fs/ext3/dir.c --- a/fs/ext3/dir.c Thu May 8 00:24:29 2003 +++ b/fs/ext3/dir.c Thu May 8 00:24:29 2003 @@ -216,7 +216,7 @@ offset = 0; brelse (bh); } - UPDATE_ATIME(inode); + update_atime(inode); out: return ret; } @@ -489,7 +489,7 @@ } finished: info->last_pos = filp->f_pos; - UPDATE_ATIME(inode); + update_atime(inode); return 0; } diff -Nru a/fs/ext3/fsync.c b/fs/ext3/fsync.c --- a/fs/ext3/fsync.c Thu May 8 00:24:30 2003 +++ b/fs/ext3/fsync.c Thu May 8 00:24:30 2003 @@ -27,8 +27,6 @@ #include #include #include -#include -#include /* * akpm: A new design for ext3_sync_file(). diff -Nru a/fs/ext3/xattr.c b/fs/ext3/xattr.c --- a/fs/ext3/xattr.c Thu May 8 00:24:29 2003 +++ b/fs/ext3/xattr.c Thu May 8 00:24:29 2003 @@ -1142,22 +1142,33 @@ &ext3_xattr_trusted_handler); if (err) goto out; +#ifdef CONFIG_EXT3_FS_SECURITY + err = ext3_xattr_register(EXT3_XATTR_INDEX_SECURITY, + &ext3_xattr_security_handler); + if (err) + goto out1; +#endif #ifdef CONFIG_EXT3_FS_POSIX_ACL err = init_ext3_acl(); if (err) - goto out1; + goto out2; #endif ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL, sizeof(struct mb_cache_entry) + sizeof(struct mb_cache_entry_index), 1, 6); if (!ext3_xattr_cache) { err = -ENOMEM; - goto out2; + goto out3; } return 0; -out2: +out3: #ifdef CONFIG_EXT3_FS_POSIX_ACL exit_ext3_acl(); +out2: +#endif +#ifdef CONFIG_EXT3_FS_SECURITY + ext3_xattr_unregister(EXT3_XATTR_INDEX_SECURITY, + &ext3_xattr_security_handler); out1: #endif ext3_xattr_unregister(EXT3_XATTR_INDEX_TRUSTED, @@ -1176,6 +1187,10 @@ ext3_xattr_cache = NULL; #ifdef CONFIG_EXT3_FS_POSIX_ACL exit_ext3_acl(); +#endif +#ifdef CONFIG_EXT3_FS_SECURITY + ext3_xattr_unregister(EXT3_XATTR_INDEX_SECURITY, + &ext3_xattr_security_handler); #endif ext3_xattr_unregister(EXT3_XATTR_INDEX_TRUSTED, &ext3_xattr_trusted_handler); diff -Nru a/fs/ext3/xattr.h b/fs/ext3/xattr.h --- a/fs/ext3/xattr.h Thu May 8 00:24:30 2003 +++ b/fs/ext3/xattr.h Thu May 8 00:24:30 2003 @@ -21,6 +21,7 @@ #define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2 #define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3 #define EXT3_XATTR_INDEX_TRUSTED 4 +#define EXT3_XATTR_INDEX_SECURITY 6 struct ext3_xattr_header { __u32 h_magic; /* magic number for identification */ @@ -141,3 +142,4 @@ extern struct ext3_xattr_handler ext3_xattr_user_handler; extern struct ext3_xattr_handler ext3_xattr_trusted_handler; +extern struct ext3_xattr_handler ext3_xattr_security_handler; diff -Nru a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/ext3/xattr_security.c Thu May 8 00:24:30 2003 @@ -0,0 +1,55 @@ +/* + * linux/fs/ext3/xattr_security.c + * Handler for storing security labels as extended attributes. + */ + +#include +#include +#include +#include +#include +#include +#include "xattr.h" + +#define XATTR_SECURITY_PREFIX "security." + +static size_t +ext3_xattr_security_list(char *list, struct inode *inode, + const char *name, int name_len) +{ + const int prefix_len = sizeof(XATTR_SECURITY_PREFIX)-1; + + if (list) { + memcpy(list, XATTR_SECURITY_PREFIX, prefix_len); + memcpy(list+prefix_len, name, name_len); + list[prefix_len + name_len] = '\0'; + } + return prefix_len + name_len + 1; +} + +static int +ext3_xattr_security_get(struct inode *inode, const char *name, + void *buffer, size_t size) +{ + if (strcmp(name, "") == 0) + return -EINVAL; + return ext3_xattr_get(inode, EXT3_XATTR_INDEX_SECURITY, name, + buffer, size); +} + +static int +ext3_xattr_security_set(struct inode *inode, const char *name, + const void *value, size_t size, int flags) +{ + if (strcmp(name, "") == 0) + return -EINVAL; + return ext3_xattr_set(inode, EXT3_XATTR_INDEX_SECURITY, name, + value, size, flags); +} + +struct ext3_xattr_handler ext3_xattr_security_handler = { + .prefix = XATTR_SECURITY_PREFIX, + .list = ext3_xattr_security_list, + .get = ext3_xattr_security_get, + .set = ext3_xattr_security_set, +}; diff -Nru a/fs/file_table.c b/fs/file_table.c --- a/fs/file_table.c Thu May 8 00:24:27 2003 +++ b/fs/file_table.c Thu May 8 00:24:27 2003 @@ -141,7 +141,7 @@ security_file_free(file); } -void fput(struct file * file) +void fput(struct file *file) { if (atomic_dec_and_test(&file->f_count)) __fput(file); @@ -189,6 +189,34 @@ spin_unlock(&files->file_lock); return file; } + +/* + * Lightweight file lookup - no refcnt increment if fd table isn't shared. + * You can use this only if it is guranteed that the current task already + * holds a refcnt to that file. That check has to be done at fget() only + * and a flag is returned to be passed to the corresponding fput_light(). + * There must not be a cloning between an fget_light/fput_light pair. + */ +struct file *fget_light(unsigned int fd, int *fput_needed) +{ + struct file *file; + struct files_struct *files = current->files; + + *fput_needed = 0; + if (likely((atomic_read(&files->count) == 1))) { + file = fcheck(fd); + } else { + spin_lock(&files->file_lock); + file = fcheck(fd); + if (file) { + get_file(file); + *fput_needed = 1; + } + spin_unlock(&files->file_lock); + } + return file; +} + void put_filp(struct file *file) { diff -Nru a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c --- a/fs/hugetlbfs/inode.c Thu May 8 00:24:30 2003 +++ b/fs/hugetlbfs/inode.c Thu May 8 00:24:30 2003 @@ -62,7 +62,7 @@ down(&inode->i_sem); - UPDATE_ATIME(inode); + update_atime(inode); vma->vm_flags |= VM_HUGETLB | VM_RESERVED; vma->vm_ops = &hugetlb_vm_ops; ret = hugetlb_prefault(mapping, vma); diff -Nru a/fs/minix/dir.c b/fs/minix/dir.c --- a/fs/minix/dir.c Thu May 8 00:24:29 2003 +++ b/fs/minix/dir.c Thu May 8 00:24:29 2003 @@ -127,7 +127,7 @@ done: filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset; - UPDATE_ATIME(inode); + update_atime(inode); unlock_kernel(); return 0; } diff -Nru a/fs/namei.c b/fs/namei.c --- a/fs/namei.c Thu May 8 00:24:28 2003 +++ b/fs/namei.c Thu May 8 00:24:28 2003 @@ -405,7 +405,7 @@ goto loop; current->link_count++; current->total_link_count++; - UPDATE_ATIME(dentry->d_inode); + update_atime(dentry->d_inode); err = dentry->d_inode->i_op->follow_link(dentry, nd); current->link_count--; return err; @@ -1327,7 +1327,7 @@ error = security_inode_follow_link(dentry, nd); if (error) goto exit_dput; - UPDATE_ATIME(dentry->d_inode); + update_atime(dentry->d_inode); error = dentry->d_inode->i_op->follow_link(dentry, nd); dput(dentry); if (error) diff -Nru a/fs/namespace.c b/fs/namespace.c --- a/fs/namespace.c Thu May 8 00:24:29 2003 +++ b/fs/namespace.c Thu May 8 00:24:29 2003 @@ -24,7 +24,6 @@ #include extern struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data); -extern int do_remount_sb(struct super_block *sb, int flags, void * data); extern int __init init_rootfs(void); extern int __init fs_subsys_init(void); @@ -326,7 +325,7 @@ down_write(&sb->s_umount); if (!(sb->s_flags & MS_RDONLY)) { lock_kernel(); - retval = do_remount_sb(sb, MS_RDONLY, 0); + retval = do_remount_sb(sb, MS_RDONLY, 0, 0); unlock_kernel(); } up_write(&sb->s_umount); @@ -555,7 +554,7 @@ return -EINVAL; down_write(&sb->s_umount); - err = do_remount_sb(sb, flags, data); + err = do_remount_sb(sb, flags, data, 0); if (!err) nd->mnt->mnt_flags=mnt_flags; up_write(&sb->s_umount); diff -Nru a/fs/nfs/inode.c b/fs/nfs/inode.c --- a/fs/nfs/inode.c Thu May 8 00:24:29 2003 +++ b/fs/nfs/inode.c Thu May 8 00:24:29 2003 @@ -682,7 +682,7 @@ * such as stat(2) */ inode->i_ino = hash; - /* We can't support UPDATE_ATIME(), since the server will reset it */ + /* We can't support update_atime(), since the server will reset it */ inode->i_flags |= S_NOATIME; inode->i_mode = fattr->mode; /* Why so? Because we want revalidate for devices/FIFOs, and diff -Nru a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c --- a/fs/nfsd/vfs.c Thu May 8 00:24:28 2003 +++ b/fs/nfsd/vfs.c Thu May 8 00:24:28 2003 @@ -1124,7 +1124,7 @@ if (!inode->i_op || !inode->i_op->readlink) goto out; - UPDATE_ATIME(inode); + update_atime(inode); /* N.B. Why does this call need a get_fs()?? * Remove the set_fs and watch the fireworks:-) --okir */ diff -Nru a/fs/ntfs/inode.c b/fs/ntfs/inode.c --- a/fs/ntfs/inode.c Thu May 8 00:24:30 2003 +++ b/fs/ntfs/inode.c Thu May 8 00:24:30 2003 @@ -1736,7 +1736,7 @@ * @vi: inode to mark dirty * * This is called from fs/inode.c::__mark_inode_dirty(), when the inode itself - * is being marked dirty. An example is when UPDATE_ATIME() is invoked. + * is being marked dirty. An example is when update_atime() is invoked. * * We mark the inode dirty by setting both the page in which the mft record * resides and the buffer heads in that page which correspond to the mft record diff -Nru a/fs/partitions/check.c b/fs/partitions/check.c --- a/fs/partitions/check.c Thu May 8 00:24:30 2003 +++ b/fs/partitions/check.c Thu May 8 00:24:30 2003 @@ -96,19 +96,6 @@ char *disk_name(struct gendisk *hd, int part, char *buf) { -#ifdef CONFIG_DEVFS_FS - if (hd->devfs_name[0] != '\0') { - if (part) - snprintf(buf, BDEVNAME_SIZE, "%s/part%d", - hd->devfs_name, part); - else if (hd->minors != 1) - snprintf(buf, BDEVNAME_SIZE, "%s/disc", hd->devfs_name); - else - snprintf(buf, BDEVNAME_SIZE, "%s", hd->devfs_name); - return buf; - } -#endif - if (!part) snprintf(buf, BDEVNAME_SIZE, "%s", hd->disk_name); else if (isdigit(hd->disk_name[strlen(hd->disk_name)-1])) @@ -443,53 +430,3 @@ } kobject_del(&disk->kobj); } - -struct dev_name { - struct list_head list; - dev_t dev; - char namebuf[BDEVNAME_SIZE]; - char *name; -}; - -static LIST_HEAD(device_names); - -char *partition_name(dev_t dev) -{ - struct gendisk *hd; - static char nomem [] = ""; - char b[BDEVNAME_SIZE]; - struct dev_name *dname; - struct list_head *tmp; - int part; - - list_for_each(tmp, &device_names) { - dname = list_entry(tmp, struct dev_name, list); - if (dname->dev == dev) - return dname->name; - } - - dname = kmalloc(sizeof(*dname), GFP_KERNEL); - - if (!dname) - return nomem; - /* - * ok, add this new device name to the list - */ - hd = get_gendisk(dev, &part); - dname->name = NULL; - if (hd) { - dname->name = disk_name(hd, part, dname->namebuf); - module_put(hd->fops->owner); - put_disk(hd); - } - if (!dname->name) { - sprintf(dname->namebuf, "[dev %s]", __bdevname(dev, b)); - dname->name = dname->namebuf; - } - - dname->dev = dev; - list_add(&dname->list, &device_names); - - return dname->name; -} - diff -Nru a/fs/pipe.c b/fs/pipe.c --- a/fs/pipe.c Thu May 8 00:24:29 2003 +++ b/fs/pipe.c Thu May 8 00:24:29 2003 @@ -121,7 +121,7 @@ kill_fasync(PIPE_FASYNC_WRITERS(*inode), SIGIO, POLL_OUT); } if (ret > 0) - UPDATE_ATIME(inode); + update_atime(inode); return ret; } diff -Nru a/fs/qnx4/dir.c b/fs/qnx4/dir.c --- a/fs/qnx4/dir.c Thu May 8 00:24:29 2003 +++ b/fs/qnx4/dir.c Thu May 8 00:24:29 2003 @@ -76,7 +76,7 @@ } brelse(bh); } - UPDATE_ATIME(inode); + update_atime(inode); out: unlock_kernel(); diff -Nru a/fs/read_write.c b/fs/read_write.c --- a/fs/read_write.c Thu May 8 00:24:29 2003 +++ b/fs/read_write.c Thu May 8 00:24:29 2003 @@ -115,9 +115,10 @@ { off_t retval; struct file * file; + int fput_needed; retval = -EBADF; - file = fget(fd); + file = fget_light(fd, &fput_needed); if (!file) goto bad; @@ -128,7 +129,7 @@ if (res != (loff_t)retval) retval = -EOVERFLOW; /* LFS: should only happen on 32 bit platforms */ } - fput(file); + fput_light(file, fput_needed); bad: return retval; } @@ -141,9 +142,10 @@ int retval; struct file * file; loff_t offset; + int fput_needed; retval = -EBADF; - file = fget(fd); + file = fget_light(fd, &fput_needed); if (!file) goto bad; @@ -161,7 +163,7 @@ retval = 0; } out_putf: - fput(file); + fput_light(file, fput_needed); bad: return retval; } @@ -251,11 +253,12 @@ { struct file *file; ssize_t ret = -EBADF; + int fput_needed; - file = fget(fd); + file = fget_light(fd, &fput_needed); if (file) { ret = vfs_read(file, buf, count, &file->f_pos); - fput(file); + fput_light(file, fput_needed); } return ret; @@ -265,11 +268,12 @@ { struct file *file; ssize_t ret = -EBADF; + int fput_needed; - file = fget(fd); + file = fget_light(fd, &fput_needed); if (file) { ret = vfs_write(file, buf, count, &file->f_pos); - fput(file); + fput_light(file, fput_needed); } return ret; @@ -280,14 +284,15 @@ { struct file *file; ssize_t ret = -EBADF; + int fput_needed; if (pos < 0) return -EINVAL; - file = fget(fd); + file = fget_light(fd, &fput_needed); if (file) { ret = vfs_read(file, buf, count, &pos); - fput(file); + fput_light(file, fput_needed); } return ret; @@ -298,14 +303,15 @@ { struct file *file; ssize_t ret = -EBADF; + int fput_needed; if (pos < 0) return -EINVAL; - file = fget(fd); + file = fget_light(fd, &fput_needed); if (file) { ret = vfs_write(file, buf, count, &pos); - fput(file); + fput_light(file, fput_needed); } return ret; @@ -479,11 +485,12 @@ { struct file *file; ssize_t ret = -EBADF; + int fput_needed; - file = fget(fd); + file = fget_light(fd, &fput_needed); if (file) { ret = vfs_readv(file, vec, vlen, &file->f_pos); - fput(file); + fput_light(file, fput_needed); } return ret; @@ -494,11 +501,12 @@ { struct file *file; ssize_t ret = -EBADF; + int fput_needed; - file = fget(fd); + file = fget_light(fd, &fput_needed); if (file) { ret = vfs_writev(file, vec, vlen, &file->f_pos); - fput(file); + fput_light(file, fput_needed); } return ret; @@ -511,12 +519,13 @@ struct inode * in_inode, * out_inode; loff_t pos; ssize_t retval; + int fput_needed_in, fput_needed_out; /* * Get input file, and verify that it is ok.. */ retval = -EBADF; - in_file = fget(in_fd); + in_file = fget_light(in_fd, &fput_needed_in); if (!in_file) goto out; if (!(in_file->f_mode & FMODE_READ)) @@ -539,7 +548,7 @@ * Get output file, and verify that it is ok.. */ retval = -EBADF; - out_file = fget(out_fd); + out_file = fget_light(out_fd, &fput_needed_out); if (!out_file) goto fput_in; if (!(out_file->f_mode & FMODE_WRITE)) @@ -579,9 +588,9 @@ retval = -EOVERFLOW; fput_out: - fput(out_file); + fput_light(out_file, fput_needed_out); fput_in: - fput(in_file); + fput_light(in_file, fput_needed_in); out: return retval; } diff -Nru a/fs/reiserfs/dir.c b/fs/reiserfs/dir.c --- a/fs/reiserfs/dir.c Thu May 8 00:24:29 2003 +++ b/fs/reiserfs/dir.c Thu May 8 00:24:29 2003 @@ -185,7 +185,7 @@ filp->f_pos = next_pos; pathrelse (&path_to_entry); reiserfs_check_path(&path_to_entry) ; - UPDATE_ATIME(inode) ; + update_atime(inode) ; out: reiserfs_write_unlock(inode->i_sb); return ret; diff -Nru a/fs/select.c b/fs/select.c --- a/fs/select.c Thu May 8 00:24:27 2003 +++ b/fs/select.c Thu May 8 00:24:27 2003 @@ -176,7 +176,7 @@ { struct poll_wqueues table; poll_table *wait; - int retval, i, off; + int retval, i; long __timeout = *timeout; spin_lock(¤t->files->file_lock); @@ -193,38 +193,58 @@ wait = NULL; retval = 0; for (;;) { + unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp; + set_current_state(TASK_INTERRUPTIBLE); - for (i = 0 ; i < n; i++) { - unsigned long bit = BIT(i); - unsigned long mask; - struct file *file; - off = i / __NFDBITS; - if (!(bit & BITS(fds, off))) + inp = fds->in; outp = fds->out; exp = fds->ex; + rinp = fds->res_in; routp = fds->res_out; rexp = fds->res_ex; + + for (i = 0; i < n; ++rinp, ++routp, ++rexp) { + unsigned long in, out, ex, all_bits, bit = 1, mask, j; + unsigned long res_in = 0, res_out = 0, res_ex = 0; + struct file_operations *f_op = NULL; + struct file *file = NULL; + + in = *inp++; out = *outp++; ex = *exp++; + all_bits = in | out | ex; + if (all_bits == 0) { + i += __NFDBITS; continue; - file = fget(i); - mask = POLLNVAL; - if (file) { - mask = DEFAULT_POLLMASK; - if (file->f_op && file->f_op->poll) - mask = file->f_op->poll(file, wait); - fput(file); } - if ((mask & POLLIN_SET) && ISSET(bit, __IN(fds,off))) { - SET(bit, __RES_IN(fds,off)); - retval++; - wait = NULL; - } - if ((mask & POLLOUT_SET) && ISSET(bit, __OUT(fds,off))) { - SET(bit, __RES_OUT(fds,off)); - retval++; - wait = NULL; - } - if ((mask & POLLEX_SET) && ISSET(bit, __EX(fds,off))) { - SET(bit, __RES_EX(fds,off)); - retval++; - wait = NULL; + + for (j = 0; j < __NFDBITS; ++j, ++i, bit <<= 1) { + if (i >= n) + break; + if (!(bit & all_bits)) + continue; + file = fget(i); + if (file) { + f_op = file->f_op; + mask = DEFAULT_POLLMASK; + if (f_op && f_op->poll) + mask = (*f_op->poll)(file, retval ? NULL : wait); + fput(file); + if ((mask & POLLIN_SET) && (in & bit)) { + res_in |= bit; + retval++; + } + if ((mask & POLLOUT_SET) && (out & bit)) { + res_out |= bit; + retval++; + } + if ((mask & POLLEX_SET) && (ex & bit)) { + res_ex |= bit; + retval++; + } + } } + if (res_in) + *rinp = res_in; + if (res_out) + *routp = res_out; + if (res_ex) + *rexp = res_ex; } wait = NULL; if (retval || !__timeout || signal_pending(current)) diff -Nru a/fs/seq_file.c b/fs/seq_file.c --- a/fs/seq_file.c Thu May 8 00:24:29 2003 +++ b/fs/seq_file.c Thu May 8 00:24:29 2003 @@ -338,3 +338,13 @@ kfree(op); return res; } + +int seq_release_private(struct inode *inode, struct file *file) +{ + struct seq_file *seq = file->private_data; + + kfree(seq->private); + seq->private = NULL; + return seq_release(inode, file); +} + diff -Nru a/fs/stat.c b/fs/stat.c --- a/fs/stat.c Thu May 8 00:24:28 2003 +++ b/fs/stat.c Thu May 8 00:24:28 2003 @@ -244,7 +244,7 @@ if (inode->i_op && inode->i_op->readlink) { error = security_inode_readlink(nd.dentry); if (!error) { - UPDATE_ATIME(inode); + update_atime(inode); error = inode->i_op->readlink(nd.dentry, buf, bufsiz); } } diff -Nru a/fs/super.c b/fs/super.c --- a/fs/super.c Thu May 8 00:24:28 2003 +++ b/fs/super.c Thu May 8 00:24:28 2003 @@ -31,6 +31,7 @@ #include #include #include +#include /* for the emergency remount stuff */ #include @@ -431,6 +432,18 @@ return err; } +static void mark_files_ro(struct super_block *sb) +{ + struct file *f; + + file_list_lock(); + list_for_each_entry(f, &sb->s_files, f_list) { + if (S_ISREG(f->f_dentry->d_inode->i_mode) && file_count(f)) + f->f_mode &= ~FMODE_WRITE; + } + file_list_unlock(); +} + /** * do_remount_sb - asks filesystem to change mount options. * @sb: superblock in question @@ -439,21 +452,25 @@ * * Alters the mount options of a mounted file system. */ -int do_remount_sb(struct super_block *sb, int flags, void *data) +int do_remount_sb(struct super_block *sb, int flags, void *data, int force) { int retval; if (!(flags & MS_RDONLY) && bdev_read_only(sb->s_bdev)) return -EACCES; - /*flags |= MS_RDONLY;*/ if (flags & MS_RDONLY) acct_auto_close(sb); shrink_dcache_sb(sb); fsync_super(sb); + /* If we are remounting RDONLY, make sure there are no rw files open */ - if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY)) - if (!fs_may_remount_ro(sb)) + if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY)) { + if (force) + mark_files_ro(sb); + else if (!fs_may_remount_ro(sb)) return -EBUSY; + } + if (sb->s_op->remount_fs) { lock_super(sb); retval = sb->s_op->remount_fs(sb, &flags, data); @@ -465,6 +482,28 @@ return 0; } +static void do_emergency_remount(unsigned long foo) +{ + struct super_block *sb; + + spin_lock(&sb_lock); + list_for_each_entry(sb, &super_blocks, s_list) { + sb->s_count++; + spin_unlock(&sb_lock); + down_read(&sb->s_umount); + if (sb->s_root && sb->s_bdev && !(sb->s_flags & MS_RDONLY)) + do_remount_sb(sb, MS_RDONLY, NULL, 1); + drop_super(sb); + spin_lock(&sb_lock); + } + spin_unlock(&sb_lock); +} + +void emergency_remount(void) +{ + pdflush_operation(do_emergency_remount, 0); +} + /* * Unnamed block devices are dummy devices used by virtual * filesystems which don't use real block-devices. -- jrs @@ -618,7 +657,7 @@ } s->s_flags |= MS_ACTIVE; } - do_remount_sb(s, flags, data); + do_remount_sb(s, flags, data, 0); return s; } diff -Nru a/fs/sysv/dir.c b/fs/sysv/dir.c --- a/fs/sysv/dir.c Thu May 8 00:24:28 2003 +++ b/fs/sysv/dir.c Thu May 8 00:24:28 2003 @@ -116,7 +116,7 @@ done: filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset; - UPDATE_ATIME(inode); + update_atime(inode); unlock_kernel(); return 0; } diff -Nru a/fs/udf/dir.c b/fs/udf/dir.c --- a/fs/udf/dir.c Thu May 8 00:24:28 2003 +++ b/fs/udf/dir.c Thu May 8 00:24:28 2003 @@ -98,7 +98,7 @@ } result = do_udf_readdir(dir, filp, filldir, dirent); - UPDATE_ATIME(dir); + update_atime(dir); unlock_kernel(); return result; } diff -Nru a/fs/ufs/dir.c b/fs/ufs/dir.c --- a/fs/ufs/dir.c Thu May 8 00:24:29 2003 +++ b/fs/ufs/dir.c Thu May 8 00:24:29 2003 @@ -166,7 +166,7 @@ offset = 0; brelse (bh); } - UPDATE_ATIME(inode); + update_atime(inode); unlock_kernel(); return 0; } diff -Nru a/fs/xattr.c b/fs/xattr.c --- a/fs/xattr.c Thu May 8 00:24:28 2003 +++ b/fs/xattr.c Thu May 8 00:24:28 2003 @@ -79,15 +79,16 @@ error = -EOPNOTSUPP; if (d->d_inode->i_op && d->d_inode->i_op->setxattr) { + down(&d->d_inode->i_sem); error = security_inode_setxattr(d, kname, kvalue, size, flags); if (error) goto out; - down(&d->d_inode->i_sem); error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags); + if (!error) + security_inode_post_setxattr(d, kname, kvalue, size, flags); +out: up(&d->d_inode->i_sem); } - -out: xattr_free(kvalue, size); return error; } diff -Nru a/include/asm-i386/apicdef.h b/include/asm-i386/apicdef.h --- a/include/asm-i386/apicdef.h Thu May 8 00:24:29 2003 +++ b/include/asm-i386/apicdef.h Thu May 8 00:24:29 2003 @@ -11,13 +11,6 @@ #define APIC_DEFAULT_PHYS_BASE 0xfee00000 #define APIC_ID 0x20 -#ifdef CONFIG_X86_SUMMIT - #define APIC_ID_MASK (0xFF<<24) - #define GET_APIC_ID(x) (((x)>>24)&0xFF) -#else - #define APIC_ID_MASK (0x0F<<24) - #define GET_APIC_ID(x) (((x)>>24)&0x0F) -#endif #define APIC_LVR 0x30 #define APIC_LVR_MASK 0xFF00FF #define GET_APIC_VERSION(x) ((x)&0xFF) diff -Nru a/include/asm-i386/edd.h b/include/asm-i386/edd.h --- a/include/asm-i386/edd.h Thu May 8 00:24:27 2003 +++ b/include/asm-i386/edd.h Thu May 8 00:24:27 2003 @@ -141,7 +141,7 @@ u32 array_number; u32 reserved1; u64 reserved2; - } __attribute((packed)) raid; + } __attribute__ ((packed)) raid; struct { u8 device; u8 reserved1; diff -Nru a/include/asm-i386/fixmap.h b/include/asm-i386/fixmap.h --- a/include/asm-i386/fixmap.h Thu May 8 00:24:27 2003 +++ b/include/asm-i386/fixmap.h Thu May 8 00:24:27 2003 @@ -60,7 +60,7 @@ #ifdef CONFIG_X86_F00F_BUG FIX_F00F_IDT, /* Virtual mapping for IDT */ #endif -#ifdef CONFIG_X86_SUMMIT +#ifdef CONFIG_X86_CYCLONE_TIMER FIX_CYCLONE_TIMER, /*cyclone timer register*/ #endif #ifdef CONFIG_HIGHMEM diff -Nru a/include/asm-i386/genapic.h b/include/asm-i386/genapic.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-i386/genapic.h Thu May 8 00:24:30 2003 @@ -0,0 +1,106 @@ +#ifndef _ASM_GENAPIC_H +#define _ASM_GENAPIC_H 1 + +/* + * Generic APIC driver interface. + * + * An straight forward mapping of the APIC related parts of the + * x86 subarchitecture interface to a dynamic object. + * + * This is used by the "generic" x86 subarchitecture. + * + * Copyright 2003 Andi Kleen, SuSE Labs. + */ + +struct mpc_config_translation; +struct mpc_config_bus; +struct mp_config_table; +struct mpc_config_processor; + +struct genapic { + char *name; + int (*probe)(void); + + int (*apic_id_registered)(void); + unsigned long (*target_cpus)(void); + int int_delivery_mode; + int int_dest_mode; + int apic_broadcast_id; + int esr_disable; + unsigned long (*check_apicid_used)(unsigned long bitmap, int apicid); + unsigned long (*check_apicid_present)(int apicid); + int no_balance_irq; + void (*init_apic_ldr)(void); + unsigned long (*ioapic_phys_id_map)(unsigned long map); + + void (*clustered_apic_check)(void); + int (*multi_timer_check)(int apic, int irq); + int (*apicid_to_node)(int logical_apicid); + int (*cpu_to_logical_apicid)(int cpu); + int (*cpu_present_to_apicid)(int mps_cpu); + unsigned long (*apicid_to_cpu_present)(int phys_apicid); + int (*mpc_apic_id)(struct mpc_config_processor *m, + struct mpc_config_translation *t); + void (*setup_portio_remap)(void); + int (*check_phys_apicid_present)(int boot_cpu_physical_apicid); + + /* mpparse */ + void (*mpc_oem_bus_info)(struct mpc_config_bus *, char *, + struct mpc_config_translation *); + void (*mpc_oem_pci_bus)(struct mpc_config_bus *, + struct mpc_config_translation *); + + /* When one of the next two hooks returns 1 the genapic + is switched to this. Essentially they are additional probe + functions. */ + int (*mps_oem_check)(struct mp_config_table *mpc, char *oem, + char *productid); + int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id); + + unsigned (*get_apic_id)(unsigned long x); + unsigned long apic_id_mask; + + /* ipi */ + void (*send_IPI_mask)(int mask, int vector); + void (*send_IPI_allbutself)(int vector); + void (*send_IPI_all)(int vector); +}; + +#define APICFUNC(x) .x = x + +#define APIC_INIT(aname, aprobe) { \ + .name = aname, \ + .probe = aprobe, \ + .int_delivery_mode = INT_DELIVERY_MODE, \ + .int_dest_mode = INT_DEST_MODE, \ + .apic_broadcast_id = APIC_BROADCAST_ID, \ + .no_balance_irq = NO_BALANCE_IRQ, \ + APICFUNC(apic_id_registered), \ + APICFUNC(target_cpus), \ + APICFUNC(check_apicid_used), \ + APICFUNC(check_apicid_present), \ + APICFUNC(init_apic_ldr), \ + APICFUNC(ioapic_phys_id_map), \ + APICFUNC(clustered_apic_check), \ + APICFUNC(multi_timer_check), \ + APICFUNC(apicid_to_node), \ + APICFUNC(cpu_to_logical_apicid), \ + APICFUNC(cpu_present_to_apicid), \ + APICFUNC(apicid_to_cpu_present), \ + APICFUNC(mpc_apic_id), \ + APICFUNC(setup_portio_remap), \ + APICFUNC(check_phys_apicid_present), \ + APICFUNC(mpc_oem_bus_info), \ + APICFUNC(mpc_oem_pci_bus), \ + APICFUNC(mps_oem_check), \ + APICFUNC(get_apic_id), \ + .apic_id_mask = APIC_ID_MASK, \ + APICFUNC(acpi_madt_oem_check), \ + APICFUNC(send_IPI_mask), \ + APICFUNC(send_IPI_allbutself), \ + APICFUNC(send_IPI_all), \ + } + +extern struct genapic *genapic; + +#endif diff -Nru a/include/asm-i386/kmap_types.h b/include/asm-i386/kmap_types.h --- a/include/asm-i386/kmap_types.h Thu May 8 00:24:29 2003 +++ b/include/asm-i386/kmap_types.h Thu May 8 00:24:29 2003 @@ -3,7 +3,7 @@ #include -#if CONFIG_DEBUG_HIGHMEM +#ifdef CONFIG_DEBUG_HIGHMEM # define D(n) __KM_FENCE_##n , #else # define D(n) 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 Thu May 8 00:24:30 2003 +++ b/include/asm-i386/mach-bigsmp/mach_apic.h Thu May 8 00:24:30 2003 @@ -15,18 +15,28 @@ static inline int apic_id_registered(void) { - return (1); + return (1); } #define APIC_DFR_VALUE (APIC_DFR_CLUSTER) -#define TARGET_CPUS ((cpu_online_map < 0xf)?cpu_online_map:0xf) +static inline unsigned long target_cpus(void) +{ + return ((cpu_online_map < 0xf)?cpu_online_map:0xf); +} +#define TARGET_CPUS (target_cpus()) #define INT_DELIVERY_MODE dest_LowestPrio #define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */ #define APIC_BROADCAST_ID (0x0f) -#define check_apicid_used(bitmap, apicid) (0) -#define check_apicid_present(bit) (phys_cpu_present_map & (1 << bit)) +static inline unsigned long check_apicid_used(unsigned long bitmap, int apicid) +{ + return 0; +} +static inline unsigned long check_apicid_present(int bit) +{ + return (phys_cpu_present_map & (1 << bit)); +} static inline unsigned long calculate_ldr(unsigned long old) { @@ -114,5 +124,14 @@ { return (1); } + +#define APIC_ID_MASK (0x0F<<24) + +static inline unsigned get_apic_id(unsigned long x) +{ + return (((x)>>24)&0x0F); +} + +#define GET_APIC_ID(x) get_apic_id(x) #endif /* __ASM_MACH_APIC_H */ diff -Nru a/include/asm-i386/mach-bigsmp/mach_ipi.h b/include/asm-i386/mach-bigsmp/mach_ipi.h --- a/include/asm-i386/mach-bigsmp/mach_ipi.h Thu May 8 00:24:28 2003 +++ b/include/asm-i386/mach-bigsmp/mach_ipi.h Thu May 8 00:24:28 2003 @@ -1,7 +1,7 @@ #ifndef __ASM_MACH_IPI_H #define __ASM_MACH_IPI_H -static inline void send_IPI_mask_sequence(int mask, int vector); +inline void send_IPI_mask_sequence(int mask, int vector); static inline void send_IPI_mask(int mask, int vector) { 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 Thu May 8 00:24:30 2003 +++ b/include/asm-i386/mach-default/mach_apic.h Thu May 8 00:24:30 2003 @@ -3,11 +3,15 @@ #define APIC_DFR_VALUE (APIC_DFR_FLAT) +static inline unsigned long target_cpus(void) +{ #ifdef CONFIG_SMP - #define TARGET_CPUS (cpu_online_map) + return cpu_online_map; #else - #define TARGET_CPUS 0x01 + return 1; #endif +} +#define TARGET_CPUS (target_cpus()) #define NO_BALANCE_IRQ (0) #define esr_disable (0) @@ -16,13 +20,15 @@ #define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */ #define APIC_BROADCAST_ID 0x0F -#define check_apicid_used(bitmap, apicid) (bitmap & (1 << apicid)) -#define check_apicid_present(bit) (phys_cpu_present_map & (1 << bit)) -static inline int apic_id_registered(void) +static inline unsigned long check_apicid_used(unsigned long bitmap, int apicid) +{ + return (bitmap & (1UL << apicid)); +} + +static inline unsigned long check_apicid_present(int bit) { - return (test_bit(GET_APIC_ID(apic_read(APIC_ID)), - &phys_cpu_present_map)); + return (phys_cpu_present_map & (1UL << bit)); } /* @@ -42,7 +48,7 @@ apic_write_around(APIC_LDR, val); } -static inline ulong ioapic_phys_id_map(ulong phys_map) +static inline unsigned long ioapic_phys_id_map(unsigned long phys_map) { return phys_map; } @@ -97,6 +103,21 @@ static inline int check_phys_apicid_present(int boot_cpu_physical_apicid) { return test_bit(boot_cpu_physical_apicid, &phys_cpu_present_map); +} + +#define APIC_ID_MASK (0xF<<24) + +static inline unsigned get_apic_id(unsigned long x) +{ + return (((x)>>24)&0xF); +} + +#define GET_APIC_ID(x) get_apic_id(x) + +static inline int apic_id_registered(void) +{ + return (test_bit(GET_APIC_ID(apic_read(APIC_ID)), + &phys_cpu_present_map)); } #endif /* __ASM_MACH_APIC_H */ diff -Nru a/include/asm-i386/mach-default/mach_ipi.h b/include/asm-i386/mach-default/mach_ipi.h --- a/include/asm-i386/mach-default/mach_ipi.h Thu May 8 00:24:30 2003 +++ b/include/asm-i386/mach-default/mach_ipi.h Thu May 8 00:24:30 2003 @@ -1,8 +1,8 @@ #ifndef __ASM_MACH_IPI_H #define __ASM_MACH_IPI_H -static inline void send_IPI_mask_bitmask(int mask, int vector); -static inline void __send_IPI_shortcut(unsigned int shortcut, int vector); +inline void send_IPI_mask_bitmask(int mask, int vector); +inline void __send_IPI_shortcut(unsigned int shortcut, int vector); static inline void send_IPI_mask(int mask, int vector) { diff -Nru a/include/asm-i386/mach-default/mach_mpparse.h b/include/asm-i386/mach-default/mach_mpparse.h --- a/include/asm-i386/mach-default/mach_mpparse.h Thu May 8 00:24:30 2003 +++ b/include/asm-i386/mach-default/mach_mpparse.h Thu May 8 00:24:30 2003 @@ -12,14 +12,16 @@ { } -static inline void mps_oem_check(struct mp_config_table *mpc, char *oem, +static inline int mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid) { + return 0; } /* Hook from generic ACPI tables.c */ -static inline void acpi_madt_oem_check(char *oem_id, char *oem_table_id) +static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) { + return 0; } diff -Nru a/include/asm-i386/mach-generic/mach_apic.h b/include/asm-i386/mach-generic/mach_apic.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-i386/mach-generic/mach_apic.h Thu May 8 00:24:30 2003 @@ -0,0 +1,30 @@ +#ifndef __ASM_MACH_APIC_H +#define __ASM_MACH_APIC_H + +#include + +#define esr_disable (genapic->esr_disable) +#define NO_BALANCE_IRQ (genapic->no_balance_irq) +#define APIC_BROADCAST_ID (genapic->apic_broadcast_id) +#define INT_DELIVERY_MODE (genapic->int_delivery_mode) +#define INT_DEST_MODE (genapic->int_dest_mode) +#define TARGET_CPUS (genapic->target_cpus()) +#define apic_id_registered (genapic->apic_id_registered) +#define apic_id_registered (genapic->apic_id_registered) +#define init_apic_ldr (genapic->init_apic_ldr) +#define ioapic_phys_id_map (genapic->ioapic_phys_id_map) +#define clustered_apic_check (genapic->clustered_apic_check) +#define multi_timer_check (genapic->multi_timer_check) +#define apicid_to_node (genapic->apicid_to_node) +#define cpu_to_logical_apicid (genapic->cpu_to_logical_apicid) +#define cpu_present_to_apicid (genapic->cpu_present_to_apicid) +#define apicid_to_cpu_present (genapic->apicid_to_cpu_present) +#define mpc_apic_id (genapic->mpc_apic_id) +#define setup_portio_remap (genapic->setup_portio_remap) +#define check_apicid_present (genapic->check_apicid_present) +#define check_phys_apicid_present (genapic->check_phys_apicid_present) +#define check_apicid_used (genapic->check_apicid_used) +#define GET_APIC_ID (genapic->get_apic_id) +#define APIC_ID_MASK (genapic->apic_id_mask) + +#endif /* __ASM_MACH_APIC_H */ diff -Nru a/include/asm-i386/mach-generic/mach_ipi.h b/include/asm-i386/mach-generic/mach_ipi.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-i386/mach-generic/mach_ipi.h Thu May 8 00:24:30 2003 @@ -0,0 +1,10 @@ +#ifndef _MACH_IPI_H +#define _MACH_IPI_H 1 + +#include + +#define send_IPI_mask (genapic->send_IPI_mask) +#define send_IPI_allbutself (genapic->send_IPI_allbutself) +#define send_IPI_all (genapic->send_IPI_all) + +#endif diff -Nru a/include/asm-i386/mach-generic/mach_mpparse.h b/include/asm-i386/mach-generic/mach_mpparse.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-i386/mach-generic/mach_mpparse.h Thu May 8 00:24:30 2003 @@ -0,0 +1,12 @@ +#ifndef _MACH_MPPARSE_H +#define _MACH_MPPARSE_H 1 + +#include + +#define mpc_oem_bus_info (genapic->mpc_oem_bus_info) +#define mpc_oem_pci_bus (genapic->mpc_oem_pci_bus) + +int mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid); +int acpi_madt_oem_check(char *oem_id, char *oem_table_id); + +#endif diff -Nru a/include/asm-i386/mach-numaq/mach_apic.h b/include/asm-i386/mach-numaq/mach_apic.h --- a/include/asm-i386/mach-numaq/mach_apic.h Thu May 8 00:24:28 2003 +++ b/include/asm-i386/mach-numaq/mach_apic.h Thu May 8 00:24:28 2003 @@ -1,6 +1,9 @@ #ifndef __ASM_MACH_APIC_H #define __ASM_MACH_APIC_H +#include +#include + #define APIC_DFR_VALUE (APIC_DFR_CLUSTER) #define TARGET_CPUS (0xf) @@ -102,5 +105,14 @@ { return (1); } + +#define APIC_ID_MASK (0xF<<24) + +static inline unsigned get_apic_id(unsigned long x) +{ + return (((x)>>24)&0x0F); +} + +#define GET_APIC_ID(x) get_apic_id(x) #endif /* __ASM_MACH_APIC_H */ 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 Thu May 8 00:24:29 2003 +++ b/include/asm-i386/mach-summit/mach_apic.h Thu May 8 00:24:29 2003 @@ -1,7 +1,13 @@ #ifndef __ASM_MACH_APIC_H #define __ASM_MACH_APIC_H +#include + +#ifdef CONFIG_X86_GENERICARCH +#define x86_summit 1 /* must be an constant expressiona for generic arch */ +#else extern int x86_summit; +#endif #define esr_disable (x86_summit ? 1 : 0) #define NO_BALANCE_IRQ (0) @@ -9,20 +15,34 @@ #define XAPIC_DEST_CPUS_MASK 0x0Fu #define XAPIC_DEST_CLUSTER_MASK 0xF0u -#define xapic_phys_to_log_apicid(phys_apic) ( (1ul << ((phys_apic) & 0x3)) |\ - ((phys_apic) & XAPIC_DEST_CLUSTER_MASK) ) +static inline unsigned long xapic_phys_to_log_apicid(int phys_apic) +{ + return ( (1ul << ((phys_apic) & 0x3)) | + ((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) + +static inline unsigned long target_cpus(void) +{ + return (x86_summit ? XAPIC_DEST_CPUS_MASK : cpu_online_map); +} +#define TARGET_CPUS (target_cpus()) #define INT_DELIVERY_MODE (x86_summit ? dest_Fixed : dest_LowestPrio) #define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */ -#define APIC_BROADCAST_ID (x86_summit ? 0xFF : 0x0F) -#define check_apicid_used(bitmap, apicid) (x86_summit ? 0 : (bitmap & (1 << apicid))) +#define APIC_BROADCAST_ID (0x0F) +static inline unsigned long check_apicid_used(unsigned long bitmap, int apicid) +{ + return (x86_summit ? 0 : (bitmap & (1 << apicid))); +} /* we don't use the phys_cpu_present_map to indicate apicid presence */ -#define check_apicid_present(bit) (x86_summit ? 1 : (phys_cpu_present_map & (1 << bit))) +static inline unsigned long check_apicid_present(int bit) +{ + return (x86_summit ? 1 : (phys_cpu_present_map & (1 << bit))); +} extern u8 bios_cpu_apicid[]; @@ -112,5 +132,14 @@ else return test_bit(boot_cpu_physical_apicid, &phys_cpu_present_map); } + +#define APIC_ID_MASK (0xFF<<24) + +static inline unsigned get_apic_id(unsigned long x) +{ + return (((x)>>24)&0xFF); +} + +#define GET_APIC_ID(x) get_apic_id(x) #endif /* __ASM_MACH_APIC_H */ diff -Nru a/include/asm-i386/mach-summit/mach_ipi.h b/include/asm-i386/mach-summit/mach_ipi.h --- a/include/asm-i386/mach-summit/mach_ipi.h Thu May 8 00:24:28 2003 +++ b/include/asm-i386/mach-summit/mach_ipi.h Thu May 8 00:24:28 2003 @@ -1,7 +1,7 @@ #ifndef __ASM_MACH_IPI_H #define __ASM_MACH_IPI_H -static inline void send_IPI_mask_sequence(int mask, int vector); +inline void send_IPI_mask_sequence(int mask, int vector); static inline void send_IPI_mask(int mask, int vector) { diff -Nru a/include/asm-i386/mach-summit/mach_mpparse.h b/include/asm-i386/mach-summit/mach_mpparse.h --- a/include/asm-i386/mach-summit/mach_mpparse.h Thu May 8 00:24:28 2003 +++ b/include/asm-i386/mach-summit/mach_mpparse.h Thu May 8 00:24:28 2003 @@ -14,26 +14,34 @@ { } -static inline void mps_oem_check(struct mp_config_table *mpc, char *oem, +static inline int mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid) { if (!strncmp(oem, "IBM ENSW", 8) && (!strncmp(productid, "VIGIL SMP", 9) || !strncmp(productid, "EXA", 3) || !strncmp(productid, "RUTHLESS SMP", 12))){ +#ifndef CONFIG_X86_GENERICARCH x86_summit = 1; +#endif use_cyclone = 1; /*enable cyclone-timer*/ + return 1; } + return 0; } /* Hook from generic ACPI tables.c */ -static inline void acpi_madt_oem_check(char *oem_id, char *oem_table_id) +static inline int acpi_madt_oem_check(char *oem_id, char *oem_table_id) { if (!strncmp(oem_id, "IBM", 3) && (!strncmp(oem_table_id, "SERVIGIL", 8) || !strncmp(oem_table_id, "EXA", 3))){ +#ifndef CONFIG_X86_GENERICARCH x86_summit = 1; +#endif use_cyclone = 1; /*enable cyclone-timer*/ + return 1; } + return 0; } #endif /* __ASM_MACH_MPPARSE_H */ diff -Nru a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h --- a/include/asm-i386/mmzone.h Thu May 8 00:24:29 2003 +++ b/include/asm-i386/mmzone.h Thu May 8 00:24:29 2003 @@ -120,7 +120,7 @@ #ifdef CONFIG_X86_NUMAQ #include -#elif CONFIG_X86_SUMMIT +#elif CONFIG_NUMA /* summit or generic arch */ #include #elif CONFIG_X86_PC #define get_memcfg_numa get_memcfg_numa_flat diff -Nru a/include/asm-i386/mpspec.h b/include/asm-i386/mpspec.h --- a/include/asm-i386/mpspec.h Thu May 8 00:24:27 2003 +++ b/include/asm-i386/mpspec.h Thu May 8 00:24:27 2003 @@ -16,7 +16,7 @@ /* * a maximum of 16 APICs with the current APIC ID architecture. */ -#if defined(CONFIG_X86_NUMAQ) || defined (CONFIG_X86_SUMMIT) +#if defined(CONFIG_X86_NUMAQ) || defined (CONFIG_X86_SUMMIT) || defined(CONFIG_X86_GENERICARCH) #define MAX_APICS 256 #else #define MAX_APICS 16 diff -Nru a/include/asm-i386/numnodes.h b/include/asm-i386/numnodes.h --- a/include/asm-i386/numnodes.h Thu May 8 00:24:28 2003 +++ b/include/asm-i386/numnodes.h Thu May 8 00:24:28 2003 @@ -5,7 +5,7 @@ #ifdef CONFIG_X86_NUMAQ #include -#elif CONFIG_X86_SUMMIT +#elif CONFIG_NUMA #include #else #define MAX_NUMNODES 1 diff -Nru a/include/asm-i386/processor.h b/include/asm-i386/processor.h --- a/include/asm-i386/processor.h Thu May 8 00:24:27 2003 +++ b/include/asm-i386/processor.h Thu May 8 00:24:27 2003 @@ -536,7 +536,7 @@ #define ASM_NOP6 K8_NOP6 #define ASM_NOP7 K8_NOP7 #define ASM_NOP8 K8_NOP8 -#elif CONFIG_MK7 +#elif defined(CONFIG_MK7) #define ASM_NOP1 K7_NOP1 #define ASM_NOP2 K7_NOP2 #define ASM_NOP3 K7_NOP3 diff -Nru a/include/asm-i386/smp.h b/include/asm-i386/smp.h --- a/include/asm-i386/smp.h Thu May 8 00:24:29 2003 +++ b/include/asm-i386/smp.h Thu May 8 00:24:29 2003 @@ -87,11 +87,17 @@ return -1; } #ifdef CONFIG_X86_LOCAL_APIC -static __inline int hard_smp_processor_id(void) + +#ifdef APIC_DEFINITION +extern int hard_smp_processor_id(void); +#else +#include +static inline int hard_smp_processor_id(void) { /* we don't want to mark this access volatile - bad code generation */ return GET_APIC_ID(*(unsigned long *)(APIC_BASE+APIC_ID)); } +#endif static __inline int logical_smp_processor_id(void) { diff -Nru a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h --- a/include/asm-i386/uaccess.h Thu May 8 00:24:27 2003 +++ b/include/asm-i386/uaccess.h Thu May 8 00:24:28 2003 @@ -62,8 +62,6 @@ :"1" (addr),"g" ((int)(size)),"g" (current_thread_info()->addr_limit.seg)); \ flag; }) -#ifdef CONFIG_X86_WP_WORKS_OK - /** * access_ok: - Checks if a user space pointer is valid * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE. Note that @@ -85,14 +83,6 @@ */ #define access_ok(type,addr,size) (__range_ok(addr,size) == 0) -#else - -#define access_ok(type,addr,size) ( (__range_ok(addr,size) == 0) && \ - ((type) == VERIFY_READ || boot_cpu_data.wp_works_ok || \ - __verify_write((void *)(addr),(size)))) - -#endif - /** * verify_area: - Obsolete, use access_ok() * @type: Type of access: %VERIFY_READ or %VERIFY_WRITE @@ -191,14 +181,8 @@ __ret_gu; \ }) -extern void __put_user_1(void); -extern void __put_user_2(void); -extern void __put_user_4(void); -extern void __put_user_8(void); - extern void __put_user_bad(void); - /** * put_user: - Write a simple value into user space. * @x: Value to copy to user space. @@ -299,6 +283,8 @@ : "=r"(err) \ : "A" (x), "r" (addr), "i"(-EFAULT), "0"(err)) +#ifdef CONFIG_X86_WP_WORKS_OK + #define __put_user_size(x,ptr,size,retval,errret) \ do { \ retval = 0; \ @@ -311,6 +297,18 @@ } \ } while (0) +#else + +#define __put_user_size(x,ptr,size,retval,errret) \ +do { \ + __typeof__(*(ptr)) __pus_tmp = x; \ + retval = 0; \ + \ + if(unlikely(__copy_to_user_ll(ptr, &__pus_tmp, size) != 0)) \ + retval = errret; \ +} while (0) + +#endif struct __large_struct { unsigned long buf[100]; }; #define __m(x) (*(struct __large_struct *)(x)) diff -Nru a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h --- a/include/asm-i386/unistd.h Thu May 8 00:24:29 2003 +++ b/include/asm-i386/unistd.h Thu May 8 00:24:29 2003 @@ -399,6 +399,8 @@ * What we want is __attribute__((weak,alias("sys_ni_syscall"))), * but it doesn't work on all toolchains, so we just do it by hand */ +#ifndef cond_syscall #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall"); +#endif #endif /* _ASM_I386_UNISTD_H_ */ diff -Nru a/include/asm-ppc64/io.h b/include/asm-ppc64/io.h --- a/include/asm-ppc64/io.h Thu May 8 00:24:30 2003 +++ b/include/asm-ppc64/io.h Thu May 8 00:24:30 2003 @@ -107,7 +107,6 @@ #define IO_SPACE_LIMIT ~(0UL) -#define MEM_SPACE_LIMIT ~(0UL) #ifdef __KERNEL__ diff -Nru a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h --- a/include/asm-ppc64/mmu.h Thu May 8 00:24:29 2003 +++ b/include/asm-ppc64/mmu.h Thu May 8 00:24:29 2003 @@ -221,6 +221,13 @@ #endif /* __ASSEMBLY__ */ +/* + * Location of cpu0's segment table + */ +#define STAB0_PAGE 0x9 +#define STAB0_PHYS_ADDR (STAB0_PAGE< +#include + +#ifndef __ASSEMBLY__ struct naca_struct { - void *xItVpdAreas; - void *xRamDisk; - u64 xRamDiskSize; /* In pages */ - struct paca_struct *paca; /* Ptr to an array of pacas */ - u64 debug_switch; /* Bits to control debug printing */ - u16 dCacheL1LineSize; /* Line size of L1 DCache in bytes */ - u16 dCacheL1LogLineSize; /* Log-2 of DCache line size */ - u16 dCacheL1LinesPerPage; /* DCache lines per page */ - u16 iCacheL1LineSize; /* Line size of L1 ICache in bytes */ - u16 iCacheL1LogLineSize; /* Log-2 of ICache line size */ - u16 iCacheL1LinesPerPage; /* ICache lines per page */ - u16 slb_size; /* SLB size in entries */ - u64 physicalMemorySize; /* Size of real memory in bytes */ - u64 pftSize; /* Log base 2 of page table size */ - u64 serialPortAddr; /* Phyical address of serial port */ - u8 interrupt_controller; /* Type of interrupt controller */ - u8 resv0; /* Type of interrupt controller */ - u16 platform; /* Platform flags */ - u8 resv1[12]; /* Padding */ + /*================================================================== + * Cache line 1: 0x0000 - 0x007F + * Kernel only data - undefined for user space + *================================================================== + */ + void *xItVpdAreas; /* VPD Data 0x00 */ + void *xRamDisk; /* iSeries ramdisk 0x08 */ + u64 xRamDiskSize; /* In pages 0x10 */ + struct paca_struct *paca; /* Ptr to an array of pacas 0x18 */ + u64 debug_switch; /* Debug print control 0x20 */ + u64 banner; /* Ptr to banner string 0x28 */ + u64 log; /* Ptr to log buffer 0x30 */ + u64 serialPortAddr; /* Phy addr of serial port 0x38 */ + u64 interrupt_controller; /* Type of int controller 0x40 */ + u64 slb_size; /* SLB size in entries 0x48 */ + u64 pftSize; /* Log 2 of page table size 0x50 */ + void *systemcfg; /* Pointer to systemcfg data 0x58 */ + u32 dCacheL1LogLineSize; /* L1 d-cache line size Log2 0x60 */ + u32 dCacheL1LinesPerPage; /* L1 d-cache lines / page 0x64 */ + u32 iCacheL1LogLineSize; /* L1 i-cache line size Log2 0x68 */ + u32 iCacheL1LinesPerPage; /* L1 i-cache lines / page 0x6c */ + u64 resv0[2]; /* Reserved 0x70 - 0x7F */ }; extern struct naca_struct *naca; + +#endif /* __ASSEMBLY__ */ + +#define NACA_PAGE 0x4 +#define NACA_PHYS_ADDR (NACA_PAGE<> SID_SHIFT) & SID_MASK) +/* align addr on a size boundary - adjust address up/down if needed */ +#define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1))) +#define _ALIGN_DOWN(addr,size) ((addr)&(~((size)-1))) + +/* align addr on a size boundary - adjust address up if needed */ +#define _ALIGN(addr,size) _ALIGN_UP(addr,size) + +/* to align the pointer to the (next) double word boundary */ +#define DOUBLEWORD_ALIGN(addr) _ALIGN(addr,sizeof(unsigned long)) + +/* to align the pointer to the (next) page boundary */ +#define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE) + #ifdef __KERNEL__ #ifndef __ASSEMBLY__ #include @@ -37,7 +54,7 @@ { unsigned long lines, line_size; - line_size = naca->dCacheL1LineSize; + line_size = systemcfg->dCacheL1LineSize; lines = naca->dCacheL1LinesPerPage; __asm__ __volatile__( @@ -113,19 +130,6 @@ #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) #endif /* __ASSEMBLY__ */ - -/* align addr on a size boundary - adjust address up/down if needed */ -#define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1))) -#define _ALIGN_DOWN(addr,size) ((addr)&(~((size)-1))) - -/* align addr on a size boundary - adjust address up if needed */ -#define _ALIGN(addr,size) _ALIGN_UP(addr,size) - -/* to align the pointer to the (next) double word boundary */ -#define DOUBLEWORD_ALIGN(addr) _ALIGN(addr,sizeof(unsigned long)) - -/* to align the pointer to the (next) page boundary */ -#define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE) #ifdef MODULE #define __page_aligned __attribute__((__aligned__(PAGE_SIZE))) diff -Nru a/include/asm-ppc64/proc_fs.h b/include/asm-ppc64/proc_fs.h --- a/include/asm-ppc64/proc_fs.h Thu May 8 00:24:28 2003 +++ b/include/asm-ppc64/proc_fs.h Thu May 8 00:24:28 2003 @@ -25,9 +25,14 @@ #include -void pmc_proc_init(struct proc_dir_entry *iSeries_proc); -void proc_ppc64_init(void); +struct proc_ppc64_t { + struct proc_dir_entry *root; + struct proc_dir_entry *naca; + struct proc_dir_entry *paca; + struct proc_dir_entry *systemcfg; + struct proc_dir_entry *rtas; +}; -#include +extern struct proc_ppc64_t proc_ppc64; -#endif +#endif /* _PPC64_PROC_FS_H */ diff -Nru a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h --- a/include/asm-ppc64/processor.h Thu May 8 00:24:27 2003 +++ b/include/asm-ppc64/processor.h Thu May 8 00:24:27 2003 @@ -469,8 +469,6 @@ #define IOCR_SPC 0x00000001 -/* Processor Version Register */ - /* Processor Version Register (PVR) field extraction */ #define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */ @@ -595,6 +593,8 @@ asm volatile("mfasr %0" : "=r" (rval)); rval;}) #ifndef __ASSEMBLY__ +extern unsigned long *_get_SP(void); + extern int have_of; struct task_struct; @@ -654,8 +654,10 @@ struct pt_regs *regs; /* Pointer to saved register state */ mm_segment_t fs; /* for get_fs() validation */ double fpr[32]; /* Complete floating point set */ - unsigned long fpscr; /* Floating point status */ - unsigned int fpexc_mode; /* Floating-point exception mode */ + unsigned long fpscr; /* Floating point status (plus pad) */ + unsigned long fpexc_mode; /* Floating-point exception mode */ + unsigned long saved_msr; /* Save MSR across signal handlers */ + unsigned long saved_softe; /* Ditto for Soft Enable/Disable */ }; #define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack) @@ -702,7 +704,7 @@ return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8); } -static inline unsigned int __pack_fe01(unsigned int fpmode) +static inline unsigned long __pack_fe01(unsigned int fpmode) { return ((fpmode << 10) & MSR_FE0) | ((fpmode << 8) & MSR_FE1); } @@ -739,6 +741,15 @@ #define cpu_has_noexecute() (processor_type() == PV_POWER4 || \ processor_type() == PV_POWER4p) + +/* XXX we have to call HV to set when in LPAR */ +#define cpu_has_dabr() (1) + +#define cpu_has_iabr() (processor_type() != PV_POWER4 && \ + processor_type() != PV_POWER4p) + +#define cpu_alignexc_sets_dsisr() (processor_type() != PV_POWER4 && \ + processor_type() != PV_POWER4p) #endif /* ASSEMBLY */ diff -Nru a/include/asm-ppc64/ptrace.h b/include/asm-ppc64/ptrace.h --- a/include/asm-ppc64/ptrace.h Thu May 8 00:24:29 2003 +++ b/include/asm-ppc64/ptrace.h Thu May 8 00:24:29 2003 @@ -64,9 +64,8 @@ #define STACK_FRAME_OVERHEAD 112 /* size of minimum stack frame */ -/* Size of stack frame allocated when calling signal handler. */ -/* FIXME: What should this be on 64-bit kernel (64 for 32-bit) */ -#define __SIGNAL_FRAMESIZE 64 +/* Size of dummy stack frame allocated when calling signal handler. */ +#define __SIGNAL_FRAMESIZE 128 #define __SIGNAL_FRAMESIZE32 64 #define instruction_pointer(regs) ((regs)->nip) diff -Nru a/include/asm-ppc64/rtas.h b/include/asm-ppc64/rtas.h --- a/include/asm-ppc64/rtas.h Thu May 8 00:24:30 2003 +++ b/include/asm-ppc64/rtas.h Thu May 8 00:24:30 2003 @@ -166,8 +166,6 @@ extern void rtas_power_off(void); extern void rtas_halt(void); -extern struct proc_dir_entry *rtas_proc_dir; - /* Some RTAS ops require a data buffer and that buffer must be < 4G. * Rather than having a memory allocator, just use this buffer * (get the lock first), make the RTAS call. Copy the data instead diff -Nru a/include/asm-ppc64/sigcontext.h b/include/asm-ppc64/sigcontext.h --- a/include/asm-ppc64/sigcontext.h Thu May 8 00:24:28 2003 +++ b/include/asm-ppc64/sigcontext.h Thu May 8 00:24:28 2003 @@ -9,6 +9,8 @@ */ #include +#include + struct sigcontext { unsigned long _unused[4]; @@ -16,7 +18,9 @@ int _pad0; unsigned long handler; unsigned long oldmask; - struct pt_regs *regs; + struct pt_regs *regs; + elf_gregset_t gp_regs; + elf_fpregset_t fp_regs; }; #endif /* _ASM_PPC64_SIGCONTEXT_H */ diff -Nru a/include/asm-ppc64/systemcfg.h b/include/asm-ppc64/systemcfg.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-ppc64/systemcfg.h Thu May 8 00:24:30 2003 @@ -0,0 +1,109 @@ +#ifndef _SYSTEMCFG_H +#define _SYSTEMCFG_H + +/* + * Copyright (C) 2002 Peter Bergner , IBM + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +/* Change Activity: + * 2002/09/30 : bergner : Created + * End Change Activity + */ + + +#ifndef __KERNEL__ +#include +#include +#include +#include +#endif + +/* + * If the major version changes we are incompatible. + * Minor version changes are a hint. + */ +#define SYSTEMCFG_MAJOR 1 +#define SYSTEMCFG_MINOR 0 + +#ifndef __ASSEMBLY__ + +struct systemcfg { + __u8 eye_catcher[16]; /* Eyecatcher: SYSTEMCFG:PPC64 0x00 */ + struct { /* Systemcfg version numbers */ + __u32 major; /* Major number 0x10 */ + __u32 minor; /* Minor number 0x14 */ + } version; + + __u32 platform; /* Platform flags 0x18 */ + __u32 processor; /* Processor type 0x1C */ + __u64 processorCount; /* # of physical processors 0x20 */ + __u64 physicalMemorySize; /* Size of real memory(B) 0x28 */ + __u64 tb_orig_stamp; /* Timebase at boot 0x30 */ + __u64 tb_ticks_per_sec; /* Timebase tics / sec 0x38 */ + __u64 tb_to_xs; /* Inverse of TB to 2^20 0x40 */ + __u64 stamp_xsec; /* 0x48 */ + __u64 tb_update_count; /* Timebase atomicity ctr 0x50 */ + __u32 tz_minuteswest; /* Minutes west of Greenwich 0x58 */ + __u32 tz_dsttime; /* Type of dst correction 0x5C */ + __u32 dCacheL1Size; /* L1 d-cache size 0x60 */ + __u32 dCacheL1LineSize; /* L1 d-cache line size 0x64 */ + __u32 iCacheL1Size; /* L1 i-cache size 0x68 */ + __u32 iCacheL1LineSize; /* L1 i-cache line size 0x6C */ + __u8 reserved0[3984]; /* Reserve rest of page 0x70 */ +}; + +#ifdef __KERNEL__ +extern struct systemcfg *systemcfg; +#else + +/* Processor Version Register (PVR) field extraction */ +#define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */ +#define PVR_REV(pvr) (((pvr) >> 0) & 0xFFFF) /* Revison field */ + +/* Processor Version Numbers */ +#define PV_NORTHSTAR 0x0033 +#define PV_PULSAR 0x0034 +#define PV_POWER4 0x0035 +#define PV_ICESTAR 0x0036 +#define PV_SSTAR 0x0037 +#define PV_POWER4p 0x0038 +#define PV_630 0x0040 +#define PV_630p 0x0041 + +/* Platforms supported by PPC64 */ +#define PLATFORM_PSERIES 0x0100 +#define PLATFORM_PSERIES_LPAR 0x0101 +#define PLATFORM_ISERIES_LPAR 0x0201 + + +static inline volatile struct systemcfg *systemcfg_init(void) +{ + int fd = open("/proc/ppc64/systemcfg", O_RDONLY); + volatile struct systemcfg *ret; + + if (fd == -1) + return 0; + ret = mmap(0, sizeof(struct systemcfg), PROT_READ, MAP_SHARED, fd, 0); + close(fd); + if (!ret) + return 0; + if (ret->version.major != SYSTEMCFG_MAJOR || ret->version.minor < SYSTEMCFG_MINOR) { + munmap((void *)ret, sizeof(struct systemcfg)); + return 0; + } + return ret; +} +#endif /* __KERNEL__ */ + +#endif /* __ASSEMBLY__ */ + +#define SYSTEMCFG_PAGE 0x5 +#define SYSTEMCFG_PHYS_ADDR (SYSTEMCFG_PAGE< + +/* * 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 @@ -13,8 +14,9 @@ unsigned long uc_flags; struct ucontext *uc_link; stack_t uc_stack; - struct sigcontext uc_mcontext; - sigset_t uc_sigmask; /* mask last for extensibility */ + sigset_t uc_sigmask; + sigset_t __unsued[15]; /* Allow for uc_sigmask growth */ + struct sigcontext uc_mcontext; /* last for extensibility */ }; #endif /* _ASMPPC64_UCONTEXT_H */ diff -Nru a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h --- a/include/asm-ppc64/unistd.h Thu May 8 00:24:27 2003 +++ b/include/asm-ppc64/unistd.h Thu May 8 00:24:27 2003 @@ -260,7 +260,7 @@ #define __NR_clock_getres 247 #define __NR_clock_nanosleep 248 -#define __NR_syscalls 249 +#define __NR_syscalls 239 #ifdef __KERNEL__ #define NR_syscalls __NR_syscalls #endif diff -Nru a/include/asm-ppc64/xics.h b/include/asm-ppc64/xics.h --- a/include/asm-ppc64/xics.h Thu May 8 00:24:29 2003 +++ b/include/asm-ppc64/xics.h Thu May 8 00:24:29 2003 @@ -12,7 +12,17 @@ #ifndef _PPC64_KERNEL_XICS_H #define _PPC64_KERNEL_XICS_H +#include + void xics_init_IRQ(void); int xics_get_irq(struct pt_regs *); +void xics_setup_cpu(void); +void xics_cause_IPI(int cpu); + +struct xics_ipi_struct { + volatile unsigned long value; +} ____cacheline_aligned; + +extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; #endif /* _PPC64_KERNEL_XICS_H */ diff -Nru a/include/linux/atm_he.h b/include/linux/atm_he.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/linux/atm_he.h Thu May 8 00:24:30 2003 @@ -0,0 +1,20 @@ +/* atm_he.h */ + +#ifndef LINUX_ATM_HE_H +#define LINUX_ATM_HE_H + +#include + +#define HE_GET_REG _IOW('a', ATMIOC_SARPRV, struct atmif_sioc) + +#define HE_REGTYPE_PCI 1 +#define HE_REGTYPE_RCM 2 +#define HE_REGTYPE_TCM 3 +#define HE_REGTYPE_MBOX 4 + +struct he_ioctl_reg { + unsigned addr, val; + char type; +}; + +#endif /* LINUX_ATM_HE_H */ diff -Nru a/include/linux/atmbr2684.h b/include/linux/atmbr2684.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/linux/atmbr2684.h Thu May 8 00:24:30 2003 @@ -0,0 +1,101 @@ +#ifndef _LINUX_ATMBR2684_H +#define _LINUX_ATMBR2684_H + +#include +#include /* For IFNAMSIZ */ + +/* + * Type of media we're bridging (ethernet, token ring, etc) Currently only + * ethernet is supported + */ +#define BR2684_MEDIA_ETHERNET (0) /* 802.3 */ +#define BR2684_MEDIA_802_4 (1) /* 802.4 */ +#define BR2684_MEDIA_TR (2) /* 802.5 - token ring */ +#define BR2684_MEDIA_FDDI (3) +#define BR2684_MEDIA_802_6 (4) /* 802.6 */ + +/* + * Is there FCS inbound on this VC? This currently isn't supported. + */ +#define BR2684_FCSIN_NO (0) +#define BR2684_FCSIN_IGNORE (1) +#define BR2684_FCSIN_VERIFY (2) + +/* + * Is there FCS outbound on this VC? This currently isn't supported. + */ +#define BR2684_FCSOUT_NO (0) +#define BR2684_FCSOUT_SENDZERO (1) +#define BR2684_FCSOUT_GENERATE (2) + +/* + * Does this VC include LLC encapsulation? + */ +#define BR2684_ENCAPS_VC (0) /* VC-mux */ +#define BR2684_ENCAPS_LLC (1) +#define BR2684_ENCAPS_AUTODETECT (2) /* Unsuported */ + +/* + * This is for the ATM_NEWBACKENDIF call - these are like socket families: + * the first element of the structure is the backend number and the rest + * is per-backend specific + */ +struct atm_newif_br2684 { + atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */ + int media; /* BR2684_MEDIA_* */ + char ifname[IFNAMSIZ]; + int mtu; +}; + +/* + * This structure is used to specify a br2684 interface - either by a + * positive integer (returned by ATM_NEWBACKENDIF) or the interfaces name + */ +#define BR2684_FIND_BYNOTHING (0) +#define BR2684_FIND_BYNUM (1) +#define BR2684_FIND_BYIFNAME (2) +struct br2684_if_spec { + int method; /* BR2684_FIND_* */ + union { + char ifname[IFNAMSIZ]; + int devnum; + } spec; +}; + +/* + * This is for the ATM_SETBACKEND call - these are like socket families: + * the first element of the structure is the backend number and the rest + * is per-backend specific + */ +struct atm_backend_br2684 { + atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */ + struct br2684_if_spec ifspec; + int fcs_in; /* BR2684_FCSIN_* */ + int fcs_out; /* BR2684_FCSOUT_* */ + int fcs_auto; /* 1: fcs_{in,out} disabled if no FCS rx'ed */ + int encaps; /* BR2684_ENCAPS_* */ + int has_vpiid; /* 1: use vpn_id - Unsupported */ + __u8 vpn_id[7]; + int send_padding; /* unsupported */ + int min_size; /* we will pad smaller packets than this */ +}; + +/* + * The BR2684_SETFILT ioctl is an experimental mechanism for folks + * terminating a large number of IP-only vcc's. When netfilter allows + * efficient per-if in/out filters, this support will be removed + */ +struct br2684_filter { + __u32 prefix; /* network byte order */ + __u32 netmask; /* 0 = disable filter */ +}; + +struct br2684_filter_set { + struct br2684_if_spec ifspec; + struct br2684_filter filter; +}; + +#define BR2684_SETFILT _IOW( 'a', ATMIOC_BACKEND + 0, \ + struct br2684_filter_set) + +#endif /* _LINUX_ATMBR2684_H */ diff -Nru a/include/linux/atmdev.h b/include/linux/atmdev.h --- a/include/linux/atmdev.h Thu May 8 00:24:29 2003 +++ b/include/linux/atmdev.h Thu May 8 00:24:29 2003 @@ -96,6 +96,8 @@ /* enable or disable single-copy */ #define ATM_SETBACKEND _IOW('a',ATMIOC_SPECIAL+2,atm_backend_t) /* set backend handler */ +#define ATM_NEWBACKENDIF _IOW('a',ATMIOC_SPECIAL+3,atm_backend_t) + /* use backend to make new if */ /* * These are backend handkers that can be set via the ATM_SETBACKEND call @@ -104,7 +106,7 @@ */ #define ATM_BACKEND_RAW 0 #define ATM_BACKEND_PPP 1 /* PPPoATM - RFC2364 */ -#define ATM_BACKEND_BR_2684 2 /* Bridged RFC1483/2684 */ +#define ATM_BACKEND_BR2684 2 /* Bridged RFC1483/2684 */ /* for ATM_GETTYPE */ #define ATM_ITFTYP_LEN 8 /* maximum length of interface type name */ @@ -304,9 +306,6 @@ struct sockaddr_atmsvc local; struct sockaddr_atmsvc remote; void (*callback)(struct atm_vcc *vcc); - struct sk_buff_head listenq; - int backlog_quota; /* number of connection requests we */ - /* can still accept */ int reply; /* also used by ATMTCP */ /* Multipoint part ------------------------------------------------- */ struct atm_vcc *session; /* session VCC descriptor */ diff -Nru a/include/linux/blkpg.h b/include/linux/blkpg.h --- a/include/linux/blkpg.h Thu May 8 00:24:28 2003 +++ b/include/linux/blkpg.h Thu May 8 00:24:28 2003 @@ -54,10 +54,4 @@ char volname[BLKPG_VOLNAMELTH]; /* volume label */ }; -#ifdef __KERNEL__ - -extern char * partition_name(dev_t dev); - -#endif /* __KERNEL__ */ - #endif /* _LINUX_BLKPG_H */ diff -Nru a/include/linux/brlvger.h b/include/linux/brlvger.h --- a/include/linux/brlvger.h Thu May 8 00:24:28 2003 +++ b/include/linux/brlvger.h Thu May 8 00:24:28 2003 @@ -30,16 +30,8 @@ #define BRLVGER_DISPLAY_OFF 3 #define BRLVGER_BUZZ 4 -#ifdef CONFIG_USB_DYNAMIC_MINORS -#define MAX_NR_BRLVGER_DEVS 256 -#define BRLVGER_MINOR 0 -#else -/* Number of supported devices, and range of covered minors */ -#define MAX_NR_BRLVGER_DEVS 4 - /* Base minor for the char devices */ #define BRLVGER_MINOR 128 -#endif /* Size of some fields */ #define BRLVGER_HWVER_SIZE 2 diff -Nru a/include/linux/devfs_fs_kernel.h b/include/linux/devfs_fs_kernel.h --- a/include/linux/devfs_fs_kernel.h Thu May 8 00:24:29 2003 +++ b/include/linux/devfs_fs_kernel.h Thu May 8 00:24:29 2003 @@ -27,6 +27,8 @@ umode_t mode, void *ops, void *info); extern int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...) __attribute__((format (printf, 3, 4))); +extern int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...) + __attribute__((format (printf, 3, 4))); extern int devfs_mk_symlink(const char *name, const char *link); extern int devfs_mk_dir(const char *fmt, ...) __attribute__((format (printf, 1, 2))); @@ -48,6 +50,10 @@ return NULL; } static inline int devfs_mk_bdev(dev_t dev, umode_t mode, const char *fmt, ...) +{ + return 0; +} +static inline int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...) { return 0; } diff -Nru a/include/linux/file.h b/include/linux/file.h --- a/include/linux/file.h Thu May 8 00:24:27 2003 +++ b/include/linux/file.h Thu May 8 00:24:27 2003 @@ -35,7 +35,15 @@ extern void FASTCALL(__fput(struct file *)); extern void FASTCALL(fput(struct file *)); + +static inline void fput_light(struct file *file, int fput_needed) +{ + if (unlikely(fput_needed)) + fput(file); +} + extern struct file * FASTCALL(fget(unsigned int fd)); +extern struct file * FASTCALL(fget_light(unsigned int fd, int *fput_needed)); extern void FASTCALL(set_close_on_exec(unsigned int fd, int flag)); extern void put_filp(struct file *); extern int get_unused_fd(void); diff -Nru a/include/linux/fs.h b/include/linux/fs.h --- a/include/linux/fs.h Thu May 8 00:24:28 2003 +++ b/include/linux/fs.h Thu May 8 00:24:28 2003 @@ -206,8 +206,8 @@ #include #include +/* Used to be a macro which just called the function, now just a function */ extern void update_atime (struct inode *); -#define UPDATE_ATIME(inode) update_atime (inode) extern void inode_init(unsigned long); extern void mnt_init(unsigned long); @@ -1113,6 +1113,10 @@ extern int filemap_fdatawait(struct address_space *); extern void sync_supers(void); extern void sync_filesystems(int wait); +extern void emergency_sync(void); +extern void emergency_remount(void); +extern int do_remount_sb(struct super_block *sb, int flags, + void *data, int force); extern sector_t bmap(struct inode *, sector_t); extern int setattr_mask(unsigned int); extern int notify_change(struct dentry *, struct iattr *); diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h --- a/include/linux/i2c.h Thu May 8 00:24:28 2003 +++ b/include/linux/i2c.h Thu May 8 00:24:28 2003 @@ -39,12 +39,6 @@ /* --- General options ------------------------------------------------ */ -#define I2C_ALGO_MAX 4 /* control memory consumption */ -#define I2C_ADAP_MAX 16 -#define I2C_DRIVER_MAX 16 -#define I2C_CLIENT_MAX 32 -#define I2C_DUMMY_MAX 4 - struct i2c_msg; struct i2c_algorithm; struct i2c_adapter; @@ -131,6 +125,7 @@ * i2c_attach_client. */ int (*attach_adapter)(struct i2c_adapter *); + int (*detach_adapter)(struct i2c_adapter *); /* tells the driver that a client is about to be deleted & gives it * the chance to remove its private data. Also, if the client struct @@ -145,6 +140,7 @@ int (*command)(struct i2c_client *client,unsigned int cmd, void *arg); struct device_driver driver; + struct list_head list; }; #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver) @@ -169,6 +165,7 @@ int usage_count; /* How many accesses currently */ /* to the client */ struct device dev; /* the device structure */ + struct list_head list; }; #define to_i2c_client(d) container_of(d, struct i2c_client, dev) @@ -228,6 +225,7 @@ struct module *owner; unsigned int id;/* == is algo->id | hwdep.struct->id, */ /* for registered values see below */ + unsigned int class; struct i2c_algorithm *algo;/* the algorithm to access the bus */ void *algo_data; @@ -236,12 +234,10 @@ int (*client_unregister)(struct i2c_client *); /* data fields that are valid for all devices */ - struct semaphore bus; - struct semaphore list; + struct semaphore bus_lock; + struct semaphore clist_lock; unsigned int flags;/* flags specifying div. data */ - struct i2c_client *clients[I2C_CLIENT_MAX]; - int timeout; int retries; struct device dev; /* the adapter device */ @@ -250,6 +246,10 @@ /* No need to set this when you initialize the adapter */ int inode; #endif /* def CONFIG_PROC_FS */ + + int nr; + struct list_head clients; + struct list_head list; }; #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev) @@ -265,7 +265,11 @@ /*flags for the driver struct: */ #define I2C_DF_NOTIFY 0x01 /* notify on bus (de/a)ttaches */ -#define I2C_DF_DUMMY 0x02 /* do not connect any clients */ +#if 0 +/* this flag is gone -- there is a (optional) driver->detach_adapter + * callback now which can be used instead */ +# define I2C_DF_DUMMY 0x02 +#endif /*flags for the client struct: */ #define I2C_CLIENT_ALLOW_USE 0x01 /* Client allows access */ @@ -275,6 +279,12 @@ #define I2C_CLIENT_TEN 0x10 /* we have a ten bit chip address */ /* Must equal I2C_M_TEN below */ +/* i2c adapter classes (bitmask) */ +#define I2C_ADAP_CLASS_SMBUS (1<<0) /* lm_sensors, ... */ +#define I2C_ADAP_CLASS_TV_ANALOG (1<<1) /* bttv + friends */ +#define I2C_ADAP_CLASS_TV_DIGINAL (1<<2) /* dbv cards */ +#define I2C_ADAP_CLASS_DDC (1<<3) /* i2c-matroxfb ? */ + /* i2c_client_address_data is the struct for holding default client * addresses for a driver and for the parameters supplied on the * command line @@ -331,6 +341,11 @@ extern int i2c_use_client(struct i2c_client *); extern int i2c_release_client(struct i2c_client *); +/* call the i2c_client->command() of all attached clients with + * the given arguments */ +extern void i2c_clients_command(struct i2c_adapter *adap, + unsigned int cmd, void *arg); + /* returns -EBUSY if address has been taken, 0 if not. Note that the only other place at which this is called is within i2c_attach_client; so you can cheat by simply not registering. Not recommended, of course! */ @@ -352,7 +367,8 @@ * or -1 if the adapter was not registered. */ extern int i2c_adapter_id(struct i2c_adapter *adap); - +extern struct i2c_adapter* i2c_get_adapter(int id); +extern void i2c_put_adapter(struct i2c_adapter *adap); /* Return the functionality mask */ diff -Nru a/include/linux/input.h b/include/linux/input.h --- a/include/linux/input.h Thu May 8 00:24:28 2003 +++ b/include/linux/input.h Thu May 8 00:24:28 2003 @@ -894,9 +894,6 @@ int input_accept_process(struct input_handle *handle, struct file *file); int input_flush_device(struct input_handle* handle, struct file* file); -/* will go away once devfs_register gets sanitized */ -void input_register_minor(char *name, int minor, int minor_base); - void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value); #define input_report_key(a,b,c) input_event(a, EV_KEY, b, !!(c)) diff -Nru a/include/linux/ipx.h b/include/linux/ipx.h --- a/include/linux/ipx.h Thu May 8 00:24:30 2003 +++ b/include/linux/ipx.h Thu May 8 00:24:30 2003 @@ -5,8 +5,7 @@ #define IPX_NODE_LEN 6 #define IPX_MTU 576 -struct sockaddr_ipx -{ +struct sockaddr_ipx { sa_family_t sipx_family; __u16 sipx_port; __u32 sipx_network; @@ -16,9 +15,8 @@ }; /* - * So we can fit the extra info for SIOCSIFADDR into the address nicely + * So we can fit the extra info for SIOCSIFADDR into the address nicely */ - #define sipx_special sipx_port #define sipx_action sipx_zero #define IPX_DLTITF 0 @@ -56,14 +54,13 @@ * OLD Route Definition for backward compatibility. */ -struct ipx_route_def -{ - __u32 ipx_network; - __u32 ipx_router_network; +struct ipx_route_def { + __u32 ipx_network; + __u32 ipx_router_network; #define IPX_ROUTE_NO_ROUTER 0 - unsigned char ipx_router_node[IPX_NODE_LEN]; - unsigned char ipx_device[16]; - unsigned short ipx_flags; + unsigned char ipx_router_node[IPX_NODE_LEN]; + unsigned char ipx_device[16]; + unsigned short ipx_flags; #define IPX_RT_SNAP 8 #define IPX_RT_8022 4 #define IPX_RT_BLUEBOOK 2 @@ -71,7 +68,7 @@ }; #define SIOCAIPXITFCRT (SIOCPROTOPRIVATE) -#define SIOCAIPXPRISLT (SIOCPROTOPRIVATE+1) -#define SIOCIPXCFGDATA (SIOCPROTOPRIVATE+2) -#define SIOCIPXNCPCONN (SIOCPROTOPRIVATE+3) -#endif /* def _IPX_H_ */ +#define SIOCAIPXPRISLT (SIOCPROTOPRIVATE + 1) +#define SIOCIPXCFGDATA (SIOCPROTOPRIVATE + 2) +#define SIOCIPXNCPCONN (SIOCPROTOPRIVATE + 3) +#endif /* _IPX_H_ */ diff -Nru a/include/linux/list.h b/include/linux/list.h --- a/include/linux/list.h Thu May 8 00:24:29 2003 +++ b/include/linux/list.h Thu May 8 00:24:29 2003 @@ -297,6 +297,19 @@ prefetch(pos->member.next)) /** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** * list_for_each_rcu - iterate over an rcu-protected list * @pos: the &struct list_head to use as a loop counter. * @head: the head for your list. diff -Nru a/include/linux/major.h b/include/linux/major.h --- a/include/linux/major.h Thu May 8 00:24:28 2003 +++ b/include/linux/major.h Thu May 8 00:24:28 2003 @@ -27,6 +27,7 @@ #define MUX_MAJOR 11 /* PA-RISC only */ #define QIC02_TAPE_MAJOR 12 #define XT_DISK_MAJOR 13 +#define INPUT_MAJOR 13 #define SOUND_MAJOR 14 #define CDU31A_CDROM_MAJOR 15 #define JOYSTICK_MAJOR 15 diff -Nru a/include/linux/netfilter_ipv4/ip_nat_core.h b/include/linux/netfilter_ipv4/ip_nat_core.h --- a/include/linux/netfilter_ipv4/ip_nat_core.h Thu May 8 00:24:27 2003 +++ b/include/linux/netfilter_ipv4/ip_nat_core.h Thu May 8 00:24:27 2003 @@ -16,10 +16,10 @@ extern struct list_head protos; -extern unsigned int icmp_reply_translation(struct sk_buff *skb, - struct ip_conntrack *conntrack, - unsigned int hooknum, - int dir); +extern int icmp_reply_translation(struct sk_buff **pskb, + struct ip_conntrack *conntrack, + unsigned int hooknum, + int dir); extern void replace_in_hashes(struct ip_conntrack *conntrack, struct ip_nat_info *info); @@ -30,4 +30,10 @@ extern struct ip_nat_protocol ip_nat_protocol_tcp; extern struct ip_nat_protocol ip_nat_protocol_udp; extern struct ip_nat_protocol ip_nat_protocol_icmp; + +/* Call this before modifying an existing IP packet: ensures it is + modifiable and linear to the point you care about (writable_len). + Returns true or false. */ +extern int skb_ip_make_writable(struct sk_buff **pskb, + unsigned int writable_len); #endif /* _IP_NAT_CORE_H */ diff -Nru a/include/linux/netfilter_ipv4/ip_nat_helper.h b/include/linux/netfilter_ipv4/ip_nat_helper.h --- a/include/linux/netfilter_ipv4/ip_nat_helper.h Thu May 8 00:24:28 2003 +++ b/include/linux/netfilter_ipv4/ip_nat_helper.h Thu May 8 00:24:28 2003 @@ -43,22 +43,23 @@ extern int ip_nat_helper_register(struct ip_nat_helper *me); extern void ip_nat_helper_unregister(struct ip_nat_helper *me); + +/* These return true or false. */ extern int ip_nat_mangle_tcp_packet(struct sk_buff **skb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, unsigned int match_offset, unsigned int match_len, - char *rep_buffer, + const char *rep_buffer, unsigned int rep_len); extern int ip_nat_mangle_udp_packet(struct sk_buff **skb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, unsigned int match_offset, unsigned int match_len, - char *rep_buffer, + const char *rep_buffer, unsigned int rep_len); -extern int ip_nat_seq_adjust(struct sk_buff *skb, - struct ip_conntrack *ct, - enum ip_conntrack_info ctinfo); -extern void ip_nat_delete_sack(struct sk_buff *skb); +extern int ip_nat_seq_adjust(struct sk_buff **pskb, + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo); #endif diff -Nru a/include/linux/netfilter_ipv4/ip_nat_protocol.h b/include/linux/netfilter_ipv4/ip_nat_protocol.h --- a/include/linux/netfilter_ipv4/ip_nat_protocol.h Thu May 8 00:24:29 2003 +++ b/include/linux/netfilter_ipv4/ip_nat_protocol.h Thu May 8 00:24:29 2003 @@ -18,10 +18,11 @@ unsigned int protonum; /* Do a packet translation according to the ip_nat_proto_manip - * and manip type. */ - void (*manip_pkt)(struct iphdr *iph, size_t len, - const struct ip_conntrack_manip *manip, - enum ip_nat_manip_type maniptype); + * and manip type. Return true if succeeded. */ + int (*manip_pkt)(struct sk_buff **pskb, + unsigned int hdroff, + const struct ip_conntrack_manip *manip, + enum ip_nat_manip_type maniptype); /* Is the manipable part of the tuple between min and max incl? */ int (*in_range)(const struct ip_conntrack_tuple *tuple, diff -Nru a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h --- a/include/linux/pfkeyv2.h Thu May 8 00:24:30 2003 +++ b/include/linux/pfkeyv2.h Thu May 8 00:24:30 2003 @@ -275,8 +275,8 @@ /* Encryption algorithms */ #define SADB_EALG_NONE 0 -#define SADB_EALG_DESCBC 1 -#define SADB_EALG_3DESCBC 2 +#define SADB_EALG_DESCBC 2 +#define SADB_EALG_3DESCBC 3 #define SADB_X_EALG_CASTCBC 6 #define SADB_X_EALG_BLOWFISHCBC 7 #define SADB_EALG_NULL 11 diff -Nru a/include/linux/proc_fs.h b/include/linux/proc_fs.h --- a/include/linux/proc_fs.h Thu May 8 00:24:27 2003 +++ b/include/linux/proc_fs.h Thu May 8 00:24:27 2003 @@ -163,6 +163,15 @@ return create_proc_info_entry(name,mode,proc_net,get_info); } +static inline struct proc_dir_entry *proc_net_fops_create(const char *name, + mode_t mode, struct file_operations *fops) +{ + struct proc_dir_entry *res = create_proc_entry(name, mode, proc_net); + if (res) + res->proc_fops = fops; + return res; +} + static inline void proc_net_remove(const char *name) { remove_proc_entry(name,proc_net); @@ -171,7 +180,7 @@ #else #define proc_root_driver NULL - +#define proc_net_fops_create(name,mode,fops) do {} while(0) static inline struct proc_dir_entry *proc_net_create(const char *name, mode_t mode, get_info_t *get_info) {return NULL;} static inline void proc_net_remove(const char *name) {} diff -Nru a/include/linux/raid/md.h b/include/linux/raid/md.h --- a/include/linux/raid/md.h Thu May 8 00:24:27 2003 +++ b/include/linux/raid/md.h Thu May 8 00:24:27 2003 @@ -61,9 +61,20 @@ #define MD_MINOR_VERSION 90 #define MD_PATCHLEVEL_VERSION 0 -extern inline char * bdev_partition_name (struct block_device *bdev) +/* + * XXX(hch): This function is broken. Someone who understands the md + * code needs to go through all callers, check whether bdev could + * be NULL and replace it with direct calls to bdevmame. + * + * This would also fix the returns buffer on stack issue nicely :) + */ +static inline const char *bdev_partition_name (struct block_device *bdev) { - return partition_name(bdev ? bdev->bd_dev : 0); + char b[BDEVNAME_SIZE]; + + if (!bdev) + return __bdevname(0, b); + return bdevname(bdev, b); } extern int register_md_personality (int p_num, mdk_personality_t *p); extern int unregister_md_personality (int p_num); diff -Nru a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h --- a/include/linux/rtnetlink.h Thu May 8 00:24:29 2003 +++ b/include/linux/rtnetlink.h Thu May 8 00:24:29 2003 @@ -78,7 +78,7 @@ /****************************************************************************** - * Definitions used in routing table administation. + * Definitions used in routing table administration. ****/ struct rtmsg @@ -129,14 +129,14 @@ #define RTPROT_STATIC 4 /* Route installed by administrator */ /* Values of protocol >= RTPROT_STATIC are not interpreted by kernel; - they just passed from user and back as is. + they are just passed from user and back as is. It will be used by hypothetical multiple routing daemons. Note that protocol values should be standardized in order to avoid conflicts. */ #define RTPROT_GATED 8 /* Apparently, GateD */ -#define RTPROT_RA 9 /* RDISC/ND router advertisments */ +#define RTPROT_RA 9 /* RDISC/ND router advertisements */ #define RTPROT_MRT 10 /* Merit MRT */ #define RTPROT_ZEBRA 11 /* Zebra */ #define RTPROT_BIRD 12 /* BIRD */ @@ -210,8 +210,8 @@ /* RTM_MULTIPATH --- array of struct rtnexthop. * - * "struct rtnexthop" describres all necessary nexthop information, - * i.e. parameters of path to a destination via this nextop. + * "struct rtnexthop" describes all necessary nexthop information, + * i.e. parameters of path to a destination via this nexthop. * * At the moment it is impossible to set different prefsrc, mtu, window * and rtt for different paths from multipath. @@ -485,7 +485,7 @@ Comments: - Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid - - If neiher of these three flags are set; + - If neither of these three flags are set; the interface is NBMA. - IFF_MULTICAST does not mean anything special: diff -Nru a/include/linux/sched.h b/include/linux/sched.h --- a/include/linux/sched.h Thu May 8 00:24:27 2003 +++ b/include/linux/sched.h Thu May 8 00:24:27 2003 @@ -294,6 +294,7 @@ typedef struct prio_array prio_array_t; struct backing_dev_info; +struct reclaim_state; /* POSIX.1b interval timer structure. */ struct k_itimer { @@ -433,6 +434,10 @@ /* journalling filesystem info */ void *journal_info; + +/* VM state */ + struct reclaim_state *reclaim_state; + struct dentry *proc_dentry; struct backing_dev_info *backing_dev_info; diff -Nru a/include/linux/security.h b/include/linux/security.h --- a/include/linux/security.h Thu May 8 00:24:29 2003 +++ b/include/linux/security.h Thu May 8 00:24:29 2003 @@ -361,6 +361,9 @@ * Check permission before setting the extended attributes * @value identified by @name for @dentry. * Return 0 if permission is granted. + * @inode_post_setxattr: + * Update inode security field after successful setxattr operation. + * @value identified by @name for @dentry. * @inode_getxattr: * Check permission before obtaining the extended attributes * identified by @name for @dentry. @@ -1036,6 +1039,8 @@ void (*inode_delete) (struct inode *inode); int (*inode_setxattr) (struct dentry *dentry, char *name, void *value, size_t size, int flags); + void (*inode_post_setxattr) (struct dentry *dentry, char *name, void *value, + size_t size, int flags); int (*inode_getxattr) (struct dentry *dentry, char *name); int (*inode_listxattr) (struct dentry *dentry); int (*inode_removexattr) (struct dentry *dentry, char *name); @@ -1464,6 +1469,12 @@ return security_ops->inode_setxattr (dentry, name, value, size, flags); } +static inline void security_inode_post_setxattr (struct dentry *dentry, char *name, + void *value, size_t size, int flags) +{ + security_ops->inode_post_setxattr (dentry, name, value, size, flags); +} + static inline int security_inode_getxattr (struct dentry *dentry, char *name) { return security_ops->inode_getxattr (dentry, name); @@ -2062,6 +2073,10 @@ { return 0; } + +static inline void security_inode_post_setxattr (struct dentry *dentry, char *name, + void *value, size_t size, int flags) +{ } static inline int security_inode_getxattr (struct dentry *dentry, char *name) { diff -Nru a/include/linux/seq_file.h b/include/linux/seq_file.h --- a/include/linux/seq_file.h Thu May 8 00:24:30 2003 +++ b/include/linux/seq_file.h Thu May 8 00:24:30 2003 @@ -60,5 +60,6 @@ int single_open(struct file *, int (*)(struct seq_file *, void *), void *); int single_release(struct inode *, struct file *); +int seq_release_private(struct inode *, struct file *); #endif #endif diff -Nru a/include/linux/slab.h b/include/linux/slab.h --- a/include/linux/slab.h Thu May 8 00:24:30 2003 +++ b/include/linux/slab.h Thu May 8 00:24:30 2003 @@ -49,7 +49,6 @@ /* prototypes */ extern void kmem_cache_init(void); -extern void kmem_cache_sizes_init(void); extern kmem_cache_t *kmem_find_general_cachep(size_t, int gfpflags); extern kmem_cache_t *kmem_cache_create(const char *, size_t, size_t, unsigned long, diff -Nru a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h --- a/include/linux/sunrpc/svc.h Thu May 8 00:24:29 2003 +++ b/include/linux/sunrpc/svc.h Thu May 8 00:24:29 2003 @@ -176,8 +176,10 @@ { if (rqstp->rq_arghi <= rqstp->rq_argused) return -ENOMEM; - rqstp->rq_respages[rqstp->rq_resused++] = - rqstp->rq_argpages[--rqstp->rq_arghi]; + rqstp->rq_arghi--; + rqstp->rq_respages[rqstp->rq_resused] = + rqstp->rq_argpages[rqstp->rq_arghi]; + rqstp->rq_resused++; return 0; } diff -Nru a/include/linux/swap.h b/include/linux/swap.h --- a/include/linux/swap.h Thu May 8 00:24:27 2003 +++ b/include/linux/swap.h Thu May 8 00:24:27 2003 @@ -66,6 +66,14 @@ unsigned long val; } swp_entry_t; +/* + * current->reclaim_state points to one of these when a task is running + * memory reclaim + */ +struct reclaim_state { + unsigned long reclaimed_slab; +}; + #ifdef __KERNEL__ struct address_space; diff -Nru a/include/linux/sysrq.h b/include/linux/sysrq.h --- a/include/linux/sysrq.h Thu May 8 00:24:27 2003 +++ b/include/linux/sysrq.h Thu May 8 00:24:27 2003 @@ -92,21 +92,3 @@ #define unregister_sysrq_key(ig,nore) __reterr() #endif - - -/* Deferred actions */ - -extern int emergency_sync_scheduled; - -#define EMERG_SYNC 1 -#define EMERG_REMOUNT 2 - -void do_emergency_sync(void); - -#ifdef CONFIG_MAGIC_SYSRQ -#define CHECK_EMERGENCY_SYNC \ - if (emergency_sync_scheduled) \ - do_emergency_sync(); -#else -#define CHECK_EMERGENCY_SYNC -#endif diff -Nru a/include/linux/tty.h b/include/linux/tty.h --- a/include/linux/tty.h Thu May 8 00:24:28 2003 +++ b/include/linux/tty.h Thu May 8 00:24:28 2003 @@ -243,6 +243,7 @@ #define L_PENDIN(tty) _L_FLAG((tty),PENDIN) #define L_IEXTEN(tty) _L_FLAG((tty),IEXTEN) +struct device; /* * Where all of the state associated with a tty is kept while the tty * is open. Since the termios state should be kept even if the tty @@ -380,7 +381,7 @@ extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc); extern int tty_register_driver(struct tty_driver *driver); extern int tty_unregister_driver(struct tty_driver *driver); -extern void tty_register_device(struct tty_driver *driver, unsigned index); +extern void tty_register_device(struct tty_driver *driver, unsigned index, struct device *dev); extern void tty_unregister_device(struct tty_driver *driver, unsigned index); extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp, int buflen); diff -Nru a/include/linux/usb.h b/include/linux/usb.h --- a/include/linux/usb.h Thu May 8 00:24:28 2003 +++ b/include/linux/usb.h Thu May 8 00:24:28 2003 @@ -73,13 +73,22 @@ /** * struct usb_interface - what usb device drivers talk to * @altsetting: array of interface descriptors, one for each alternate - * setting that may be selected. each one includes a set of - * endpoint configurations. + * setting that may be selected. Each one includes a set of + * endpoint configurations and will be in numberic order, + * 0..num_altsetting. * @num_altsetting: number of altsettings defined. * @act_altsetting: index of current altsetting. this number is always * less than num_altsetting. after the device is configured, each * interface uses its default setting of zero. + * @max_altsetting: + * @minor: the minor number assigned to this interface, if this + * interface is bound to a driver that uses the USB major number. + * If this interface does not use the USB major, this field should + * be unused. The driver should set this value in the probe() + * function of the driver, after it has been assigned a minor + * number from the USB core by calling usb_register_dev(). * @dev: driver model's view of this device + * @class_dev: driver model's class view of this device. * * USB device drivers attach to interfaces on a physical device. Each * interface encapsulates a single high level function, such as feeding @@ -111,10 +120,12 @@ unsigned max_altsetting; /* total memory allocated */ struct usb_driver *driver; /* driver */ - kdev_t kdev; /* node this interface is bound to */ + int minor; /* minor number this interface is bound to */ struct device dev; /* interface specific device info */ + struct class_device class_dev; }; #define to_usb_interface(d) container_of(d, struct usb_interface, dev) +#define class_dev_to_usb_interface(d) container_of(d, struct usb_interface, class_dev) #define interface_to_usbdev(intf) \ container_of(intf->dev.parent, struct usb_device, dev) @@ -279,7 +290,7 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface, const struct usb_device_id *id); -extern struct usb_interface *usb_find_interface(struct usb_driver *drv, kdev_t kdev); +extern struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor); extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum); @@ -433,6 +444,25 @@ extern struct bus_type usb_bus_type; +/** + * struct usb_class_driver - identifies a USB driver that wants to use the USB major number + * @name: devfs name for this driver. Will also be used by the driver + * class code to create a usb class device. + * @fops: pointer to the struct file_operations of this driver. + * @mode: the mode for the devfs file to be created for this driver. + * @minor_base: the start of the minor range for this driver. + * + * This structure is used for the usb_register_dev() and + * usb_unregister_dev() functions, to consolodate a number of the + * paramaters used for them. + */ +struct usb_class_driver { + char *name; + struct file_operations *fops; + mode_t mode; + int minor_base; +}; + /* * use these in module_init()/module_exit() * and don't forget MODULE_DEVICE_TABLE(usb, ...) @@ -440,8 +470,10 @@ extern int usb_register(struct usb_driver *); extern void usb_deregister(struct usb_driver *); -extern int usb_register_dev(struct file_operations *fops, int minor, int num_minors, int *start_minor); -extern void usb_deregister_dev(int num_minors, int start_minor); +extern int usb_register_dev(struct usb_interface *intf, + struct usb_class_driver *class_driver); +extern void usb_deregister_dev(struct usb_interface *intf, + struct usb_class_driver *class_driver); extern int usb_device_probe(struct device *dev); extern int usb_device_remove(struct device *dev); diff -Nru a/include/net/dn_dev.h b/include/net/dn_dev.h --- a/include/net/dn_dev.h Thu May 8 00:24:27 2003 +++ b/include/net/dn_dev.h Thu May 8 00:24:27 2003 @@ -71,7 +71,6 @@ #define DN_DEV_MPOINT 4 int state; /* Initial state */ int forwarding; /* 0=EndNode, 1=L1Router, 2=L2Router */ - unsigned short blksize; /* Block Size */ unsigned long t2; /* Default value of t2 */ unsigned long t3; /* Default value of t3 */ int priority; /* Priority to be a router */ diff -Nru a/include/net/dn_fib.h b/include/net/dn_fib.h --- a/include/net/dn_fib.h Thu May 8 00:24:28 2003 +++ b/include/net/dn_fib.h Thu May 8 00:24:28 2003 @@ -101,10 +101,6 @@ int (*lookup)(struct dn_fib_table *t, const struct flowi *fl, struct dn_fib_res *res); int (*flush)(struct dn_fib_table *t); -#ifdef CONFIG_PROC_FS - int (*get_info)(struct dn_fib_table *table, char *buf, - int first, int count); -#endif /* CONFIG_PROC_FS */ int (*dump)(struct dn_fib_table *t, struct sk_buff *skb, struct netlink_callback *cb); unsigned char data[0]; @@ -183,6 +179,9 @@ extern struct dn_fib_table *dn_fib_tables[]; #else /* Endnode */ + +#define dn_fib_init() (0) +#define dn_fib_cleanup() (0) #define dn_fib_lookup(fl, res) (-ESRCH) #define dn_fib_info_put(fi) do { } while(0) diff -Nru a/include/net/dn_route.h b/include/net/dn_route.h --- a/include/net/dn_route.h Thu May 8 00:24:27 2003 +++ b/include/net/dn_route.h Thu May 8 00:24:27 2003 @@ -74,7 +74,7 @@ __u16 rt_saddr; __u16 rt_daddr; __u16 rt_gateway; - __u16 __padding; + __u16 rt_local_src; /* Source used for forwarding packets */ __u16 rt_src_map; __u16 rt_dst_map; diff -Nru a/include/net/ipx.h b/include/net/ipx.h --- a/include/net/ipx.h Thu May 8 00:24:27 2003 +++ b/include/net/ipx.h Thu May 8 00:24:27 2003 @@ -12,6 +12,7 @@ #include #include #include +#include struct ipx_address { __u32 net; @@ -25,11 +26,11 @@ #define IPX_MAX_PPROP_HOPS 8 struct ipxhdr { - __u16 ipx_checksum __attribute__ ((packed)); + __u16 ipx_checksum __attribute__ ((packed)); #define IPX_NO_CHECKSUM 0xFFFF - __u16 ipx_pktsize __attribute__ ((packed)); - __u8 ipx_tctrl; - __u8 ipx_type; + __u16 ipx_pktsize __attribute__ ((packed)); + __u8 ipx_tctrl; + __u8 ipx_type; #define IPX_TYPE_UNKNOWN 0x00 #define IPX_TYPE_RIP 0x01 /* may also be 0 */ #define IPX_TYPE_SAP 0x04 /* may also be 0 */ @@ -47,42 +48,42 @@ struct ipx_interface { /* IPX address */ - __u32 if_netnum; - unsigned char if_node[IPX_NODE_LEN]; - atomic_t refcnt; + __u32 if_netnum; + unsigned char if_node[IPX_NODE_LEN]; + atomic_t refcnt; /* physical device info */ struct net_device *if_dev; struct datalink_proto *if_dlink; - unsigned short if_dlink_type; + unsigned short if_dlink_type; /* socket support */ - unsigned short if_sknum; - struct sock *if_sklist; - spinlock_t if_sklist_lock; + unsigned short if_sknum; + struct sock *if_sklist; + spinlock_t if_sklist_lock; /* administrative overhead */ - int if_ipx_offset; - unsigned char if_internal; - unsigned char if_primary; + int if_ipx_offset; + unsigned char if_internal; + unsigned char if_primary; - struct ipx_interface *if_next; + struct list_head node; /* node in ipx_interfaces list */ }; struct ipx_route { - __u32 ir_net; + __u32 ir_net; struct ipx_interface *ir_intrfc; - unsigned char ir_routed; - unsigned char ir_router_node[IPX_NODE_LEN]; - struct ipx_route *ir_next; - atomic_t refcnt; + unsigned char ir_routed; + unsigned char ir_router_node[IPX_NODE_LEN]; + struct list_head node; /* node in ipx_routes list */ + atomic_t refcnt; }; #ifdef __KERNEL__ struct ipx_cb { - u8 ipx_tctrl; - u32 ipx_dest_net; - u32 ipx_source_net; + u8 ipx_tctrl; + u32 ipx_dest_net; + u32 ipx_source_net; struct { u32 netnum; int index; @@ -92,14 +93,16 @@ struct ipx_opt { struct ipx_address dest_addr; struct ipx_interface *intrfc; - unsigned short port; + unsigned short port; #ifdef CONFIG_IPX_INTERN - unsigned char node[IPX_NODE_LEN]; + unsigned char node[IPX_NODE_LEN]; #endif - unsigned short type; - /* To handle special ncp connection-handling sockets for mars_nwe, - * the connection number must be stored in the socket. */ - unsigned short ipx_ncp_conn; + unsigned short type; + /* + * To handle special ncp connection-handling sockets for mars_nwe, + * the connection number must be stored in the socket. + */ + unsigned short ipx_ncp_conn; }; #define ipx_sk(__sk) ((struct ipx_opt *)(__sk)->protinfo) @@ -108,10 +111,11 @@ #define IPX_MIN_EPHEMERAL_SOCKET 0x4000 #define IPX_MAX_EPHEMERAL_SOCKET 0x7fff -extern struct ipx_route *ipx_routes; +extern struct list_head ipx_routes; extern rwlock_t ipx_routes_lock; -extern struct ipx_interface *ipx_interfaces; +extern struct list_head ipx_interfaces; +extern struct ipx_interface *ipx_interfaces_head(void); extern spinlock_t ipx_interfaces_lock; extern struct ipx_interface *ipx_primary_net; @@ -121,4 +125,4 @@ extern const char *ipx_frame_name(unsigned short); extern const char *ipx_device_name(struct ipx_interface *intrfc); -#endif /* def _NET_INET_IPX_H_ */ +#endif /* _NET_INET_IPX_H_ */ diff -Nru a/init/main.c b/init/main.c --- a/init/main.c Thu May 8 00:24:28 2003 +++ b/init/main.c Thu May 8 00:24:28 2003 @@ -417,7 +417,6 @@ */ console_init(); profile_init(); - kmem_cache_init(); local_irq_enable(); calibrate_delay(); #ifdef CONFIG_BLK_DEV_INITRD @@ -430,7 +429,7 @@ #endif page_address_init(); mem_init(); - kmem_cache_sizes_init(); + kmem_cache_init(); pidmap_init(); pgtable_cache_init(); pte_chain_init(); diff -Nru a/ipc/shm.c b/ipc/shm.c --- a/ipc/shm.c Thu May 8 00:24:28 2003 +++ b/ipc/shm.c Thu May 8 00:24:29 2003 @@ -149,7 +149,7 @@ static int shm_mmap(struct file * file, struct vm_area_struct * vma) { - UPDATE_ATIME(file->f_dentry->d_inode); + update_atime(file->f_dentry->d_inode); vma->vm_ops = &shm_vm_ops; shm_inc(file->f_dentry->d_inode->i_ino); return 0; diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c --- a/kernel/ksyms.c Thu May 8 00:24:27 2003 +++ b/kernel/ksyms.c Thu May 8 00:24:27 2003 @@ -540,6 +540,7 @@ EXPORT_SYMBOL(seq_lseek); EXPORT_SYMBOL(single_open); EXPORT_SYMBOL(single_release); +EXPORT_SYMBOL(seq_release_private); /* Program loader interfaces */ #ifdef CONFIG_MMU @@ -578,8 +579,6 @@ /* all busmice */ EXPORT_SYMBOL(fasync_helper); EXPORT_SYMBOL(kill_fasync); - -EXPORT_SYMBOL(partition_name); /* binfmt_aout */ EXPORT_SYMBOL(get_write_access); diff -Nru a/kernel/panic.c b/kernel/panic.c --- a/kernel/panic.c Thu May 8 00:24:30 2003 +++ b/kernel/panic.c Thu May 8 00:24:30 2003 @@ -96,9 +96,8 @@ disabled_wait(caller); #endif local_irq_enable(); - for(;;) { - CHECK_EMERGENCY_SYNC - } + for (;;) + ; } /** diff -Nru a/lib/inflate.c b/lib/inflate.c --- a/lib/inflate.c Thu May 8 00:24:28 2003 +++ b/lib/inflate.c Thu May 8 00:24:28 2003 @@ -271,14 +271,15 @@ STATIC unsigned hufts; /* track memory usage */ -STATIC int huft_build(b, n, s, d, e, t, m) -unsigned *b; /* code lengths in bits (all assumed <= BMAX) */ -unsigned n; /* number of codes (assumed <= N_MAX) */ -unsigned s; /* number of simple-valued codes (0..s-1) */ -const ush *d; /* list of base values for non-simple codes */ -const ush *e; /* list of extra bits for non-simple codes */ -struct huft **t; /* result: starting table */ -int *m; /* maximum lookup bits, returns actual */ +STATIC int huft_build( + unsigned *b, /* code lengths in bits (all assumed <= BMAX) */ + unsigned n, /* number of codes (assumed <= N_MAX) */ + unsigned s, /* number of simple-valued codes (0..s-1) */ + const ush *d, /* list of base values for non-simple codes */ + const ush *e, /* list of extra bits for non-simple codes */ + struct huft **t, /* result: starting table */ + int *m /* maximum lookup bits, returns actual */ + ) /* Given a list of code lengths and a maximum table size, make a set of tables to decode that set of codes. Return zero on success, one if the given code set is incomplete (the tables are still built in this @@ -489,8 +490,9 @@ -STATIC int huft_free(t) -struct huft *t; /* table to free */ +STATIC int huft_free( + struct huft *t /* table to free */ + ) /* Free the malloc'ed tables built by huft_build(), which makes a linked list of the tables it made, with the links in a dummy first entry of each table. */ @@ -510,9 +512,12 @@ } -STATIC int inflate_codes(tl, td, bl, bd) -struct huft *tl, *td; /* literal/length and distance decoder tables */ -int bl, bd; /* number of bits decoded by tl[] and td[] */ +STATIC int inflate_codes( + struct huft *tl, /* literal/length decoder tables */ + struct huft *td, /* distance decoder tables */ + int bl, /* number of bits decoded by tl[] */ + int bd /* number of bits decoded by td[] */ + ) /* inflate (decompress) the codes in a deflated (compressed) block. Return an error code or zero if it all goes ok. */ { @@ -619,7 +624,7 @@ -STATIC int inflate_stored() +STATIC int inflate_stored(void) /* "decompress" an inflated type 0 (stored) block. */ { unsigned n; /* number of bytes in block */ @@ -675,7 +680,7 @@ -STATIC int inflate_fixed() +STATIC int inflate_fixed(void) /* decompress an inflated type 1 (fixed Huffman codes) block. We should either replace this with a custom decoder, or at least precompute the Huffman tables. */ @@ -729,7 +734,7 @@ -STATIC int inflate_dynamic() +STATIC int inflate_dynamic(void) /* decompress an inflated type 2 (dynamic Huffman codes) block. */ { int i; /* temporary variables */ @@ -907,8 +912,9 @@ -STATIC int inflate_block(e) -int *e; /* last block flag */ +STATIC int inflate_block( + int *e /* last block flag */ + ) /* decompress an inflated block */ { unsigned t; /* block type */ @@ -954,7 +960,7 @@ -STATIC int inflate() +STATIC int inflate(void) /* decompress an inflated entry */ { int e; /* last block flag */ diff -Nru a/mm/filemap.c b/mm/filemap.c --- a/mm/filemap.c Thu May 8 00:24:28 2003 +++ b/mm/filemap.c Thu May 8 00:24:28 2003 @@ -681,7 +681,7 @@ *ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset; if (cached_page) page_cache_release(cached_page); - UPDATE_ATIME(inode); + update_atime(inode); } int file_read_actor(read_descriptor_t *desc, struct page *page, @@ -774,7 +774,7 @@ if (retval > 0) *ppos = pos + retval; } - UPDATE_ATIME(filp->f_dentry->d_inode); + update_atime(filp->f_dentry->d_inode); goto out; } @@ -1259,7 +1259,7 @@ if (!mapping->a_ops->readpage) return -ENOEXEC; - UPDATE_ATIME(inode); + update_atime(inode); vma->vm_ops = &generic_file_vm_ops; return 0; } diff -Nru a/mm/page-writeback.c b/mm/page-writeback.c --- a/mm/page-writeback.c Thu May 8 00:24:29 2003 +++ b/mm/page-writeback.c Thu May 8 00:24:29 2003 @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -237,7 +236,6 @@ .nonblocking = 1, }; - CHECK_EMERGENCY_SYNC for ( ; ; ) { struct page_state ps; long background_thresh; diff -Nru a/mm/page_alloc.c b/mm/page_alloc.c --- a/mm/page_alloc.c Thu May 8 00:24:27 2003 +++ b/mm/page_alloc.c Thu May 8 00:24:27 2003 @@ -537,6 +537,7 @@ int i; int cold; int do_retry; + struct reclaim_state reclaim_state; if (wait) might_sleep(); @@ -608,7 +609,12 @@ goto nopage; current->flags |= PF_MEMALLOC; + reclaim_state.reclaimed_slab = 0; + current->reclaim_state = &reclaim_state; + try_to_free_pages(classzone, gfp_mask, order); + + current->reclaim_state = NULL; current->flags &= ~PF_MEMALLOC; /* go through the zonelist yet one more time */ diff -Nru a/mm/shmem.c b/mm/shmem.c --- a/mm/shmem.c Thu May 8 00:24:28 2003 +++ b/mm/shmem.c Thu May 8 00:24:28 2003 @@ -1013,7 +1013,7 @@ ops = &shmem_vm_ops; if (!inode->i_sb || !S_ISREG(inode->i_mode)) return -EACCES; - UPDATE_ATIME(inode); + update_atime(inode); vma->vm_ops = ops; return 0; } @@ -1307,7 +1307,7 @@ } *ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset; - UPDATE_ATIME(inode); + update_atime(inode); } static ssize_t shmem_file_read(struct file *filp, char *buf, size_t count, loff_t *ppos) diff -Nru a/mm/slab.c b/mm/slab.c --- a/mm/slab.c Thu May 8 00:24:29 2003 +++ b/mm/slab.c Thu May 8 00:24:29 2003 @@ -76,6 +76,7 @@ #include #include #include +#include #include #include #include @@ -567,11 +568,40 @@ return cachep->array[smp_processor_id()]; } -/* Initialisation - setup the `cache' cache. */ +/* Initialisation. + * Called after the gfp() functions have been enabled, and before smp_init(). + */ void __init kmem_cache_init(void) { size_t left_over; + struct cache_sizes *sizes; + struct cache_names *names; + /* + * Fragmentation resistance on low memory - only use bigger + * page orders on machines with more than 32MB of memory. + */ + if (num_physpages > (32 << 20) >> PAGE_SHIFT) + slab_break_gfp_order = BREAK_GFP_ORDER_HI; + + + /* Bootstrap is tricky, because several objects are allocated + * from caches that do not exist yet: + * 1) initialize the cache_cache cache: it contains the kmem_cache_t + * structures of all caches, except cache_cache itself: cache_cache + * is statically allocated. + * Initially an __init data area is used for the head array, it's + * replaced with a kmalloc allocated array at the end of the bootstrap. + * 2) Create the first kmalloc cache. + * The kmem_cache_t for the new cache is allocated normally. An __init + * data area is used for the head array. + * 3) Create the remaining kmalloc caches, with minimally sized head arrays. + * 4) Replace the __init data head arrays for cache_cache and the first + * kmalloc cache with kmalloc allocated arrays. + * 5) Resize the head arrays of the kmalloc caches to their final sizes. + */ + + /* 1) create the cache_cache */ init_MUTEX(&cache_chain_sem); INIT_LIST_HEAD(&cache_chain); list_add(&cache_cache.next, &cache_chain); @@ -585,27 +615,10 @@ cache_cache.colour = left_over/cache_cache.colour_off; cache_cache.colour_next = 0; - /* Register a cpu startup notifier callback - * that initializes ac_data for all new cpus - */ - register_cpu_notifier(&cpucache_notifier); -} - -/* Initialisation - setup remaining internal and general caches. - * Called after the gfp() functions have been enabled, and before smp_init(). - */ -void __init kmem_cache_sizes_init(void) -{ - struct cache_sizes *sizes = malloc_sizes; - struct cache_names *names = cache_names; - - /* - * Fragmentation resistance on low memory - only use bigger - * page orders on machines with more than 32MB of memory. - */ - if (num_physpages > (32 << 20) >> PAGE_SHIFT) - slab_break_gfp_order = BREAK_GFP_ORDER_HI; + /* 2+3) create the kmalloc caches */ + sizes = malloc_sizes; + names = cache_names; while (sizes->cs_size) { /* For performance, all the general caches are L1 aligned. @@ -634,10 +647,7 @@ sizes++; names++; } - /* - * The generic caches are running - time to kick out the - * bootstrap cpucaches. - */ + /* 4) Replace the bootstrap head arrays */ { void * ptr; @@ -656,29 +666,42 @@ malloc_sizes[0].cs_cachep->array[smp_processor_id()] = ptr; local_irq_enable(); } + + /* 5) resize the head arrays to their final sizes */ + { + kmem_cache_t *cachep; + down(&cache_chain_sem); + list_for_each_entry(cachep, &cache_chain, next) + enable_cpucache(cachep); + up(&cache_chain_sem); + } + + /* Done! */ + g_cpucache_up = FULL; + + /* Register a cpu startup notifier callback + * that initializes ac_data for all new cpus + */ + register_cpu_notifier(&cpucache_notifier); + + + /* The reap timers are started later, with a module init call: + * That part of the kernel is not yet operational. + */ } int __init cpucache_init(void) { - kmem_cache_t *cachep; int cpu; - down(&cache_chain_sem); - g_cpucache_up = FULL; - - list_for_each_entry(cachep, &cache_chain, next) - enable_cpucache(cachep); - /* * Register the timers that return unneeded * pages to gfp. */ - for (cpu = 0; cpu < NR_CPUS; cpu++) { if (cpu_online(cpu)) start_cpu_timer(cpu); } - up(&cache_chain_sem); return 0; } @@ -712,6 +735,7 @@ { unsigned long i = (1<gfporder); struct page *page = virt_to_page(addr); + const unsigned long nr_freed = i; /* free_pages() does not clear the type bit - we do that. * The pages have been unlinked from their cache-slab, @@ -720,9 +744,11 @@ */ while (i--) { ClearPageSlab(page); - dec_page_state(nr_slab); page++; } + sub_page_state(nr_slab, nr_freed); + if (current->reclaim_state) + current->reclaim_state->reclaimed_slab += nr_freed; free_pages((unsigned long)addr, cachep->gfporder); } @@ -914,12 +940,19 @@ } #if FORCED_DEBUG - if ((size < (PAGE_SIZE>>3)) && !(flags & SLAB_MUST_HWCACHE_ALIGN)) - /* - * do not red zone large object, causes severe - * fragmentation. - */ + /* + * Enable redzoning and last user accounting, except + * - for caches with forced alignment: redzoning would violate the + * alignment + * - for caches with large objects, if the increased size would + * increase the object size above the next power of two: caches + * with object sizes just above a power of two have a significant + * amount of internal fragmentation + */ + if ((size < (PAGE_SIZE>>3) || fls(size-1) == fls(size-1+3*BYTES_PER_WORD)) + && !(flags & SLAB_MUST_HWCACHE_ALIGN)) { flags |= SLAB_RED_ZONE|SLAB_STORE_USER; + } flags |= SLAB_POISON; #endif #endif @@ -1756,10 +1789,12 @@ slabp = GET_PAGE_SLAB(virt_to_page(objp)); list_del(&slabp->list); objnr = (objp - slabp->s_mem) / cachep->objsize; + check_slabp(cachep, slabp); slab_bufctl(slabp)[objnr] = slabp->free; slabp->free = objnr; STATS_DEC_ACTIVE(cachep); slabp->inuse--; + check_slabp(cachep, slabp); /* fixup slab chains */ if (slabp->inuse == 0) { diff -Nru a/mm/swapfile.c b/mm/swapfile.c --- a/mm/swapfile.c Thu May 8 00:24:28 2003 +++ b/mm/swapfile.c Thu May 8 00:24:28 2003 @@ -886,6 +886,10 @@ * requirements, they are simply tossed out - we will never use those blocks * for swapping. * + * For S_ISREG swapfiles we hold i_sem across the life of the swapon. This + * prevents root from shooting her foot off by ftruncating an in-use swapfile, + * which will scribble on the fs. + * * The amount of disk space which a single swap extent represents varies. * Typically it is in the 1-4 megabyte range. So we can have hundreds of * extents in the list. To avoid much list walking, we cache the previous @@ -1095,6 +1099,8 @@ bdev = swap_file->f_dentry->d_inode->i_bdev; set_blocksize(bdev, p->old_block_size); bd_release(bdev); + } else { + up(&swap_file->f_dentry->d_inode->i_mapping->host->i_sem); } filp_close(swap_file, NULL); err = 0; @@ -1228,6 +1234,8 @@ int swapfilesize; unsigned short *swap_map; struct page *page = NULL; + struct inode *inode; + struct inode *downed_inode = NULL; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -1274,39 +1282,42 @@ } p->swap_file = swap_file; + inode = swap_file->f_dentry->d_inode; + mapping = swap_file->f_dentry->d_inode->i_mapping; + + error = -EBUSY; + for (i = 0; i < nr_swapfiles; i++) { + struct swap_info_struct *q = &swap_info[i]; + + if (i == type || !q->swap_file) + continue; + if (mapping == q->swap_file->f_dentry->d_inode->i_mapping) + goto bad_swap; + } error = -EINVAL; - if (S_ISBLK(swap_file->f_dentry->d_inode->i_mode)) { - bdev = swap_file->f_dentry->d_inode->i_bdev; + if (S_ISBLK(inode->i_mode)) { + bdev = inode->i_bdev; error = bd_claim(bdev, sys_swapon); if (error < 0) { bdev = NULL; goto bad_swap; } p->old_block_size = block_size(bdev); - error = set_blocksize(swap_file->f_dentry->d_inode->i_bdev, - PAGE_SIZE); + error = set_blocksize(inode->i_bdev, PAGE_SIZE); if (error < 0) goto bad_swap; p->bdev = bdev; - } else if (S_ISREG(swap_file->f_dentry->d_inode->i_mode)) { - p->bdev = swap_file->f_dentry->d_inode->i_sb->s_bdev; + } else if (S_ISREG(inode->i_mode)) { + p->bdev = inode->i_sb->s_bdev; + downed_inode = mapping->host; + down(&downed_inode->i_sem); } else { goto bad_swap; } - mapping = swap_file->f_dentry->d_inode->i_mapping; swapfilesize = mapping->host->i_size >> PAGE_SHIFT; - error = -EBUSY; - for (i = 0 ; i < nr_swapfiles ; i++) { - struct swap_info_struct *q = &swap_info[i]; - if (i == type || !q->swap_file) - continue; - if (mapping == q->swap_file->f_dentry->d_inode->i_mapping) - goto bad_swap; - } - /* * Read the swap header. */ @@ -1452,6 +1463,8 @@ } if (name) putname(name); + if (error && downed_inode) + up(&downed_inode->i_sem); return error; } diff -Nru a/mm/vmalloc.c b/mm/vmalloc.c --- a/mm/vmalloc.c Thu May 8 00:24:29 2003 +++ b/mm/vmalloc.c Thu May 8 00:24:29 2003 @@ -97,8 +97,7 @@ do { struct page *page = **pages; - if (!pte_none(*pte)) - printk(KERN_ERR "alloc_area_pte: page already exists\n"); + WARN_ON(!pte_none(*pte)); if (!page) return -ENOMEM; diff -Nru a/mm/vmscan.c b/mm/vmscan.c --- a/mm/vmscan.c Thu May 8 00:24:27 2003 +++ b/mm/vmscan.c Thu May 8 00:24:27 2003 @@ -817,12 +817,14 @@ * excessive rotation of the inactive list, which is _supposed_ to be an LRU, * yes? */ -int try_to_free_pages(struct zone *classzone, +int try_to_free_pages(struct zone *cz, unsigned int gfp_mask, unsigned int order) { int priority; + int ret = 0; const int nr_pages = SWAP_CLUSTER_MAX; int nr_reclaimed = 0; + struct reclaim_state *reclaim_state = current->reclaim_state; inc_page_state(allocstall); @@ -831,11 +833,12 @@ struct page_state ps; get_page_state(&ps); - nr_reclaimed += shrink_caches(classzone, priority, - &total_scanned, gfp_mask, - nr_pages, &ps); - if (nr_reclaimed >= nr_pages) - return 1; + nr_reclaimed += shrink_caches(cz, priority, &total_scanned, + gfp_mask, nr_pages, &ps); + if (nr_reclaimed >= nr_pages) { + ret = 1; + goto out; + } if (!(gfp_mask & __GFP_FS)) break; /* Let the caller handle it */ /* @@ -847,12 +850,18 @@ /* Take a nap, wait for some writeback to complete */ blk_congestion_wait(WRITE, HZ/10); - if (classzone - classzone->zone_pgdat->node_zones < ZONE_HIGHMEM) + if (cz - cz->zone_pgdat->node_zones < ZONE_HIGHMEM) { shrink_slab(total_scanned, gfp_mask); + if (reclaim_state) { + nr_reclaimed += reclaim_state->reclaimed_slab; + reclaim_state->reclaimed_slab = 0; + } + } } if ((gfp_mask & __GFP_FS) && !(gfp_mask & __GFP_NORETRY)) out_of_memory(); - return 0; +out: + return ret; } /* @@ -878,6 +887,7 @@ int to_free = nr_pages; int priority; int i; + struct reclaim_state *reclaim_state = current->reclaim_state; inc_page_state(pageoutrun); @@ -908,8 +918,11 @@ max_scan = SWAP_CLUSTER_MAX; to_free -= shrink_zone(zone, max_scan, GFP_KERNEL, to_reclaim, &nr_mapped, ps, priority); - if (i < ZONE_HIGHMEM) + if (i < ZONE_HIGHMEM) { + reclaim_state->reclaimed_slab = 0; shrink_slab(max_scan + nr_mapped, GFP_KERNEL); + to_free += reclaim_state->reclaimed_slab; + } if (zone->all_unreclaimable) continue; if (zone->pages_scanned > zone->present_pages * 2) @@ -940,10 +953,14 @@ pg_data_t *pgdat = (pg_data_t*)p; struct task_struct *tsk = current; DEFINE_WAIT(wait); + struct reclaim_state reclaim_state = { + .reclaimed_slab = 0, + }; daemonize("kswapd%d", pgdat->node_id); set_cpus_allowed(tsk, node_to_cpumask(pgdat->node_id)); - + current->reclaim_state = &reclaim_state; + /* * Tell the memory management that we're a "memory allocator", * and that if we need more memory we should get access to it diff -Nru a/net/Kconfig b/net/Kconfig --- a/net/Kconfig Thu May 8 00:24:27 2003 +++ b/net/Kconfig Thu May 8 00:24:27 2003 @@ -266,6 +266,23 @@ subnetwork boundaries. These shortcut connections bypass routers enhancing overall network performance. +config ATM_BR2684 + tristate "RFC1483/2684 Bridged protocols" + depends on ATM && INET + help + ATM PVCs can carry ethernet PDUs according to rfc2684 (formerly 1483) + This device will act like an ethernet from the kernels point of view, + with the traffic being carried by ATM PVCs (currently 1 PVC/device). + This is sometimes used over DSL lines. If in doubt, say N. + +config ATM_BR2684_IPFILTER + bool "Per-VC IP filter kludge" + depends on ATM_BR2684 + help + This is an experimental mechanism for users who need to terminating a + large number of IP-only vcc's. Do not enable this unless you are sure + you know what you are doing. + config VLAN_8021Q tristate "802.1Q VLAN Support" diff -Nru a/net/atm/Makefile b/net/atm/Makefile --- a/net/atm/Makefile Thu May 8 00:24:27 2003 +++ b/net/atm/Makefile Thu May 8 00:24:27 2003 @@ -7,6 +7,7 @@ obj-$(CONFIG_ATM) := addr.o pvc.o signaling.o svc.o common.o atm_misc.o raw.o resources.o obj-$(CONFIG_ATM_CLIP) += clip.o ipcommon.o +obj-$(CONFIG_ATM_BR2684) += br2684.o ipcommon.o obj-$(CONFIG_NET_SCH_ATM) += ipcommon.o obj-$(CONFIG_PROC_FS) += proc.o diff -Nru a/net/atm/br2684.c b/net/atm/br2684.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/net/atm/br2684.c Thu May 8 00:24:30 2003 @@ -0,0 +1,803 @@ +/* +Experimental ethernet netdevice using ATM AAL5 as underlying carrier +(RFC1483 obsoleted by RFC2684) for Linux 2.4 +Author: Marcell GAL, 2000, XDSL Ltd, Hungary +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ipcommon.h" + +/* + * Define this to use a version of the code which interacts with the higher + * layers in a more intellegent way, by always reserving enough space for + * our header at the begining of the packet. However, there may still be + * some problems with programs like tcpdump. In 2.5 we'll sort out what + * we need to do to get this perfect. For now we just will copy the packet + * if we need space for the header + */ +/* #define FASTER_VERSION */ + +#ifdef DEBUG +#define DPRINTK(format, args...) printk(KERN_DEBUG "br2684: " format, ##args) +#else +#define DPRINTK(format, args...) +#endif + +#ifdef SKB_DEBUG +static void skb_debug(const struct sk_buff *skb) +{ +#define NUM2PRINT 50 + char buf[NUM2PRINT * 3 + 1]; /* 3 chars per byte */ + int i = 0; + for (i = 0; i < skb->len && i < NUM2PRINT; i++) { + sprintf(buf + i * 3, "%2.2x ", 0xff & skb->data[i]); + } + printk(KERN_DEBUG "br2684: skb: %s\n", buf); +} +#else +#define skb_debug(skb) do {} while (0) +#endif + +static unsigned char llc_oui_pid_pad[] = + { 0xAA, 0xAA, 0x03, 0x00, 0x80, 0xC2, 0x00, 0x07, 0x00, 0x00 }; +#define PADLEN (2) + +enum br2684_encaps { + e_vc = BR2684_ENCAPS_VC, + e_llc = BR2684_ENCAPS_LLC, +}; + +struct br2684_vcc { + struct atm_vcc *atmvcc; + struct br2684_dev *brdev; + /* keep old push,pop functions for chaining */ + void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb); + /* void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb); */ + enum br2684_encaps encaps; + struct list_head brvccs; +#ifdef CONFIG_ATM_BR2684_IPFILTER + struct br2684_filter filter; +#endif /* CONFIG_ATM_BR2684_IPFILTER */ +#ifndef FASTER_VERSION + unsigned copies_needed, copies_failed; +#endif /* FASTER_VERSION */ +}; + +struct br2684_dev { + struct net_device net_dev; + struct list_head br2684_devs; + int number; + struct list_head brvccs; /* one device <=> one vcc (before xmas) */ + struct net_device_stats stats; + int mac_was_set; +}; + +/* + * This lock should be held for writing any time the list of devices or + * their attached vcc's could be altered. It should be held for reading + * any time these are being queried. Note that we sometimes need to + * do read-locking under interrupt context, so write locking must block + * the current CPU's interrupts + */ +static rwlock_t devs_lock = RW_LOCK_UNLOCKED; + +static LIST_HEAD(br2684_devs); + +static inline struct br2684_dev *BRPRIV(const struct net_device *net_dev) +{ + return (struct br2684_dev *) ((char *) (net_dev) - + (unsigned long) (&((struct br2684_dev *) 0)->net_dev)); +} + +static inline struct br2684_dev *list_entry_brdev(const struct list_head *le) +{ + return list_entry(le, struct br2684_dev, br2684_devs); +} + +static inline struct br2684_vcc *BR2684_VCC(const struct atm_vcc *atmvcc) +{ + return (struct br2684_vcc *) (atmvcc->user_back); +} + +static inline struct br2684_vcc *list_entry_brvcc(const struct list_head *le) +{ + return list_entry(le, struct br2684_vcc, brvccs); +} + +/* Caller should hold read_lock(&devs_lock) */ +static struct br2684_dev *br2684_find_dev(const struct br2684_if_spec *s) +{ + struct list_head *lh; + struct br2684_dev *brdev; + switch (s->method) { + case BR2684_FIND_BYNUM: + list_for_each(lh, &br2684_devs) { + brdev = list_entry_brdev(lh); + if (brdev->number == s->spec.devnum) + return brdev; + } + break; + case BR2684_FIND_BYIFNAME: + list_for_each(lh, &br2684_devs) { + brdev = list_entry_brdev(lh); + if (!strncmp(brdev->net_dev.name, s->spec.ifname, + sizeof brdev->net_dev.name)) + return brdev; + } + break; + } + return NULL; +} + +/* + * Send a packet out a particular vcc. Not to useful right now, but paves + * the way for multiple vcc's per itf. Returns true if we can send, + * otherwise false + */ +static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev, + struct br2684_vcc *brvcc) +{ + struct atm_vcc *atmvcc; +#ifdef FASTER_VERSION + if (brvcc->encaps == e_llc) + memcpy(skb_push(skb, 8), llc_oui_pid_pad, 8); + /* last 2 bytes of llc_oui_pid_pad are managed by header routines; + yes, you got it: 8 + 2 = sizeof(llc_oui_pid_pad) + */ +#else + int minheadroom = (brvcc->encaps == e_llc) ? 10 : 2; + if (skb_headroom(skb) < minheadroom) { + struct sk_buff *skb2 = skb_realloc_headroom(skb, minheadroom); + brvcc->copies_needed++; + dev_kfree_skb(skb); + if (skb2 == NULL) { + brvcc->copies_failed++; + return 0; + } + skb = skb2; + } + skb_push(skb, minheadroom); + if (brvcc->encaps == e_llc) + memcpy(skb->data, llc_oui_pid_pad, 10); + else + memset(skb->data, 0, 2); +#endif /* FASTER_VERSION */ + skb_debug(skb); + + ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc; + DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev); + if (!atm_may_send(atmvcc, skb->truesize)) { + /* we free this here for now, because we cannot know in a higher + layer whether the skb point it supplied wasn't freed yet. + now, it always is. + */ + dev_kfree_skb(skb); + return 0; + } + atomic_add(skb->truesize, &atmvcc->sk->wmem_alloc); + ATM_SKB(skb)->atm_options = atmvcc->atm_options; + brdev->stats.tx_packets++; + brdev->stats.tx_bytes += skb->len; + atmvcc->send(atmvcc, skb); + return 1; +} + +static inline struct br2684_vcc *pick_outgoing_vcc(struct sk_buff *skb, + struct br2684_dev *brdev) +{ + return list_empty(&brdev->brvccs) ? NULL : + list_entry_brvcc(brdev->brvccs.next); /* 1 vcc/dev right now */ +} + +static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct br2684_dev *brdev = BRPRIV(dev); + struct br2684_vcc *brvcc; + + DPRINTK("br2684_start_xmit, skb->dst=%p\n", skb->dst); + read_lock(&devs_lock); + brvcc = pick_outgoing_vcc(skb, brdev); + if (brvcc == NULL) { + DPRINTK("no vcc attached to dev %s\n", dev->name); + brdev->stats.tx_errors++; + brdev->stats.tx_carrier_errors++; + /* netif_stop_queue(dev); */ + dev_kfree_skb(skb); + read_unlock(&devs_lock); + return -EUNATCH; + } + if (!br2684_xmit_vcc(skb, brdev, brvcc)) { + /* + * We should probably use netif_*_queue() here, but that + * involves added complication. We need to walk before + * we can run + */ + /* don't free here! this pointer might be no longer valid! + dev_kfree_skb(skb); + */ + brdev->stats.tx_errors++; + brdev->stats.tx_fifo_errors++; + } + read_unlock(&devs_lock); + return 0; +} + +static struct net_device_stats *br2684_get_stats(struct net_device *dev) +{ + DPRINTK("br2684_get_stats\n"); + return &BRPRIV(dev)->stats; +} + +#ifdef FASTER_VERSION +/* + * These mirror eth_header and eth_header_cache. They are not usually + * exported for use in modules, so we grab them from net_device + * after ether_setup() is done with it. Bit of a hack. + */ +static int (*my_eth_header)(struct sk_buff *, struct net_device *, + unsigned short, void *, void *, unsigned); +static int (*my_eth_header_cache)(struct neighbour *, struct hh_cache *); + +static int +br2684_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, void *daddr, void *saddr, unsigned len) +{ + u16 *pad_before_eth; + int t = my_eth_header(skb, dev, type, daddr, saddr, len); + if (t > 0) { + pad_before_eth = (u16 *) skb_push(skb, 2); + *pad_before_eth = 0; + return dev->hard_header_len; /* or return 16; ? */ + } else + return t; +} + +static int +br2684_header_cache(struct neighbour *neigh, struct hh_cache *hh) +{ +/* hh_data is 16 bytes long. if encaps is ether-llc we need 24, so +xmit will add the additional header part in that case */ + u16 *pad_before_eth = (u16 *)(hh->hh_data); + int t = my_eth_header_cache(neigh, hh); + DPRINTK("br2684_header_cache, neigh=%p, hh_cache=%p\n", neigh, hh); + if (t < 0) + return t; + else { + *pad_before_eth = 0; + hh->hh_len = PADLEN + ETH_HLEN; + } + return 0; +} + +/* + * This is similar to eth_type_trans, which cannot be used because of + * our dev->hard_header_len + */ +static inline unsigned short br_type_trans(struct sk_buff *skb, + struct net_device *dev) +{ + struct ethhdr *eth; + unsigned char *rawp; + eth = skb->mac.ethernet; + + if (*eth->h_dest & 1) { + if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0) + skb->pkt_type = PACKET_BROADCAST; + else + skb->pkt_type = PACKET_MULTICAST; + } + + else if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN)) + skb->pkt_type = PACKET_OTHERHOST; + + if (ntohs(eth->h_proto) >= 1536) + return eth->h_proto; + + rawp = skb->data; + + /* + * This is a magic hack to spot IPX packets. Older Novell breaks + * the protocol design and runs IPX over 802.3 without an 802.2 LLC + * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This + * won't work for fault tolerant netware but does for the rest. + */ + if (*(unsigned short *) rawp == 0xFFFF) + return htons(ETH_P_802_3); + + /* + * Real 802.2 LLC + */ + return htons(ETH_P_802_2); +} +#endif /* FASTER_VERSION */ + +/* + * We remember when the MAC gets set, so we don't override it later with + * the ESI of the ATM card of the first VC + */ +static int (*my_eth_mac_addr)(struct net_device *, void *); +static int br2684_mac_addr(struct net_device *dev, void *p) +{ + int err = my_eth_mac_addr(dev, p); + if (!err) + BRPRIV(dev)->mac_was_set = 1; + return err; +} + +#ifdef CONFIG_ATM_BR2684_IPFILTER +/* this IOCTL is experimental. */ +static int br2684_setfilt(struct atm_vcc *atmvcc, unsigned long arg) +{ + struct br2684_vcc *brvcc; + struct br2684_filter_set fs; + + if (copy_from_user(&fs, (void *) arg, sizeof fs)) + return -EFAULT; + if (fs.ifspec.method != BR2684_FIND_BYNOTHING) { + /* + * This is really a per-vcc thing, but we can also search + * by device + */ + struct br2684_dev *brdev; + read_lock(&devs_lock); + brdev = br2684_find_dev(&fs.ifspec); + if (brdev == NULL || list_empty(&brdev->brvccs) || + brdev->brvccs.next != brdev->brvccs.prev) /* >1 VCC */ + brvcc = NULL; + else + brvcc = list_entry_brvcc(brdev->brvccs.next); + read_unlock(&devs_lock); + if (brvcc == NULL) + return -ESRCH; + } else + brvcc = BR2684_VCC(atmvcc); + memcpy(&brvcc->filter, &fs.filter, sizeof(brvcc->filter)); + return 0; +} + +/* Returns 1 if packet should be dropped */ +static inline int +packet_fails_filter(u16 type, struct br2684_vcc *brvcc, struct sk_buff *skb) +{ + if (brvcc->filter.netmask == 0) + return 0; /* no filter in place */ + if (type == __constant_htons(ETH_P_IP) && + (((struct iphdr *) (skb->data))->daddr & brvcc->filter. + netmask) == brvcc->filter.prefix) + return 0; + if (type == __constant_htons(ETH_P_ARP)) + return 0; + /* TODO: we should probably filter ARPs too.. don't want to have + * them returning values that don't make sense, or is that ok? + */ + return 1; /* drop */ +} +#endif /* CONFIG_ATM_BR2684_IPFILTER */ + +static void br2684_close_vcc(struct br2684_vcc *brvcc) +{ + DPRINTK("removing VCC %p from dev %p\n", brvcc, brvcc->brdev); + write_lock_irq(&devs_lock); + list_del(&brvcc->brvccs); + write_unlock_irq(&devs_lock); + brvcc->atmvcc->user_back = NULL; /* what about vcc->recvq ??? */ + brvcc->old_push(brvcc->atmvcc, NULL); /* pass on the bad news */ + kfree(brvcc); + MOD_DEC_USE_COUNT; +} + +/* when AAL5 PDU comes in: */ +static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) +{ + struct br2684_vcc *brvcc = BR2684_VCC(atmvcc); + struct br2684_dev *brdev = brvcc->brdev; + int plen = sizeof(llc_oui_pid_pad) + ETH_HLEN; + + DPRINTK("br2684_push\n"); + + if (skb == NULL) { /* skb==NULL means VCC is being destroyed */ + br2684_close_vcc(brvcc); + if (list_empty(&brdev->brvccs)) { + read_lock(&devs_lock); + list_del(&brdev->br2684_devs); + read_unlock(&devs_lock); + unregister_netdev(&brdev->net_dev); + kfree(brdev); + } + return; + } + + skb_debug(skb); + atm_return(atmvcc, skb->truesize); + DPRINTK("skb from brdev %p\n", brdev); + if (brvcc->encaps == e_llc) { + /* let us waste some time for checking the encapsulation. + Note, that only 7 char is checked so frames with a valid FCS + are also accepted (but FCS is not checked of course) */ + if (memcmp(skb->data, llc_oui_pid_pad, 7)) { + brdev->stats.rx_errors++; + dev_kfree_skb(skb); + return; + } + } else { + plen = PADLEN + ETH_HLEN; /* pad, dstmac,srcmac, ethtype */ + /* first 2 chars should be 0 */ + if (*((u16 *) (skb->data)) != 0) { + brdev->stats.rx_errors++; + dev_kfree_skb(skb); + return; + } + } + if (skb->len < plen) { + brdev->stats.rx_errors++; + dev_kfree_skb(skb); /* dev_ not needed? */ + return; + } + +#ifdef FASTER_VERSION + /* FIXME: tcpdump shows that pointer to mac header is 2 bytes earlier, + than should be. What else should I set? */ + skb_pull(skb, plen); + skb->mac.raw = ((char *) (skb->data)) - ETH_HLEN; + skb->pkt_type = PACKET_HOST; +#ifdef CONFIG_BR2684_FAST_TRANS + skb->protocol = ((u16 *) skb->data)[-1]; +#else /* some protocols might require this: */ + skb->protocol = br_type_trans(skb, &brdev->net_dev); +#endif /* CONFIG_BR2684_FAST_TRANS */ +#else + skb_pull(skb, plen - ETH_HLEN); + skb->protocol = eth_type_trans(skb, &brdev->net_dev); +#endif /* FASTER_VERSION */ +#ifdef CONFIG_ATM_BR2684_IPFILTER + if (packet_fails_filter(skb->protocol, brvcc, skb)) { + brdev->stats.rx_dropped++; + dev_kfree_skb(skb); + return; + } +#endif /* CONFIG_ATM_BR2684_IPFILTER */ + skb->dev = &brdev->net_dev; + ATM_SKB(skb)->vcc = atmvcc; /* needed ? */ + DPRINTK("received packet's protocol: %x\n", ntohs(skb->protocol)); + skb_debug(skb); + if (!(brdev->net_dev.flags & IFF_UP)) { /* sigh, interface is down */ + brdev->stats.rx_dropped++; + dev_kfree_skb(skb); + return; + } + brdev->stats.rx_packets++; + brdev->stats.rx_bytes += skb->len; + netif_rx(skb); +} + +static int br2684_regvcc(struct atm_vcc *atmvcc, unsigned long arg) +{ +/* assign a vcc to a dev +Note: we do not have explicit unassign, but look at _push() +*/ + int err; + struct br2684_vcc *brvcc; + struct sk_buff_head copy; + struct sk_buff *skb; + struct br2684_dev *brdev; + struct atm_backend_br2684 be; + + MOD_INC_USE_COUNT; + if (copy_from_user(&be, (void *) arg, sizeof be)) { + MOD_DEC_USE_COUNT; + return -EFAULT; + } + write_lock_irq(&devs_lock); + brdev = br2684_find_dev(&be.ifspec); + if (brdev == NULL) { + printk(KERN_ERR + "br2684: tried to attach to non-existant device\n"); + err = -ENXIO; + goto error; + } + if (atmvcc->push == NULL) { + err = -EBADFD; + goto error; + } + if (!list_empty(&brdev->brvccs)) { /* Only 1 VCC/dev right now */ + err = -EEXIST; + goto error; + } + if (be.fcs_in != BR2684_FCSIN_NO || be.fcs_out != BR2684_FCSOUT_NO || + be.fcs_auto || be.has_vpiid || be.send_padding || (be.encaps != + BR2684_ENCAPS_VC && be.encaps != BR2684_ENCAPS_LLC) || + be.min_size != 0) { + err = -EINVAL; + goto error; + } + brvcc = kmalloc(sizeof(struct br2684_vcc), GFP_KERNEL); + if (!brvcc) { + err = -ENOMEM; + goto error; + } + memset(brvcc, 0, sizeof(struct br2684_vcc)); + DPRINTK("br2684_regvcc vcc=%p, encaps=%d, brvcc=%p\n", atmvcc, be.encaps, + brvcc); + if (list_empty(&brdev->brvccs) && !brdev->mac_was_set) { + unsigned char *esi = atmvcc->dev->esi; + if (esi[0] | esi[1] | esi[2] | esi[3] | esi[4] | esi[5]) + memcpy(brdev->net_dev.dev_addr, esi, + brdev->net_dev.addr_len); + else + brdev->net_dev.dev_addr[2] = 1; + } + list_add(&brvcc->brvccs, &brdev->brvccs); + write_unlock_irq(&devs_lock); + brvcc->brdev = brdev; + brvcc->atmvcc = atmvcc; + atmvcc->user_back = brvcc; + brvcc->encaps = (enum br2684_encaps) be.encaps; + brvcc->old_push = atmvcc->push; + barrier(); + atmvcc->push = br2684_push; + skb_queue_head_init(©); + skb_migrate(&atmvcc->sk->receive_queue, ©); + while ((skb = skb_dequeue(©))) { + BRPRIV(skb->dev)->stats.rx_bytes -= skb->len; + BRPRIV(skb->dev)->stats.rx_packets--; + br2684_push(atmvcc, skb); + } + return 0; + error: + write_unlock_irq(&devs_lock); + MOD_DEC_USE_COUNT; + return err; +} + +static int br2684_create(unsigned long arg) +{ + int err; + struct br2684_dev *brdev; + struct atm_newif_br2684 ni; + + DPRINTK("br2684_create\n"); + /* + * We track module use by vcc's NOT the devices they're on. We're + * protected here against module death by the kernel_lock, but if + * we need to sleep we should make sure that the module doesn't + * disappear under us. + */ + MOD_INC_USE_COUNT; + if (copy_from_user(&ni, (void *) arg, sizeof ni)) { + MOD_DEC_USE_COUNT; + return -EFAULT; + } + if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500) { + MOD_DEC_USE_COUNT; + return -EINVAL; + } + if ((brdev = kmalloc(sizeof(struct br2684_dev), GFP_KERNEL)) == NULL) { + MOD_DEC_USE_COUNT; + return -ENOMEM; + } + memset(brdev, 0, sizeof(struct br2684_dev)); + INIT_LIST_HEAD(&brdev->brvccs); + + write_lock_irq(&devs_lock); + brdev->number = list_empty(&br2684_devs) ? 1 : + list_entry_brdev(br2684_devs.prev)->number + 1; + list_add_tail(&brdev->br2684_devs, &br2684_devs); + write_unlock_irq(&devs_lock); + + if (ni.ifname[0] != '\0') { + memcpy(brdev->net_dev.name, ni.ifname, + sizeof(brdev->net_dev.name)); + brdev->net_dev.name[sizeof(brdev->net_dev.name) - 1] = '\0'; + } else + sprintf(brdev->net_dev.name, "nas%d", brdev->number); + DPRINTK("registered netdev %s\n", brdev->net_dev.name); + ether_setup(&brdev->net_dev); + brdev->mac_was_set = 0; +#ifdef FASTER_VERSION + my_eth_header = brdev->net_dev.hard_header; + brdev->net_dev.hard_header = br2684_header; + my_eth_header_cache = brdev->net_dev.hard_header_cache; + brdev->net_dev.hard_header_cache = br2684_header_cache; + brdev->net_dev.hard_header_len = sizeof(llc_oui_pid_pad) + ETH_HLEN; /* 10 + 14 */ +#endif + my_eth_mac_addr = brdev->net_dev.set_mac_address; + brdev->net_dev.set_mac_address = br2684_mac_addr; + brdev->net_dev.hard_start_xmit = br2684_start_xmit; + brdev->net_dev.get_stats = br2684_get_stats; + + /* open, stop, do_ioctl ? */ + err = register_netdev(&brdev->net_dev); + MOD_DEC_USE_COUNT; + if (err < 0) { + printk(KERN_ERR "br2684_create: register_netdev failed\n"); + write_lock_irq(&devs_lock); + list_del(&brdev->br2684_devs); + write_unlock_irq(&devs_lock); + kfree(brdev); + return err; + } + return 0; +} + +/* + * This handles ioctls actually performed on our vcc - we must return + * -ENOIOCTLCMD for any unrecognized ioctl + */ +static int br2684_ioctl(struct atm_vcc *atmvcc, unsigned int cmd, + unsigned long arg) +{ + int err; + switch(cmd) { + case ATM_SETBACKEND: + case ATM_NEWBACKENDIF: { + atm_backend_t b; + MOD_INC_USE_COUNT; + err = get_user(b, (atm_backend_t *) arg); + MOD_DEC_USE_COUNT; + if (err) + return -EFAULT; + if (b != ATM_BACKEND_BR2684) + return -ENOIOCTLCMD; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (cmd == ATM_SETBACKEND) + return br2684_regvcc(atmvcc, arg); + else + return br2684_create(arg); + } +#ifdef CONFIG_ATM_BR2684_IPFILTER + case BR2684_SETFILT: + if (atmvcc->push != br2684_push) + return -ENOIOCTLCMD; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + MOD_INC_USE_COUNT; + err = br2684_setfilt(atmvcc, arg); + MOD_DEC_USE_COUNT; + return err; +#endif /* CONFIG_ATM_BR2684_IPFILTER */ + } + return -ENOIOCTLCMD; +} + +/* Never put more than 256 bytes in at once */ +static int br2684_proc_engine(loff_t pos, char *buf) +{ + struct list_head *lhd, *lhc; + struct br2684_dev *brdev; + struct br2684_vcc *brvcc; + list_for_each(lhd, &br2684_devs) { + brdev = list_entry_brdev(lhd); + if (pos-- == 0) + return sprintf(buf, "dev %.16s: num=%d, mac=%02X:%02X:" + "%02X:%02X:%02X:%02X (%s)\n", brdev->net_dev.name, + brdev->number, + brdev->net_dev.dev_addr[0], + brdev->net_dev.dev_addr[1], + brdev->net_dev.dev_addr[2], + brdev->net_dev.dev_addr[3], + brdev->net_dev.dev_addr[4], + brdev->net_dev.dev_addr[5], + brdev->mac_was_set ? "set" : "auto"); + list_for_each(lhc, &brdev->brvccs) { + brvcc = list_entry_brvcc(lhc); + if (pos-- == 0) + return sprintf(buf, " vcc %d.%d.%d: encaps=%s" +#ifndef FASTER_VERSION + ", failed copies %u/%u" +#endif /* FASTER_VERSION */ + "\n", brvcc->atmvcc->dev->number, + brvcc->atmvcc->vpi, brvcc->atmvcc->vci, + (brvcc->encaps == e_llc) ? "LLC" : "VC" +#ifndef FASTER_VERSION + , brvcc->copies_failed + , brvcc->copies_needed +#endif /* FASTER_VERSION */ + ); +#ifdef CONFIG_ATM_BR2684_IPFILTER +#define b1(var, byte) ((u8 *) &brvcc->filter.var)[byte] +#define bs(var) b1(var, 0), b1(var, 1), b1(var, 2), b1(var, 3) + if (brvcc->filter.netmask != 0 && pos-- == 0) + return sprintf(buf, " filter=%d.%d.%d.%d/" + "%d.%d.%d.%d\n", bs(prefix), bs(netmask)); +#undef bs +#undef b1 +#endif /* CONFIG_ATM_BR2684_IPFILTER */ + } + } + return 0; +} + +static ssize_t br2684_proc_read(struct file *file, char *buf, size_t count, + loff_t *pos) +{ + unsigned long page; + int len = 0, x, left; + page = get_zeroed_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + left = PAGE_SIZE - 256; + if (count < left) + left = count; + read_lock(&devs_lock); + for (;;) { + x = br2684_proc_engine(*pos, &((char *) page)[len]); + if (x == 0) + break; + if (x > left) + /* + * This should only happen if the user passed in + * a "count" too small for even one line + */ + x = -EINVAL; + if (x < 0) { + len = x; + break; + } + len += x; + left -= x; + (*pos)++; + if (left < 256) + break; + } + read_unlock(&devs_lock); + if (len > 0 && copy_to_user(buf, (char *) page, len)) + len = -EFAULT; + free_page(page); + return len; +} + +static struct file_operations br2684_proc_operations = { + read: br2684_proc_read, +}; + +extern struct proc_dir_entry *atm_proc_root; /* from proc.c */ + +extern int (*br2684_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long); + +/* the following avoids some spurious warnings from the compiler */ +#define UNUSED __attribute__((unused)) + +static int __init UNUSED br2684_init(void) +{ + struct proc_dir_entry *p; + if ((p = create_proc_entry("br2684", 0, atm_proc_root)) == NULL) + return -ENOMEM; + p->proc_fops = &br2684_proc_operations; + br2684_ioctl_hook = br2684_ioctl; + return 0; +} + +static void __exit UNUSED br2684_exit(void) +{ + struct br2684_dev *brdev; + br2684_ioctl_hook = NULL; + remove_proc_entry("br2684", atm_proc_root); + while (!list_empty(&br2684_devs)) { + brdev = list_entry_brdev(br2684_devs.next); + unregister_netdev(&brdev->net_dev); + list_del(&brdev->br2684_devs); + kfree(brdev); + } +} + +module_init(br2684_init); +module_exit(br2684_exit); + +MODULE_AUTHOR("Marcell GAL"); +MODULE_DESCRIPTION("RFC2684 bridged protocols over ATM/AAL5"); +MODULE_LICENSE("GPL"); diff -Nru a/net/atm/clip.c b/net/atm/clip.c --- a/net/atm/clip.c Thu May 8 00:24:30 2003 +++ b/net/atm/clip.c Thu May 8 00:24:30 2003 @@ -127,6 +127,8 @@ struct atmarp_entry *entry = NEIGH2ENTRY(n); struct clip_vcc *clip_vcc; + write_lock(&n->lock); + for (clip_vcc = entry->vccs; clip_vcc; clip_vcc = clip_vcc->next) if (clip_vcc->idle_timeout && @@ -141,6 +143,7 @@ if (entry->vccs || time_before(jiffies, entry->expires)) { np = &n->next; + write_unlock(&n->lock); continue; } if (atomic_read(&n->refcnt) > 1) { @@ -152,11 +155,13 @@ NULL) dev_kfree_skb(skb); np = &n->next; + write_unlock(&n->lock); continue; } *np = n->next; DPRINTK("expired neigh %p\n",n); n->dead = 1; + write_unlock(&n->lock); neigh_release(n); } } diff -Nru a/net/atm/common.c b/net/atm/common.c --- a/net/atm/common.c Thu May 8 00:24:30 2003 +++ b/net/atm/common.c Thu May 8 00:24:30 2003 @@ -62,6 +62,13 @@ EXPORT_SYMBOL(pppoatm_ioctl_hook); #endif +#if defined(CONFIG_ATM_BR2684) || defined(CONFIG_ATM_BR2684_MODULE) +int (*br2684_ioctl_hook)(struct atm_vcc *, unsigned int, unsigned long); +#ifdef CONFIG_ATM_BR2684_MODULE +EXPORT_SYMBOL(br2684_ioctl_hook); +#endif +#endif + #include "resources.h" /* atm_find_dev */ #include "common.h" /* prototypes */ #include "protocols.h" /* atm_init_ */ @@ -120,7 +127,6 @@ vcc->vpi = vcc->vci = 0; /* no VCI/VPI yet */ vcc->atm_options = vcc->aal_options = 0; init_waitqueue_head(&vcc->sleep); - skb_queue_head_init(&vcc->listenq); sk->sleep = &vcc->sleep; sock->sk = sk; return 0; @@ -489,7 +495,7 @@ vcc = ATM_SD(sock); poll_wait(file,&vcc->sleep,wait); mask = 0; - if (skb_peek(&vcc->sk->receive_queue) || skb_peek(&vcc->listenq)) + if (skb_peek(&vcc->sk->receive_queue)) mask |= POLLIN | POLLRDNORM; if (test_bit(ATM_VF_RELEASED,&vcc->flags) || test_bit(ATM_VF_CLOSE,&vcc->flags)) @@ -781,6 +787,13 @@ #if defined(CONFIG_PPPOATM) || defined(CONFIG_PPPOATM_MODULE) if (pppoatm_ioctl_hook) { ret_val = pppoatm_ioctl_hook(vcc, cmd, arg); + if (ret_val != -ENOIOCTLCMD) + goto done; + } +#endif +#if defined(CONFIG_ATM_BR2684) || defined(CONFIG_ATM_BR2684_MODULE) + if (br2684_ioctl_hook) { + ret_val = br2684_ioctl_hook(vcc, cmd, arg); if (ret_val != -ENOIOCTLCMD) goto done; } diff -Nru a/net/atm/lec.c b/net/atm/lec.c --- a/net/atm/lec.c Thu May 8 00:24:29 2003 +++ b/net/atm/lec.c Thu May 8 00:24:29 2003 @@ -302,7 +302,7 @@ #endif min_frame_size = LEC_MINIMUM_8023_SIZE; if (skb->len < min_frame_size) { - if (skb->truesize < min_frame_size) { + if ((skb->len + skb_tailroom(skb)) < min_frame_size) { skb2 = skb_copy_expand(skb, 0, min_frame_size - skb->truesize, GFP_ATOMIC); dev_kfree_skb(skb); diff -Nru a/net/atm/mpc.c b/net/atm/mpc.c --- a/net/atm/mpc.c Thu May 8 00:24:29 2003 +++ b/net/atm/mpc.c Thu May 8 00:24:29 2003 @@ -324,7 +324,9 @@ return; } -static const char * __attribute__ ((unused)) mpoa_device_type_string(char type) +static const char *mpoa_device_type_string(char type) __attribute__ ((unused)); + +static const char *mpoa_device_type_string(char type) { switch(type) { case NON_MPOA: @@ -429,7 +431,7 @@ if (tlvs == NULL) return; } if (end_of_tlvs - tlvs != 0) - printk("mpoa: (%s) lane2_assoc_ind: ignoring %d bytes of trailing TLV carbage\n", + printk("mpoa: (%s) lane2_assoc_ind: ignoring %Zd bytes of trailing TLV carbage\n", dev->name, end_of_tlvs - tlvs); return; } diff -Nru a/net/atm/signaling.c b/net/atm/signaling.c --- a/net/atm/signaling.c Thu May 8 00:24:29 2003 +++ b/net/atm/signaling.c Thu May 8 00:24:29 2003 @@ -129,12 +129,12 @@ case as_indicate: vcc = *(struct atm_vcc **) &msg->listen_vcc; DPRINTK("as_indicate!!!\n"); - if (!vcc->backlog_quota) { + if (vcc->sk->ack_backlog == vcc->sk->max_ack_backlog) { sigd_enq(0,as_reject,vcc,NULL,NULL); return 0; } - vcc->backlog_quota--; - skb_queue_tail(&vcc->listenq,skb); + vcc->sk->ack_backlog++; + skb_queue_tail(&vcc->sk->receive_queue,skb); if (vcc->callback) { DPRINTK("waking vcc->sleep 0x%p\n", &vcc->sleep); diff -Nru a/net/atm/svc.c b/net/atm/svc.c --- a/net/atm/svc.c Thu May 8 00:24:29 2003 +++ b/net/atm/svc.c Thu May 8 00:24:29 2003 @@ -64,8 +64,8 @@ DPRINTK("svc_disconnect %p\n",vcc); if (test_bit(ATM_VF_REGIS,&vcc->flags)) { - sigd_enq(vcc,as_close,NULL,NULL,NULL); add_wait_queue(&vcc->sleep,&wait); + sigd_enq(vcc,as_close,NULL,NULL,NULL); while (!test_bit(ATM_VF_RELEASED,&vcc->flags) && sigd) { set_current_state(TASK_UNINTERRUPTIBLE); schedule(); @@ -74,7 +74,7 @@ } /* beware - socket is still in use by atmsigd until the last as_indicate has been answered */ - while ((skb = skb_dequeue(&vcc->listenq))) { + while ((skb = skb_dequeue(&vcc->sk->receive_queue))) { DPRINTK("LISTEN REL\n"); sigd_enq2(NULL,as_reject,vcc,NULL,NULL,&vcc->qos,0); dev_kfree_skb(skb); @@ -124,8 +124,8 @@ if (!test_bit(ATM_VF_HASQOS,&vcc->flags)) return -EBADFD; vcc->local = *addr; vcc->reply = WAITING; - sigd_enq(vcc,as_bind,NULL,NULL,&vcc->local); add_wait_queue(&vcc->sleep,&wait); + sigd_enq(vcc,as_bind,NULL,NULL,&vcc->local); while (vcc->reply == WAITING && sigd) { set_current_state(TASK_UNINTERRUPTIBLE); schedule(); @@ -169,12 +169,13 @@ !vcc->qos.rxtp.traffic_class) return -EINVAL; vcc->remote = *addr; vcc->reply = WAITING; + add_wait_queue(&vcc->sleep,&wait); sigd_enq(vcc,as_connect,NULL,NULL,&vcc->remote); if (flags & O_NONBLOCK) { + remove_wait_queue(&vcc->sleep,&wait); sock->state = SS_CONNECTING; return -EINPROGRESS; } - add_wait_queue(&vcc->sleep,&wait); error = 0; while (vcc->reply == WAITING && sigd) { set_current_state(TASK_INTERRUPTIBLE); @@ -243,8 +244,8 @@ /* let server handle listen on unbound sockets */ if (test_bit(ATM_VF_SESSION,&vcc->flags)) return -EINVAL; vcc->reply = WAITING; - sigd_enq(vcc,as_listen,NULL,NULL,&vcc->local); add_wait_queue(&vcc->sleep,&wait); + sigd_enq(vcc,as_listen,NULL,NULL,&vcc->local); while (vcc->reply == WAITING && sigd) { set_current_state(TASK_UNINTERRUPTIBLE); schedule(); @@ -252,7 +253,7 @@ remove_wait_queue(&vcc->sleep,&wait); if (!sigd) return -EUNATCH; set_bit(ATM_VF_LISTEN,&vcc->flags); - vcc->backlog_quota = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT; + vcc->sk->max_ack_backlog = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT; return vcc->reply; } @@ -276,7 +277,7 @@ DECLARE_WAITQUEUE(wait,current); add_wait_queue(&old_vcc->sleep,&wait); - while (!(skb = skb_dequeue(&old_vcc->listenq)) && sigd) { + while (!(skb = skb_dequeue(&old_vcc->sk->receive_queue)) && sigd) { if (test_bit(ATM_VF_RELEASED,&old_vcc->flags)) break; if (test_bit(ATM_VF_CLOSE,&old_vcc->flags)) { error = old_vcc->reply; @@ -305,7 +306,7 @@ error = atm_connect(newsock,msg->pvc.sap_addr.itf, msg->pvc.sap_addr.vpi,msg->pvc.sap_addr.vci); dev_kfree_skb(skb); - old_vcc->backlog_quota++; + old_vcc->sk->ack_backlog--; if (error) { sigd_enq2(NULL,as_reject,old_vcc,NULL,NULL, &old_vcc->qos,error); @@ -313,8 +314,8 @@ } /* wait should be short, so we ignore the non-blocking flag */ new_vcc->reply = WAITING; - sigd_enq(new_vcc,as_accept,old_vcc,NULL,NULL); add_wait_queue(&new_vcc->sleep,&wait); + sigd_enq(new_vcc,as_accept,old_vcc,NULL,NULL); while (new_vcc->reply == WAITING && sigd) { set_current_state(TASK_UNINTERRUPTIBLE); schedule(); @@ -347,8 +348,8 @@ DECLARE_WAITQUEUE(wait,current); vcc->reply = WAITING; - sigd_enq2(vcc,as_modify,NULL,NULL,&vcc->local,qos,0); add_wait_queue(&vcc->sleep,&wait); + sigd_enq2(vcc,as_modify,NULL,NULL,&vcc->local,qos,0); while (vcc->reply == WAITING && !test_bit(ATM_VF_RELEASED,&vcc->flags) && sigd) { set_current_state(TASK_UNINTERRUPTIBLE); diff -Nru a/net/bridge/br_input.c b/net/bridge/br_input.c --- a/net/bridge/br_input.c Thu May 8 00:24:28 2003 +++ b/net/bridge/br_input.c Thu May 8 00:24:28 2003 @@ -143,6 +143,9 @@ return -1; } + if (!memcmp(p->br->dev.dev_addr, dest, ETH_ALEN)) + skb->pkt_type = PACKET_HOST; + NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL, br_handle_frame_finish); rcu_read_unlock(); diff -Nru a/net/core/neighbour.c b/net/core/neighbour.c --- a/net/core/neighbour.c Thu May 8 00:24:27 2003 +++ b/net/core/neighbour.c Thu May 8 00:24:27 2003 @@ -440,8 +440,8 @@ if (!neigh->dead) { printk(KERN_WARNING - "Destroying alive neighbour %p from %08lx\n", neigh, - *(((unsigned long *)&neigh) - 1)); + "Destroying alive neighbour %p\n", neigh); + dump_stack(); return; } diff -Nru a/net/core/skbuff.c b/net/core/skbuff.c --- a/net/core/skbuff.c Thu May 8 00:24:29 2003 +++ b/net/core/skbuff.c Thu May 8 00:24:29 2003 @@ -126,9 +126,6 @@ struct sk_buff *skb; u8 *data; - if (gfp_mask & __GFP_WAIT) - might_sleep(); - /* Get the HEAD */ skb = kmem_cache_alloc(skbuff_head_cache, gfp_mask & ~__GFP_DMA); diff -Nru a/net/decnet/Kconfig b/net/decnet/Kconfig --- a/net/decnet/Kconfig Thu May 8 00:24:30 2003 +++ b/net/decnet/Kconfig Thu May 8 00:24:30 2003 @@ -17,11 +17,11 @@ depends on DECNET && EXPERIMENTAL ---help--- Add support for turning your DECnet Endnode into a level 1 or 2 - router. This is an unfinished option for developers only. If you + router. This is an experimental, but functional option. If you do say Y here, then make sure that you also say Y to "Kernel/User network link driver", "Routing messages" and "Network packet filtering". The first two are required to allow configuration via - rtnetlink (currently you need Alexey Kuznetsov's iproute2 package + rtnetlink (you will need Alexey Kuznetsov's iproute2 package from ). The "Network packet filtering" option will be required for the forthcoming routing daemon to work. @@ -34,4 +34,6 @@ If you say Y here, you will be able to specify different routes for packets with different FWMARK ("firewalling mark") values (see ipchains(8), "-m" argument). + +source "net/decnet/netfilter/Kconfig" diff -Nru a/net/decnet/Makefile b/net/decnet/Makefile --- a/net/decnet/Makefile Thu May 8 00:24:28 2003 +++ b/net/decnet/Makefile Thu May 8 00:24:28 2003 @@ -1,7 +1,10 @@ obj-$(CONFIG_DECNET) += decnet.o -decnet-y := af_decnet.o dn_nsp_in.o dn_nsp_out.o dn_route.o dn_dev.o dn_neigh.o dn_timer.o +decnet-y := af_decnet.o dn_nsp_in.o dn_nsp_out.o \ + dn_route.o dn_dev.o dn_neigh.o dn_timer.o decnet-$(CONFIG_DECNET_ROUTER) += dn_fib.o dn_rules.o dn_table.o -decnet-$(CONFIG_DECNET_FW) += dn_fw.o decnet-y += sysctl_net_decnet.o + +obj-$(CONFIG_NETFILTER) += netfilter/ + diff -Nru a/net/decnet/TODO b/net/decnet/TODO --- a/net/decnet/TODO Thu May 8 00:24:29 2003 +++ b/net/decnet/TODO Thu May 8 00:24:29 2003 @@ -23,15 +23,9 @@ o check MSG_CTRUNC is set where it should be. - o Start to hack together user level software and add more DECnet support - in ifconfig for example. - o Find all the commonality between DECnet and IPv4 routing code and extract it into a small library of routines. [probably a project for 2.7.xx] - o Add the routing message grabbing netfilter module [written, tested, - awaiting merge] - o Add perfect socket hashing - an idea suggested by Paul Koning. Currently we have a half-way house scheme which seems to work reasonably well, but the full scheme is still worth implementing, its not not top of my list @@ -44,6 +38,4 @@ o DECnet sendpages() function o AIO for DECnet - - o Eliminate dn_db->parms.blksize diff -Nru a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c --- a/net/decnet/af_decnet.c Thu May 8 00:24:29 2003 +++ b/net/decnet/af_decnet.c Thu May 8 00:24:29 2003 @@ -116,6 +116,7 @@ #include #include #include +#include #include #include #include @@ -676,45 +677,6 @@ } -static char *dn_state2asc(unsigned char state) -{ - switch(state) { - case DN_O: - return "OPEN"; - case DN_CR: - return " CR"; - case DN_DR: - return " DR"; - case DN_DRC: - return " DRC"; - case DN_CC: - return " CC"; - case DN_CI: - return " CI"; - case DN_NR: - return " NR"; - case DN_NC: - return " NC"; - case DN_CD: - return " CD"; - case DN_RJ: - return " RJ"; - case DN_RUN: - return " RUN"; - case DN_DI: - return " DI"; - case DN_DIC: - return " DIC"; - case DN_DN: - return " DN"; - case DN_CL: - return " CL"; - case DN_CN: - return " CN"; - } - - return "????"; -} static int dn_create(struct socket *sock, int protocol) { @@ -1001,6 +963,7 @@ fl.fld_dst = dn_saddr2dn(&scp->peer); fl.fld_src = dn_saddr2dn(&scp->addr); dn_sk_ports_copy(&fl, scp); + fl.proto = DNPROTO_NSP; if (dn_route_output_sock(&sk->dst_cache, &fl, sk, flags) < 0) goto out; sk->route_caps = sk->dst_cache->dev->features; @@ -1964,7 +1927,7 @@ unsigned char fctype; long timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); - if (flags & ~(MSG_TRYHARD|MSG_OOB|MSG_DONTWAIT|MSG_EOR|MSG_NOSIGNAL)) + if (flags & ~(MSG_TRYHARD|MSG_OOB|MSG_DONTWAIT|MSG_EOR|MSG_NOSIGNAL|MSG_MORE)) return -EOPNOTSUPP; if (addr_len && (addr_len != sizeof(struct sockaddr_dn))) @@ -2143,6 +2106,95 @@ .data = (void*)1, }; +#ifdef CONFIG_PROC_FS +struct dn_iter_state { + int bucket; +}; + +static struct sock *dn_socket_get_first(struct seq_file *seq) +{ + struct dn_iter_state *state = seq->private; + struct sock *n = NULL; + + for(state->bucket = 0; + state->bucket < DN_SK_HASH_SIZE; + ++state->bucket) { + n = dn_sk_hash[state->bucket]; + if (n) + break; + } + + return n; +} + +static struct sock *dn_socket_get_next(struct seq_file *seq, + struct sock *n) +{ + struct dn_iter_state *state = seq->private; + + n = n->next; +try_again: + if (n) + goto out; + if (++state->bucket >= DN_SK_HASH_SIZE) + goto out; + n = dn_sk_hash[state->bucket]; + goto try_again; +out: + return n; +} + +static struct sock *socket_get_idx(struct seq_file *seq, loff_t *pos) +{ + struct sock *sk = dn_socket_get_first(seq); + + if (sk) { + while(*pos && (sk = dn_socket_get_next(seq, sk))) + --*pos; + } + return *pos ? NULL : sk; +} + +static void *dn_socket_get_idx(struct seq_file *seq, loff_t pos) +{ + void *rc; + read_lock_bh(&dn_hash_lock); + rc = socket_get_idx(seq, &pos); + if (!rc) { + read_unlock_bh(&dn_hash_lock); + } + return rc; +} + +static void *dn_socket_seq_start(struct seq_file *seq, loff_t *pos) +{ + return *pos ? dn_socket_get_idx(seq, *pos - 1) : (void*)1; +} + +static void *dn_socket_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + void *rc; + + if (v == (void*)1) { + rc = dn_socket_get_idx(seq, 0); + goto out; + } + + rc = dn_socket_get_next(seq, v); + if (rc) + goto out; + read_unlock_bh(&dn_hash_lock); +out: + ++*pos; + return rc; +} + +static void dn_socket_seq_stop(struct seq_file *seq, void *v) +{ + if (v && v != (void*)1) + read_unlock_bh(&dn_hash_lock); +} + #define IS_NOT_PRINTABLE(x) ((x) < 32 || (x) > 126) static void dn_printable_object(struct sockaddr_dn *dn, unsigned char *buf) @@ -2163,70 +2215,127 @@ } } -static int dn_get_info(char *buffer, char **start, off_t offset, int length) +static char *dn_state2asc(unsigned char state) { - struct sock *sk; - struct dn_scp *scp; - int len = 0; - off_t pos = 0; - off_t begin = 0; + switch(state) { + case DN_O: + return "OPEN"; + case DN_CR: + return " CR"; + case DN_DR: + return " DR"; + case DN_DRC: + return " DRC"; + case DN_CC: + return " CC"; + case DN_CI: + return " CI"; + case DN_NR: + return " NR"; + case DN_NC: + return " NC"; + case DN_CD: + return " CD"; + case DN_RJ: + return " RJ"; + case DN_RUN: + return " RUN"; + case DN_DI: + return " DI"; + case DN_DIC: + return " DIC"; + case DN_DN: + return " DN"; + case DN_CL: + return " CL"; + case DN_CN: + return " CN"; + } + + return "????"; +} + +static inline void dn_socket_format_entry(struct seq_file *seq, struct sock *sk) +{ + struct dn_scp *scp = DN_SK(sk); char buf1[DN_ASCBUF_LEN]; char buf2[DN_ASCBUF_LEN]; char local_object[DN_MAXOBJL+3]; char remote_object[DN_MAXOBJL+3]; - int i; - len += sprintf(buffer + len, "Local Remote\n"); + dn_printable_object(&scp->addr, local_object); + dn_printable_object(&scp->peer, remote_object); - read_lock(&dn_hash_lock); - for(i = 0; i < DN_SK_HASH_SIZE; i++) { - for(sk = dn_sk_hash[i]; sk != NULL; sk = sk->next) { - scp = DN_SK(sk); - - dn_printable_object(&scp->addr, local_object); - dn_printable_object(&scp->peer, remote_object); - - len += sprintf(buffer + len, - "%6s/%04X %04d:%04d %04d:%04d %01d %-16s %6s/%04X %04d:%04d %04d:%04d %01d %-16s %4s %s\n", - dn_addr2asc(dn_ntohs(dn_saddr2dn(&scp->addr)), buf1), - scp->addrloc, - scp->numdat, - scp->numoth, - scp->ackxmt_dat, - scp->ackxmt_oth, - scp->flowloc_sw, - local_object, - dn_addr2asc(dn_ntohs(dn_saddr2dn(&scp->peer)), buf2), - scp->addrrem, - scp->numdat_rcv, - scp->numoth_rcv, - scp->ackrcv_dat, - scp->ackrcv_oth, - scp->flowrem_sw, - remote_object, - dn_state2asc(scp->state), - ((scp->accept_mode == ACC_IMMED) ? "IMMED" : "DEFER")); - - pos = begin + len; - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > (offset + length)) - break; - } + seq_printf(seq, + "%6s/%04X %04d:%04d %04d:%04d %01d %-16s " + "%6s/%04X %04d:%04d %04d:%04d %01d %-16s %4s %s\n", + dn_addr2asc(dn_ntohs(dn_saddr2dn(&scp->addr)), buf1), + scp->addrloc, + scp->numdat, + scp->numoth, + scp->ackxmt_dat, + scp->ackxmt_oth, + scp->flowloc_sw, + local_object, + dn_addr2asc(dn_ntohs(dn_saddr2dn(&scp->peer)), buf2), + scp->addrrem, + scp->numdat_rcv, + scp->numoth_rcv, + scp->ackrcv_dat, + scp->ackrcv_oth, + scp->flowrem_sw, + remote_object, + dn_state2asc(scp->state), + ((scp->accept_mode == ACC_IMMED) ? "IMMED" : "DEFER")); +} + +static int dn_socket_seq_show(struct seq_file *seq, void *v) +{ + if (v == (void*)1) { + seq_puts(seq, "Local Remote\n"); + } else { + dn_socket_format_entry(seq, v); } - read_unlock(&dn_hash_lock); + return 0; +} - *start = buffer + (offset - begin); - len -= (offset - begin); +static struct seq_operations dn_socket_seq_ops = { + .start = dn_socket_seq_start, + .next = dn_socket_seq_next, + .stop = dn_socket_seq_stop, + .show = dn_socket_seq_show, +}; - if (len > length) - len = length; +static int dn_socket_seq_open(struct inode *inode, struct file *file) +{ + struct seq_file *seq; + int rc = -ENOMEM; + struct dn_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL); - return len; + if (!s) + goto out; + + rc = seq_open(file, &dn_socket_seq_ops); + if (rc) + goto out_kfree; + + seq = file->private_data; + seq->private = s; + memset(s, 0, sizeof(*s)); +out: + return rc; +out_kfree: + kfree(s); + goto out; } +static struct file_operations dn_socket_seq_fops = { + .open = dn_socket_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; +#endif static struct net_proto_family dn_family_ops = { .family = AF_DECnet, @@ -2258,13 +2367,11 @@ void dn_register_sysctl(void); void dn_unregister_sysctl(void); - MODULE_DESCRIPTION("The Linux DECnet Network Protocol"); MODULE_AUTHOR("Linux DECnet Project Team"); MODULE_LICENSE("GPL"); - -static char banner[] __initdata = KERN_INFO "NET4: DECnet for Linux: V.2.5.67s (C) 1995-2003 Linux DECnet Project Team\n"; +static char banner[] __initdata = KERN_INFO "NET4: DECnet for Linux: V.2.5.68s (C) 1995-2003 Linux DECnet Project Team\n"; static int __init decnet_init(void) { @@ -2281,15 +2388,12 @@ dev_add_pack(&dn_dix_packet_type); register_netdevice_notifier(&dn_dev_notifier); - proc_net_create("decnet", 0, dn_get_info); + proc_net_fops_create("decnet", S_IRUGO, &dn_socket_seq_fops); dn_neigh_init(); dn_dev_init(); dn_route_init(); - -#ifdef CONFIG_DECNET_ROUTER dn_fib_init(); -#endif /* CONFIG_DECNET_ROUTER */ dn_register_sysctl(); @@ -2316,10 +2420,7 @@ dn_route_cleanup(); dn_dev_cleanup(); dn_neigh_cleanup(); - -#ifdef CONFIG_DECNET_ROUTER dn_fib_cleanup(); -#endif /* CONFIG_DECNET_ROUTER */ proc_net_remove("decnet"); diff -Nru a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c --- a/net/decnet/dn_dev.c Thu May 8 00:24:28 2003 +++ b/net/decnet/dn_dev.c Thu May 8 00:24:28 2003 @@ -20,6 +20,8 @@ * Steve Whitehouse : /proc/sys/net/decnet/conf//forwarding * Steve Whitehouse : Removed timer1 - it's a user space issue now * Patrick Caulfield : Fixed router hello message format + * Steve Whitehouse : Got rid of constant sizes for blksize for + * devices. All mtu based now. */ #include @@ -28,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -72,16 +75,13 @@ static int dn_eth_up(struct net_device *); static void dn_eth_down(struct net_device *); static void dn_send_brd_hello(struct net_device *dev, struct dn_ifaddr *ifa); -#if 0 static void dn_send_ptp_hello(struct net_device *dev, struct dn_ifaddr *ifa); -#endif static struct dn_dev_parms dn_dev_list[] = { { .type = ARPHRD_ETHER, /* Ethernet */ .mode = DN_DEV_BCAST, .state = DN_DEV_S_RU, - .blksize = 1498, .t2 = 1, .t3 = 10, .name = "ethernet", @@ -94,7 +94,6 @@ .type = ARPHRD_IPGRE, /* DECnet tunneled over GRE in IP */ .mode = DN_DEV_BCAST, .state = DN_DEV_S_RU, - .blksize = 1400, .t2 = 1, .t3 = 10, .name = "ipgre", @@ -106,7 +105,6 @@ .type = ARPHRD_X25, /* Bog standard X.25 */ .mode = DN_DEV_UCAST, .state = DN_DEV_S_DS, - .blksize = 230, .t2 = 1, .t3 = 120, .name = "x25", @@ -119,7 +117,6 @@ .type = ARPHRD_PPP, /* DECnet over PPP */ .mode = DN_DEV_BCAST, .state = DN_DEV_S_RU, - .blksize = 230, .t2 = 1, .t3 = 10, .name = "ppp", @@ -127,24 +124,20 @@ .timer3 = dn_send_brd_hello, }, #endif -#if 0 { .type = ARPHRD_DDCMP, /* DECnet over DDCMP */ .mode = DN_DEV_UCAST, .state = DN_DEV_S_DS, - .blksize = 230, .t2 = 1, .t3 = 120, .name = "ddcmp", .ctl_name = NET_DECNET_CONF_DDCMP, .timer3 = dn_send_ptp_hello, }, -#endif { .type = ARPHRD_LOOPBACK, /* Loopback interface - always last */ .mode = DN_DEV_BCAST, .state = DN_DEV_S_RU, - .blksize = 1498, .t2 = 1, .t3 = 10, .name = "loopback", @@ -254,6 +247,21 @@ }, {0}} }; +static inline __u16 mtu2blksize(struct net_device *dev) +{ + u32 blksize = dev->mtu; + if (blksize > 0xffff) + blksize = 0xffff; + + if (dev->type == ARPHRD_ETHER || + dev->type == ARPHRD_PPP || + dev->type == ARPHRD_IPGRE || + dev->type == ARPHRD_LOOPBACK) + blksize -= 2; + + return (__u16)blksize; +} + static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *parms) { struct dn_dev_sysctl_table *t; @@ -858,7 +866,7 @@ memcpy(msg->tiver, dn_eco_version, 3); dn_dn2eth(msg->id, ifa->ifa_local); msg->iinfo = DN_RT_INFO_ENDN; - msg->blksize = dn_htons(dn_db->parms.blksize); + msg->blksize = dn_htons(mtu2blksize(dev)); msg->area = 0x00; memset(msg->seed, 0, 8); memcpy(msg->neighbor, dn_hiord, ETH_ALEN); @@ -920,10 +928,10 @@ unsigned short *pktlen; char *src; - if (dn_db->parms.blksize < (26 + 7)) + if (mtu2blksize(dev) < (26 + 7)) return; - n = dn_db->parms.blksize - 26; + n = mtu2blksize(dev) - 26; n /= 7; if (n > 32) @@ -946,7 +954,7 @@ ptr += ETH_ALEN; *ptr++ = dn_db->parms.forwarding == 1 ? DN_RT_INFO_L1RT : DN_RT_INFO_L2RT; - *((unsigned short *)ptr) = dn_htons(dn_db->parms.blksize); + *((unsigned short *)ptr) = dn_htons(mtu2blksize(dev)); ptr += 2; *ptr++ = dn_db->parms.priority; /* Priority */ *ptr++ = 0; /* Area: Reserved */ @@ -990,16 +998,13 @@ dn_send_router_hello(dev, ifa); } -#if 0 static void dn_send_ptp_hello(struct net_device *dev, struct dn_ifaddr *ifa) { int tdlen = 16; int size = dev->hard_header_len + 2 + 4 + tdlen; struct sk_buff *skb = dn_alloc_skb(NULL, size, GFP_ATOMIC); - struct dn_dev *dn_db = dev->dn_ptr; int i; unsigned char *ptr; - struct dn_neigh *dn = (struct dn_neigh *)dn_db->router; char src[ETH_ALEN]; if (skb == NULL) @@ -1020,7 +1025,6 @@ dn_dn2eth(src, ifa->ifa_local); dn_rt_finish_output(skb, dn_rt_all_rt_mcast, src); } -#endif static int dn_eth_up(struct net_device *dev) { @@ -1332,6 +1336,63 @@ #ifdef CONFIG_PROC_FS +static inline struct net_device *dn_dev_get_next(struct seq_file *seq, struct net_device *dev) +{ + do { + dev = dev->next; + } while(dev && !dev->dn_ptr); + + return dev; +} + +static struct net_device *dn_dev_get_idx(struct seq_file *seq, loff_t pos) +{ + struct net_device *dev; + + dev = dev_base; + if (dev && !dev->dn_ptr) + dev = dn_dev_get_next(seq, dev); + if (pos) { + while(dev && (dev = dn_dev_get_next(seq, dev))) + --pos; + } + return dev; +} + +static void *dn_dev_seq_start(struct seq_file *seq, loff_t *pos) +{ + if (*pos) { + struct net_device *dev; + read_lock(&dev_base_lock); + dev = dn_dev_get_idx(seq, *pos - 1); + if (dev == NULL) + read_unlock(&dev_base_lock); + return dev; + } + return (void*)1; +} + +static void *dn_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct net_device *dev = v; + loff_t one = 1; + + if (v == (void*)1) { + dev = dn_dev_seq_start(seq, &one); + } else { + dev = dn_dev_get_next(seq, dev); + if (dev == NULL) + read_unlock(&dev_base_lock); + } + ++*pos; + return dev; +} + +static void dn_dev_seq_stop(struct seq_file *seq, void *v) +{ + if (v && v != (void*)1) + read_unlock(&dev_base_lock); +} static char *dn_type2asc(char type) { @@ -1347,56 +1408,50 @@ return "?"; } -static int decnet_dev_get_info(char *buffer, char **start, off_t offset, int length) +static int dn_dev_seq_show(struct seq_file *seq, void *v) { - struct dn_dev *dn_db; - struct net_device *dev; - int len = 0; - off_t pos = 0; - off_t begin = 0; - char peer_buf[DN_ASCBUF_LEN]; - char router_buf[DN_ASCBUF_LEN]; - + if (v == (void*)1) + seq_puts(seq, "Name Flags T1 Timer1 T3 Timer3 BlkSize Pri State DevType Router Peer\n"); + else { + struct net_device *dev = v; + char peer_buf[DN_ASCBUF_LEN]; + char router_buf[DN_ASCBUF_LEN]; + struct dn_dev *dn_db = dev->dn_ptr; - len += sprintf(buffer, "Name Flags T1 Timer1 T3 Timer3 BlkSize Pri State DevType Router Peer\n"); - - read_lock(&dev_base_lock); - for (dev = dev_base; dev; dev = dev->next) { - if ((dn_db = (struct dn_dev *)dev->dn_ptr) == NULL) - continue; - - len += sprintf(buffer + len, "%-8s %1s %04u %04u %04lu %04lu %04hu %03d %02x %-10s %-7s %-7s\n", + seq_printf(seq, "%-8s %1s %04u %04u %04lu %04lu" + " %04hu %03d %02x %-10s %-7s %-7s\n", dev->name ? dev->name : "???", dn_type2asc(dn_db->parms.mode), 0, 0, dn_db->t3, dn_db->parms.t3, - dn_db->parms.blksize, + mtu2blksize(dev), dn_db->parms.priority, dn_db->parms.state, dn_db->parms.name, dn_db->router ? dn_addr2asc(dn_ntohs(*(dn_address *)dn_db->router->primary_key), router_buf) : "", dn_db->peer ? dn_addr2asc(dn_ntohs(*(dn_address *)dn_db->peer->primary_key), peer_buf) : ""); + } + return 0; +} +static struct seq_operations dn_dev_seq_ops = { + .start = dn_dev_seq_start, + .next = dn_dev_seq_next, + .stop = dn_dev_seq_stop, + .show = dn_dev_seq_show, +}; - pos = begin + len; - - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > offset + length) - break; - } - - read_unlock(&dev_base_lock); - - *start = buffer + (offset - begin); - len -= (offset - begin); - - if (len > length) len = length; - - return(len); +static int dn_dev_seq_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &dn_dev_seq_ops); } +static struct file_operations dn_dev_seq_fops = { + .open = dn_dev_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + #endif /* CONFIG_PROC_FS */ static struct rtnetlink_link dnet_rtnetlink_table[RTM_MAX-RTM_BASE+1] = @@ -1448,9 +1503,7 @@ rtnetlink_links[PF_DECnet] = dnet_rtnetlink_table; -#ifdef CONFIG_PROC_FS - proc_net_create("decnet_dev", 0, decnet_dev_get_info); -#endif /* CONFIG_PROC_FS */ + proc_net_fops_create("decnet_dev", S_IRUGO, &dn_dev_seq_fops); #ifdef CONFIG_SYSCTL { diff -Nru a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c --- a/net/decnet/dn_fib.c Thu May 8 00:24:30 2003 +++ b/net/decnet/dn_fib.c Thu May 8 00:24:30 2003 @@ -67,18 +67,18 @@ int error; u8 scope; } dn_fib_props[RTA_MAX+1] = { - { .error = 0, .scope = RT_SCOPE_NOWHERE }, /* RTN_UNSPEC */ - { .error = 0, .scope = RT_SCOPE_UNIVERSE }, /* RTN_UNICAST */ - { .error = 0, .scope = RT_SCOPE_HOST }, /* RTN_LOCAL */ - { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, /* RTN_BROADCAST */ - { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, /* RTN_ANYCAST */ - { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, /* RTN_MULTICAST */ - { .error = -EINVAL, .scope = RT_SCOPE_UNIVERSE }, /* RTN_BLACKHOLE */ - { .error = -EHOSTUNREACH, .scope = RT_SCOPE_UNIVERSE }, /* RTN_UNREACHABLE */ - { .error = -EACCES, .scope = RT_SCOPE_UNIVERSE }, /* RTN_PROHIBIT */ - { .error = -EAGAIN, .scope = RT_SCOPE_UNIVERSE }, /* RTN_THROW */ - { .error = 0, .scope = RT_SCOPE_NOWHERE }, /* RTN_NAT */ - { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE } /* RTN_XRESOLVE */ + [RTN_UNSPEC] = { .error = 0, .scope = RT_SCOPE_NOWHERE }, + [RTN_UNICAST] = { .error = 0, .scope = RT_SCOPE_UNIVERSE }, + [RTN_LOCAL] = { .error = 0, .scope = RT_SCOPE_HOST }, + [RTN_BROADCAST] = { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, + [RTN_ANYCAST] = { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, + [RTN_MULTICAST] = { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, + [RTN_BLACKHOLE] = { .error = -EINVAL, .scope = RT_SCOPE_UNIVERSE }, + [RTN_UNREACHABLE] = { .error = -EHOSTUNREACH, .scope = RT_SCOPE_UNIVERSE }, + [RTN_PROHIBIT] = { .error = -EACCES, .scope = RT_SCOPE_UNIVERSE }, + [RTN_THROW] = { .error = -EAGAIN, .scope = RT_SCOPE_UNIVERSE }, + [RTN_NAT] = { .error = 0, .scope = RT_SCOPE_NOWHERE }, + [RTN_XRESOLVE] = { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE }, }; void dn_fib_free_info(struct dn_fib_info *fi) @@ -792,53 +792,12 @@ dn_rt_cache_flush(-1); } -#ifdef CONFIG_PROC_FS - -static int decnet_rt_get_info(char *buffer, char **start, off_t offset, int length) -{ - int first = offset / 128; - char *ptr = buffer; - int count = (length + 127) / 128; - int len; - int i; - struct dn_fib_table *tb; - - *start = buffer + (offset % 128); - - if (--first < 0) { - sprintf(buffer, "%-127s\n", "Iface\tDest\tGW \tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU\tWindow\tIRTT"); - --count; - ptr += 128; - first = 0; - } - - - for(i = RT_MIN_TABLE; (i <= RT_TABLE_MAX) && (count > 0); i++) { - if ((tb = dn_fib_get_table(i, 0)) != NULL) { - int n = tb->get_info(tb, ptr, first, count); - count -= n; - ptr += n * 128; - } - } - - len = ptr - *start; - if (len >= length) - return length; - if (len >= 0) - return len; - - return 0; -} -#endif /* CONFIG_PROC_FS */ - static struct notifier_block dn_fib_dnaddr_notifier = { .notifier_call = dn_fib_dnaddr_event, }; void __exit dn_fib_cleanup(void) { - proc_net_remove("decnet_route"); - dn_fib_table_cleanup(); dn_fib_rules_cleanup(); @@ -848,10 +807,6 @@ void __init dn_fib_init(void) { - -#ifdef CONFIG_PROC_FS - proc_net_create("decnet_route", 0, decnet_rt_get_info); -#endif dn_fib_table_init(); dn_fib_rules_init(); diff -Nru a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c --- a/net/decnet/dn_neigh.c Thu May 8 00:24:29 2003 +++ b/net/decnet/dn_neigh.c Thu May 8 00:24:29 2003 @@ -202,7 +202,7 @@ struct net_device *dev = neigh->dev; char mac_addr[ETH_ALEN]; - dn_dn2eth(mac_addr, rt->rt_saddr); + dn_dn2eth(mac_addr, rt->rt_local_src); if (!dev->hard_header || dev->hard_header(skb, dev, ntohs(skb->protocol), neigh->ha, mac_addr, skb->len) >= 0) return neigh->ops->queue_xmit(skb); @@ -692,48 +692,23 @@ goto out; } -static int dn_seq_release(struct inode *inode, struct file *file) -{ - struct seq_file *seq = (struct seq_file *)file->private_data; - - kfree(seq->private); - seq->private = NULL; - return seq_release(inode, file); -} - static struct file_operations dn_neigh_seq_fops = { .open = dn_neigh_seq_open, .read = seq_read, .llseek = seq_lseek, - .release = dn_seq_release, + .release = seq_release_private, }; -static int __init dn_neigh_proc_init(void) -{ - int rc = 0; - struct proc_dir_entry *p = create_proc_entry("decnet_neigh", S_IRUGO, proc_net); - if (p) - p->proc_fops = &dn_neigh_seq_fops; - else - rc = -ENOMEM; - return rc; -} - -#else -static int __init dn_neigh_proc_init(void) -{ - return 0; -} #endif void __init dn_neigh_init(void) { neigh_table_init(&dn_neigh_table); - - dn_neigh_proc_init(); + proc_net_fops_create("decnet_neigh", S_IRUGO, &dn_neigh_seq_fops); } void __exit dn_neigh_cleanup(void) { + proc_net_remove("decnet_neigh"); neigh_table_clear(&dn_neigh_table); } diff -Nru a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c --- a/net/decnet/dn_nsp_in.c Thu May 8 00:24:28 2003 +++ b/net/decnet/dn_nsp_in.c Thu May 8 00:24:28 2003 @@ -28,6 +28,7 @@ * Steve Whitehouse: Added backlog congestion level return codes. * Patrick Caulfield: * Steve Whitehouse: Added flow control support (outbound) + * Steve Whitehouse: Prepare for nonlinear skbs */ /****************************************************************************** @@ -240,7 +241,7 @@ cb->info = msg->info; cb->segsize = dn_ntohs(msg->segsize); - if (skb->len < sizeof(*msg)) + if (!pskb_may_pull(skb, sizeof(*msg))) goto err_out; skb_pull(skb, sizeof(*msg)); @@ -721,34 +722,19 @@ unsigned char *ptr = (unsigned char *)skb->data; unsigned short reason = NSP_REASON_NL; + if (!pskb_may_pull(skb, 2)) + goto free_out; + skb->h.raw = skb->data; cb->nsp_flags = *ptr++; if (decnet_debug_level & 2) printk(KERN_DEBUG "dn_nsp_rx: Message type 0x%02x\n", (int)cb->nsp_flags); - if (skb->len < 2) - goto free_out; - if (cb->nsp_flags & 0x83) goto free_out; /* - * Returned packets... - * Swap src & dst and look up in the normal way. - */ - if (cb->rt_flags & DN_RT_F_RTS) { - unsigned short tmp = cb->dst_port; - cb->dst_port = cb->src_port; - cb->src_port = tmp; - tmp = cb->dst; - cb->dst = cb->src; - cb->src = tmp; - sk = dn_find_by_skb(skb); - goto got_it; - } - - /* * Filter out conninits and useless packet types */ if ((cb->nsp_flags & 0x0c) == 0x08) { @@ -759,12 +745,14 @@ goto free_out; case 0x10: case 0x60: + if (unlikely(cb->rt_flags & DN_RT_F_RTS)) + goto free_out; sk = dn_find_listener(skb, &reason); goto got_it; } } - if (skb->len < 3) + if (!pskb_may_pull(skb, 3)) goto free_out; /* @@ -777,13 +765,26 @@ /* * If not a connack, grab the source address too. */ - if (skb->len >= 5) { + if (pskb_may_pull(skb, 5)) { cb->src_port = *(unsigned short *)ptr; ptr += 2; skb_pull(skb, 5); } /* + * Returned packets... + * Swap src & dst and look up in the normal way. + */ + if (unlikely(cb->rt_flags & DN_RT_F_RTS)) { + unsigned short tmp = cb->dst_port; + cb->dst_port = cb->src_port; + cb->src_port = tmp; + tmp = cb->dst; + cb->dst = cb->src; + cb->src = tmp; + } + + /* * Find the socket to which this skb is destined. */ sk = dn_find_by_skb(skb); @@ -795,6 +796,15 @@ /* Reset backoff */ scp->nsp_rxtshift = 0; + /* + * We linearize everything except data segments here. + */ + if (cb->nsp_flags & ~0x60) { + if (unlikely(skb_is_nonlinear(skb)) && + skb_linearize(skb, GFP_ATOMIC) != 0) + goto free_out; + } + bh_lock_sock(sk); ret = NET_RX_SUCCESS; if (decnet_debug_level & 8) @@ -835,7 +845,10 @@ struct dn_skb_cb *cb = DN_SKB_CB(skb); if (cb->rt_flags & DN_RT_F_RTS) { - dn_returned_conn_init(sk, skb); + if (cb->nsp_flags == 0x18 || cb->nsp_flags == 0x68) + dn_returned_conn_init(sk, skb); + else + kfree_skb(skb); return NET_RX_SUCCESS; } diff -Nru a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c --- a/net/decnet/dn_nsp_out.c Thu May 8 00:24:30 2003 +++ b/net/decnet/dn_nsp_out.c Thu May 8 00:24:30 2003 @@ -96,6 +96,7 @@ fl.fld_src = dn_saddr2dn(&scp->addr); fl.fld_dst = dn_saddr2dn(&scp->peer); dn_sk_ports_copy(&fl, scp); + fl.proto = DNPROTO_NSP; if (dn_route_output_sock(&sk->dst_cache, &fl, sk, 0) == 0) { dst = sk_dst_get(sk); sk->route_caps = dst->dev->features; @@ -349,8 +350,7 @@ { unsigned char *ptr = skb_push(skb, len); - if (len < 5) - BUG(); + BUG_ON(len < 5); *ptr++ = msgflag; *((unsigned short *)ptr) = scp->addrrem; @@ -367,8 +367,7 @@ unsigned short ackcrs = scp->numoth_rcv & 0x0FFF; unsigned short *ptr; - if (hlen < 9) - BUG(); + BUG_ON(hlen < 9); scp->ackxmt_dat = acknum; scp->ackxmt_oth = ackcrs; @@ -485,8 +484,8 @@ * We don't expect to see acknowledgements for packets we * haven't sent yet. */ - if (xmit_count == 0) - BUG(); + WARN_ON(xmit_count == 0); + /* * If the packet has only been sent once, we can use it * to calculate the RTT and also open the window a little diff -Nru a/net/decnet/dn_route.c b/net/decnet/dn_route.c --- a/net/decnet/dn_route.c Thu May 8 00:24:30 2003 +++ b/net/decnet/dn_route.c Thu May 8 00:24:30 2003 @@ -39,6 +39,7 @@ * no ref count on net devices. * Steve Whitehouse : RCU for the route cache * Steve Whitehouse : Preparations for the flow cache + * Steve Whitehouse : Prepare for nonlinear skbs */ /****************************************************************************** @@ -70,6 +71,7 @@ #include #include #include +#include #include #include #include @@ -97,14 +99,17 @@ static unsigned char dn_hiord_addr[6] = {0xAA,0x00,0x04,0x00,0x00,0x00}; -int dn_rt_min_delay = 2*HZ; -int dn_rt_max_delay = 10*HZ; -static unsigned long dn_rt_deadline = 0; +int dn_rt_min_delay = 2 * HZ; +int dn_rt_max_delay = 10 * HZ; +int dn_rt_mtu_expires = 10 * 60 * HZ; + +static unsigned long dn_rt_deadline; static int dn_dst_gc(void); static struct dst_entry *dn_dst_check(struct dst_entry *, __u32); static struct dst_entry *dn_dst_negative_advice(struct dst_entry *); static void dn_dst_link_failure(struct sk_buff *); +static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu); static int dn_route_input(struct sk_buff *); static void dn_run_flush(unsigned long dummy); @@ -124,6 +129,7 @@ .check = dn_dst_check, .negative_advice = dn_dst_negative_advice, .link_failure = dn_dst_link_failure, + .update_pmtu = dn_dst_update_pmtu, .entry_size = sizeof(struct dn_route), .entries = ATOMIC_INIT(0), }; @@ -210,16 +216,49 @@ return 0; } +/* + * The decnet standards don't impose a particular minimum mtu, what they + * do insist on is that the routing layer accepts a datagram of at least + * 230 bytes long. Here we have to subtract the routing header length from + * 230 to get the minimum acceptable mtu. If there is no neighbour, then we + * assume the worst and use a long header size. + * + * We update both the mtu and the advertised mss (i.e. the segment size we + * advertise to the other end). + */ +static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu) +{ + u32 min_mtu = 230; + struct dn_dev *dn = dst->neighbour ? + (struct dn_dev *)dst->neighbour->dev->dn_ptr : NULL; + + if (dn && dn->use_long == 0) + min_mtu -= 6; + else + min_mtu -= 21; + + if (dst->metrics[RTAX_MTU-1] > mtu && mtu >= min_mtu) { + if (!(dst_metric_locked(dst, RTAX_MTU))) { + dst->metrics[RTAX_MTU-1] = mtu; + dst_set_expires(dst, dn_rt_mtu_expires); + } + if (!(dst_metric_locked(dst, RTAX_ADVMSS))) { + u32 mss = mtu - DN_MAX_NSP_DATA_HEADER; + if (dst->metrics[RTAX_ADVMSS-1] > mss) + dst->metrics[RTAX_ADVMSS-1] = mss; + } + } +} + +/* + * When a route has been marked obsolete. (e.g. routing cache flush) + */ static struct dst_entry *dn_dst_check(struct dst_entry *dst, __u32 cookie) { dst_release(dst); return NULL; } -/* - * This is called through sendmsg() when you specify MSG_TRYHARD - * and there is already a route in cache. - */ static struct dst_entry *dn_dst_negative_advice(struct dst_entry *dst) { dst_release(dst); @@ -467,7 +506,7 @@ struct dn_skb_cb *cb = DN_SKB_CB(skb); unsigned char *ptr = skb->data; - if (skb->len < 21) /* 20 for long header, 1 for shortest nsp */ + if (!pskb_may_pull(skb, 21)) /* 20 for long header, 1 for shortest nsp */ goto drop_it; skb_pull(skb, 20); @@ -505,7 +544,7 @@ struct dn_skb_cb *cb = DN_SKB_CB(skb); unsigned char *ptr = skb->data; - if (skb->len < 6) /* 5 for short header + 1 for shortest nsp */ + if (!pskb_may_pull(skb, 6)) /* 5 for short header + 1 for shortest nsp */ goto drop_it; skb_pull(skb, 5); @@ -555,6 +594,9 @@ if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) goto out; + if (!pskb_may_pull(skb, 3)) + goto dump_it; + skb_pull(skb, 2); if (len > skb->len) @@ -573,6 +615,8 @@ */ if (flags & DN_RT_F_PF) { padlen = flags & ~DN_RT_F_PF; + if (!pskb_may_pull(skb, padlen + 1)) + goto dump_it; skb_pull(skb, padlen); flags = *skb->data; } @@ -594,6 +638,10 @@ padlen); if (flags & DN_RT_PKT_CNTL) { + if (unlikely(skb_is_nonlinear(skb)) && + skb_linearize(skb, GFP_ATOMIC) != 0) + goto dump_it; + switch(flags & DN_RT_CNTL_MSK) { case DN_RT_PKT_INIT: dn_dev_init_pkt(skb); @@ -712,7 +760,7 @@ * packets, so we don't need to test for them here. */ cb->rt_flags &= ~DN_RT_F_IE; - if (rt->rt_flags | RTCF_DOREDIRECT) + if (rt->rt_flags & RTCF_DOREDIRECT) cb->rt_flags |= DN_RT_F_IE; return NF_HOOK(PF_DECnet, NF_DN_FORWARD, skb, dev, skb->dev, neigh->output); @@ -788,8 +836,10 @@ { __u16 tmp = dn_ntohs(addr1) ^ dn_ntohs(addr2); int match = 16; - while(tmp) - tmp >>= 1, match--; + while(tmp) { + tmp >>= 1; + match--; + } return match; } @@ -899,17 +949,19 @@ /* No destination? Assume its local */ if (!fl.fld_dst) { fl.fld_dst = fl.fld_src; -#if 0 - if (!fl.fld_dst) - /* grab an address from loopback? */ -#endif + err = -EADDRNOTAVAIL; if (dev_out) dev_put(dev_out); - if (!fl.fld_dst) - goto out; dev_out = &loopback_dev; dev_hold(dev_out); + if (!fl.fld_dst) { + fl.fld_dst = + fl.fld_src = dnet_select_source(dev_out, 0, + RT_SCOPE_HOST); + if (!fl.fld_dst) + goto out; + } fl.oif = loopback_dev.ifindex; res.type = RTN_LOCAL; goto make_route; @@ -1061,6 +1113,7 @@ rt->rt_saddr = fl.fld_src; rt->rt_daddr = fl.fld_dst; rt->rt_gateway = gateway ? gateway : fl.fld_dst; + rt->rt_local_src = fl.fld_src; rt->rt_dst_map = fl.fld_dst; rt->rt_src_map = fl.fld_src; @@ -1075,14 +1128,14 @@ rt->u.dst.input = dn_rt_bug; rt->rt_flags = flags; if (flags & RTCF_LOCAL) - rt->u.dst.output = dn_nsp_rx; + rt->u.dst.input = dn_nsp_rx; - if (dn_rt_set_next_hop(rt, &res)) + err = dn_rt_set_next_hop(rt, &res); + if (err) goto e_neighbour; hash = dn_hash(rt->fl.fld_src, rt->fl.fld_dst); dn_insert_route(rt, hash, (struct dn_route **)pprt); - err = 0; done: if (neigh) @@ -1175,6 +1228,7 @@ unsigned hash; int flags = 0; __u16 gateway = 0; + __u16 local_src = 0; struct flowi fl = { .nl_u = { .dn_u = { .daddr = cb->dst, .saddr = cb->src, @@ -1275,6 +1329,8 @@ if (out_dev == in_dev && !(flags & RTCF_NAT)) flags |= RTCF_DOREDIRECT; + local_src = DN_FIB_RES_PREFSRC(res); + case RTN_BLACKHOLE: case RTN_UNREACHABLE: break; @@ -1319,6 +1375,8 @@ rt->rt_gateway = fl.fld_dst; if (gateway) rt->rt_gateway = gateway; + rt->rt_local_src = local_src ? local_src : rt->rt_saddr; + rt->rt_dst_map = fl.fld_dst; rt->rt_src_map = fl.fld_src; @@ -1352,12 +1410,12 @@ if (rt->u.dst.dev) dev_hold(rt->u.dst.dev); - if (dn_rt_set_next_hop(rt, &res)) + err = dn_rt_set_next_hop(rt, &res); + if (err) goto e_neighbour; hash = dn_hash(rt->fl.fld_src, rt->fl.fld_dst); dn_insert_route(rt, hash, (struct dn_route **)&skb->dst); - err = 0; done: if (neigh) @@ -1449,7 +1507,7 @@ * they deal only with inputs and not with replies like they do * currently. */ - RTA_PUT(skb, RTA_PREFSRC, 2, &rt->rt_saddr); + RTA_PUT(skb, RTA_PREFSRC, 2, &rt->rt_local_src); if (rt->rt_daddr != rt->rt_gateway) RTA_PUT(skb, RTA_GATEWAY, 2, &rt->rt_gateway); if (rtnetlink_put_metrics(skb, rt->u.dst.metrics) < 0) @@ -1490,6 +1548,7 @@ struct flowi fl; memset(&fl, 0, sizeof(fl)); + fl.proto = DNPROTO_NSP; skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); if (skb == NULL) @@ -1609,54 +1668,114 @@ } #ifdef CONFIG_PROC_FS +struct dn_rt_cache_iter_state { + int bucket; +}; -static int decnet_cache_get_info(char *buffer, char **start, off_t offset, int length) +static struct dn_route *dn_rt_cache_get_first(struct seq_file *seq) { - int len = 0; - off_t pos = 0; - off_t begin = 0; - struct dn_route *rt; - int i; - char buf1[DN_ASCBUF_LEN], buf2[DN_ASCBUF_LEN]; + struct dn_route *rt = NULL; + struct dn_rt_cache_iter_state *s = seq->private; - for(i = 0; i <= dn_rt_hash_mask; i++) { + for(s->bucket = dn_rt_hash_mask; s->bucket >= 0; --s->bucket) { rcu_read_lock(); - rt = dn_rt_hash_table[i].chain; - for(; rt != NULL; rt = rt->u.rt_next) { - read_barrier_depends(); - len += sprintf(buffer + len, "%-8s %-7s %-7s %04d %04d %04d\n", - rt->u.dst.dev ? rt->u.dst.dev->name : "*", - dn_addr2asc(dn_ntohs(rt->rt_daddr), buf1), - dn_addr2asc(dn_ntohs(rt->rt_saddr), buf2), - atomic_read(&rt->u.dst.__refcnt), - rt->u.dst.__use, - (int) dst_metric(&rt->u.dst, RTAX_RTT) - ); - + rt = dn_rt_hash_table[s->bucket].chain; + if (rt) + break; + rcu_read_unlock(); + } + return rt; +} +static struct dn_route *dn_rt_cache_get_next(struct seq_file *seq, struct dn_route *rt) +{ + struct dn_rt_cache_iter_state *s = seq->private; - pos = begin + len; - - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > offset + length) - break; - } + smp_read_barrier_depends(); + rt = rt->u.rt_next; + while(!rt) { rcu_read_unlock(); - if (pos > offset + length) + if (--s->bucket < 0) break; + rcu_read_lock(); + rt = dn_rt_hash_table[s->bucket].chain; } + return rt; +} + +static void *dn_rt_cache_seq_start(struct seq_file *seq, loff_t *pos) +{ + struct dn_route *rt = dn_rt_cache_get_first(seq); + + if (rt) { + while(*pos && (rt = dn_rt_cache_get_next(seq, rt))) + --*pos; + } + return *pos ? NULL : rt; +} + +static void *dn_rt_cache_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct dn_route *rt = dn_rt_cache_get_next(seq, v); + ++*pos; + return rt; +} - *start = buffer + (offset - begin); - len -= (offset - begin); +static void dn_rt_cache_seq_stop(struct seq_file *seq, void *v) +{ + rcu_read_unlock(); +} - if (len > length) len = length; +static int dn_rt_cache_seq_show(struct seq_file *seq, void *v) +{ + struct dn_route *rt = v; + char buf1[DN_ASCBUF_LEN], buf2[DN_ASCBUF_LEN]; - return(len); + seq_printf(seq, "%-8s %-7s %-7s %04d %04d %04d\n", + rt->u.dst.dev ? rt->u.dst.dev->name : "*", + dn_addr2asc(dn_ntohs(rt->rt_daddr), buf1), + dn_addr2asc(dn_ntohs(rt->rt_saddr), buf2), + atomic_read(&rt->u.dst.__refcnt), + rt->u.dst.__use, + (int) dst_metric(&rt->u.dst, RTAX_RTT)); + return 0; } +static struct seq_operations dn_rt_cache_seq_ops = { + .start = dn_rt_cache_seq_start, + .next = dn_rt_cache_seq_next, + .stop = dn_rt_cache_seq_stop, + .show = dn_rt_cache_seq_show, +}; + +static int dn_rt_cache_seq_open(struct inode *inode, struct file *file) +{ + struct seq_file *seq; + int rc = -ENOMEM; + struct dn_rt_cache_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL); + + if (!s) + goto out; + rc = seq_open(file, &dn_rt_cache_seq_ops); + if (rc) + goto out_kfree; + seq = file->private_data; + seq->private = s; + memset(s, 0, sizeof(*s)); +out: + return rc; +out_kfree: + kfree(s); + goto out; +} + +static struct file_operations dn_rt_cache_seq_fops = { + .open = dn_rt_cache_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + #endif /* CONFIG_PROC_FS */ void __init dn_route_init(void) @@ -1714,9 +1833,7 @@ dn_dst_ops.gc_thresh = (dn_rt_hash_mask + 1); -#ifdef CONFIG_PROC_FS - proc_net_create("decnet_cache",0,decnet_cache_get_info); -#endif /* CONFIG_PROC_FS */ + proc_net_fops_create("decnet_cache", S_IRUGO, &dn_rt_cache_seq_fops); } void __exit dn_route_cleanup(void) diff -Nru a/net/decnet/dn_table.c b/net/decnet/dn_table.c --- a/net/decnet/dn_table.c Thu May 8 00:24:28 2003 +++ b/net/decnet/dn_table.c Thu May 8 00:24:28 2003 @@ -744,86 +744,6 @@ return err; } -#ifdef CONFIG_PROC_FS - -static unsigned dn_fib_flag_trans(int type, int dead, u16 mask, struct dn_fib_info *fi) -{ - static unsigned type2flags[RTN_MAX+1] = { - 0, 0, 0, 0, 0, 0, 0, RTF_REJECT, RTF_REJECT, 0, 0, 0 - }; - unsigned flags = type2flags[type]; - - if (fi && fi->fib_nh->nh_gw) - flags |= RTF_GATEWAY; - if (mask == 0xFFFF) - flags |= RTF_HOST; - if (dead) - flags |= RTF_UP; - return flags; -} - -static void dn_fib_node_get_info(int type, int dead, struct dn_fib_info *fi, u16 prefix, u16 mask, char *buffer) -{ - int len; - unsigned flags = dn_fib_flag_trans(type, dead, mask, fi); - - if (fi) { - len = sprintf(buffer, "%s\t%04x\t%04x\t%04x\t%d\t%u\t%d\t%04x\t%d\t%u\t%u", - fi->dn_fib_dev ? fi->dn_fib_dev->name : "*", prefix, - fi->fib_nh->nh_gw, flags, 0, 0, fi->fib_priority, - mask, 0, 0, 0); - } else { - len = sprintf(buffer, "*\t%04x\t%04x\t%04x\t%d\t%u\t%d\t%04x\t%d\t%u\t%u", - prefix, 0, - flags, 0, 0, 0, - mask, 0, 0, 0); - } - memset(buffer+len, ' ', 127-len); - buffer[127] = '\n'; -} - -static int dn_fib_table_get_info(struct dn_fib_table *tb, char *buffer, int first, int count) -{ - struct dn_hash *table = (struct dn_hash *)tb->data; - struct dn_zone *dz; - int pos = 0; - int n = 0; - - read_lock(&dn_fib_tables_lock); - for(dz = table->dh_zone_list; dz; dz = dz->dz_next) { - int i; - struct dn_fib_node *f; - int maxslot = dz->dz_divisor; - struct dn_fib_node **fp = dz->dz_hash; - - if (dz->dz_nent == 0) - continue; - - if (pos + dz->dz_nent < first) { - pos += dz->dz_nent; - continue; - } - - for(i = 0; i < maxslot; i++, fp++) { - for(f = *fp; f ; f = f->fn_next) { - if (++pos <= first) - continue; - dn_fib_node_get_info(f->fn_type, - f->fn_state & DN_S_ZOMBIE, - DN_FIB_INFO(f), - dz_prefix(f->fn_key, dz), - DZ_MASK(dz), buffer); - buffer += 128; - if (++n >= count) - goto out; - } - } - } -out: - read_unlock(&dn_fib_tables_lock); - return n; -} -#endif /* CONFIG_PROC_FS */ struct dn_fib_table *dn_fib_get_table(int n, int create) { @@ -855,9 +775,6 @@ t->delete = dn_fib_table_delete; t->lookup = dn_fib_table_lookup; t->flush = dn_fib_table_flush; -#ifdef CONFIG_PROC_FS - t->get_info = dn_fib_table_get_info; -#endif t->dump = dn_fib_table_dump; memset(t->data, 0, sizeof(struct dn_hash)); dn_fib_tables[n] = t; diff -Nru a/net/decnet/netfilter/Kconfig b/net/decnet/netfilter/Kconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/net/decnet/netfilter/Kconfig Thu May 8 00:24:30 2003 @@ -0,0 +1,15 @@ +# +# DECnet netfilter configuration +# + +menu "DECnet: Netfilter Configuration" + depends on DECNET && NETFILTER && EXPERIMENTAL + +config DECNET_NF_GRABULATOR + tristate "Routing message grabulator (for userland routing daemon)" + help + Enable this module if you want to use the userland DECnet routing + daemon. You will also need to enable routing support for DECnet + unless you just want to monitor routing messages from other nodes. + +endmenu diff -Nru a/net/decnet/netfilter/Makefile b/net/decnet/netfilter/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/net/decnet/netfilter/Makefile Thu May 8 00:24:30 2003 @@ -0,0 +1,6 @@ +# +# Makefile for DECnet netfilter modules +# + +obj-$(CONFIG_DECNET_NF_GRABULATOR) += dn_rtmsg.o + diff -Nru a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/net/decnet/netfilter/dn_rtmsg.c Thu May 8 00:24:30 2003 @@ -0,0 +1,167 @@ +/* + * DECnet An implementation of the DECnet protocol suite for the LINUX + * operating system. DECnet is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * DECnet Routing Message Grabulator + * + * (C) 2000 ChyGwyn Limited - http://www.chygwyn.com/ + * This code may be copied under the GPL v.2 or at your option + * any later version. + * + * Author: Steven Whitehouse + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +static struct sock *dnrmg = NULL; + + +static struct sk_buff *dnrmg_build_message(struct sk_buff *rt_skb, int *errp) +{ + struct sk_buff *skb = NULL; + size_t size; + unsigned char *old_tail; + struct nlmsghdr *nlh; + unsigned char *ptr; + struct nf_dn_rtmsg *rtm; + + size = NLMSG_SPACE(rt_skb->len); + size += NLMSG_ALIGN(sizeof(struct nf_dn_rtmsg)); + skb = alloc_skb(size, GFP_ATOMIC); + if (!skb) + goto nlmsg_failure; + old_tail = skb->tail; + nlh = NLMSG_PUT(skb, 0, 0, 0, size - sizeof(*nlh)); + rtm = (struct nf_dn_rtmsg *)NLMSG_DATA(nlh); + rtm->nfdn_ifindex = rt_skb->dev->ifindex; + ptr = NFDN_RTMSG(rtm); + memcpy(ptr, rt_skb->data, rt_skb->len); + nlh->nlmsg_len = skb->tail - old_tail; + return skb; + +nlmsg_failure: + if (skb) + kfree(skb); + *errp = -ENOMEM; + if (net_ratelimit()) + printk(KERN_ERR "dn_rtmsg: error creating netlink message\n"); + return NULL; +} + +static void dnrmg_send_peer(struct sk_buff *skb) +{ + struct sk_buff *skb2; + int status = 0; + int group = 0; + unsigned char flags = *skb->data; + + switch(flags & DN_RT_CNTL_MSK) { + case DN_RT_PKT_L1RT: + group = DNRMG_L1_GROUP; + break; + case DN_RT_PKT_L2RT: + group = DNRMG_L2_GROUP; + break; + default: + return; + } + + skb2 = dnrmg_build_message(skb, &status); + if (skb2 == NULL) + return; + NETLINK_CB(skb2).dst_groups = group; + netlink_broadcast(dnrmg, skb2, 0, group, GFP_ATOMIC); +} + + +static unsigned int dnrmg_hook(unsigned int hook, + struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + dnrmg_send_peer(*pskb); + return NF_ACCEPT; +} + + +#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err)); return; } while (0) + +static inline void dnrmg_receive_user_skb(struct sk_buff *skb) +{ + struct nlmsghdr *nlh = (struct nlmsghdr *)skb->data; + + if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) + return; + + if (!cap_raised(NETLINK_CB(skb).eff_cap, CAP_NET_ADMIN)) + RCV_SKB_FAIL(-EPERM); + + /* Eventually we might send routing messages too */ + + RCV_SKB_FAIL(-EINVAL); +} + +static void dnrmg_receive_user_sk(struct sock *sk, int len) +{ + struct sk_buff *skb; + + while((skb = skb_dequeue(&sk->receive_queue)) != NULL) { + dnrmg_receive_user_skb(skb); + kfree_skb(skb); + } +} + +static struct nf_hook_ops dnrmg_ops = { + .hook = dnrmg_hook, + .pf = PF_DECnet, + .hooknum = NF_DN_ROUTE, + .priority = NF_DN_PRI_DNRTMSG, +}; + +static int __init init(void) +{ + int rv = 0; + + dnrmg = netlink_kernel_create(NETLINK_DNRTMSG, dnrmg_receive_user_sk); + if (dnrmg == NULL) { + printk(KERN_ERR "dn_rtmsg: Cannot create netlink socket"); + return -ENOMEM; + } + + rv = nf_register_hook(&dnrmg_ops); + if (rv) { + sock_release(dnrmg->socket); + } + + return rv; +} + +static void __exit fini(void) +{ + nf_unregister_hook(&dnrmg_ops); + sock_release(dnrmg->socket); +} + + +MODULE_DESCRIPTION("DECnet Routing Message Grabulator"); +MODULE_AUTHOR("Steven Whitehouse "); +MODULE_LICENSE("GPL"); + +module_init(init); +module_exit(fini); + diff -Nru a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c --- a/net/ipv4/af_inet.c Thu May 8 00:24:27 2003 +++ b/net/ipv4/af_inet.c Thu May 8 00:24:27 2003 @@ -926,6 +926,7 @@ struct net_proto_family inet_family_ops = { .family = PF_INET, .create = inet_create, + .owner = THIS_MODULE, }; diff -Nru a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c --- a/net/ipv4/fib_frontend.c Thu May 8 00:24:30 2003 +++ b/net/ipv4/fib_frontend.c Thu May 8 00:24:30 2003 @@ -115,9 +115,9 @@ if (res.type != RTN_LOCAL) goto out; dev = FIB_RES_DEV(res); - if (dev) - atomic_inc(&dev->refcnt); + if (dev) + dev_hold(dev); out: fib_res_put(&res); return dev; diff -Nru a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c --- a/net/ipv4/fib_semantics.c Thu May 8 00:24:28 2003 +++ b/net/ipv4/fib_semantics.c Thu May 8 00:24:28 2003 @@ -406,7 +406,7 @@ if (!(dev->flags&IFF_UP)) return -ENETDOWN; nh->nh_dev = dev; - atomic_inc(&dev->refcnt); + dev_hold(dev); nh->nh_scope = RT_SCOPE_LINK; return 0; } @@ -429,7 +429,7 @@ nh->nh_oif = FIB_RES_OIF(res); if ((nh->nh_dev = FIB_RES_DEV(res)) == NULL) goto out; - atomic_inc(&nh->nh_dev->refcnt); + dev_hold(nh->nh_dev); err = -ENETDOWN; if (!(nh->nh_dev->flags & IFF_UP)) goto out; @@ -451,7 +451,7 @@ return -ENETDOWN; } nh->nh_dev = in_dev->dev; - atomic_inc(&nh->nh_dev->refcnt); + dev_hold(nh->nh_dev); nh->nh_scope = RT_SCOPE_HOST; in_dev_put(in_dev); } diff -Nru a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c --- a/net/ipv4/netfilter/ip_nat_core.c Thu May 8 00:24:27 2003 +++ b/net/ipv4/netfilter/ip_nat_core.c Thu May 8 00:24:27 2003 @@ -13,6 +13,8 @@ #include #include #include /* For tcp_prot in getorigdst */ +#include +#include #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock) #define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock) @@ -698,14 +700,26 @@ list_prepend(&byipsproto[ipsprotohash], &info->byipsproto); } -static void -manip_pkt(u_int16_t proto, struct iphdr *iph, size_t len, +/* Returns true if succeeded. */ +static int +manip_pkt(u_int16_t proto, + struct sk_buff **pskb, + unsigned int iphdroff, const struct ip_conntrack_manip *manip, - enum ip_nat_manip_type maniptype, - __u32 *nfcache) + enum ip_nat_manip_type maniptype) { - *nfcache |= NFC_ALTERED; - find_nat_proto(proto)->manip_pkt(iph, len, manip, maniptype); + struct iphdr *iph; + + (*pskb)->nfcache |= NFC_ALTERED; + if (!skb_ip_make_writable(pskb, iphdroff+sizeof(iph))) + return 0; + + iph = (void *)(*pskb)->data + iphdroff; + + /* Manipulate protcol part. */ + if (!find_nat_proto(proto)->manip_pkt(pskb, iphdroff + iph->ihl*4, + manip, maniptype)) + return 0; if (maniptype == IP_NAT_MANIP_SRC) { iph->check = ip_nat_cheat_check(~iph->saddr, manip->ip, @@ -716,17 +730,7 @@ iph->check); iph->daddr = manip->ip; } -#if 0 - if (ip_fast_csum((u8 *)iph, iph->ihl) != 0) - DEBUGP("IP: checksum on packet bad.\n"); - - if (proto == IPPROTO_TCP) { - void *th = (u_int32_t *)iph + iph->ihl; - if (tcp_v4_check(th, len - 4*iph->ihl, iph->saddr, iph->daddr, - csum_partial((char *)th, len-4*iph->ihl, 0))) - DEBUGP("TCP: checksum on packet bad\n"); - } -#endif + return 1; } static inline int exp_for_packet(struct ip_conntrack_expect *exp, @@ -754,25 +758,13 @@ unsigned int i; struct ip_nat_helper *helper; enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); - int is_tcp = (*pskb)->nh.iph->protocol == IPPROTO_TCP; + int proto = (*pskb)->nh.iph->protocol; /* Need nat lock to protect against modification, but neither conntrack (referenced) and helper (deleted with synchronize_bh()) can vanish. */ READ_LOCK(&ip_nat_lock); for (i = 0; i < info->num_manips; i++) { - /* raw socket (tcpdump) may have clone of incoming - skb: don't disturb it --RR */ - if (skb_cloned(*pskb) && !(*pskb)->sk) { - struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC); - if (!nskb) { - READ_UNLOCK(&ip_nat_lock); - return NF_DROP; - } - kfree_skb(*pskb); - *pskb = nskb; - } - if (info->manips[i].direction == dir && info->manips[i].hooknum == hooknum) { DEBUGP("Mangling %p: %s to %u.%u.%u.%u %u\n", @@ -781,12 +773,12 @@ ? "SRC" : "DST", NIPQUAD(info->manips[i].manip.ip), htons(info->manips[i].manip.u.all)); - manip_pkt((*pskb)->nh.iph->protocol, - (*pskb)->nh.iph, - (*pskb)->len, - &info->manips[i].manip, - info->manips[i].maniptype, - &(*pskb)->nfcache); + if (manip_pkt(proto, pskb, 0, + &info->manips[i].manip, + info->manips[i].maniptype) < 0) { + READ_UNLOCK(&ip_nat_lock); + return NF_DROP; + } } } helper = info->helper; @@ -839,12 +831,14 @@ /* Adjust sequence number only once per packet * (helper is called at all hooks) */ - if (is_tcp && (hooknum == NF_IP_POST_ROUTING - || hooknum == NF_IP_LOCAL_IN)) { + if (proto == IPPROTO_TCP + && (hooknum == NF_IP_POST_ROUTING + || hooknum == NF_IP_LOCAL_IN)) { DEBUGP("ip_nat_core: adjusting sequence number\n"); /* future: put this in a l4-proto specific function, * and call this function here. */ - ip_nat_seq_adjust(*pskb, ct, ctinfo); + if (!ip_nat_seq_adjust(pskb, ct, ctinfo)) + ret = NF_DROP; } return ret; @@ -855,39 +849,51 @@ /* not reached */ } -unsigned int -icmp_reply_translation(struct sk_buff *skb, +int +icmp_reply_translation(struct sk_buff **pskb, struct ip_conntrack *conntrack, unsigned int hooknum, int dir) { - struct iphdr *iph = skb->nh.iph; - struct icmphdr *hdr = (struct icmphdr *)((u_int32_t *)iph + iph->ihl); - struct iphdr *inner = (struct iphdr *)(hdr + 1); - size_t datalen = skb->len - ((void *)inner - (void *)iph); + struct { + struct icmphdr icmp; + struct iphdr ip; + } *inside; unsigned int i; struct ip_nat_info *info = &conntrack->nat.info; - IP_NF_ASSERT(skb->len >= iph->ihl*4 + sizeof(struct icmphdr)); + if (!skb_ip_make_writable(pskb,(*pskb)->nh.iph->ihl*4+sizeof(*inside))) + return 0; + inside = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4; + + /* We're actually going to mangle it beyond trivial checksum + adjustment, so make sure the current checksum is correct. */ + if ((*pskb)->ip_summed != CHECKSUM_UNNECESSARY + && (u16)csum_fold(skb_checksum(*pskb, (*pskb)->nh.iph->ihl*4, + (*pskb)->len, 0))) + return 0; + /* Must be RELATED */ - IP_NF_ASSERT(skb->nfct - (struct ip_conntrack *)skb->nfct->master + IP_NF_ASSERT((*pskb)->nfct + - (struct ip_conntrack *)(*pskb)->nfct->master == IP_CT_RELATED - || skb->nfct - (struct ip_conntrack *)skb->nfct->master + || (*pskb)->nfct + - (struct ip_conntrack *)(*pskb)->nfct->master == IP_CT_RELATED+IP_CT_IS_REPLY); /* Redirects on non-null nats must be dropped, else they'll start talking to each other without our translation, and be confused... --RR */ - if (hdr->type == ICMP_REDIRECT) { + if (inside->icmp.type == ICMP_REDIRECT) { /* Don't care about races here. */ if (info->initialized != ((1 << IP_NAT_MANIP_SRC) | (1 << IP_NAT_MANIP_DST)) || info->num_manips != 0) - return NF_DROP; + return 0; } DEBUGP("icmp_reply_translation: translating error %p hook %u dir %s\n", - skb, hooknum, dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY"); + *pskb, hooknum, dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY"); /* Note: May not be from a NAT'd host, but probably safest to do translation always as if it came from the host itself (even though a "host unreachable" coming from the host @@ -918,11 +924,13 @@ ? "DST" : "SRC", NIPQUAD(info->manips[i].manip.ip), ntohs(info->manips[i].manip.u.udp.port)); - manip_pkt(inner->protocol, inner, - skb->len - ((void *)inner - (void *)iph), - &info->manips[i].manip, - !info->manips[i].maniptype, - &skb->nfcache); + if (manip_pkt(inside->ip.protocol, pskb, + (*pskb)->nh.iph->ihl*4 + + sizeof(inside->icmp), + &info->manips[i].manip, + !info->manips[i].maniptype) < 0) + goto unlock_fail; + /* Outer packet needs to have IP header NATed like it's a reply. */ @@ -932,22 +940,82 @@ info->manips[i].maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST", NIPQUAD(info->manips[i].manip.ip)); - manip_pkt(0, iph, skb->len, - &info->manips[i].manip, - info->manips[i].maniptype, - &skb->nfcache); + if (manip_pkt(0, pskb, 0, + &info->manips[i].manip, + info->manips[i].maniptype) < 0) + goto unlock_fail; } } READ_UNLOCK(&ip_nat_lock); - /* Since we mangled inside ICMP packet, recalculate its - checksum from scratch. (Hence the handling of incorrect - checksums in conntrack, so we don't accidentally fix one.) */ - hdr->checksum = 0; - hdr->checksum = ip_compute_csum((unsigned char *)hdr, - sizeof(*hdr) + datalen); + inside->icmp.checksum = 0; + inside->icmp.checksum = csum_fold(skb_checksum(*pskb, + (*pskb)->nh.iph->ihl*4, + (*pskb)->len, 0)); + return 1; - return NF_ACCEPT; + unlock_fail: + READ_UNLOCK(&ip_nat_lock); + return 0; +} + +int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len) +{ + struct sk_buff *nskb; + unsigned int iplen; + + if (writable_len > (*pskb)->len) + return 0; + + /* Not exclusive use of packet? Must copy. */ + if (skb_shared(*pskb) || skb_cloned(*pskb)) + goto copy_skb; + + /* Alexey says IP hdr is always modifiable and linear, so ok. */ + if (writable_len <= (*pskb)->nh.iph->ihl*4) + return 1; + + iplen = writable_len - (*pskb)->nh.iph->ihl*4; + + /* DaveM says protocol headers are also modifiable. */ + switch ((*pskb)->nh.iph->protocol) { + case IPPROTO_TCP: { + struct tcphdr hdr; + if (skb_copy_bits(*pskb, (*pskb)->nh.iph->ihl*4, + &hdr, sizeof(hdr)) != 0) + goto copy_skb; + if (writable_len <= (*pskb)->nh.iph->ihl*4 + hdr.doff*4) + goto pull_skb; + goto copy_skb; + } + case IPPROTO_UDP: + if (writable_len<=(*pskb)->nh.iph->ihl*4+sizeof(struct udphdr)) + goto pull_skb; + goto copy_skb; + case IPPROTO_ICMP: + if (writable_len + <= (*pskb)->nh.iph->ihl*4 + sizeof(struct icmphdr)) + goto pull_skb; + goto copy_skb; + /* Insert other cases here as desired */ + } + +copy_skb: + nskb = skb_copy(*pskb, GFP_ATOMIC); + if (!nskb) + return 0; + BUG_ON(skb_is_nonlinear(nskb)); + + /* Rest of kernel will get very unhappy if we pass it a + suddenly-orphaned skbuff */ + if ((*pskb)->sk) + skb_set_owner_w(nskb, (*pskb)->sk); + kfree_skb(*pskb); + *pskb = nskb; + return 1; + +pull_skb: + return pskb_may_pull(*pskb, writable_len); } int __init ip_nat_init(void) diff -Nru a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c --- a/net/ipv4/netfilter/ip_nat_helper.c Thu May 8 00:24:28 2003 +++ b/net/ipv4/netfilter/ip_nat_helper.c Thu May 8 00:24:28 2003 @@ -46,14 +46,14 @@ #endif DECLARE_LOCK(ip_nat_seqofs_lock); - -static inline int -ip_nat_resize_packet(struct sk_buff **skb, - struct ip_conntrack *ct, - enum ip_conntrack_info ctinfo, - int new_size) + +/* Setup TCP sequence correction given this change at this sequence */ +static inline void +adjust_tcp_sequence(u32 seq, + int sizediff, + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo) { - struct iphdr *iph; int dir; struct ip_nat_seq *this_way, *other_way; @@ -65,52 +65,89 @@ this_way = &ct->nat.info.seq[dir]; other_way = &ct->nat.info.seq[!dir]; - if (new_size > (*skb)->len + skb_tailroom(*skb)) { - struct sk_buff *newskb; - newskb = skb_copy_expand(*skb, skb_headroom(*skb), - new_size - (*skb)->len, - GFP_ATOMIC); - - if (!newskb) { - printk("ip_nat_resize_packet: oom\n"); - return 0; - } else { - kfree_skb(*skb); - *skb = newskb; - } + DEBUGP("ip_nat_resize_packet: Seq_offset before: "); + DUMP_OFFSET(this_way); + + LOCK_BH(&ip_nat_seqofs_lock); + + /* SYN adjust. If it's uninitialized, of this is after last + * correction, record it: we don't handle more than one + * adjustment in the window, but do deal with common case of a + * retransmit */ + if (this_way->offset_before == this_way->offset_after + || before(this_way->correction_pos, seq)) { + this_way->correction_pos = seq; + this_way->offset_before = this_way->offset_after; + this_way->offset_after += sizediff; } + UNLOCK_BH(&ip_nat_seqofs_lock); - iph = (*skb)->nh.iph; - if (iph->protocol == IPPROTO_TCP) { - struct tcphdr *tcph = (void *)iph + iph->ihl*4; - - DEBUGP("ip_nat_resize_packet: Seq_offset before: "); - DUMP_OFFSET(this_way); - - LOCK_BH(&ip_nat_seqofs_lock); - - /* SYN adjust. If it's uninitialized, of this is after last - * correction, record it: we don't handle more than one - * adjustment in the window, but do deal with common case of a - * retransmit */ - if (this_way->offset_before == this_way->offset_after - || before(this_way->correction_pos, ntohl(tcph->seq))) { - this_way->correction_pos = ntohl(tcph->seq); - this_way->offset_before = this_way->offset_after; - this_way->offset_after = (int32_t) - this_way->offset_before + new_size - - (*skb)->len; - } + DEBUGP("ip_nat_resize_packet: Seq_offset after: "); + DUMP_OFFSET(this_way); +} + +/* Frobs data inside this packet, which is linear. */ +static void mangle_contents(struct sk_buff *skb, + unsigned int dataoff, + unsigned int match_offset, + unsigned int match_len, + const char *rep_buffer, + unsigned int rep_len) +{ + unsigned char *data; + + BUG_ON(skb_is_nonlinear(skb)); + data = (unsigned char *)skb->nh.iph + dataoff; - UNLOCK_BH(&ip_nat_seqofs_lock); + /* move post-replacement */ + memmove(data + match_offset + rep_len, + data + match_offset + match_len, + skb->tail - (data + match_offset + match_len)); - DEBUGP("ip_nat_resize_packet: Seq_offset after: "); - DUMP_OFFSET(this_way); + /* insert data from buffer */ + memcpy(data + match_offset, rep_buffer, rep_len); + + /* update skb info */ + if (rep_len > match_len) { + DEBUGP("ip_nat_mangle_packet: Extending packet by " + "%u from %u bytes\n", rep_len - match_len, + skb->len); + skb_put(skb, rep_len - match_len); + } else { + DEBUGP("ip_nat_mangle_packet: Shrinking packet from " + "%u from %u bytes\n", match_len - rep_len, + skb->len); + __skb_trim(skb, skb->len + rep_len - match_len); } - - return 1; + + /* fix IP hdr checksum information */ + skb->nh.iph->tot_len = htons(skb->len); + ip_send_check(skb->nh.iph); + skb->csum = csum_partial(data, skb->len - dataoff, 0); } +/* Unusual, but possible case. */ +static int enlarge_skb(struct sk_buff **pskb, unsigned int extra) +{ + struct sk_buff *nskb; + + if ((*pskb)->len + extra > 65535) + return 0; + + nskb = skb_copy_expand(*pskb, skb_headroom(*pskb), extra, GFP_ATOMIC); + if (!nskb) + return 0; + + /* Transfer socket to new skb. */ + if ((*pskb)->sk) + skb_set_owner_w(nskb, (*pskb)->sk); +#ifdef CONFIG_NETFILTER_DEBUG + nskb->nf_debug = (*pskb)->nf_debug; +#endif + kfree_skb(*pskb); + *pskb = nskb; + return 1; +} /* Generic function for mangling variable-length address changes inside * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX @@ -121,91 +158,41 @@ * * */ int -ip_nat_mangle_tcp_packet(struct sk_buff **skb, +ip_nat_mangle_tcp_packet(struct sk_buff **pskb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, unsigned int match_offset, unsigned int match_len, - char *rep_buffer, + const char *rep_buffer, unsigned int rep_len) { - struct iphdr *iph = (*skb)->nh.iph; + struct iphdr *iph; struct tcphdr *tcph; - unsigned char *data; - u_int32_t tcplen, newlen, newtcplen; - tcplen = (*skb)->len - iph->ihl*4; - newtcplen = tcplen - match_len + rep_len; - newlen = iph->ihl*4 + newtcplen; - - if (newlen > 65535) { - if (net_ratelimit()) - printk("ip_nat_mangle_tcp_packet: nat'ed packet " - "exceeds maximum packet size\n"); + if (!skb_ip_make_writable(pskb, (*pskb)->len)) return 0; - } - if ((*skb)->len != newlen) { - if (!ip_nat_resize_packet(skb, ct, ctinfo, newlen)) { - printk("resize_packet failed!!\n"); - return 0; - } - } + if (rep_len > match_len + && rep_len - match_len > skb_tailroom(*pskb) + && !enlarge_skb(pskb, rep_len - match_len)) + return 0; - /* Alexey says: if a hook changes _data_ ... it can break - original packet sitting in tcp queue and this is fatal */ - if (skb_cloned(*skb)) { - struct sk_buff *nskb = skb_copy(*skb, GFP_ATOMIC); - if (!nskb) { - if (net_ratelimit()) - printk("Out of memory cloning TCP packet\n"); - return 0; - } - /* Rest of kernel will get very unhappy if we pass it - a suddenly-orphaned skbuff */ - if ((*skb)->sk) - skb_set_owner_w(nskb, (*skb)->sk); - kfree_skb(*skb); - *skb = nskb; - } + SKB_LINEAR_ASSERT(*pskb); - /* skb may be copied !! */ - iph = (*skb)->nh.iph; + iph = (*pskb)->nh.iph; tcph = (void *)iph + iph->ihl*4; - data = (void *)tcph + tcph->doff*4; - - if (rep_len != match_len) - /* move post-replacement */ - memmove(data + match_offset + rep_len, - data + match_offset + match_len, - (*skb)->tail - (data + match_offset + match_len)); - - /* insert data from buffer */ - memcpy(data + match_offset, rep_buffer, rep_len); - - /* update skb info */ - if (newlen > (*skb)->len) { - DEBUGP("ip_nat_mangle_tcp_packet: Extending packet by " - "%u to %u bytes\n", newlen - (*skb)->len, newlen); - skb_put(*skb, newlen - (*skb)->len); - } else { - DEBUGP("ip_nat_mangle_tcp_packet: Shrinking packet from " - "%u to %u bytes\n", (*skb)->len, newlen); - skb_trim(*skb, newlen); - } - - /* fix checksum information */ - iph->tot_len = htons(newlen); - (*skb)->csum = csum_partial((char *)tcph + tcph->doff*4, - newtcplen - tcph->doff*4, 0); + mangle_contents(*pskb, iph->ihl*4 + tcph->doff*4, + match_offset, match_len, rep_buffer, rep_len); tcph->check = 0; - tcph->check = tcp_v4_check(tcph, newtcplen, iph->saddr, iph->daddr, + tcph->check = tcp_v4_check(tcph, (*pskb)->len - iph->ihl*4, + iph->saddr, iph->daddr, csum_partial((char *)tcph, tcph->doff*4, - (*skb)->csum)); - ip_send_check(iph); - + (*pskb)->csum)); + adjust_tcp_sequence(ntohl(tcph->seq), + (int)match_len - (int)rep_len, + ct, ctinfo); return 1; } @@ -220,219 +207,164 @@ * should be fairly easy to do. */ int -ip_nat_mangle_udp_packet(struct sk_buff **skb, +ip_nat_mangle_udp_packet(struct sk_buff **pskb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo, unsigned int match_offset, unsigned int match_len, - char *rep_buffer, + const char *rep_buffer, unsigned int rep_len) { - struct iphdr *iph = (*skb)->nh.iph; - struct udphdr *udph = (void *)iph + iph->ihl * 4; - unsigned char *data; - u_int32_t udplen, newlen, newudplen; + struct iphdr *iph; + struct udphdr *udph; + int need_csum = ((*pskb)->csum != 0); - udplen = (*skb)->len - iph->ihl*4; - newudplen = udplen - match_len + rep_len; - newlen = iph->ihl*4 + newudplen; - - if (newlen > 65535) { - if (net_ratelimit()) - printk("ip_nat_mangle_udp_packet: nat'ed packet " - "exceeds maximum packet size\n"); + if (!skb_ip_make_writable(pskb, (*pskb)->len)) return 0; - } - if ((*skb)->len != newlen) { - if (!ip_nat_resize_packet(skb, ct, ctinfo, newlen)) { - printk("resize_packet failed!!\n"); - return 0; - } - } - - /* Alexey says: if a hook changes _data_ ... it can break - original packet sitting in tcp queue and this is fatal */ - if (skb_cloned(*skb)) { - struct sk_buff *nskb = skb_copy(*skb, GFP_ATOMIC); - if (!nskb) { - if (net_ratelimit()) - printk("Out of memory cloning TCP packet\n"); - return 0; - } - /* Rest of kernel will get very unhappy if we pass it - a suddenly-orphaned skbuff */ - if ((*skb)->sk) - skb_set_owner_w(nskb, (*skb)->sk); - kfree_skb(*skb); - *skb = nskb; - } + if (rep_len > match_len + && rep_len - match_len > skb_tailroom(*pskb) + && !enlarge_skb(pskb, rep_len - match_len)) + return 0; - /* skb may be copied !! */ - iph = (*skb)->nh.iph; + iph = (*pskb)->nh.iph; udph = (void *)iph + iph->ihl*4; - data = (void *)udph + sizeof(struct udphdr); - - if (rep_len != match_len) - /* move post-replacement */ - memmove(data + match_offset + rep_len, - data + match_offset + match_len, - (*skb)->tail - (data + match_offset + match_len)); - - /* insert data from buffer */ - memcpy(data + match_offset, rep_buffer, rep_len); + mangle_contents(*pskb, iph->ihl*4 + sizeof(*udph), + match_offset, match_len, rep_buffer, rep_len); - /* update skb info */ - if (newlen > (*skb)->len) { - DEBUGP("ip_nat_mangle_udp_packet: Extending packet by " - "%u to %u bytes\n", newlen - (*skb)->len, newlen); - skb_put(*skb, newlen - (*skb)->len); - } else { - DEBUGP("ip_nat_mangle_udp_packet: Shrinking packet from " - "%u to %u bytes\n", (*skb)->len, newlen); - skb_trim(*skb, newlen); - } - - /* update the length of the UDP and IP packets to the new values*/ - udph->len = htons((*skb)->len - iph->ihl*4); - iph->tot_len = htons(newlen); + /* update the length of the UDP packet */ + udph->len = htons((*pskb)->len - iph->ihl*4); /* fix udp checksum if udp checksum was previously calculated */ - if ((*skb)->csum != 0) { - (*skb)->csum = csum_partial((char *)udph + - sizeof(struct udphdr), - newudplen - sizeof(struct udphdr), - 0); - + if (need_csum) { udph->check = 0; - udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, - newudplen, IPPROTO_UDP, - csum_partial((char *)udph, + udph->check + = csum_tcpudp_magic(iph->saddr, iph->daddr, + (*pskb)->len - iph->ihl*4, + IPPROTO_UDP, + csum_partial((char *)udph, sizeof(struct udphdr), - (*skb)->csum)); - } - - ip_send_check(iph); - + (*pskb)->csum)); + } else + (*pskb)->csum = 0; return 1; } /* Adjust one found SACK option including checksum correction */ static void -sack_adjust(struct tcphdr *tcph, - unsigned char *ptr, +sack_adjust(struct sk_buff *skb, + struct tcphdr *tcph, + unsigned int sackoff, + unsigned int sackend, struct ip_nat_seq *natseq) { - struct tcp_sack_block *sp = (struct tcp_sack_block *)(ptr+2); - int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3; - int i; - - for (i = 0; i < num_sacks; i++, sp++) { + while (sackoff < sackend) { + struct tcp_sack_block *sack; u_int32_t new_start_seq, new_end_seq; - if (after(ntohl(sp->start_seq) - natseq->offset_before, + sack = (void *)skb->data + sackoff; + if (after(ntohl(sack->start_seq) - natseq->offset_before, natseq->correction_pos)) - new_start_seq = ntohl(sp->start_seq) + new_start_seq = ntohl(sack->start_seq) - natseq->offset_after; else - new_start_seq = ntohl(sp->start_seq) + new_start_seq = ntohl(sack->start_seq) - natseq->offset_before; new_start_seq = htonl(new_start_seq); - if (after(ntohl(sp->end_seq) - natseq->offset_before, + if (after(ntohl(sack->end_seq) - natseq->offset_before, natseq->correction_pos)) - new_end_seq = ntohl(sp->end_seq) + new_end_seq = ntohl(sack->end_seq) - natseq->offset_after; else - new_end_seq = ntohl(sp->end_seq) + new_end_seq = ntohl(sack->end_seq) - natseq->offset_before; new_end_seq = htonl(new_end_seq); DEBUGP("sack_adjust: start_seq: %d->%d, end_seq: %d->%d\n", - ntohl(sp->start_seq), new_start_seq, - ntohl(sp->end_seq), new_end_seq); + ntohl(sack->start_seq), new_start_seq, + ntohl(sack->end_seq), new_end_seq); tcph->check = - ip_nat_cheat_check(~sp->start_seq, new_start_seq, - ip_nat_cheat_check(~sp->end_seq, + ip_nat_cheat_check(~sack->start_seq, new_start_seq, + ip_nat_cheat_check(~sack->end_seq, new_end_seq, tcph->check)); - - sp->start_seq = new_start_seq; - sp->end_seq = new_end_seq; + sack->start_seq = new_start_seq; + sack->end_seq = new_end_seq; + sackoff += sizeof(*sack); } } - -/* TCP SACK sequence number adjustment, return 0 if sack found and adjusted */ -static inline int -ip_nat_sack_adjust(struct sk_buff *skb, - struct ip_conntrack *ct, - enum ip_conntrack_info ctinfo) +/* TCP SACK sequence number adjustment */ +static inline unsigned int +ip_nat_sack_adjust(struct sk_buff **pskb, + struct tcphdr *tcph, + struct ip_conntrack *ct, + enum ip_conntrack_info ctinfo) { - struct iphdr *iph; - struct tcphdr *tcph; - unsigned char *ptr; - int length, dir, sack_adjusted = 0; + unsigned int dir, optoff, optend; - iph = skb->nh.iph; - tcph = (void *)iph + iph->ihl*4; - length = (tcph->doff*4)-sizeof(struct tcphdr); - ptr = (unsigned char *)(tcph+1); + optoff = (*pskb)->nh.iph->ihl*4 + sizeof(struct tcphdr); + optend = (*pskb)->nh.iph->ihl*4 + tcph->doff*4; + + if (!skb_ip_make_writable(pskb, optend)) + return 0; dir = CTINFO2DIR(ctinfo); - while (length > 0) { - int opcode = *ptr++; - int opsize; + while (optoff < optend) { + /* Usually: option, length. */ + unsigned char *op = (*pskb)->data + optoff; - switch (opcode) { + switch (op[0]) { case TCPOPT_EOL: - return !sack_adjusted; + return 1; case TCPOPT_NOP: - length--; + optoff++; continue; default: - opsize = *ptr++; - if (opsize > length) /* no partial opts */ - return !sack_adjusted; - if (opcode == TCPOPT_SACK) { - /* found SACK */ - if((opsize >= (TCPOLEN_SACK_BASE - +TCPOLEN_SACK_PERBLOCK)) && - !((opsize - TCPOLEN_SACK_BASE) - % TCPOLEN_SACK_PERBLOCK)) - sack_adjust(tcph, ptr-2, - &ct->nat.info.seq[!dir]); - - sack_adjusted = 1; - } - ptr += opsize-2; - length -= opsize; + /* no partial options */ + if (optoff + 1 == optend + || optoff + op[1] > optend + || op[1] < 2) + return 0; + if (op[0] == TCPOPT_SACK + && op[1] >= 2+TCPOLEN_SACK_PERBLOCK + && ((op[1] - 2) % TCPOLEN_SACK_PERBLOCK) == 0) + sack_adjust(*pskb, tcph, optoff+2, + optoff+op[1], + &ct->nat.info.seq[!dir]); + optoff += op[1]; } } - return !sack_adjusted; + return 1; } -/* TCP sequence number adjustment */ -int -ip_nat_seq_adjust(struct sk_buff *skb, +/* TCP sequence number adjustment. Returns true or false. */ +int +ip_nat_seq_adjust(struct sk_buff **pskb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) { - struct iphdr *iph; struct tcphdr *tcph; int dir, newseq, newack; struct ip_nat_seq *this_way, *other_way; - - iph = skb->nh.iph; - tcph = (void *)iph + iph->ihl*4; dir = CTINFO2DIR(ctinfo); this_way = &ct->nat.info.seq[dir]; other_way = &ct->nat.info.seq[!dir]; - + + /* No adjustments to make? Very common case. */ + if (!this_way->offset_before && !this_way->offset_after + && !other_way->offset_before && !other_way->offset_after) + return 1; + + if (!skb_ip_make_writable(pskb, (*pskb)->nh.iph->ihl*4+sizeof(*tcph))) + return 0; + + tcph = (void *)(*pskb)->data + (*pskb)->nh.iph->ihl*4; if (after(ntohl(tcph->seq), this_way->correction_pos)) newseq = ntohl(tcph->seq) + this_way->offset_after; else @@ -458,9 +390,7 @@ tcph->seq = newseq; tcph->ack_seq = newack; - ip_nat_sack_adjust(skb, ct, ctinfo); - - return 0; + return ip_nat_sack_adjust(pskb, tcph, ct, ctinfo); } static inline int diff -Nru a/net/ipv4/netfilter/ip_nat_proto_icmp.c b/net/ipv4/netfilter/ip_nat_proto_icmp.c --- a/net/ipv4/netfilter/ip_nat_proto_icmp.c Thu May 8 00:24:28 2003 +++ b/net/ipv4/netfilter/ip_nat_proto_icmp.c Thu May 8 00:24:28 2003 @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -42,17 +43,24 @@ return 0; } -static void -icmp_manip_pkt(struct iphdr *iph, size_t len, +static int +icmp_manip_pkt(struct sk_buff **pskb, + unsigned int hdroff, const struct ip_conntrack_manip *manip, enum ip_nat_manip_type maniptype) { - struct icmphdr *hdr = (struct icmphdr *)((u_int32_t *)iph + iph->ihl); + struct icmphdr *hdr; + + if (!skb_ip_make_writable(pskb, hdroff + sizeof(*hdr))) + return 0; + + hdr = (void *)(*pskb)->data + hdroff; hdr->checksum = ip_nat_cheat_check(hdr->un.echo.id ^ 0xFFFF, - manip->u.icmp.id, - hdr->checksum); + manip->u.icmp.id, + hdr->checksum); hdr->un.echo.id = manip->u.icmp.id; + return 1; } static unsigned int diff -Nru a/net/ipv4/netfilter/ip_nat_proto_tcp.c b/net/ipv4/netfilter/ip_nat_proto_tcp.c --- a/net/ipv4/netfilter/ip_nat_proto_tcp.c Thu May 8 00:24:27 2003 +++ b/net/ipv4/netfilter/ip_nat_proto_tcp.c Thu May 8 00:24:27 2003 @@ -7,6 +7,7 @@ #include #include #include +#include static int tcp_in_range(const struct ip_conntrack_tuple *tuple, @@ -73,36 +74,49 @@ return 0; } -static void -tcp_manip_pkt(struct iphdr *iph, size_t len, +static int +tcp_manip_pkt(struct sk_buff **pskb, + unsigned int hdroff, const struct ip_conntrack_manip *manip, enum ip_nat_manip_type maniptype) { - struct tcphdr *hdr = (struct tcphdr *)((u_int32_t *)iph + iph->ihl); + struct tcphdr *hdr; u_int32_t oldip; - u_int16_t *portptr; + u_int16_t *portptr, oldport; + int hdrsize = 8; /* TCP connection tracking guarantees this much */ + + /* this could be a inner header returned in icmp packet; in such + cases we cannot update the checksum field since it is outside of + the 8 bytes of transport layer headers we are guaranteed */ + if ((*pskb)->len >= hdroff + sizeof(struct tcphdr)) + hdrsize = sizeof(struct tcphdr); + + if (!skb_ip_make_writable(pskb, hdroff + hdrsize)) + return 0; + + hdr = (void *)(*pskb)->data + hdroff; if (maniptype == IP_NAT_MANIP_SRC) { /* Get rid of src ip and src pt */ - oldip = iph->saddr; + oldip = (*pskb)->nh.iph->saddr; portptr = &hdr->source; } else { /* Get rid of dst ip and dst pt */ - oldip = iph->daddr; + oldip = (*pskb)->nh.iph->daddr; portptr = &hdr->dest; } - /* this could be a inner header returned in icmp packet; in such - cases we cannot update the checksum field since it is outside of - the 8 bytes of transport layer headers we are guaranteed */ - if(((void *)&hdr->check + sizeof(hdr->check) - (void *)iph) <= len) { - hdr->check = ip_nat_cheat_check(~oldip, manip->ip, - ip_nat_cheat_check(*portptr ^ 0xFFFF, + oldport = *portptr; + *portptr = manip->u.tcp.port; + + if (hdrsize < sizeof(*hdr)) + return 1; + + hdr->check = ip_nat_cheat_check(~oldip, manip->ip, + ip_nat_cheat_check(oldport ^ 0xFFFF, manip->u.tcp.port, hdr->check)); - } - - *portptr = manip->u.tcp.port; + return 1; } static unsigned int diff -Nru a/net/ipv4/netfilter/ip_nat_proto_udp.c b/net/ipv4/netfilter/ip_nat_proto_udp.c --- a/net/ipv4/netfilter/ip_nat_proto_udp.c Thu May 8 00:24:28 2003 +++ b/net/ipv4/netfilter/ip_nat_proto_udp.c Thu May 8 00:24:28 2003 @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -72,22 +73,27 @@ return 0; } -static void -udp_manip_pkt(struct iphdr *iph, size_t len, +static int +udp_manip_pkt(struct sk_buff **pskb, + unsigned int hdroff, const struct ip_conntrack_manip *manip, enum ip_nat_manip_type maniptype) { - struct udphdr *hdr = (struct udphdr *)((u_int32_t *)iph + iph->ihl); + struct udphdr *hdr; u_int32_t oldip; u_int16_t *portptr; + if (!skb_ip_make_writable(pskb, hdroff + sizeof(hdr))) + return 0; + + hdr = (void *)(*pskb)->data + hdroff; if (maniptype == IP_NAT_MANIP_SRC) { /* Get rid of src ip and src pt */ - oldip = iph->saddr; + oldip = (*pskb)->nh.iph->saddr; portptr = &hdr->source; } else { /* Get rid of dst ip and dst pt */ - oldip = iph->daddr; + oldip = (*pskb)->nh.iph->daddr; portptr = &hdr->dest; } if (hdr->check) /* 0 is a special case meaning no checksum */ @@ -96,6 +102,7 @@ manip->u.udp.port, hdr->check)); *portptr = manip->u.udp.port; + return 1; } static unsigned int diff -Nru a/net/ipv4/netfilter/ip_nat_proto_unknown.c b/net/ipv4/netfilter/ip_nat_proto_unknown.c --- a/net/ipv4/netfilter/ip_nat_proto_unknown.c Thu May 8 00:24:29 2003 +++ b/net/ipv4/netfilter/ip_nat_proto_unknown.c Thu May 8 00:24:29 2003 @@ -29,12 +29,13 @@ return 0; } -static void -unknown_manip_pkt(struct iphdr *iph, size_t len, +static int +unknown_manip_pkt(struct sk_buff **pskb, + unsigned int hdroff, const struct ip_conntrack_manip *manip, enum ip_nat_manip_type maniptype) { - return; + return 1; } static unsigned int diff -Nru a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c --- a/net/ipv4/netfilter/ip_nat_standalone.c Thu May 8 00:24:29 2003 +++ b/net/ipv4/netfilter/ip_nat_standalone.c Thu May 8 00:24:29 2003 @@ -71,10 +71,6 @@ /* maniptype == SRC for postrouting. */ enum ip_nat_manip_type maniptype = HOOK2MANIP(hooknum); - /* FIXME: Push down to extensions --RR */ - if (skb_is_nonlinear(*pskb) && skb_linearize(*pskb, GFP_ATOMIC) != 0) - return NF_DROP; - /* We never see fragments: conntrack defrags on pre-routing and local-out, and ip_nat_out protects post-routing. */ IP_NF_ASSERT(!((*pskb)->nh.iph->frag_off @@ -95,12 +91,14 @@ /* Exception: ICMP redirect to new connection (not in hash table yet). We must not let this through, in case we're doing NAT to the same network. */ - struct iphdr *iph = (*pskb)->nh.iph; - struct icmphdr *hdr = (struct icmphdr *) - ((u_int32_t *)iph + iph->ihl); - if (iph->protocol == IPPROTO_ICMP - && hdr->type == ICMP_REDIRECT) - return NF_DROP; + if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) { + struct icmphdr hdr; + + if (skb_copy_bits(*pskb, (*pskb)->nh.iph->ihl*4, + &hdr, sizeof(hdr)) == 0 + && hdr.type == ICMP_REDIRECT) + return NF_DROP; + } return NF_ACCEPT; } @@ -108,8 +106,11 @@ case IP_CT_RELATED: case IP_CT_RELATED+IP_CT_IS_REPLY: if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) { - return icmp_reply_translation(*pskb, ct, hooknum, - CTINFO2DIR(ctinfo)); + if (!icmp_reply_translation(pskb, ct, hooknum, + CTINFO2DIR(ctinfo))) + return NF_DROP; + else + return NF_ACCEPT; } /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */ case IP_CT_NEW: @@ -174,10 +175,6 @@ const struct net_device *out, int (*okfn)(struct sk_buff *)) { - /* FIXME: Push down to extensions --RR */ - if (skb_is_nonlinear(*pskb) && skb_linearize(*pskb, GFP_ATOMIC) != 0) - return NF_DROP; - /* root is playing with raw sockets. */ if ((*pskb)->len < sizeof(struct iphdr) || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) @@ -213,10 +210,6 @@ u_int32_t saddr, daddr; unsigned int ret; - /* FIXME: Push down to extensions --RR */ - if (skb_is_nonlinear(*pskb) && skb_linearize(*pskb, GFP_ATOMIC) != 0) - return NF_DROP; - /* root is playing with raw sockets. */ if ((*pskb)->len < sizeof(struct iphdr) || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) @@ -387,4 +380,5 @@ EXPORT_SYMBOL(ip_nat_mangle_tcp_packet); EXPORT_SYMBOL(ip_nat_mangle_udp_packet); EXPORT_SYMBOL(ip_nat_used_tuple); +EXPORT_SYMBOL(skb_ip_make_writable); MODULE_LICENSE("GPL"); diff -Nru a/net/ipv4/netfilter/ip_nat_tftp.c b/net/ipv4/netfilter/ip_nat_tftp.c --- a/net/ipv4/netfilter/ip_nat_tftp.c Thu May 8 00:24:28 2003 +++ b/net/ipv4/netfilter/ip_nat_tftp.c Thu May 8 00:24:28 2003 @@ -57,9 +57,7 @@ struct sk_buff **pskb) { int dir = CTINFO2DIR(ctinfo); - struct iphdr *iph = (*pskb)->nh.iph; - struct udphdr *udph = (void *)iph + iph->ihl * 4; - struct tftphdr *tftph = (void *)udph + 8; + struct tftphdr tftph; struct ip_conntrack_tuple repl; if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL) @@ -71,7 +69,11 @@ return NF_ACCEPT; } - switch (ntohs(tftph->opcode)) { + if (skb_copy_bits(*pskb, (*pskb)->nh.iph->ihl*4+sizeof(struct udphdr), + &tftph, sizeof(tftph)) != 0) + return NF_DROP; + + switch (ntohs(tftph.opcode)) { /* RRQ and WRQ works the same way */ case TFTP_OPCODE_READ: case TFTP_OPCODE_WRITE: @@ -104,8 +106,10 @@ #if 0 const struct ip_conntrack_tuple *repl = &master->tuplehash[IP_CT_DIR_REPLY].tuple; - struct iphdr *iph = (*pskb)->nh.iph; - struct udphdr *udph = (void *)iph + iph->ihl*4; + struct udphdr udph; + + if (skb_copy_bits(*pskb,(*pskb)->nh.iph->ihl*4,&udph,sizeof(udph))!=0) + return NF_DROP; #endif IP_NF_ASSERT(info); @@ -119,8 +123,8 @@ mr.range[0].min_ip = mr.range[0].max_ip = orig->dst.ip; DEBUGP("orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u " "newsrc: %u.%u.%u.%u\n", - NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source), - NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest), + NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph.source), + NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph.dest), NIPQUAD(orig->dst.ip)); } else { mr.range[0].min_ip = mr.range[0].max_ip = orig->src.ip; @@ -130,8 +134,8 @@ DEBUGP("orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u " "newdst: %u.%u.%u.%u:%u\n", - NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source), - NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest), + NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph.source), + NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph.dest), NIPQUAD(orig->src.ip), ntohs(orig->src.u.udp.port)); } diff -Nru a/net/ipv4/netfilter/ipchains_core.c b/net/ipv4/netfilter/ipchains_core.c --- a/net/ipv4/netfilter/ipchains_core.c Thu May 8 00:24:30 2003 +++ b/net/ipv4/netfilter/ipchains_core.c Thu May 8 00:24:30 2003 @@ -839,7 +839,9 @@ i->branch->refcount--; kfree(i); i = tmp; - MOD_DEC_USE_COUNT; + /* We will block in cleanup's unregister sockopt if unloaded, + so this is safe. */ + module_put(THIS_MODULE); } return 0; } @@ -870,6 +872,11 @@ struct ip_fwkernel *i; FWC_HAVE_LOCK(fwc_wlocks); + + /* Are we unloading now? We will block on nf_unregister_sockopt */ + if (!try_module_get(THIS_MODULE)) + return ENOPROTOOPT; + /* Special case if no rules already present */ if (chainptr->chain == NULL) { @@ -886,7 +893,6 @@ if (rule->branch) rule->branch->refcount++; append_successful: - MOD_INC_USE_COUNT; return 0; } @@ -900,6 +906,11 @@ struct ip_fwkernel *f = chainptr->chain; FWC_HAVE_LOCK(fwc_wlocks); + + /* Are we unloading now? We will block on nf_unregister_sockopt */ + if (!try_module_get(THIS_MODULE)) + return ENOPROTOOPT; + /* special case if the position is number 1 */ if (position == 1) { frwl->next = chainptr->chain; @@ -917,7 +928,6 @@ f->next = frwl; insert_successful: - MOD_INC_USE_COUNT; return 0; } @@ -952,7 +962,9 @@ kfree(tmp); } - MOD_DEC_USE_COUNT; + /* We will block in cleanup's unregister sockopt if unloaded, + so this is safe. */ + module_put(THIS_MODULE); return 0; } @@ -1059,7 +1071,9 @@ else chainptr->chain = ftmp->next; kfree(ftmp); - MOD_DEC_USE_COUNT; + /* We will block in cleanup's unregister sockopt if unloaded, + so this is safe. */ + module_put(THIS_MODULE); break; } @@ -1101,7 +1115,9 @@ tmp->next = tmp2->next; kfree(tmp2); - MOD_DEC_USE_COUNT; + /* We will block in cleanup's unregister sockopt if unloaded, + so this is safe. */ + module_put(THIS_MODULE); return 0; } @@ -1149,12 +1165,15 @@ if (strcmp(tmp->label,label) == 0) return EEXIST; + /* Are we unloading now? We will block on nf_unregister_sockopt */ + if (!try_module_get(THIS_MODULE)) + return ENOPROTOOPT; + tmp->next = ip_init_chain(label, 0, FW_SKIP); /* refcount is * zero since this is a * user defined chain * * and therefore can be * deleted */ - MOD_INC_USE_COUNT; return 0; } diff -Nru a/net/ipv4/netfilter/ipfwadm_core.c b/net/ipv4/netfilter/ipfwadm_core.c --- a/net/ipv4/netfilter/ipfwadm_core.c Thu May 8 00:24:28 2003 +++ b/net/ipv4/netfilter/ipfwadm_core.c Thu May 8 00:24:28 2003 @@ -707,7 +707,9 @@ ftmp = *chainptr; *chainptr = ftmp->fw_next; kfree(ftmp); - MOD_DEC_USE_COUNT; + /* We will block in cleanup's unregister sockopt if unloaded, + so this is safe. */ + module_put(THIS_MODULE); } WRITE_UNLOCK(&ip_fw_lock); } @@ -718,6 +720,10 @@ { struct ip_fw *ftmp; + /* Are we unloading now? We will block on nf_unregister_sockopt */ + if (!try_module_get(THIS_MODULE)) + return ENOPROTOOPT; + ftmp = kmalloc( sizeof(struct ip_fw), GFP_KERNEL ); if ( ftmp == NULL ) { @@ -748,7 +754,6 @@ ftmp->fw_next = *chainptr; *chainptr=ftmp; WRITE_UNLOCK(&ip_fw_lock); - MOD_INC_USE_COUNT; return(0); } @@ -758,6 +763,10 @@ struct ip_fw *chtmp=NULL; struct ip_fw *volatile chtmp_prev=NULL; + /* Are we unloading now? We will block on nf_unregister_sockopt */ + if (!try_module_get(THIS_MODULE)) + return ENOPROTOOPT; + ftmp = kmalloc( sizeof(struct ip_fw), GFP_KERNEL ); if ( ftmp == NULL ) { @@ -796,7 +805,6 @@ else *chainptr=ftmp; WRITE_UNLOCK(&ip_fw_lock); - MOD_INC_USE_COUNT; return(0); } @@ -869,7 +877,9 @@ } WRITE_UNLOCK(&ip_fw_lock); if (was_found) { - MOD_DEC_USE_COUNT; + /* We will block in cleanup's unregister sockopt if unloaded, + so this is safe. */ + module_put(THIS_MODULE); return 0; } else return(EINVAL); diff -Nru a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c --- a/net/ipv4/tcp_minisocks.c Thu May 8 00:24:29 2003 +++ b/net/ipv4/tcp_minisocks.c Thu May 8 00:24:29 2003 @@ -444,6 +444,8 @@ while((tw = tcp_tw_death_row[tcp_tw_death_row_slot]) != NULL) { tcp_tw_death_row[tcp_tw_death_row_slot] = tw->next_death; + if (tw->next_death) + tw->next_death->pprev_death = tw->pprev_death; tw->pprev_death = NULL; spin_unlock(&tw_death_lock); diff -Nru a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c --- a/net/ipv6/af_inet6.c Thu May 8 00:24:29 2003 +++ b/net/ipv6/af_inet6.c Thu May 8 00:24:29 2003 @@ -111,7 +111,6 @@ #ifdef INET_REFCNT_DEBUG atomic_dec(&inet6_sock_nr); #endif - module_put(THIS_MODULE); } static __inline__ kmem_cache_t *inet6_sk_slab(int protocol) @@ -243,11 +242,6 @@ atomic_inc(&inet6_sock_nr); atomic_inc(&inet_sock_nr); #endif - if (!try_module_get(THIS_MODULE)) { - inet_sock_release(sk); - return -EBUSY; - } - if (inet->num) { /* It assumes that any protocol which allows * the user to assign a number at socket @@ -259,7 +253,6 @@ if (sk->prot->init) { int err = sk->prot->init(sk); if (err != 0) { - module_put(THIS_MODULE); inet_sock_release(sk); return err; } @@ -542,6 +535,7 @@ struct net_proto_family inet6_family_ops = { .family = PF_INET6, .create = inet6_create, + .owner = THIS_MODULE, }; #ifdef MODULE diff -Nru a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c --- a/net/ipv6/exthdrs.c Thu May 8 00:24:27 2003 +++ b/net/ipv6/exthdrs.c Thu May 8 00:24:27 2003 @@ -252,8 +252,13 @@ return 1; } - if (hdr->type != IPV6_SRCRT_TYPE_0 || (hdr->hdrlen & 0x01)) { - icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, hdr->type != IPV6_SRCRT_TYPE_0 ? 2 : 1); + if (hdr->type != IPV6_SRCRT_TYPE_0) { + icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->type) - skb->nh.raw); + return -1; + } + + if (hdr->hdrlen & 0x01) { + icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, (&hdr->hdrlen) - skb->nh.raw); return -1; } diff -Nru a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c --- a/net/ipv6/ip6_fib.c Thu May 8 00:24:29 2003 +++ b/net/ipv6/ip6_fib.c Thu May 8 00:24:29 2003 @@ -593,7 +593,7 @@ #ifdef CONFIG_IPV6_SUBTREES /* Subtree creation failed, probably main tree node - is orphan. If it is, shot it. + is orphan. If it is, shoot it. */ st_failure: if (fn && !(fn->fn_flags&RTN_RTINFO|RTN_ROOT)) @@ -953,7 +953,7 @@ #if RT6_DEBUG >= 2 if (rt->u.dst.obsolete>0) { - BUG_TRAP(fn==NULL || rt->u.dst.obsolete<=0); + BUG_TRAP(fn==NULL); return -ENOENT; } #endif @@ -979,7 +979,7 @@ } /* - * Tree transversal function. + * Tree traversal function. * * Certainly, it is not interrupt safe. * However, it is internally reenterable wrt itself and fib6_add/fib6_del. @@ -1179,14 +1179,14 @@ */ if (rt->rt6i_flags&RTF_EXPIRES && rt->rt6i_expires) { - if ((long)(now - rt->rt6i_expires) > 0) { + if (time_after(now, rt->rt6i_expires)) { RT6_TRACE("expiring %p\n", rt); return -1; } gc_args.more++; } else if (rt->rt6i_flags & RTF_CACHE) { if (atomic_read(&rt->u.dst.__refcnt) == 0 && - (long)(now - rt->u.dst.lastuse) >= gc_args.timeout) { + time_after_eq(now, rt->u.dst.lastuse + gc_args.timeout)) { RT6_TRACE("aging clone %p\n", rt); return -1; } diff -Nru a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c --- a/net/ipv6/netfilter/ip6t_ah.c Thu May 8 00:24:27 2003 +++ b/net/ipv6/netfilter/ip6t_ah.c Thu May 8 00:24:27 2003 @@ -19,13 +19,6 @@ #define DEBUGP(format, args...) #endif -struct ahhdr { - __u8 nexthdr; - __u8 hdrlen; - __u16 reserved; - __u32 spi; -}; - /* Returns 1 if the spi is matched by the range, 0 otherwise */ static inline int spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert) @@ -48,7 +41,7 @@ u_int16_t datalen, int *hotdrop) { - struct ahhdr *ah = NULL; + struct ip_auth_hdr *ah = NULL; const struct ip6t_ah *ahinfo = matchinfo; unsigned int temp; int len; @@ -128,12 +121,12 @@ /* AH header not found */ if ( temp != MASK_AH ) return 0; - if (len < (int)sizeof(struct ahhdr)){ + if (len < (int)sizeof(struct ip_auth_hdr)){ *hotdrop = 1; return 0; } - ah=skb->data+ptr; + ah = (struct ip_auth_hdr *) (skb->data + ptr); DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen); DEBUGP("RES %04X ", ah->reserved); diff -Nru a/net/ipv6/netfilter/ip6t_esp.c b/net/ipv6/netfilter/ip6t_esp.c --- a/net/ipv6/netfilter/ip6t_esp.c Thu May 8 00:24:29 2003 +++ b/net/ipv6/netfilter/ip6t_esp.c Thu May 8 00:24:29 2003 @@ -19,10 +19,6 @@ #define DEBUGP(format, args...) #endif -struct esphdr { - __u32 spi; -}; - /* Returns 1 if the spi is matched by the range, 0 otherwise */ static inline int spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert) @@ -45,7 +41,7 @@ u_int16_t datalen, int *hotdrop) { - struct esphdr *esp = NULL; + struct ip_esp_hdr *esp = NULL; const struct ip6t_esp *espinfo = matchinfo; unsigned int temp; int len; @@ -118,12 +114,12 @@ /* ESP header not found */ if ( temp != MASK_ESP ) return 0; - if (len < (int)sizeof(struct esphdr)){ + if (len < (int)sizeof(struct ip_esp_hdr)){ *hotdrop = 1; return 0; } - esp=skb->data+ptr; + esp = (struct ip_esp_hdr *) (skb->data + ptr); DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(esp->spi), ntohl(esp->spi)); diff -Nru a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c --- a/net/ipv6/netfilter/ip6t_frag.c Thu May 8 00:24:28 2003 +++ b/net/ipv6/netfilter/ip6t_frag.c Thu May 8 00:24:28 2003 @@ -147,7 +147,7 @@ return 0; } - frag=skb->data+ptr; + frag = (struct fraghdr *) (skb->data + ptr); DEBUGP("IPv6 FRAG LEN %u %u ", hdrlen, frag->hdrlen); DEBUGP("INFO %04X ", frag->info); diff -Nru a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c --- a/net/ipv6/netfilter/ip6t_ipv6header.c Thu May 8 00:24:30 2003 +++ b/net/ipv6/netfilter/ip6t_ipv6header.c Thu May 8 00:24:30 2003 @@ -18,12 +18,6 @@ MODULE_DESCRIPTION("IPv6 headers match"); MODULE_AUTHOR("Andras Kis-Szabo "); -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(format, args...) -#endif - static int ipv6header_match(const struct sk_buff *skb, const struct net_device *in, @@ -39,10 +33,8 @@ int len; u8 nexthdr; unsigned int ptr; - struct inet6_skb_parm *opt = (struct inet6_skb_parm *)skb->cb; /* Make sure this isn't an evil packet */ - DEBUGP("ipv6_header entered \n"); /* type of the 1st exthdr */ nexthdr = skb->nh.ipv6h->nexthdr; @@ -52,44 +44,10 @@ len = skb->len - ptr; temp = 0; - DEBUGP("ipv6_header nexthdr %02X \n",nexthdr); - DEBUGP("ipv6_header ptr %08X \n",ptr); - DEBUGP("ipv6_header skblen %04X \n",skb->len); - DEBUGP("ipv6_header skbdatalen %04X \n",skb->data_len); - DEBUGP("ipv6_header len %04X \n",len); -#if 0 - for (temp=0;templen;temp++){ - if (!(temp % 16 )) DEBUGP("\nipv6_header data "); - DEBUGP("%02X ",skb->data[temp]); - } -#endif - DEBUGP("\nipv6_header h.raw %02X %02X %02X %02X \n", - skb->h.raw[0], - skb->h.raw[1], - skb->h.raw[2], - skb->h.raw[3]); - DEBUGP("ipv6_header nh.raw %02X %02X %02X %02X \n", - skb->nh.raw[0], - skb->nh.raw[1], - skb->nh.raw[2], - skb->nh.raw[3]); - DEBUGP("ipv6_header CB %02X %02X %02X %02X %02X %02X %02X \n", - opt->iif, - opt->ra, - opt->hop, - opt->auth, - opt->dst0, - opt->srcrt, - opt->dst1); - - temp = 0; - while (ip6t_ext_hdr(nexthdr)) { struct ipv6_opt_hdr *hdr; int hdrlen; - DEBUGP("ipv6_header header iteration \n"); - /* Is there enough space for the next ext header? */ if (len < (int)sizeof(struct ipv6_opt_hdr)) return 0; @@ -114,8 +72,6 @@ else hdrlen = ipv6_optlen(hdr); - DEBUGP("ipv6_header hdrlen %04X \n",hdrlen); - /* set the flag */ switch (nexthdr){ case NEXTHDR_HOP: @@ -134,7 +90,6 @@ temp |= MASK_DSTOPTS; break; default: - DEBUGP("IPV6HEADER match: unknown nextheader %u\n",nexthdr); return 0; break; } @@ -142,17 +97,13 @@ nexthdr = hdr->nexthdr; len -= hdrlen; ptr += hdrlen; - if ( ptr > skb->len ) { - DEBUGP("ipv6_header new ptr %04X \n",ptr); + if (ptr > skb->len) break; - } } if ( (nexthdr != NEXTHDR_NONE ) && (nexthdr != NEXTHDR_ESP) ) temp |= MASK_PROTO; - DEBUGP ("ipv6header: %02X %02X \n", temp, info->matchflags); - if (info->modeflag) return (!( (temp & info->matchflags) ^ info->matchflags) ^ info->invflags); @@ -169,11 +120,8 @@ { /* Check for obvious errors */ /* This match is valid in all hooks! */ - if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_ipv6header_info))) { - DEBUGP("ip6t_ipv6header: matchsize != %u\n", - IP6T_ALIGN(sizeof(struct ip6t_ipv6header_info))); + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_ipv6header_info))) return 0; - } return 1; } diff -Nru a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c --- a/net/ipv6/netfilter/ip6t_rt.c Thu May 8 00:24:28 2003 +++ b/net/ipv6/netfilter/ip6t_rt.c Thu May 8 00:24:28 2003 @@ -130,7 +130,7 @@ return 0; } - route=skb->data+ptr; + route = (struct ipv6_rt_hdr *) (skb->data + ptr); DEBUGP("IPv6 RT LEN %u %u ", hdrlen, route->hdrlen); DEBUGP("TYPE %04X ", route->type); diff -Nru a/net/ipv6/route.c b/net/ipv6/route.c --- a/net/ipv6/route.c Thu May 8 00:24:29 2003 +++ b/net/ipv6/route.c Thu May 8 00:24:29 2003 @@ -39,6 +39,7 @@ #ifdef CONFIG_PROC_FS #include +#include #endif #include @@ -564,7 +565,7 @@ static unsigned long last_gc; unsigned long now = jiffies; - if ((long)(now - last_gc) < ip6_rt_gc_min_interval && + if (time_after(last_gc + ip6_rt_gc_min_interval, now) && atomic_read(&ip6_dst_ops.entries) <= ip6_rt_max_size) goto out; @@ -1173,7 +1174,7 @@ int ip6_pkt_discard(struct sk_buff *skb) { IP6_INC_STATS(Ip6OutNoRoutes); - icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, skb->dev); + icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, skb->dev); kfree_skb(skb); return 0; } @@ -1751,27 +1752,28 @@ extern struct rt6_statistics rt6_stats; -static int rt6_proc_stats(char *buffer, char **start, off_t offset, int length) +static int rt6_stats_seq_show(struct seq_file *seq, void *v) { - int len; - - len = sprintf(buffer, "%04x %04x %04x %04x %04x %04x\n", + seq_printf(seq, "%04x %04x %04x %04x %04x %04x\n", rt6_stats.fib_nodes, rt6_stats.fib_route_nodes, rt6_stats.fib_rt_alloc, rt6_stats.fib_rt_entries, rt6_stats.fib_rt_cache, atomic_read(&ip6_dst_ops.entries)); - len -= offset; - - if (len > length) - len = length; - if(len < 0) - len = 0; - - *start = buffer + offset; + return 0; +} - return len; +static int rt6_stats_seq_open(struct inode *inode, struct file *file) +{ + return single_open(file, rt6_stats_seq_show, NULL); } + +static struct file_operations rt6_stats_seq_fops = { + .open = rt6_stats_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; #endif /* CONFIG_PROC_FS */ #ifdef CONFIG_SYSCTL @@ -1877,6 +1879,8 @@ void __init ip6_route_init(void) { + struct proc_dir_entry *p; + ip6_dst_ops.kmem_cachep = kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0, SLAB_HWCACHE_ALIGN, @@ -1884,7 +1888,9 @@ fib6_init(); #ifdef CONFIG_PROC_FS proc_net_create("ipv6_route", 0, rt6_proc_info); - proc_net_create("rt6_stats", 0, rt6_proc_stats); + p = create_proc_entry("rt6_stats", S_IRUGO, proc_net); + if (p) + p->proc_fops = &rt6_stats_seq_fops; #endif xfrm6_init(); } @@ -1894,7 +1900,7 @@ { #ifdef CONFIG_PROC_FS proc_net_remove("ipv6_route"); - proc_net_remove("rt6_stats"); + remove_proc_entry("rt6_stats", proc_net); #endif xfrm6_fini(); rt6_ifdown(NULL); diff -Nru a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c --- a/net/ipx/af_ipx.c Thu May 8 00:24:28 2003 +++ b/net/ipx/af_ipx.c Thu May 8 00:24:28 2003 @@ -81,10 +81,10 @@ static struct proto_ops ipx_dgram_ops; -struct ipx_route *ipx_routes; +LIST_HEAD(ipx_routes); rwlock_t ipx_routes_lock = RW_LOCK_UNLOCKED; -struct ipx_interface *ipx_interfaces; +LIST_HEAD(ipx_interfaces); spinlock_t ipx_interfaces_lock = SPIN_LOCK_UNLOCKED; struct ipx_interface *ipx_primary_net; @@ -95,11 +95,21 @@ atomic_t ipx_sock_nr; #endif +struct ipx_interface *ipx_interfaces_head(void) +{ + struct ipx_interface *rc = NULL; + + if (!list_empty(&ipx_interfaces)) + rc = list_entry(ipx_interfaces.next, + struct ipx_interface, node); + return rc; +} + static void ipxcfg_set_auto_select(char val) { ipxcfg_auto_select_primary = val; if (val && !ipx_primary_net) - ipx_primary_net = ipx_interfaces; + ipx_primary_net = ipx_interfaces_head(); } static int ipxcfg_get_config_data(struct ipx_config_data *arg) @@ -197,17 +207,21 @@ static void ipxitf_clear_primary_net(void) { - ipx_primary_net = ipxcfg_auto_select_primary ? ipx_interfaces : NULL; + ipx_primary_net = NULL; + if (ipxcfg_auto_select_primary) + ipx_primary_net = ipx_interfaces_head(); } static struct ipx_interface *__ipxitf_find_using_phys(struct net_device *dev, unsigned short datalink) { - struct ipx_interface *i = ipx_interfaces; - - while (i && (i->if_dev != dev || i->if_dlink_type != datalink)) - i = i->if_next; + struct ipx_interface *i; + list_for_each_entry(i, &ipx_interfaces, node) + if (i->if_dev == dev && i->if_dlink_type == datalink) + goto out; + i = NULL; +out: return i; } @@ -229,16 +243,20 @@ struct ipx_interface *i; spin_lock_bh(&ipx_interfaces_lock); - if (net) - for (i = ipx_interfaces; i && i->if_netnum != net; - i = i->if_next) - ; - else - i = ipx_primary_net; + if (net) { + list_for_each_entry(i, &ipx_interfaces, node) + if (i->if_netnum == net) + goto hold; + i = NULL; + goto unlock; + } + + i = ipx_primary_net; if (i) +hold: ipxitf_hold(i); +unlock: spin_unlock_bh(&ipx_interfaces_lock); - return i; } @@ -342,15 +360,7 @@ spin_unlock_bh(&intrfc->if_sklist_lock); /* remove this interface from list */ - if (intrfc == ipx_interfaces) - ipx_interfaces = intrfc->if_next; - else { - struct ipx_interface *i = ipx_interfaces; - while (i && i->if_next != intrfc) - i = i->if_next; - if (i && i->if_next == intrfc) - i->if_next = intrfc->if_next; - } + list_del(&intrfc->node); /* remove this interface from *special* networks */ if (intrfc == ipx_primary_net) @@ -380,16 +390,13 @@ goto out; spin_lock_bh(&ipx_interfaces_lock); - for (i = ipx_interfaces; i;) { - tmp = i->if_next; + list_for_each_entry_safe(i, tmp, &ipx_interfaces, node) if (i->if_dev == dev) { if (event == NETDEV_UP) ipxitf_hold(i); else __ipxitf_put(i); } - i = tmp; - } spin_unlock_bh(&ipx_interfaces_lock); out: return NOTIFY_DONE; @@ -872,7 +879,7 @@ IPX_SKB_CB(skb)->last_hop.netnum = intrfc->if_netnum; /* xmit on all other interfaces... */ spin_lock_bh(&ipx_interfaces_lock); - for (ifcs = ipx_interfaces; ifcs; ifcs = ifcs->if_next) { + list_for_each_entry(ifcs, &ipx_interfaces, node) { /* Except unconfigured interfaces */ if (!ifcs->if_netnum) continue; @@ -902,16 +909,8 @@ static void ipxitf_insert(struct ipx_interface *intrfc) { - intrfc->if_next = NULL; spin_lock_bh(&ipx_interfaces_lock); - if (!ipx_interfaces) - ipx_interfaces = intrfc; - else { - struct ipx_interface *i = ipx_interfaces; - while (i->if_next) - i = i->if_next; - i->if_next = intrfc; - } + list_add_tail(&intrfc->node, &ipx_interfaces); spin_unlock_bh(&ipx_interfaces_lock); if (ipxcfg_auto_select_primary && !ipx_primary_net) @@ -1278,12 +1277,14 @@ struct ipx_route *r; read_lock_bh(&ipx_routes_lock); - for (r = ipx_routes; r && r->ir_net != net; r = r->ir_next) - ; - if (r) - ipxrtr_hold(r); + list_for_each_entry(r, &ipx_routes, node) + if (r->ir_net == net) { + ipxrtr_hold(r); + goto unlock; + } + r = NULL; +unlock: read_unlock_bh(&ipx_routes_lock); - return r; } @@ -1306,8 +1307,7 @@ atomic_set(&rt->refcnt, 1); ipxrtr_hold(rt); write_lock_bh(&ipx_routes_lock); - rt->ir_next = ipx_routes; - ipx_routes = rt; + list_add(&rt->node, &ipx_routes); write_unlock_bh(&ipx_routes_lock); } else { rc = -EEXIST; @@ -1334,16 +1334,14 @@ static void ipxrtr_del_routes(struct ipx_interface *intrfc) { - struct ipx_route **r, *tmp; + struct ipx_route *r, *tmp; write_lock_bh(&ipx_routes_lock); - for (r = &ipx_routes; (tmp = *r) != NULL;) { - if (tmp->ir_intrfc == intrfc) { - *r = tmp->ir_next; - ipxrtr_put(tmp); - } else - r = &(tmp->ir_next); - } + list_for_each_entry_safe(r, tmp, &ipx_routes, node) + if (r->ir_intrfc == intrfc) { + list_del(&r->node); + ipxrtr_put(r); + } write_unlock_bh(&ipx_routes_lock); } @@ -1364,26 +1362,21 @@ static int ipxrtr_delete(long net) { - struct ipx_route **r; - struct ipx_route *tmp; + struct ipx_route *r, *tmp; int rc; write_lock_bh(&ipx_routes_lock); - for (r = &ipx_routes; (tmp = *r) != NULL;) { - if (tmp->ir_net == net) { + list_for_each_entry_safe(r, tmp, &ipx_routes, node) + if (r->ir_net == net) { /* Directly connected; can't lose route */ rc = -EPERM; - if (!tmp->ir_routed) + if (!r->ir_routed) goto out; - - *r = tmp->ir_next; - ipxrtr_put(tmp); + list_del(&r->node); + ipxrtr_put(r); rc = 0; goto out; } - - r = &(tmp->ir_next); - } rc = -ENOENT; out: write_unlock_bh(&ipx_routes_lock); diff -Nru a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c --- a/net/ipx/ipx_proc.c Thu May 8 00:24:27 2003 +++ b/net/ipx/ipx_proc.c Thu May 8 00:24:27 2003 @@ -17,12 +17,23 @@ { struct ipx_interface *i; - for (i = ipx_interfaces; pos && i; i = i->if_next) - --pos; - + list_for_each_entry(i, &ipx_interfaces, node) + if (!pos--) + goto out; + i = NULL; +out: return i; } +static struct ipx_interface *ipx_interfaces_next(struct ipx_interface *i) +{ + struct ipx_interface *rc = NULL; + + if (i->node.next != &ipx_interfaces) + rc = list_entry(i->node.next, struct ipx_interface, node); + return rc; +} + static void *ipx_seq_interface_start(struct seq_file *seq, loff_t *pos) { loff_t l = *pos; @@ -36,15 +47,10 @@ struct ipx_interface *i; ++*pos; - if (v == (void *)1) { - i = NULL; - if (ipx_interfaces) - i = ipx_interfaces; - goto out; - } - i = v; - i = i->if_next; -out: + if (v == (void *)1) + i = ipx_interfaces_head(); + else + i = ipx_interfaces_next(v); return i; } @@ -83,13 +89,33 @@ return 0; } +static struct ipx_route *ipx_routes_head(void) +{ + struct ipx_route *rc = NULL; + + if (!list_empty(&ipx_routes)) + rc = list_entry(ipx_routes.next, struct ipx_route, node); + return rc; +} + +static struct ipx_route *ipx_routes_next(struct ipx_route *r) +{ + struct ipx_route *rc = NULL; + + if (r->node.next != &ipx_routes) + rc = list_entry(r->node.next, struct ipx_route, node); + return rc; +} + static __inline__ struct ipx_route *ipx_get_route_idx(loff_t pos) { struct ipx_route *r; - for (r = ipx_routes; pos && r; r = r->ir_next) - --pos; - + list_for_each_entry(r, &ipx_routes, node) + if (!pos--) + goto out; + r = NULL; +out: return r; } @@ -105,15 +131,10 @@ struct ipx_route *r; ++*pos; - if (v == (void *)1) { - r = NULL; - if (ipx_routes) - r = ipx_routes; - goto out; - } - r = v; - r = r->ir_next; -out: + if (v == (void *)1) + r = ipx_routes_head(); + else + r = ipx_routes_next(v); return r; } @@ -149,7 +170,9 @@ struct sock *s = NULL; struct ipx_interface *i; - for (i = ipx_interfaces; pos && i; i = i->if_next) { + list_for_each_entry(i, &ipx_interfaces, node) { + if (!pos) + break; spin_lock_bh(&i->if_sklist_lock); for (s = i->if_sklist; pos && s; s = s->next) --pos; @@ -181,11 +204,12 @@ ++*pos; if (v == (void *)1) { sk = NULL; - if (!ipx_interfaces) + i = ipx_interfaces_head(); + if (!i) goto out; - sk = ipx_interfaces->if_sklist; + sk = i->if_sklist; if (sk) - spin_lock_bh(&ipx_interfaces->if_sklist_lock); + spin_lock_bh(&i->if_sklist_lock); goto out; } sk = v; @@ -198,9 +222,9 @@ spin_unlock_bh(&i->if_sklist_lock); sk = NULL; for (;;) { - if (!i->if_next) + i = ipx_interfaces_next(i); + if (!i) break; - i = i->if_next; spin_lock_bh(&i->if_sklist_lock); if (i->if_sklist) { sk = i->if_sklist; diff -Nru a/net/netlink/netlink_dev.c b/net/netlink/netlink_dev.c --- a/net/netlink/netlink_dev.c Thu May 8 00:24:28 2003 +++ b/net/netlink/netlink_dev.c Thu May 8 00:24:28 2003 @@ -220,14 +220,6 @@ }, }; -static void __init make_devfs_entries (const char *name, int minor) -{ - devfs_register (NULL, name, DEVFS_FL_DEFAULT, - NETLINK_MAJOR, minor, - S_IFCHR | S_IRUSR | S_IWUSR, - &netlink_fops, NULL); -} - int __init init_netlink(void) { int i; @@ -236,18 +228,20 @@ printk(KERN_ERR "netlink: unable to get major %d\n", NETLINK_MAJOR); return -EIO; } + devfs_mk_dir("netlink"); + /* Someone tell me the official names for the uppercase ones */ for (i = 0; i < sizeof(entries)/sizeof(entries[0]); i++) { - char name[20]; - sprintf(name, "netlink/%s", entries[i].name); - make_devfs_entries(name, entries[i].minor); + devfs_mk_cdev(MKDEV(NETLINK_MAJOR, entries[i].minor), + S_IFCHR|S_IRUSR|S_IWUSR, "netlink/%s", entries[i].name); } + for (i = 0; i < 16; i++) { - char name[20]; - sprintf(name, "netlink/tap%d", i); - make_devfs_entries(name, i + 16); + devfs_mk_cdev(MKDEV(NETLINK_MAJOR, i + 16), + S_IFCHR|S_IRUSR|S_IWUSR, "netlink/tap%d", i); } + return 0; } diff -Nru a/net/socket.c b/net/socket.c --- a/net/socket.c Thu May 8 00:24:28 2003 +++ b/net/socket.c Thu May 8 00:24:28 2003 @@ -1280,26 +1280,26 @@ * We don't need try_module_get here, as the listening socket (sock) * has the protocol module (sock->ops->owner) held. */ - __module_get(sock->ops->owner); + __module_get(newsock->ops->owner); err = sock->ops->accept(sock, newsock, sock->file->f_flags); if (err < 0) - goto out_module_put; + goto out_release; if (upeer_sockaddr) { if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) { err = -ECONNABORTED; - goto out_module_put; + goto out_release; } err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen); if (err < 0) - goto out_module_put; + goto out_release; } /* File flags are not inherited via accept() unlike another OSes. */ if ((err = sock_map_fd(newsock)) < 0) - goto out_module_put; + goto out_release; security_socket_post_accept(sock, newsock); @@ -1307,8 +1307,6 @@ sockfd_put(sock); out: return err; -out_module_put: - module_put(sock->ops->owner); out_release: sock_release(newsock); goto out_put; diff -Nru a/net/unix/af_unix.c b/net/unix/af_unix.c --- a/net/unix/af_unix.c Thu May 8 00:24:29 2003 +++ b/net/unix/af_unix.c Thu May 8 00:24:29 2003 @@ -625,7 +625,7 @@ goto put_fail; if (u->type == type) - UPDATE_ATIME(nd.dentry->d_inode); + update_atime(nd.dentry->d_inode); path_release(&nd); @@ -641,7 +641,7 @@ struct dentry *dentry; dentry = unix_sk(u)->dentry; if (dentry) - UPDATE_ATIME(dentry->d_inode); + update_atime(dentry->d_inode); } else goto fail; } diff -Nru a/scripts/Makefile.build b/scripts/Makefile.build --- a/scripts/Makefile.build Thu May 8 00:24:29 2003 +++ b/scripts/Makefile.build Thu May 8 00:24:29 2003 @@ -66,6 +66,12 @@ $(subdir-ym) $(always) @: +# Linus's kernel sanity checking tool +ifneq ($(KBUILD_CHECKSRC),0) +quiet_cmd_checksrc = CHECK $< + cmd_checksrc = $(CHECK) $(CFLAGS) $< ; +endif + # Module versioning # --------------------------------------------------------------------------- @@ -91,6 +97,8 @@ cmd_vcc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $< define rule_vcc_o_c + $(if $($(quiet)cmd_checksrc),echo ' $($(quiet)cmd_checksrc)';) \ + $(cmd_checksrc) \ $(if $($(quiet)cmd_vcc_o_c),echo ' $($(quiet)cmd_vcc_o_c)';) \ $(cmd_vcc_o_c); \ \ @@ -158,6 +166,15 @@ quiet_cmd_cc_o_c = CC $(quiet_modtag) $@ cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< +define rule_cc_o_c + $(if $($(quiet)cmd_checksrc),echo ' $($(quiet)cmd_checksrc)';) \ + $(cmd_checksrc) \ + $(if $($(quiet)cmd_cc_o_c),echo ' $($(quiet)cmd_cc_o_c)';) \ + $(cmd_cc_o_c); \ + scripts/fixdep $(depfile) $@ '$(cmd_cc_o_c)' > $(@D)/.$(@F).tmp; \ + rm -f $(depfile); \ + mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd +endef # Built-in and composite module parts @@ -165,7 +182,7 @@ ifdef CONFIG_MODVERSIONS $(call if_changed_rule,vcc_o_c) else - $(call if_changed_dep,cc_o_c) + $(call if_changed_rule,cc_o_c) endif # Single-part modules are special since we need to mark them in $(MODVERDIR) @@ -174,7 +191,7 @@ ifdef CONFIG_MODVERSIONS $(call if_changed_rule,vcc_o_c) else - $(call if_changed_dep,cc_o_c) + $(call if_changed_rule,cc_o_c) endif $(touch-module) diff -Nru a/security/dummy.c b/security/dummy.c --- a/security/dummy.c Thu May 8 00:24:28 2003 +++ b/security/dummy.c Thu May 8 00:24:28 2003 @@ -334,6 +334,11 @@ return 0; } +static void dummy_inode_post_setxattr (struct dentry *dentry, char *name, void *value, + size_t size, int flags) +{ +} + static int dummy_inode_getxattr (struct dentry *dentry, char *name) { return 0; @@ -803,6 +808,7 @@ set_to_dummy_if_null(ops, inode_getattr); set_to_dummy_if_null(ops, inode_delete); set_to_dummy_if_null(ops, inode_setxattr); + set_to_dummy_if_null(ops, inode_post_setxattr); set_to_dummy_if_null(ops, inode_getxattr); set_to_dummy_if_null(ops, inode_listxattr); set_to_dummy_if_null(ops, inode_removexattr); diff -Nru a/sound/core/info.c b/sound/core/info.c --- a/sound/core/info.c Thu May 8 00:24:30 2003 +++ b/sound/core/info.c Thu May 8 00:24:30 2003 @@ -1079,15 +1079,9 @@ p->data = (void *) entry; entry->p = p; up(&info_mutex); -#ifdef CONFIG_DEVFS_FS - if (strncmp(name, "controlC", 8)) { /* created in sound.c */ - char dname[32]; - sprintf(dname, "snd/%s", name); - devfs_register(NULL, dname, DEVFS_FL_DEFAULT, - _major, minor, mode, - &snd_fops, NULL); - } -#endif + + if (strncmp(name, "controlC", 8) == 0) /* created in sound.c */ + devfs_mk_cdev(MKDEV(_major, minor), mode, "snd/%s", name); return entry; } diff -Nru a/sound/core/sound.c b/sound/core/sound.c --- a/sound/core/sound.c Thu May 8 00:24:29 2003 +++ b/sound/core/sound.c Thu May 8 00:24:29 2003 @@ -323,13 +323,8 @@ static int __init alsa_sound_init(void) { -#ifdef CONFIG_DEVFS_FS short controlnum; - char controlname[24]; -#endif -#ifdef CONFIG_SND_OSSEMUL - int err; -#endif + int err = 0; int card; snd_ecards_limit = cards_limit; @@ -356,21 +351,19 @@ #ifdef CONFIG_SND_OSSEMUL snd_info_minor_register(); #endif -#ifdef CONFIG_DEVFS_FS + for (controlnum = 0; controlnum < cards_limit; controlnum++) { - sprintf(controlname, "snd/controlC%d", controlnum); - devfs_register(NULL, controlname, DEVFS_FL_DEFAULT, - major, controlnum<<5, device_mode | S_IFCHR, - &snd_fops, NULL); + devfs_mk_cdev(MKDEV(major, controlnum<<5), + device_mode | S_IFCHR, "snd/controlC%d", controlnum); } -#endif + #ifndef MODULE printk(KERN_INFO "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n"); #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) && defined(CONFIG_APM) pm_init(); #endif - return 0; + return err; } static void __exit alsa_sound_exit(void) diff -Nru a/sound/oss/opl3sa2.c b/sound/oss/opl3sa2.c --- a/sound/oss/opl3sa2.c Thu May 8 00:24:27 2003 +++ b/sound/oss/opl3sa2.c Thu May 8 00:24:27 2003 @@ -353,7 +353,8 @@ } } - +/* Currently only used for power management */ +#ifdef CONFIG_PM static void opl3sa2_mixer_restore(opl3sa2_state_t* devc) { if (devc) { @@ -366,7 +367,7 @@ } } } - +#endif static inline void arg_to_vol_mono(unsigned int vol, int* value) { @@ -961,7 +962,6 @@ spin_unlock_irqrestore(&opl3sa2_lock,flags); return 0; } -#endif /* CONFIG_PM */ static int opl3sa2_pm_callback(struct pm_dev *pdev, pm_request_t rqst, void *data) { @@ -976,6 +976,7 @@ } return 0; } +#endif /* CONFIG_PM */ /* * Install OPL3-SA2 based card(s). @@ -1127,10 +1128,11 @@ int card; for(card = 0; card < opl3sa2_cards_num; card++) { +#ifdef CONFIG_PM if (opl3sa2_state[card].pmdev) pm_unregister(opl3sa2_state[card].pmdev); - - if(opl3sa2_state[card].cfg_mpu.slots[1] != -1) { +#endif + if (opl3sa2_state[card].cfg_mpu.slots[1] != -1) { unload_opl3sa2_mpu(&opl3sa2_state[card].cfg_mpu); } unload_opl3sa2_mss(&opl3sa2_state[card].cfg_mss); diff -Nru a/sound/oss/soundcard.c b/sound/oss/soundcard.c --- a/sound/oss/soundcard.c Thu May 8 00:24:28 2003 +++ b/sound/oss/soundcard.c Thu May 8 00:24:28 2003 @@ -549,7 +549,6 @@ static int __init oss_init(void) { int err; - char name_buf[32]; int i, j; /* drag in sound_syms.o */ @@ -573,19 +572,18 @@ sound_dmap_flag = (dmabuf > 0 ? 1 : 0); for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) { - sprintf(name_buf, "sound/%s", dev_list[i].name); - devfs_register (NULL, name_buf, DEVFS_FL_NONE, - SOUND_MAJOR, dev_list[i].minor, - S_IFCHR | dev_list[i].mode, - &oss_sound_fops, NULL); + devfs_mk_cdev(MKDEV(SOUND_MAJOR, dev_list[i].minor), + S_IFCHR | dev_list[i].mode, + "sound/%s", dev_list[i].name); + if (!dev_list[i].num) continue; + for (j = 1; j < *dev_list[i].num; j++) { - sprintf(name_buf, "sound/%s%d", dev_list[i].name, j); - devfs_register (NULL, name_buf, DEVFS_FL_NONE, - SOUND_MAJOR, dev_list[i].minor + (j * 0x10), - S_IFCHR | dev_list[i].mode, - &oss_sound_fops, NULL); + devfs_mk_cdev(MKDEV(SOUND_MAJOR, + dev_list[i].minor + (j*0x10)), + S_IFCHR | dev_list[i].mode, + "sound/%s%d", dev_list[i].name, j); } } diff -Nru a/sound/sound_core.c b/sound/sound_core.c --- a/sound/sound_core.c Thu May 8 00:24:30 2003 +++ b/sound/sound_core.c Thu May 8 00:24:30 2003 @@ -168,8 +168,8 @@ else sprintf(s->name, "sound/%s%d", name, r / SOUND_STEP); - devfs_register(NULL, s->name, 0, SOUND_MAJOR, s->unit_minor, - S_IFCHR | mode, fops, NULL); + devfs_mk_cdev(MKDEV(SOUND_MAJOR, s->unit_minor), + S_IFCHR | mode, s->name); return r; fail: