# 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.6.0-test5 -> 1.1315 # arch/i386/kernel/process.c 1.55 -> 1.56 # drivers/pci/hotplug/cpqphp_core.c 1.22 -> 1.23 # fs/afs/vnode.h 1.3 -> 1.4 # drivers/net/wireless/wl3501_cs.c 1.70 -> 1.72 # drivers/pci/hotplug/acpiphp_pci.c 1.8 -> 1.9 # drivers/net/irda/via-ircc.c 1.2 -> 1.4 # drivers/pci/hotplug/ibmphp_pci.c 1.7 -> 1.8 # fs/afs/mount.h 1.1 -> 1.2 # drivers/pcmcia/cs_internal.h 1.22 -> 1.23 # arch/ia64/kernel/fsys.S 1.18 -> 1.20 # drivers/block/ps2esdi.c 1.67 -> 1.69 # drivers/isdn/hardware/eicon/s_4bri.c 1.2 -> 1.3 # arch/i386/kernel/timers/Makefile 1.8 -> 1.9 # fs/afs/vlclient.c 1.4 -> 1.5 # drivers/scsi/imm.h 1.13 -> 1.14 # arch/ppc/kernel/align.c 1.7 -> 1.8 # drivers/serial/8250.h 1.6 -> 1.7 # drivers/net/tc35815.c 1.14 -> 1.15 # arch/parisc/kernel/pci.c 1.11 -> 1.12 # drivers/block/as-iosched.c 1.17 -> 1.18 # include/asm-ia64/sn/pci/pciio.h 1.6 -> 1.7 # include/asm-ppc/processor.h 1.34 -> 1.35 # net/ipx/ipx_proc.c 1.8 -> 1.9 # drivers/isdn/hardware/eicon/dlist.c 1.2 -> 1.3 # arch/ppc64/mm/Makefile 1.5 -> 1.6 # fs/afs/volume.c 1.2 -> 1.3 # fs/reiserfs/file.c 1.22 -> 1.23 # drivers/parisc/eisa.c 1.8 -> 1.9 # include/asm-ppc64/page.h 1.19 -> 1.20 # include/asm-ppc64/hvcall.h 1.2 -> 1.3 # fs/afs/vlclient.h 1.1 -> 1.2 # include/asm-parisc/bitops.h 1.4 -> 1.5 # drivers/cdrom/gscd.c 1.36 -> 1.37 # include/linux/if_frad.h 1.4 -> 1.5 # drivers/net/e1000/e1000.h 1.33 -> 1.37 # net/rxrpc/krxiod.c 1.5 -> 1.6 # drivers/isdn/hardware/avm/avm_cs.c 1.10 -> 1.11 # drivers/char/watchdog/i810-tco.c 1.19 -> 1.20 # mm/fremap.c 1.12 -> 1.14 # net/ipv4/proc.c 1.14 -> 1.15 # fs/afs/cell.c 1.1 -> 1.2 # drivers/net/wan/cosa.c 1.25 -> 1.26 # drivers/net/tulip/de4x5.c 1.31 -> 1.32 # fs/intermezzo/inode.c 1.8 -> 1.9 # net/ipv6/anycast.c 1.6 -> 1.8 # Documentation/modules.txt 1.4 -> (deleted) # drivers/isdn/hardware/eicon/mntfunc.c 1.2 -> 1.3 # arch/ia64/Makefile 1.59 -> 1.60 # arch/ia64/kernel/efi.c 1.22 -> 1.23 # include/linux/mm.h 1.129 -> 1.130 # include/asm-i386/processor.h 1.53 -> 1.54 # drivers/parisc/dino.c 1.7 -> 1.8 # drivers/char/agp/sis-agp.c 1.30 -> 1.31 # drivers/serial/8250.c 1.34 -> 1.36 # arch/ia64/sn/io/sn2/pcibr/pcibr_error.c 1.5 -> 1.6 # arch/parisc/defconfig 1.6 -> 1.7 # drivers/net/dgrs.c 1.20 -> 1.21 # drivers/isdn/hardware/eicon/os_bri.c 1.2 -> 1.3 # fs/afs/server.c 1.1 -> 1.2 # drivers/net/skfp/skfddi.c 1.16 -> 1.17 # security/selinux/include/security.h 1.1 -> 1.2 # arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c 1.5 -> 1.6 # net/ipv4/ip_input.c 1.17 -> 1.18 # init/initramfs.c 1.6 -> 1.8 # drivers/char/random.c 1.37 -> 1.38 # include/asm-ia64/spinlock.h 1.16 -> 1.17 # net/802/tr.c 1.14 -> 1.15 # arch/ppc64/kernel/semaphore.c 1.2 -> 1.3 # arch/arm/mach-sa1100/simpad.c 1.12 -> 1.13 # security/selinux/Kconfig 1.2 -> 1.3 # net/llc/llc_proc.c 1.14 -> 1.15 # drivers/net/pcmcia/nmclan_cs.c 1.20 -> 1.21 # arch/arm/boot/compressed/head-sa1100.S 1.6 -> 1.7 # drivers/block/ll_rw_blk.c 1.212 -> 1.213 # drivers/net/Space.c 1.34 -> 1.35 # kernel/sysctl.c 1.52 -> 1.53 # net/sched/estimator.c 1.2 -> 1.3 # drivers/cpufreq/cpufreq_userspace.c 1.8 -> 1.9 # drivers/pci/hotplug/ibmphp.h 1.9 -> 1.10 # include/linux/writeback.h 1.21 -> 1.22 # include/asm-ia64/unistd.h 1.35 -> 1.36 # net/rxrpc/krxtimod.c 1.7 -> 1.8 # include/linux/serial_core.h 1.26 -> 1.28 # arch/ppc64/kernel/chrp_setup.c 1.30 -> 1.31 # include/asm-ia64/signal.h 1.9 -> 1.10 # drivers/atm/firestream.c 1.22 -> 1.23 # fs/dcache.c 1.60 -> 1.61 # include/net/rose.h 1.5 -> 1.6 # drivers/isdn/hardware/eicon/divasmain.c 1.11 -> 1.14 # include/asm-parisc/io.h 1.4 -> 1.5 # drivers/serial/sa1100.c 1.22 -> 1.23 # fs/proc/proc_misc.c 1.89 -> 1.90 # arch/ppc64/Makefile 1.28 -> 1.32 # sound/core/ioctl32/ioctl32.c 1.17 -> 1.18 # include/rxrpc/call.h 1.2 -> 1.3 # arch/ia64/hp/common/sba_iommu.c 1.29 -> 1.30 # arch/ppc64/kernel/rtas.c 1.11 -> 1.12 # arch/i386/Kconfig 1.75 -> 1.76 # drivers/pci/hotplug/ibmphp_ebda.c 1.12 -> 1.13 # drivers/pci/hotplug/cpci_hotplug.h 1.3 -> 1.4 # include/linux/elf.h 1.24 -> 1.25 # net/x25/x25_proc.c 1.5 -> 1.6 # net/ipv4/udp.c 1.47 -> 1.49 # fs/afs/mntpt.c 1.3 -> 1.4 # include/asm-i386/numnodes.h 1.4 -> 1.5 # Documentation/networking/ifenslave.c 1.7 -> 1.8 # drivers/parisc/ccio-dma.c 1.12 -> 1.13 # net/bluetooth/af_bluetooth.c 1.22 -> 1.23 # drivers/pcmcia/sa11xx_core.c 1.12 -> 1.13 # arch/sparc/lib/memset.S 1.2 -> 1.3 # include/asm-ia64/sn/nodepda.h 1.7 -> 1.8 # drivers/parisc/iosapic.c 1.6 -> 1.7 # include/asm-sparc64/vga.h 1.1 -> 1.2 # kernel/Makefile 1.34 -> 1.35 # arch/i386/kernel/cpu/cpufreq/Kconfig 1.8 -> 1.9 # arch/parisc/vmlinux.lds.S 1.14 -> 1.15 arch/parisc/kernel/vmlinux.lds.S (moved) # net/ax25/ax25_uid.c 1.5 -> 1.6 # arch/ppc/kernel/traps.c 1.23 -> 1.24 # drivers/cpufreq/cpufreq.c 1.56 -> 1.58 # arch/ia64/kernel/time.c 1.31 -> 1.32 # arch/i386/boot98/compressed/misc.c 1.1 -> 1.2 # arch/ppc64/kernel/ppc_ksyms.c 1.22 -> 1.23 # sound/oss/dmasound/awacs_defs.h 1.2 -> 1.3 # drivers/char/watchdog/amd7xx_tco.c 1.6 -> 1.7 # sound/oss/dmasound/Makefile 1.6 -> 1.7 # net/ipv6/ip6_flowlabel.c 1.9 -> 1.12 # drivers/net/fc/iph5526.c 1.28 -> 1.29 # drivers/isdn/hardware/eicon/capimain.c 1.5 -> 1.6 # drivers/block/Kconfig 1.8 -> 1.9 # fs/ext2/symlink.c 1.4 -> 1.5 # arch/sh/boot/compressed/misc.c 1.1 -> 1.2 # drivers/net/pcmcia/3c574_cs.c 1.24 -> 1.25 # net/rxrpc/krxsecd.c 1.6 -> 1.7 # drivers/net/wan/sdladrv.c 1.10 -> 1.11 # drivers/serial/core.c 1.68 -> 1.70 drivers/serial/serial_core.c (moved) # drivers/net/e1000/e1000_osdep.h 1.12 -> 1.13 # Documentation/00-INDEX 1.10 -> 1.11 # include/asm-parisc/uaccess.h 1.3 -> 1.4 # arch/ia64/kernel/smpboot.c 1.38 -> 1.39 # kernel/softirq.c 1.44 -> 1.45 # drivers/net/wan/dscc4.c 1.46 -> 1.47 # drivers/net/bonding/bonding.h 1.2 -> 1.3 # drivers/mtd/maps/sa1100-flash.c 1.12 -> 1.13 # drivers/isdn/hardware/eicon/io.c 1.2 -> 1.3 # drivers/pcmcia/cs.c 1.58.1.1 -> 1.62 # include/asm-i386/timer.h 1.10 -> 1.11 # drivers/char/watchdog/alim1535_wdt.c 1.1 -> 1.2 # arch/ia64/kernel/entry.S 1.49 -> 1.51 # drivers/net/tokenring/abyss.c 1.11 -> 1.12 # fs/fat/file.c 1.21 -> 1.22 # include/asm-generic/cpumask_up.h 1.2 -> 1.3 # drivers/pcmcia/cardbus.c 1.29 -> 1.30 # arch/arm26/boot/compressed/misc.c 1.1 -> 1.2 # net/rxrpc/internal.h 1.4 -> 1.5 # fs/afs/main.c 1.3 -> 1.4 # arch/ppc64/defconfig 1.29 -> 1.31 # drivers/pci/hotplug/ibmphp_hpc.c 1.13 -> 1.14 # drivers/char/mwave/mwavedd.c 1.11 -> 1.12 # arch/i386/kernel/cpu/intel.c 1.21 -> 1.22 # crypto/proc.c 1.3 -> 1.4 # include/asm-i386/srat.h 1.3 -> 1.4 # drivers/pcmcia/sa1111_generic.c 1.18 -> 1.19 # scripts/mkconfigs 1.3 -> 1.4 # net/atm/proc.c 1.22 -> 1.30 # arch/ia64/sn/io/machvec/pci_dma.c 1.12 -> 1.13 # drivers/serial/clps711x.c 1.15 -> 1.16 # arch/i386/kernel/reboot.c 1.11 -> 1.12 # include/rxrpc/message.h 1.1 -> 1.2 # include/rxrpc/packet.h 1.1 -> 1.2 # drivers/parisc/led.c 1.10 -> 1.11 # net/ipv4/netfilter/ip_nat_tftp.c 1.4 -> 1.5 # net/bridge/br_forward.c 1.11 -> 1.12 # arch/i386/kernel/mpparse.c 1.49 -> 1.50 # drivers/isdn/hisax/sedlbauer_cs.c 1.12 -> 1.13 # include/asm-ia64/uaccess.h 1.10 -> 1.11 # drivers/isdn/hardware/eicon/divacapi.h 1.1 -> 1.2 # include/rxrpc/types.h 1.1 -> 1.2 # drivers/video/i810/i810_main.c 1.12 -> 1.14 # fs/reiserfs/inode.c 1.84 -> 1.85 # net/ipv4/tcp_ipv4.c 1.65 -> 1.67 # net/8021q/vlanproc.c 1.14 -> 1.15 # drivers/pci/hotplug/acpiphp_glue.c 1.16 -> 1.17 # net/decnet/dn_dev.c 1.18 -> 1.19 # drivers/net/sunhme.c 1.42 -> 1.43 # arch/sparc64/defconfig 1.98 -> 1.99 # arch/parisc/kernel/sys_parisc32.c 1.18 -> 1.19 # include/asm-ia64/sn/ioc3.h 1.3 -> (deleted) # include/asm-parisc/atomic.h 1.2 -> 1.3 # fs/afs/inode.c 1.5 -> 1.6 # drivers/cdrom/sonycd535.c 1.38 -> 1.39 # mm/filemap.c 1.206 -> 1.207 # include/asm-ppc64/ioctl.h 1.1 -> 1.2 # sound/oss/dmasound/dmasound_awacs.c 1.14 -> 1.15 # kernel/configs.c 1.3 -> 1.4 # fs/afs/dir.c 1.6 -> 1.7 # fs/afs/vlocation.c 1.1 -> 1.2 # drivers/char/pcmcia/synclink_cs.c 1.25 -> 1.26 # drivers/pci/hotplug/cpqphp_ctrl.c 1.12 -> 1.13 # sound/oss/forte.c 1.4 -> 1.5 # include/asm-ppc64/mmu_context.h 1.6 -> 1.7 # net/atm/ipcommon.c 1.2 -> 1.3 # drivers/isdn/hardware/eicon/di.c 1.2 -> 1.3 # drivers/isdn/hardware/eicon/divasi.c 1.8 -> 1.9 # sound/oss/rme96xx.c 1.16 -> 1.17 # drivers/net/e1000/e1000_main.c 1.80 -> 1.87 # include/asm-ia64/sn/hcl.h 1.6 -> 1.7 # drivers/pci/hotplug/pci_hotplug.h 1.9 -> 1.10 # drivers/char/hw_random.c 1.11 -> 1.12 # drivers/net/hp100.c 1.19 -> 1.20 # fs/exec.c 1.94 -> 1.96 # drivers/net/pcmcia/xirc2ps_cs.c 1.27 -> 1.28 # drivers/net/wireless/ray_cs.c 1.21 -> 1.23 # fs/eventpoll.c 1.23 -> 1.24 # drivers/pci/hotplug/acpiphp_res.c 1.4 -> 1.5 # drivers/isdn/hardware/eicon/debuglib.c 1.1 -> 1.2 # net/ipv6/raw.c 1.41 -> 1.44 # mm/fadvise.c 1.7 -> 1.8 # arch/parisc/kernel/irq.c 1.15 -> 1.16 # arch/alpha/boot/misc.c 1.1 -> 1.2 # include/asm-ppc64/paca.h 1.8 -> 1.9 # fs/afs/vnode.c 1.2 -> 1.3 # fs/afs/internal.h 1.5 -> 1.6 # net/atm/br2684.c 1.7 -> 1.8 # net/ipv6/proc.c 1.17 -> 1.19 # net/rxrpc/sysctl.c 1.4 -> 1.5 # fs/afs/super.c 1.5 -> 1.6 # fs/xattr.c 1.15 -> 1.16 # drivers/isdn/hardware/eicon/os_4bri.c 1.2 -> 1.3 # arch/x86_64/boot/compressed/misc.c 1.7 -> 1.8 # mm/shmem.c 1.134 -> 1.135 # drivers/isdn/hardware/eicon/diva_pci.h 1.2 -> 1.3 # net/rxrpc/peer.c 1.2 -> 1.3 # arch/ppc64/kernel/irq.c 1.31 -> 1.32 # drivers/pci/hotplug/cpci_hotplug_core.c 1.8 -> 1.9 # arch/parisc/kernel/cache.c 1.4 -> 1.5 # include/linux/eventpoll.h 1.11 -> 1.12 # arch/i386/kernel/cpu/cpufreq/Makefile 1.8 -> 1.9 # net/sched/sch_api.c 1.9 -> 1.10 # drivers/atm/Kconfig 1.7 -> 1.8 # drivers/isdn/hardware/eicon/os_pri.c 1.2 -> 1.3 # fs/binfmt_elf.c 1.51 -> 1.52 # include/asm-ppc/ioctl.h 1.3 -> 1.4 # drivers/net/hamradio/bpqether.c 1.13 -> 1.14 # net/sched/sch_atm.c 1.13 -> 1.14 # lib/inflate.c 1.4 -> 1.5 # drivers/isdn/hardware/eicon/dadapter.c 1.2 -> 1.3 # drivers/pcmcia/ricoh.h 1.10 -> 1.11 # drivers/net/e1000/e1000_ethtool.c 1.30 -> 1.33 # include/asm-ia64/sn/klclock.h 1.3 -> (deleted) # include/asm-ppc64/semaphore.h 1.5 -> 1.6 # fs/afs/cmservice.c 1.5 -> 1.6 # drivers/net/pcmcia/com20020_cs.c 1.11 -> 1.12 # arch/i386/kernel/setup.c 1.95 -> 1.96 # include/asm-ia64/hw_irq.h 1.9 -> 1.10 # drivers/isdn/hisax/elsa_cs.c 1.8 -> 1.9 # arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c 1.8 -> 1.9 # net/wanrouter/wanproc.c 1.20 -> 1.21 # arch/ppc/kernel/process.c 1.37 -> 1.38 # net/ipv4/fib_hash.c 1.15 -> 1.17 # drivers/parisc/hppb.c 1.1 -> 1.2 # drivers/net/wan/cosa.h 1.2 -> 1.3 # arch/ia64/kernel/acpi.c 1.48 -> 1.49 # drivers/serial/Makefile 1.19 -> 1.20 # arch/ia64/hp/sim/boot/boot_head.S 1.1 -> 1.2 # drivers/serial/8250_cs.c 1.16 -> 1.17 drivers/serial/serial_cs.c (moved) # sound/oss/dmasound/Kconfig 1.2 -> 1.3 # include/asm-ppc/bitops.h 1.13 -> 1.14 # net/netrom/af_netrom.c 1.38 -> 1.39 # net/rose/af_rose.c 1.32 -> 1.33 # drivers/net/wireless/atmel_cs.c 1.5 -> 1.6 # drivers/net/wan/dlci.c 1.12 -> 1.16 # include/asm-i386/mmzone.h 1.13 -> 1.14 # arch/parisc/kernel/real2.S 1.2 -> 1.3 # fs/afs/types.h 1.1 -> 1.2 # net/core/dev.c 1.100 -> 1.104 # arch/ia64/ia32/elfcore32.h 1.2 -> 1.3 # arch/ppc64/kernel/head.S 1.36 -> 1.38 # arch/ppc/kernel/asm-offsets.c 1.4 -> 1.5 # drivers/isdn/hardware/eicon/divamnt.c 1.8 -> 1.9 # drivers/isdn/hysdn/hysdn_init.c 1.5 -> 1.6 # net/decnet/af_decnet.c 1.32 -> 1.33 # drivers/char/agp/uninorth-agp.c 1.7 -> 1.8 # include/asm-ppc64/uaccess.h 1.11 -> 1.12 # drivers/net/pcmcia/ibmtr_cs.c 1.18 -> 1.19 # drivers/isdn/hardware/eicon/divasfunc.c 1.3 -> 1.4 # scripts/Makefile 1.34 -> 1.35 # arch/sparc/lib/copy_user.S 1.1 -> 1.2 # net/irda/irlan/irlan_common.c 1.17 -> 1.18 # include/linux/interrupt.h 1.26 -> 1.27 # fs/proc/kcore.c 1.11 -> 1.13 # drivers/isdn/hardware/eicon/Kconfig 1.1 -> 1.2 # drivers/isdn/hardware/eicon/debug.c 1.1 -> 1.2 # arch/ppc64/Kconfig 1.27.1.1 -> 1.29 # drivers/pci/hotplug/pcihp_skeleton.c 1.4 -> 1.5 # arch/ppc/kernel/head.S 1.33 -> 1.34 # arch/ppc64/kernel/xics.c 1.25.1.1 -> 1.28 # sound/oss/vwsnd.c 1.11 -> 1.12 # net/ipv4/raw.c 1.39 -> 1.42 # arch/i386/boot/setup.S 1.22 -> 1.23 # drivers/net/pcmcia/axnet_cs.c 1.18 -> 1.19 # drivers/pcmcia/tcic.c 1.33 -> 1.34 # net/ipv6/tcp_ipv6.c 1.71 -> 1.73 # net/bluetooth/hci_sock.c 1.24 -> 1.25 # arch/ppc64/kernel/rtc.c 1.7 -> 1.8 # drivers/isdn/hardware/eicon/xdi_adapter.h 1.2 -> 1.3 # drivers/net/wireless/wavelan_cs.c 1.25 -> 1.26 # net/xfrm/xfrm_user.c 1.37 -> 1.38 # fs/afs/callback.c 1.2 -> 1.3 # drivers/pcmcia/hd64465_ss.c 1.15 -> 1.16 # fs/Kconfig 1.28 -> 1.29 # net/sunrpc/cache.c 1.21 -> 1.22 # arch/sparc/lib/checksum.S 1.2 -> 1.3 # drivers/char/epca.c 1.31 -> 1.32 # arch/ppc64/kernel/htab.c 1.35 -> 1.36 # arch/ppc64/mm/init.c 1.50 -> 1.52 # fs/afs/kafstimod.c 1.7 -> 1.8 # arch/i386/boot/compressed/misc.c 1.11 -> 1.12 # net/rxrpc/connection.c 1.3 -> 1.4 # arch/ppc64/kernel/process.c 1.37 -> 1.39 # drivers/pci/hotplug/cpqphp_nvram.h 1.2 -> 1.3 # net/rxrpc/proc.c 1.4 -> 1.6 # arch/parisc/Kconfig 1.22 -> 1.23 # fs/jffs/inode-v23.c 1.55 -> 1.56 # drivers/isdn/hardware/eicon/diva_didd.c 1.4 -> 1.5 # fs/afs/Makefile 1.3 -> 1.4 # drivers/pcmcia/yenta_socket.c 1.46 -> 1.48 # usr/gen_init_cpio.c 1.5 -> 1.6 # include/linux/cpufreq.h 1.34 -> 1.36 # drivers/pcmcia/sa1100_generic.c 1.33 -> 1.34 # arch/ia64/sn/io/sn2/pic.c 1.3 -> 1.4 # net/ipv4/netfilter/ipt_MASQUERADE.c 1.10 -> 1.11 # drivers/isdn/hardware/eicon/message.c 1.2 -> 1.4 # drivers/video/i810/i810_main.h 1.9 -> 1.10 # net/rxrpc/Makefile 1.5 -> 1.6 # drivers/pci/hotplug/acpiphp_core.c 1.6 -> 1.7 # drivers/scsi/gdth.c 1.35 -> 1.36 # net/sched/sch_htb.c 1.14 -> 1.15 # drivers/char/watchdog/wdt_pci.c 1.27 -> 1.28 # drivers/pci/hotplug/cpci_hotplug_pci.c 1.13 -> 1.14 # drivers/net/pppoe.c 1.32 -> 1.33 # drivers/block/z2ram.c 1.29 -> 1.30 # arch/ia64/sn/io/drivers/ioconfig_bus.c 1.4 -> 1.5 # drivers/pci/hotplug/fakephp.c 1.1 -> 1.2 # include/asm-i386/setup.h 1.5 -> 1.6 # include/asm-ppc/ucontext.h 1.4 -> 1.5 # arch/ppc64/kernel/eeh.c 1.11 -> 1.12 # include/asm-ia64/ptrace.h 1.15 -> 1.16 # arch/ppc64/kernel/asm-offsets.c 1.14 -> 1.15 # drivers/net/bonding/bond_alb.c 1.2 -> 1.3 # drivers/isdn/hisax/avma1_cs.c 1.7 -> 1.8 # drivers/net/pcmcia/fmvj18x_cs.c 1.25 -> 1.26 # drivers/isdn/hardware/eicon/um_idi.c 1.3 -> 1.4 # arch/i386/kernel/timers/timer_tsc.c 1.24 -> 1.26 # drivers/net/pcmcia/smc91c92_cs.c 1.23 -> 1.24 # include/asm-ppc64/mmu.h 1.7 -> 1.8 # drivers/parisc/lasi.c 1.3 -> 1.4 # net/ax25/ax25_route.c 1.13 -> 1.14 # arch/i386/kernel/timers/timer_cyclone.c 1.10 -> 1.11 # arch/ppc64/mm/numa.c 1.8 -> 1.10 # net/decnet/dn_neigh.c 1.7 -> 1.8 # arch/ppc64/kernel/syscalls.c 1.12 -> 1.13 # arch/arm/boot/compressed/misc.c 1.5 -> 1.6 # drivers/pci/pci-driver.c 1.33 -> 1.35 # arch/ppc64/kernel/sys_ppc32.c 1.66 -> 1.67 # drivers/parisc/lba_pci.c 1.7 -> 1.8 # include/rxrpc/peer.h 1.2 -> 1.3 # drivers/video/riva/fbdev.c 1.49 -> 1.50 # drivers/net/wireless/strip.c 1.14 -> 1.15 # init/do_mounts_rd.c 1.6 -> 1.7 # drivers/net/e1000/e1000_param.c 1.21 -> 1.23 # drivers/char/agp/ati-agp.c 1.8 -> 1.9 # drivers/parisc/wax.c 1.3 -> 1.4 # include/asm-i386/cpufeature.h 1.9 -> 1.10 # include/asm-ppc64/serial.h 1.1 -> 1.2 # net/rxrpc/transport.c 1.3 -> 1.4 # arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c 1.5 -> 1.6 # include/asm-parisc/elf.h 1.6 -> 1.7 # arch/ia64/sn/io/sn2/ml_SN_intr.c 1.3 -> 1.4 # fs/afs/file.c 1.3 -> 1.4 # drivers/isdn/hardware/eicon/platform.h 1.3 -> 1.5 # sound/oss/nec_vrc5477.c 1.18 -> 1.19 # drivers/isdn/hardware/eicon/divasproc.c 1.4 -> 1.5 # arch/ppc64/mm/fault.c 1.11 -> 1.12 # arch/ppc64/kernel/vmlinux.lds.S 1.18 -> 1.19 # drivers/parisc/sba_iommu.c 1.10 -> 1.11 # drivers/serial/8250_pci.c 1.25 -> 1.26 # drivers/block/DAC960.c 1.67 -> 1.69 # arch/ppc64/kernel/stab.c 1.12 -> 1.13 # drivers/net/bonding/bond_3ad.c 1.2 -> 1.3 # include/asm-parisc/hil.h 1.2 -> (deleted) # include/asm-sparc/sfp-machine.h 1.1 -> 1.2 # drivers/net/tokenring/olympic.c 1.25 -> 1.26 # arch/ia64/sn/io/machvec/pci_bus_cvlink.c 1.9 -> 1.10 # drivers/isdn/hardware/eicon/capifunc.h 1.2 -> 1.3 # net/core/wireless.c 1.12 -> 1.13 # drivers/isdn/hardware/eicon/diva.c 1.4 -> 1.5 # kernel/sched.c 1.208 -> 1.209 # net/atm/resources.h 1.8 -> 1.9 # drivers/input/keyboard/atkbd.c 1.31 -> 1.32 # include/rxrpc/connection.h 1.1 -> 1.2 # drivers/net/tulip/de2104x.c 1.24 -> 1.25 # arch/i386/kernel/timers/timer_hpet.c 1.1 -> 1.2 # arch/ia64/sn/io/sn2/pcibr/pcibr_config.c 1.3 -> 1.4 # init/Kconfig 1.26 -> 1.28 # drivers/block/xd.c 1.57 -> 1.58 # drivers/ide/ide-io.c 1.19 -> 1.20 # drivers/net/wireless/wavelan_cs.p.h 1.9 -> 1.10 # net/ipv6/udp.c 1.47 -> 1.48 # drivers/pci/hotplug/pci_hotplug_core.c 1.40 -> 1.41 # drivers/pci/hotplug/cpqphp.h 1.10 -> 1.11 # net/ipv4/netfilter/ipt_REJECT.c 1.22 -> 1.23 # include/asm-parisc/byteorder.h 1.2 -> 1.3 # drivers/net/wireless/airo_cs.c 1.9 -> 1.10 # net/rxrpc/call.c 1.3 -> 1.4 # include/linux/atmclip.h 1.1 -> 1.2 # drivers/cdrom/Kconfig 1.4 -> 1.5 # drivers/char/agp/via-agp.c 1.51 -> 1.52 # drivers/isdn/hardware/eicon/Makefile 1.4 -> 1.5 # include/asm-ia64/sn/sn2/intr.h 1.3 -> 1.4 # drivers/net/pcmcia/pcnet_cs.c 1.24 -> 1.25 # include/rxrpc/rxrpc.h 1.1 -> 1.2 # arch/sparc/boot/btfixupprep.c 1.3 -> 1.4 # drivers/char/hvc_console.c 1.20 -> 1.21 # net/rxrpc/main.c 1.4 -> 1.5 # arch/ppc64/boot/Makefile 1.16 -> 1.18 # drivers/net/e1000/e1000_hw.h 1.17 -> 1.21 # drivers/pci/hotplug/ibmphp_res.c 1.8 -> 1.9 # arch/ppc64/xmon/xmon.c 1.27 -> 1.29 # net/ipv6/mcast.c 1.33 -> 1.37 # net/ipv4/arp.c 1.27 -> 1.29 # arch/cris/arch-v10/boot/compressed/misc.c 1.7 -> 1.8 # drivers/net/tokenring/tmspci.c 1.14 -> 1.15 # drivers/isdn/hisax/config.c 1.50 -> 1.51 # arch/parisc/kernel/sys_parisc.c 1.8 -> 1.9 # arch/sparc64/Kconfig 1.32 -> 1.33 # drivers/isdn/hardware/eicon/capifunc.c 1.6 -> 1.7 # fs/afs/volume.h 1.2 -> 1.3 # fs/afs/cache-layout.h 1.1 -> (deleted) # include/asm-ia64/acpi.h 1.7 -> 1.9 # fs/afs/cell.h 1.1 -> 1.2 # arch/parisc/kernel/drivers.c 1.6 -> 1.7 # drivers/pci/hotplug/cpqphp_nvram.c 1.9 -> 1.10 # drivers/pcmcia/i82365.c 1.44 -> 1.45 # drivers/isdn/hardware/eicon/s_bri.c 1.2 -> 1.3 # net/appletalk/atalk_proc.c 1.8 -> 1.9 # fs/ext3/super.c 1.74 -> 1.75 # drivers/net/wireless/orinoco_cs.c 1.24 -> 1.25 # arch/ia64/sn/io/sn2/pcibr/pcibr_hints.c 1.3 -> 1.4 # arch/parisc/Makefile 1.22 -> 1.23 # arch/parisc/hpux/wrappers.S 1.3 -> 1.4 # arch/ppc/kernel/misc.S 1.47 -> 1.48 # arch/arm/common/sa1111.c 1.29 -> 1.30 # drivers/serial/Kconfig 1.15 -> 1.16 # arch/ia64/hp/sim/boot/bootloader.c 1.10 -> 1.11 # drivers/net/bonding/bond_main.c 1.27 -> 1.35 # net/sched/police.c 1.2 -> 1.3 # net/ipv6/addrconf.c 1.64 -> 1.67 # arch/ia64/kernel/perfmon.c 1.56.1.1 -> 1.60 # drivers/pci/hotplug/cpqphp_pci.c 1.22 -> 1.23 # drivers/net/ppp_generic.c 1.39 -> 1.40 # net/ipv4/icmp.c 1.35 -> 1.36 # net/atm/resources.c 1.14 -> 1.16 # security/selinux/hooks.c 1.6 -> 1.7 # arch/ia64/Kconfig 1.39.1.2 -> 1.42 # drivers/char/n_r3964.c 1.14 -> 1.15 # drivers/net/pcmcia/3c589_cs.c 1.22 -> 1.23 # drivers/pci/hotplug/cpqphp_sysfs.c 1.9 -> 1.10 # drivers/parisc/asp.c 1.3 -> 1.4 # include/pcmcia/ss.h 1.24 -> 1.27 # include/asm-ppc64/mmzone.h 1.12 -> 1.13 # include/asm-ppc64/pgtable.h 1.23 -> 1.24 # drivers/isdn/hardware/eicon/dlist.h 1.2 -> 1.3 # fs/afs/kafsasyncd.c 1.5 -> 1.6 # net/appletalk/aarp.c 1.16 -> 1.18 # arch/ia64/scripts/toolchain-flags 1.4 -> 1.5 # drivers/isdn/hardware/eicon/idifunc.c 1.2 -> 1.3 # drivers/block/cciss.c 1.92 -> 1.94 # include/asm-parisc/cacheflush.h 1.4 -> 1.5 # include/asm-ppc64/rwsem.h 1.2 -> 1.3 # include/asm-ppc/highmem.h 1.12 -> 1.13 # drivers/net/wireless/netwave_cs.c 1.21 -> 1.22 # net/rose/rose_route.c 1.10 -> 1.11 # drivers/net/e1000/e1000_hw.c 1.20 -> 1.26 # net/atm/clip.c 1.21 -> 1.22 # include/asm-ppc64/topology.h 1.8 -> 1.9 # arch/parisc/kernel/signal.c 1.10 -> 1.11 # drivers/pcmcia/sa1100_simpad.c 1.11 -> 1.12 # include/asm-arm/hardware/sa1111.h 1.12 -> 1.13 # arch/ppc/kernel/signal.c 1.23 -> 1.24 # net/ipv4/igmp.c 1.35 -> 1.38 # include/asm-ppc64/rtas.h 1.6 -> 1.7 # net/netrom/nr_route.c 1.9 -> 1.10 # arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c 1.5 -> 1.6 # drivers/ide/ide-default.c 1.2 -> 1.3 # arch/ia64/kernel/init_task.c 1.12 -> 1.13 # drivers/pci/hotplug/acpiphp.h 1.6 -> 1.7 # drivers/net/bonding/bond_3ad.h 1.1 -> 1.2 # net/ipv4/route.c 1.69 -> 1.71 # arch/parisc/kernel/process.c 1.10 -> 1.11 # drivers/isdn/hardware/eicon/debuglib.h 1.1 -> 1.2 # drivers/block/acsi.c 1.53 -> 1.54 # arch/i386/kernel/i386_ksyms.c 1.53 -> 1.54 # drivers/isdn/hardware/eicon/diddfunc.c 1.2 -> 1.3 # fs/proc/kmsg.c 1.4 -> 1.5 # drivers/block/umem.c 1.43 -> 1.44 # fs/proc/generic.c 1.23 -> 1.24 # arch/parisc/kernel/syscall.S 1.13 -> 1.14 # drivers/isdn/hardware/eicon/io.h 1.2 -> 1.3 # drivers/net/hamachi.c 1.30 -> 1.31 # include/asm-ppc64/prom.h 1.8 -> 1.9 # include/linux/seq_file.h 1.7 -> 1.8 # arch/parisc/kernel/parisc_ksyms.c 1.9 -> 1.10 # arch/ppc64/kernel/pSeries_lpar.c 1.21 -> 1.22 # arch/sparc/math-emu/sfp-util.h 1.1 -> 1.2 # drivers/net/wan/sdla.c 1.15 -> 1.18 # drivers/isdn/hardware/eicon/s_pri.c 1.2 -> 1.3 # fs/ufs/namei.c 1.22 -> 1.23 # drivers/pcmcia/i82092.c 1.27 -> 1.29 # include/rxrpc/transport.h 1.1 -> 1.2 # arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c 1.12 -> 1.13 # drivers/net/slip.c 1.21 -> 1.22 # drivers/pci/hotplug/ibmphp_core.c 1.34 -> 1.35 # security/selinux/selinuxfs.c 1.2 -> 1.3 # arch/parisc/kernel/traps.c 1.10 -> 1.11 # Documentation/kernel-parameters.txt 1.28 -> 1.29 # arch/ppc64/kernel/pSeries_pci.c 1.26 -> 1.27 # scripts/mkcompile_h 1.16 -> 1.17 # fs/reiserfs/tail_conversion.c 1.26 -> 1.27 # arch/parisc/kernel/module.c 1.6 -> 1.7 # net/bluetooth/bnep/sock.c 1.11 -> 1.12 # fs/afs/super.h 1.1 -> 1.2 # arch/mips/kernel/irixelf.c 1.6 -> 1.7 # (new) -> 1.1 sound/oss/dmasound/tas3001c_tables.c # (new) -> 1.1 fs/afs/cache.h # (new) -> 1.1 arch/ia64/oprofile/init.c # (new) -> 1.1 sound/oss/dmasound/tas3001c.c # (new) -> 1.1 sound/oss/dmasound/tas3001c.h # (new) -> 1.1 arch/ia64/oprofile/Makefile # (new) -> 1.1 sound/oss/dmasound/tas_common.h # (new) -> 1.1 sound/oss/dmasound/dac3550a.c # (new) -> 1.1 include/asm-parisc/sections.h # (new) -> 1.1 arch/i386/kernel/timers/common.c # (new) -> 1.1 arch/i386/kernel/cpu/cpufreq/speedstep-smi.c # (new) -> 1.1 include/asm-i386/ist.h # (new) -> 1.2 arch/ppc64/mm/hugetlbpage.c # (new) -> 1.1 sound/oss/dmasound/tas3004.h # (new) -> 1.1 sound/oss/dmasound/tas_eq_prefs.h # (new) -> 1.1 sound/oss/dmasound/tas_common.c # (new) -> 1.1 arch/ia64/kernel/perfmon_hpsim.h # (new) -> 1.1 arch/ia64/oprofile/Kconfig # (new) -> 1.1 include/asm-ppc64/local.h # (new) -> 1.1 scripts/bin2c.c # (new) -> 1.1 arch/ppc64/boot/install.sh # (new) -> 1.1 sound/oss/dmasound/tas_ioctl.h # (new) -> 1.1 sound/oss/dmasound/tas3004_tables.c # (new) -> 1.1 include/asm-parisc/local.h # (new) -> 1.1 sound/oss/dmasound/tas3004.c # (new) -> 1.1 sound/oss/dmasound/trans_16.c # (new) -> 1.1 include/asm-ia64/intel_intrin.h # (new) -> 1.1 arch/parisc/nm # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/09/08 torvalds@home.osdl.org 1.1217.3.21 # Linux 2.6.0-test5 # -------------------------------------------- # 03/09/08 jbarnes@sgi.com 1.1153.73.27 # [PATCH] ia64: misc. sn2 updates # # Fix a couple of sn2 files. # -------------------------------------------- # 03/09/08 jbarnes@sgi.com 1.1153.73.28 # [PATCH] ia64: fix current usage in sn2 code # # For some reason, we had a structure field called 'current'. This patch # fixes that. # -------------------------------------------- # 03/09/08 davidm@tiger.hpl.hp.com 1.1217.3.22 # Merge tiger.hpl.hp.com:/data1/bk/vanilla/linux-2.5 # into tiger.hpl.hp.com:/data1/bk/lia64/to-linus-2.5 # -------------------------------------------- # 03/09/08 rmk@flint.arm.linux.org.uk 1.1217.5.1 # Merge flint.arm.linux.org.uk:/usr/src/bk/linux-2.6 # into flint.arm.linux.org.uk:/usr/src/bk/linux-2.6-pcmcia # -------------------------------------------- # 03/09/09 paulus@samba.org 1.1221 # Merge bk://ppc@ppc.bkbits.net/for-linus-ppc # into samba.org:/home/paulus/kernel/for-linus-ppc # -------------------------------------------- # 03/09/08 greg@kroah.com 1.1217.6.1 # Merge kroah.com:/home/greg/linux/BK/bleed-2.5 # into kroah.com:/home/greg/linux/BK/pci-2.6 # -------------------------------------------- # 03/09/09 paulus@samba.org 1.1222 # Merge samba.org:/home/paulus/kernel/linux-2.5 # into samba.org:/home/paulus/kernel/for-linus-ppc # -------------------------------------------- # 03/09/09 rmk@flint.arm.linux.org.uk 1.1217.7.1 # Merge # -------------------------------------------- # 03/09/09 rmk@flint.arm.linux.org.uk 1.1217.7.2 # [SERIAL] Drop "level" argument from serial PM calls. # # Since the driver model has transitioned away from using multi-level # device suspend/resume, we also drop the multi-level support from # the serial layer. # # Update the 8250 and sa1100 drivers for this change. # -------------------------------------------- # 03/09/09 rmk@flint.arm.linux.org.uk 1.1217.7.3 # [SERIAL] Convert serial config deps to select statements # # The dependencies for CONFIG_SERIAL_CORE / CONFIG_SERIAL_CORE_CONSOLE # were becoming very messy. This cset converts the dependencies to # use "select" statements instead. # -------------------------------------------- # 03/09/09 rmk@flint.arm.linux.org.uk 1.1217.7.4 # [SERIAL] Fix another missing irqreturn_t (clps711x.c) # -------------------------------------------- # 03/09/09 rmk@flint.arm.linux.org.uk 1.1217.7.5 # [SERIAL] Introduce per-port capabilities. # # This allows us to maintain quirks or capabilities on a per-port basis, # so we can handle buggy clones more effectively. # -------------------------------------------- # 03/09/09 Andries.Brouwer@cwi.nl 1.1217.8.1 # [PATCH] compilation fix ufs # # Don't use C++ "argument declarations anywhere" in the kernel, even if # newer versions of gcc accept it. # -------------------------------------------- # 03/09/09 Andries.Brouwer@cwi.nl 1.1217.8.2 # [PATCH] sparse fix sysctl # -------------------------------------------- # 03/09/09 Andries.Brouwer@cwi.nl 1.1217.8.3 # [PATCH] sparse fix eventpoll # -------------------------------------------- # 03/09/09 Andries.Brouwer@cwi.nl 1.1217.8.4 # [PATCH] sparse fix cpufreq # -------------------------------------------- # 03/09/09 Andries.Brouwer@cwi.nl 1.1217.8.5 # [PATCH] sparse fix xattr # -------------------------------------------- # 03/09/09 Andries.Brouwer@cwi.nl 1.1217.8.6 # [PATCH] sparse fix kcore # -------------------------------------------- # 03/09/09 Andries.Brouwer@cwi.nl 1.1217.8.7 # [PATCH] sparse fix ext2_readlink # -------------------------------------------- # 03/09/09 Andries.Brouwer@cwi.nl 1.1217.8.8 # [PATCH] sparse fix reboot # -------------------------------------------- # 03/09/09 Andries.Brouwer@cwi.nl 1.1217.8.9 # [PATCH] sparse fix for proc/misc # -------------------------------------------- # 03/09/09 Andries.Brouwer@cwi.nl 1.1217.8.10 # [PATCH] sparse fix for fat/file.c # -------------------------------------------- # 03/09/09 Andries.Brouwer@cwi.nl 1.1217.8.11 # [PATCH] sparse fix for kmsg # -------------------------------------------- # 03/09/09 Andries.Brouwer@cwi.nl 1.1217.8.12 # [PATCH] sparse fix for proc/generic # -------------------------------------------- # 03/09/09 torvalds@home.osdl.org 1.1217.3.23 # Merge http://lia64.bkbits.net/to-linus-2.5 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/09/09 jgarzik@pobox.com 1.1217.3.24 # [PATCH] Fix netdev close # # This should fix the "ifconfig down ... ifconfig up" problems some # people have seen. # -------------------------------------------- # 03/09/09 joe@perches.com 1.1217.3.25 # [PATCH] Add SEQ_START_TOKEN #define to seq_file.h # # Code that includes seq_file.h uses a magic pointer "(void*)1" # to start a header seq_printf. # # This patch adds a #define, so that people can start writing more # readable code. # -------------------------------------------- # 03/09/09 axboe@suse.de 1.1217.3.26 # [PATCH] Fix blk_stop_queue bug # # Benh saw some bugs where the queue would end up being in an invalid # state, and this could certainly explain one of them. We must not have a # stopped queue on the plug list, and blk_plug_device() right now will # happily plug a stopped queue. # # We don't need to have it plugged either, blk_start_queue() will make # sure that request_fn gets run. # -------------------------------------------- # 03/09/09 eike-kernel@sf-tec.de 1.1217.3.27 # [PATCH] Fix typo in fs/Kconfig # -------------------------------------------- # 03/09/09 dhowells@redhat.com 1.1217.3.28 # [PATCH] RxRPC update # # Here's a patch to update the RxRPC driver. Most of it is CodingStyle fixes, # but it also includes a few miscellaneous bug fixes. stdint types are also # turned into C99 forms (eg: u32 -> uint32_t). # -------------------------------------------- # 03/09/09 dhowells@redhat.com 1.1217.3.29 # [PATCH] AFS update # -------------------------------------------- # 03/09/09 benh@kernel.crashing.org 1.1217.9.1 # Merge kernel.crashing.org:/home/benh/kernels/linux-2.5 # into kernel.crashing.org:/home/benh/kernels/for-linus-ppc # -------------------------------------------- # 03/09/09 torvalds@home.osdl.org 1.1217.3.30 # Merge bk://bk.arm.linux.org.uk/linux-2.6-serial # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/09/09 benh@kernel.crashing.org 1.1217.3.31 # [PATCH] IDE: Fix request handling with ide-default & ATAPI # # This fixes a bug that happens when a request gets to the IDE layer for a # drive using ide-default (that is with no subdriver attached), like a # Power Management request. In this case, the core will wait for the # device status to match drive->read_stat, but that field contains by # default a value that is not suitable for ATAPI devices. This patch # fixes it. # -------------------------------------------- # 03/09/09 benh@kernel.crashing.org 1.1217.3.32 # [PATCH] IDE: Fix Power Management request race on resume # # The current IDE Power Management code I wrote has a race on wakeup when # the master device got resumed, it may take a request. At this point, a # PM resume request to a slave device of the same hwgroup would clear # hwgroup->rq and cause an Oops when the master device request completes. # # This patch fixes it. Due to the context in which PM resume requests are # sent, just not clearing hwgroup->rq for these is enough. # # I also removed a useless debug message in the PM code that was # actually misleading (people though it indicated a problem while it # didn't, it's really useless) and fix a typo in a comment. # -------------------------------------------- # 03/09/09 benh@kernel.crashing.org 1.1217.9.2 # dmasound update from Christoph Hellwig # -------------------------------------------- # 03/09/09 benh@kernel.crashing.org 1.1223 # Merge bk://ppc@ppc.bkbits.net/for-linus-ppc # into kernel.crashing.org:/home/benh/kernels/for-linus-ppc # -------------------------------------------- # 03/09/10 anton@samba.org 1.1217.1.3 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/tmp3 # -------------------------------------------- # 03/09/09 armin@melware.de 1.1217.3.33 # [PATCH] eicon ISDN driver: memory attach # # Access to cards memory now uses macros to attach # to the correct memory area of the card. # -------------------------------------------- # 03/09/09 armin@melware.de 1.1217.3.34 # [PATCH] eicon ISDN driver: capi code fix # # Fix application memory allocation, module locking, # building in-kernel, use new internal debug api. # -------------------------------------------- # 03/09/09 armin@melware.de 1.1217.3.35 # [PATCH] eicon ISDN driver: debug # # Module now can be build without debug code, necessary # if the module is built-in the kernel. # # Fixed spelling typos. # -------------------------------------------- # 03/09/09 armin@melware.de 1.1217.3.36 # [PATCH] eicon ISDN driver: list handling # # Fixed internel list handling for modules built-in kernel. # -------------------------------------------- # 03/09/09 armin@melware.de 1.1217.3.37 # [PATCH] eicon ISDN driver: endianess # # fixed endianess errors in common code part. # -------------------------------------------- # 03/09/09 armin@melware.de 1.1217.3.38 # [PATCH] eicon ISDN driver: Kernelconfig # # Main divas modules now may be build in-kernel. # 4BRI cards are configured together with BRI cards. # -------------------------------------------- # 03/09/09 armin@melware.de 1.1217.3.39 # [PATCH] eicon ISDN driver: C comments # # changed // comments to /* */ # -------------------------------------------- # 03/09/09 armin@melware.de 1.1217.3.40 # [PATCH] eicon ISDN driver: update # # Use different var-names if they are non-static, # configure 4BRI like BRI cards, fixed new /proc entries, # inline declarations for common helper functions. # -------------------------------------------- # 03/09/09 rmk@arm.linux.org.uk 1.1217.3.41 # [PATCH] stable AGP pci_device_id tables # # This should fix all the AGP drivers. # # pci_device_id tables can not and must not be marked discardable. They # are used for as long as the driver is registered. # -------------------------------------------- # 03/09/09 rmk@arm.linux.org.uk 1.1217.3.42 # [PATCH] More buggy pci drivers # # This should fix all the remaining pci drivers which mark the pci device # ID tables as being discardable at run time. # -------------------------------------------- # 03/09/10 anton@samba.org 1.1217.1.4 # ppc64: catch bad ioctl size at compile time, from x86 # -------------------------------------------- # 03/09/09 torvalds@home.osdl.org 1.1224 # Merge bk://ppc.bkbits.net/for-linus-ppc # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/09/09 davej@redhat.com 1.1153.101.25 # [CPUFREQ] Merge speedstep-smi driver. # From: Hiroshi Miura # # Intel SpeedStep driver using a BIOS SMI call. # # Quoting his original announcement: # # "This driver is based on the information from # # 1. Microsoft Windows XP Document. # we can get the SMI interface values from ax=E980/int15 BIOS call. # # 2. Intel SpeedStep Applet Document.(from HP.com) # http://h18007.www1.hp.com/support/files/evonotebook/us/download/10631.html # " Adds code to request transition ownership when processing # the system critical resume message. When a critical hibernate occurs, # the Applet does not receive any system level notification. The change forces # the Applet to re-acquire transition ownership upon resume from a critical hibernate. " # # This is informative. This saied that something 'ownership' call is needed on SMI # interface first. # # 3. Grover, Andrew's int 15h patch posted to cpufreq ml # Message-ID: # code which call BIOS to get SMI values. I included it. # # 4. Malik Martin's rev engineering results. # call is made with BX, CX, EDI register values. # and need signature 'ISG' when call. # find function values. bx=1(get) and bx=2(set) # # 5. Marc Lehmann's 'speedstep' utility, # sample of assembler code to call SMI. # # 6. My work. # find function to return max/min freq which system supportd. (bx=4) # more values are gotten, but I cannot understand... # find 'ownership' function value(bx=0, which is other than 1 2 4..). # # ToDo(in pregress) # support governor "auto" and using smi_event call, imprement auto freqchange # feature. # test on 440BX/ZX platform. # # Memo # module parameters are override result of an int 15h/eax=E890h call. # these parameter value are gotten from Windows XP registory." # # Also includes some bugfixes, updates and workarounds from me. # # NB: A lot of BIOS out there are buggy. You might want to try this driver # also with Intel's default values -- smi_cmd = 0x82 and smi_port = 0xb2 # # -------------------------------------------- # 03/09/09 bunk@fs.tum.de 1.1225 # [PATCH] ATM Ambassador no longer BROKEN_ON_SMP # # Chas Williams fixed the compilation on SMP, so we can remove the Kconfig # annotation now and let people select it in the build again. # -------------------------------------------- # 03/09/09 willy@debian.org 1.1226 # [PATCH] PA-RISC update for 2.6.0-test5 # # PA-RISC updates for 2.6.0-test5. # # Contributions from Paul Bame, James Bottomley, Randolph Chung, Helge # Deller, Grant Grundler, LaMont Jones, Matthew Wilcox # -------------------------------------------- # 03/09/09 davej@redhat.com 1.1153.101.26 # [CPUFREQ] remove $Id$ tags, update filenames # -------------------------------------------- # 03/09/09 davej@redhat.com 1.1153.101.27 # [CPUFREQ] add cpufreq_update_policy() # # Add a new cpufreq_update_policy call: # # Certain cpufreq policy notifers have different needs at different times. # Thus it needs to be possible to re-evaluate an already set cpufreq policy. # Note that the cpufreq policy should only be set by one person: the user. # Not any other in-kernel code [with one exception, of course: during # booting]. # -------------------------------------------- # 03/09/09 torvalds@osdl.org 1.1227 # [PATCH] Fix CONFIG_PCMCIA_WL3501 with older compilers # # We only support named initializers with one leval of naming, ie that # # .foo.bar = baz, # # thing should go. gcc-2.95 doesn't handle it (neither does sparse, I # think). # # Replace such initializers with # # .foo = { # .bar = baz, # }, # # instead. # -------------------------------------------- # 03/09/10 anton@samba.org 1.1217.1.5 # ppc64: Give us a generic local.h until we have atomic64 # -------------------------------------------- # 03/09/09 guillaume@morinfr.org 1.1228 # [PATCH] fix cpu_test_and_set() on UP # # cpumask_up.h is broken. It tries to access the "mask" member although # that cpumask_t is an ulong on UP. This breaks archs which uses cpumask # functions even on UP such as s390. # -------------------------------------------- # 03/09/09 torvalds@home.osdl.org 1.1229 # Merge http://ppc.bkbits.net/for-linus-ppc64 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/09/09 torvalds@home.osdl.org 1.1230 # Merge bk://linux-dj.bkbits.net/cpufreq # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/09/09 shemminger@osdl.org 1.1231 # [PATCH] Get rid of Intermezzo warning # # There is a leftover MOD_DEC_USE_COUNT intermezzo, with no matching _INC_ # anywhere. # # Since it sets owner on the file system operations there should be no # need for explicit module manipulation. # -------------------------------------------- # 03/09/09 shemminger@osdl.org 1.1232 # [PATCH] Fix modularization of Siemens line discipline # # Convert SIEMENS R3964 tty line discipline on 2.6.0-test5 to use tty_ldisc owner # instead of explicit MOD_INC/DEC. # # And fix the initializer to be a much more readable C99 one. # -------------------------------------------- # 03/09/09 joe@perches.com 1.1233 # [PATCH] Use SEQ_START_TOKEN in drivers/net/* [1/3] # -------------------------------------------- # 03/09/09 joe@perches.com 1.1234 # [PATCH] Use SEQ_START_TOKEN in include/net/* [2/3] # -------------------------------------------- # 03/09/09 joe@perches.com 1.1235 # [PATCH] Use SEQ_START_TOKEN in include/net/* [3/3] # -------------------------------------------- # 03/09/09 torvalds@home.osdl.org 1.1236 # Make rxrpc use SEQ_START_TOKEN. # -------------------------------------------- # 03/09/09 eyal@eyal.emu.id.au 1.1237 # [PATCH] wl3501 with old compiler # # Fix the ## handling to work with old gcc versions (spaces around the ',' # to make token boundaries work). # -------------------------------------------- # 03/09/09 torvalds@home.osdl.org 1.1238 # From Stephen Hemminger: we were trying to cast an "unsigned short" # to a pointer. That was a typo. # # Ack'ed by Al Viro. # -------------------------------------------- # 03/09/09 torvalds@home.osdl.org 1.1239 # Fix ray_cs for new interrupt handling. # # Damn 16-bit PCMCIA layer has no type checking. Complete crap. # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1240 # [PATCH] s/spin_lock_irqrestore/spin_unlock_irqrestore # # From: Vinay K Nallamothu # # Fix a couple of cut-n-paste errors. # # (Why on earth is a scsi driver poking at the RTC hardware?) # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1241 # [PATCH] calibrate_tsc() fix and consolidation # # From: "Pallipadi, Venkatesh" # # CONFIG_TIMER_CYCLONE doesn't build at present because calibrate_tsc() was # made static. # # The patch fixes that up and moves all calibrate_tsc functions into a common # file, avoiding the current code duplication. # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1242 # [PATCH] Initialise devfs_name in various block drivers # # From: Andrey Borzenkov # # Various block drivers are currently devfs-unaware. Andrey's patch attempts # to give them reasonable representations in devfs. # # # "The attached patch suggests some possible names for non-floppy devices # based on reading driver source. I have to ask if these make sense. At # least for cciss Mandrake devfsd patch expects different names but it # seems to be mistake (it assumes single controller always) # # "For floppy it is not as simple. Floppy cannot use genhd and must # create names manually; but I do not know what names are appropriate or # expected. # # "For acsi the target/lun name may have problem of creating compat names # (if any) by devfsd. # # "Please note that none of them created any devfs name under 2.4 as well. # So it is not a regression ..." # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1243 # [PATCH] monolitic_clock, timer_{tsc,hpet} and CPUFREQ # # From: Dmitry Torokhov # # I noticed that although timer_tsc registers cpufreq notifier to detect # frequency changes and adjust cpu_khz it does not set cyc2ns_scale. # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1244 # [PATCH] dac960 devfs_name initialisation fix # # From: Andrey Borzenkov # # DAC960.c does it incorrectly (at least in 2.6.0-test4). It will create # _directory_ /dev/rd/cNdM making it impossible to create compat block device # entry with the same name. # # The right thing it to create separate directory for each controller/target as # in attached trivial patch (untested due to lack of hardware). You will need # devfsd support for this but then you will need it for cciss or cpqarray as # well and possibly for others. Which returns us to the problem of devfsd # maintenance ... # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1245 # [PATCH] compiler warning fixes for DAC960 on alpha # # From: Dave Olien # # This patch is forwarded from Jay Estabrook at HP. I've compiled the # patch on ia32 and ia64 machines and it's good. I also recreated # the patch so it would apply to mm5 without fuzzy offsets. # Here's Jay's summary of the patch: # # Here's a very small set of patches against 2.6.0-test4 that help the # DAC960 driver compile cleaner (gets rid of warnings on Alpha) and help # it to work on some old OEM'ed DAC960 cards that were sold in our older # Alphas. # # The warnings are all concerned with "conversions to different size # without cast", as pointers and longs are same size (8-bytes) but ints # are 4-bytes, on Alpha. I don't believe the change to (long) from (int) # will affect any 32-bit architectures, but those using LP64 like Alpha, # ie SPARC64 and prolly IA64, will have the warnings go away. # # The change to make the oldest acceptable firmware version 2.70 instead # of 2.73 is made spcific to Alpha, since it is only those cards that # DEC OEM'ed from Mylex that would have such (as explained a bit better # in the patch itself). # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1246 # [PATCH] Move ikconfig to /proc/config.gz # # From: "Randy.Dunlap" # # # The SuSE kernels place their ikconfig info at /proc/config.gz: in a # different place, and compressed. We thought it was a good idea to do it # that way in 2.6 as well. # # - gzip the /proc config file, put it in /proc/config.gz; # # - Based on a SuSE patch by Oliver Xymoron , which was # derived from a patch by Nicholas Leon # # - change /proc/ikconfig/built_with to /proc/config_build_info; # # - cleanup ikconfig init/exit entry points (static, __init, __exit); # # - Makefile help from Sam Ravnborg; # # DESC # ikconfig cleanup # EDESC # From: Stephen Hemminger # # Simplify and cleanup the code: # - use single interface to seq_file where possible # - don't need to do as much of the /proc interface, only read # - use copy_to_user to avoid char at a time copy # - remove unneccesary globals # - use const char[] rather than const char * where possible. # # Didn't change the version since interface doesn't change. # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1247 # [PATCH] reiserfs direct-IO support # # From: Oleg Drokin # # This patch implements DirectIO support for reiserfs v3. This is mostly a # port from 2.4. # # Thanks to Mingming Cao from IBM for some clues in porting. # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1248 # [PATCH] Fix imm.c again # # From: Adrian Bunk # # Earlier patch wasn't correct especially in the !CONFIG_SCSI_IZIP_EPP16 # case, reading all uses of this array (IMM_MODE_STRING is used to print the # corresponding string in printks). # # If I'm not misunderstanding it, CONFIG_SCSI_IZIP_EPP16 means "use 16bit # even when 32bit is requested". # # It seems the right solution is # # static char *IMM_MODE_STRING[] = # { # [IMM_AUTODETECT] = "Autodetect", # [IMM_NIBBLE] = "SPP", # [IMM_PS2] = "PS/2", # [IMM_EPP_8] = "EPP 8 bit", # [IMM_EPP_16] = "EPP 16 bit", # #ifdef CONFIG_SCSI_IZIP_EPP16 # [IMM_EPP_32] = "EPP 16 bit", # #else # [IMM_EPP_32] = "EPP 32 bit", # #endif # [IMM_UNKNOWN] = "Unknown", # }; # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1249 # [PATCH] make selinux enable param config option, enabled by # # From: James Morris # # This patch against current bk makes the recently added SELinux boot # parameter feature a configurable option, and enables SELinux by default # when selected. These changes were made following feedback including # discussion on the SELinux list. # # The rationale for the changes is to allow SELinux to be be configured and # enabled unconditionally. If the boot parameter option is selected, then # SELinux is now enabled unless selinux=0 is specified at the kernel command # line. # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1250 # [PATCH] sound: remove duplicate includes # # From: "Randy.Dunlap" # # remove duplicate #includes in sound/ # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1251 # [PATCH] remove duplicate includes in kernel/ # # From: "Randy.Dunlap" # # remove duplicate #includes in kernel/ # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1252 # [PATCH] Handle NR_CPUS overflow # # From: john stultz # # Don't try to support more than NR_CPUS cpus: things overflow. # # Also, increase the default in config for some architectures. (Dave # Hansen). # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1253 # [PATCH] ppp devfs oops fix # # From: Christoph Hellwig # # PPP leaves the chardev registered even if we're going to fail the modprobe. # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1254 # [PATCH] d_delete-d_lookup race fix # # From: Maneesh Soni # # d_delete() calls dentry_iput() after releasing the per dentry lock. This # can race with __d_lookup and lead to situation where we can make dentry # negative with ref count > 1. The following patch makes dentry_iput() to # hold per dentry lock till d_inode is NULL and dentry has been removed from # d_alias list. # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1255 # [PATCH] ia32 idle using PNI monitor/mwait # # From: "Nakajima, Jun" # # Attached is a patch that enables PNI (Prescott New Instructions) # monitor/mwait in the kernel idle handler. # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1256 # [PATCH] remap file pages MAP_NONBLOCK fix # # From: Rajesh Venkatasubramanian # # The remap_file_pages system call with MAP_NONBLOCK flag does not # install file-ptes when the required pages are not found in the # page cache. Modify the populate functions to install file-ptes # if the mapping is non-linear and the required pages are not found # in the page cache. # # Patch is for test4-mm6. Compiles and boots. Patch tested using the # programs at: # # http://www-personal.engin.umich.edu/~vrajesh/linux/remap-file-pages/ # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1257 # [PATCH] install_page pte use-after-unmap fix # # From: Rajesh Venkatasubramanian # # Don't deref the pte pointer after having kunmapped the memory it points at. # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1258 # [PATCH] really use english date in version string # # From: Andrey Borzenkov # # LANG is not always enough to force date to english. # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1259 # [PATCH] tidy up lib/inflate.c error messages # # From: Andre McCurdy # # There is some inconsistency within lib/inflate.c and its users about # whether the error message text or the error() function should provide # the '\n'. # # This patch tries to make everyone consistent - by removing the # newline from all message texts, and adding one to the only error() # function which did not provide it (in init/do_mounts_rd.c). # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1260 # [PATCH] ext3: remove debug code # # ext3 has fancy test harness code which allows you to simulate crashes (for # testing recovery). It will make the underlying disk start ignoring writes a # specified number of seconds after the mount. # # It's inoperative without an additional offline patch anyway, and it's doing # hacky things which scared Al. So kill it; I'll maintain it in the separate # ext3 debug patch. # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1261 # [PATCH] mwave locking fixes # # From: Manfred Spraul # # The mwave driver uses a user space daemon for some modem operations. The # user space daemon calls ioctl(,IOCTL_MW_GET_IPC), and the driver returns # after an interrupt arrived. The actual wait used # interruptible_sleep_on(), which can lead to lost wakeups. A local # spinlock on the stack is used to close that race, but this is broken on # SMP, perhaps even with preempt. # # The attached patch fixes that by switching to the normal # add_wait_queue/test_if_race_occured/schedule/remove_wait_queue sequence. # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1262 # [PATCH] fix Summit srat.h includes # # From: Dave Hansen # # I was compiling for my plain 'ol PC, and was getting unresolved symbols # for get_memcfg_from_srat() and get_zholes_size(). The CONFIG_NUMA # definition right now allows it to be turned on for plain old X86_PC. # Does anyone know why this is? # # depends on SMP && HIGHMEM64G && # (X86_PC || X86_NUMAQ || X86_GENERICARCH || # (X86_SUMMIT && ACPI && !ACPI_HT_ONLY)) # # In any case, the summit code incorrectly assumes in at least 2 places # that NUMA && !NUMAQ means summit. Someone was evidently trying to cover # the generic subarch case, but that's already taken care of by the lovely # config system and CONFIG_ACPI_SRAT. This patch fixes those assumptions # and adds a nice little warning for people that try to #include srat.h # without having srat support turned on. # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1263 # [PATCH] Reduce random driver lock contention # # From: Matt Mackall # # The new locking in the random driver is consuming 60% of CPU resources in # Anton's monster power5 boxes. # # # Basically, when the primary pool is 7/8th full, we shut off the firehose # and go into a trickle mode to keep the pool fresh. Saves CPU for everyone # and should make the contention drop off the charts too (though the trickle # factor might need adjusting again for Origin-class machines). # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1264 # [PATCH] sys_fadvise needs asmlinkage # -------------------------------------------- # 03/09/10 akpm@osdl.org 1.1265 # [PATCH] CPU scheduler CAN_MIGRATE fix # # From: Andrew Theurer # # This change: # http://linux.bkbits.net:8080/linux-2.5/diffs/kernel/sched.c@1.202 # # does not seem to make sense: # # #define CAN_MIGRATE_TASK(p,rq,this_cpu) \ # ((!idle || (jiffies - (p)->last_run > cache_decay_ticks)) && \ # !task_running(rq, p) && \ # cpu_isset(this_cpu, (p)->cpus_allowed)) # # It should be just the opposite; an idle cpu should be able to have a more # aggressive steal, and a busy cpu should not. # -------------------------------------------- # 03/09/10 axboe@suse.de 1.1266 # [PATCH] get rid of warning in gscd # # From: Stephen Hemminger # # Compiler warning due to missing equal sign. # -------------------------------------------- # 03/09/10 axboe@suse.de 1.1267 # [PATCH] blk API update (and bug fix) to CDU535 cdrom driver # # This is a lot better than what is there know. # # From: Felipe W Damasio # # - cli-sti removal # - blk API update # - set_current_state # - Remove 'panic' line. # # .. and we can now remove the BROKEN_ON_SMP Kconfig annotation. # -------------------------------------------- # 03/09/10 rmk@flint.arm.linux.org.uk 1.1239.1.1 # Merge flint.arm.linux.org.uk:/usr/src/bk/linux-2.6 # into flint.arm.linux.org.uk:/usr/src/bk/linux-2.6-pcmcia # -------------------------------------------- # 03/09/10 willy@debian.org 1.1268 # [PATCH] Fill in ELF OSABI in ELF headers # # This fills in the ELF EI_OSABI field. This doesn't matter for most # architectures, but PA-RISC uses the Linux flavour of the ABI (since HPUX # uses the None flavour). # # Patch by Randolph Chung. # -------------------------------------------- # 03/09/10 armin@melware.de 1.1269 # [PATCH] Eicon ISDN driver: removed __devinitdata from pci_device_id. # # pci_device_id can not be marked __devinitdata, # was re-added with last update by accident. # -------------------------------------------- # 03/09/10 rusty@rustcorp.com.au 1.1270 # [PATCH] Remove modules.txt # # Thanks to Stephen Hemminger for pointing out how obsolete modules.txt is. # # modules.txt contains mainly ancient information which is replicated # in the kconfig help message, README, makefile.txt or the modprobe manual # page. The only part which is not covered elsewhere is the "building # external modules" which is still being debated (and belongs under the # kbuild docs). kmod.txt reference removed from index, too. # -------------------------------------------- # 03/09/10 anton@samba.org 1.1271 # [PATCH] fix oops in hvc_console # # tty_register_driver already calls tty_register_device so there is no need # to do it in hvc_console. Besides, it oopses when we do that. # -------------------------------------------- # 03/09/10 anton@samba.org 1.1272 # [PATCH] Fix initramfs permissions on directories and special files # # Set correct permissions on initramfs directories and special files. We dont # want to obey the umask here, so do the same thing we do on normal files - # call sys_chmod. # -------------------------------------------- # 03/09/10 anton@samba.org 1.1273 # [PATCH] quieten initramfs and fix /dev permissions # # Dont print the contents of the initramfs, for any decent sized cpio it will # overflow the kernel ring buffer. # # Also relax permissions on /dev (755 not 700). # -------------------------------------------- # 03/09/10 willy@debian.org 1.1274 # [PATCH] 1GB stack size limit on PA-RISC # # This patch introduces a 1GB stack size limit for stack-grows-up (ie # PA-RISC), as discussed previously. # -------------------------------------------- # 03/09/10 willy@debian.org 1.1275 # [PATCH] fs/exec.c whitespace cleanups # # Whitespace cleanup (mostly deleting trailing whitespace). # -------------------------------------------- # 03/09/10 willy@debian.org 1.1276 # [PATCH] interrupt.h needs kernel.h # # uses barrier() but does not include . # -------------------------------------------- # 03/09/10 zecke@org.rmk.(none) 1.1239.2.1 # [ARM PATCH] 1653/1: Simpad Flash Partition resubmit # # Patch from Holger Freyther # # This the the resubmit of the flash partition changes for SIMpad. # # # # Two versions one for cramfs one for all jffs2 and also the SIM has two banks instead of one even if they're next to each other... # -------------------------------------------- # 03/09/10 zecke@org.rmk.(none) 1.1239.2.2 # [ARM PATCH] 1654/1: Simpad PCMCIA resubmit # # Patch from Holger Freyther # # This fixes initialization of PCMCIA for the SIMpad # # # # unsigned long now user for the flag # -------------------------------------------- # 03/09/10 zecke@flint.arm.linux.org.uk 1.1239.2.3 # [ARM PATCH] 1656/1: Simpad board update to make it work # # Patch from Holger Freyther # # Make it work ;) # -------------------------------------------- # 03/09/10 joe@perches.com 1.1277 # [PATCH] Fix SEQ_START_TOKEN typo # # My fault. Fix for broken aarp.c which got an extra closing parenthesis. # -------------------------------------------- # 03/09/10 armin@melware.de 1.1278 # [PATCH] Eicon ISDN driver: remove old devfs_handle # # devfs_handle is not used any more. # -------------------------------------------- # 03/09/11 rmk@flint.arm.linux.org.uk 1.1239.2.4 # [ARM] Update SA1111 # # Combine the two initialisation functions, allow SA1111 to be built # as a module, and remove a redundant SA1111 function prototype. # -------------------------------------------- # 03/09/10 torvalds@home.osdl.org 1.1279 # Merge bk://bk.arm.linux.org.uk/linux-2.6-pcmcia # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/09/10 torvalds@home.osdl.org 1.1280 # Merge bk://bk.arm.linux.org.uk/linux-2.6-rmk # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/09/10 Andries.Brouwer@cwi.nl 1.1281 # [PATCH] another keyboard problem solved # # A colleague reported that the keyboard of his brandnew laptop # is dead under 2.6 while 2.4 works. # # Now I once wrote # # In order to avoid interference between scancode sequences # or mouse packets and the reponses given to commands, # the keyboard or mouse should always be disabled before # giving a command that requires a response, and probably # enabled afterwards. Some keyboards or mice do the disable # automatically in this situation, but still require an # explicit enable afterwards. # # (http://www.win.tue.nl/~aeb/linux/kbd/scancodes-9.html) # # This is what happens on this laptop. The routine atkbd_probe() # probes for a keyboard, and after detecting it, enables it. # But immediately afterwards the routine atkbd_set_3() reads # the current scancode set and sets the desired set, and as a # side effect of these commands, the keyboard gets disabled again. # # Thus, the keyboard enable must be moved after all command sending # has been done. # # Now that I patch this area anyway: we are almost always in # scancode set 2 but send the ATKBD_CMD_SETALL_MB command # that only works in scancode set 3. At best this is useless. # At worst it confuses the keyboard. So, I put this command # in a separate routine and call that only when we really # are in scancode set 3. # -------------------------------------------- # 03/09/11 viro@parcelfarce.linux.theplanet.co.uk 1.1282 # [PATCH] ps2esdi broken # # The PS/2 ESDI driver has some problems: a couple of typos on the modular # side and misuse of module_init(): # -------------------------------------------- # 03/09/11 piggin@cyberone.com.au 1.1283 # [PATCH] Badness in as_completed_request warning # # Thish fixes Suparna's fsx and aio-stress and Dave Olien's concurrent # mke2fs problems. # # It moves the hash adding into as_add_request. This fixes a small bug # where a request could be added to the merge hash after being put on the # dispatch list. # # It also moves responsibility for handling rbtree aliases (requests with # the same start sector) out of as_add_arq_rb and into its caller. This # cleans up a layering problem which was causing the state machine to go # silly. Now instead of forcing the alias out onto the dispatch list, we # chain the new request behind it, and they get sorted out at dispatch # time. # -------------------------------------------- # 03/09/11 amir.noam@intel.com 1.1284 # [bonding 2.6] fix 802.3ad long fail over with high UDP Tx stress # -------------------------------------------- # 03/09/11 amir.noam@intel.com 1.1285 # [bonding 2.6] fix load balance problem with high UDP Tx stress # -------------------------------------------- # 03/09/11 amir.noam@intel.com 1.1286 # [bonding 2.6] fix ARP monitoring bug # -------------------------------------------- # 03/09/11 amir.noam@intel.com 1.1287 # [bonding 2.6] fix kernel panic when optional feature used # -------------------------------------------- # 03/09/11 amir.noam@intel.com 1.1288 # [bonding 2.6] fix change active command # -------------------------------------------- # 03/09/11 amir.noam@intel.com 1.1289 # [bonding 2.6] fix OOPS in bonding driver, when removing primary # -------------------------------------------- # 03/09/11 amir.noam@intel.com 1.1290 # [bonding 2.6] embed stats struct inside bonding private struct # -------------------------------------------- # 03/09/11 amir.noam@intel.com 1.1291 # [bonding 2.6] fix error handling in init code # -------------------------------------------- # 03/09/11 amir.noam@intel.com 1.1292 # [bonding 2.6] make each bond device use its own /proc entry # -------------------------------------------- # 03/09/11 amir.noam@intel.com 1.1293 # [bonding 2.6] misc fixes: missing include, typos, comments # -------------------------------------------- # 03/09/11 greg@kroah.com 1.1283.1.1 # Merge kroah.com:/home/linux/BK/bleed-2.5 # into kroah.com:/home/linux/BK/pci-2.5 # -------------------------------------------- # 03/09/11 scott.feldman@intel.com 1.1294 # [e1000] new 82541/5/6/7 hardware support # # * Added 82545 (rev3), 82546 (rev3), and 82541/7 (rev2) support # - new device IDs # - internal SERDES support for 82545/6 (rev3) # - don't apply MMRBC workaround for 82545/6 (rev3) # - don't use IO mapping for reset for 82545/6 (rev3) # -------------------------------------------- # 03/09/11 scott.feldman@intel.com 1.1295 # [e1000] 82544 PCI-X hang fix + TSO updates # # * Bug fix: 82544 hang with PCI-X: if outgoing Tx buffers terminate # within evenly-aligned dwords, and the device is sharing the bus # segment with another PCI-X device, 82544 can hang the bus on a # split-completion transaction. Fix is to split buffer into two # buffers with the first one not terminating within evenly-aligned # dword address, and the second one being 4-bytes, which goes as a # non-split-conpletion PCI-X transaction. # * 8254x controllers that support TSO do an internal calculation to # make sure there is enough FIFO space to handle the overhead # of each TSO segment before DMA'ing TSO data from host memory. The # internal calculation is dependent on the mss of the TSO (defines # the number of segments), but the reserved space is a constant, so # we need to adjust the maximum size of each buffer queued to the # hardware to hold the equation and not overrun the FIFO. This is # per TSO because the mss can change from one send to the next. # -------------------------------------------- # 03/09/11 scott.feldman@intel.com 1.1296 # [e1000] Turn off ASF support on Fiber nics # # * Turn off ASF support on fiber nics. Wasn't tested and isn't # known to work, so disable before someone hurts themselves. # -------------------------------------------- # 03/09/11 scott.feldman@intel.com 1.1297 # [e1000] read correct bit from EEPROM for getting WoL settings # # * Bug fix: read the correct bit from the EEPROM that controls the # initial setting for WoL after a reset. # -------------------------------------------- # 03/09/11 scott.feldman@intel.com 1.1298 # [e1000] add ethtool flow control support # # * Add ethtool flow control support # -------------------------------------------- # 03/09/11 scott.feldman@intel.com 1.1299 # [e1000] make function our of setting media type # # * Consolidate code and make function out of setting media type. # -------------------------------------------- # 03/09/11 scott.feldman@intel.com 1.1300 # [e1000] cleanup error return codes # # * clean up error return code propagation and eliminate redundant # DEBUGOUT statements. # -------------------------------------------- # 03/09/11 scott.feldman@intel.com 1.1301 # [e1000] move static to table from .h to .c # # * Move static table from hw.h to hw.c to avoid creating a copy # of table everytime hw.h is included.in .c. # -------------------------------------------- # 03/09/11 scott.feldman@intel.com 1.1302 # [e1000] Add PHY master/slave #define override # # * Add PHY master/slave #define override to address link issues # with 82541/7 (rev2) against some low-end switches. Forcing # master will improve the time-to-link against these switches. # -------------------------------------------- # 03/09/11 scott.feldman@intel.com 1.1303 # [e1000] misc whitespace cleanup, changelog # # * misc whitespace cleanup, changelog # -------------------------------------------- # 03/09/11 rddunlap@osdl.org 1.1304 # [PATCH] tr/olympic probe: remove #warning, improve error handling # # This patch to 2.6.0-test5 removes the #warning in tokenring/olympic.c # and improves error handling in the probe function. # -------------------------------------------- # 03/09/11 felipewd@terra.com.br 1.1305 # [PATCH] slip.c: current state cleanup # -------------------------------------------- # 03/09/11 shemminger@osdl.org 1.1306 # [PATCH] fix build of cosa # # The cosa driver definition of ioctl's either conflicts or was not picked # up in the last round of _IOR redefinition (on 2.6.0-test5). # # The following makes it build, have no idea if it still works # on real hardware. # -------------------------------------------- # 03/09/11 shemminger@osdl.org 1.1307 # [PATCH] (1/4) sdla - move out of Space.c # # Patch against 2.60-test5 to move sdla driver out of Space.c for initialization # in non-module case. Since this driver doesn't come up until the device has # been configured with an ioctl (set_config); there is no way it can have # startup order problems. # -------------------------------------------- # 03/09/11 shemminger@osdl.org 1.1308 # [PATCH] (2/4) get rid of register_frad # # The sdla and dlci drivers have a callback interface which only stores a name # in a table, but doesn't do anything useful. Looks like an interface which has # lost it's usefulness and can be safely removed. # # Tested on 2.6.0-test5 by exercising the higher layer (dlci) without real hardware. # -------------------------------------------- # 03/09/11 shemminger@osdl.org 1.1309 # [PATCH] (3/4) dlci locking and registration changes # # Change the locking for the dlci device list and registration. # - use RTNL instead of a private lock (needed for net notifier in next patch). # - reorder the checks in the dlci_add to avoid complicated unwinds # - use dev->destructor to free # - hold RTNL around deassoc to protect callback from races # -------------------------------------------- # 03/09/11 shemminger@osdl.org 1.1310 # [PATCH] (4/4) dlci netdevice event handling # # Since dlci device is a pseudo device built on top of sdla, change it to # handle unregister events and delete itself. # -------------------------------------------- # 03/09/11 shemminger@osdl.org 1.1311 # [PATCH] (5/4) dlci netdevice event handling # # One more patch, found this in testing # -- need to delete device from list when unregistered # because of callback. # -------------------------------------------- # 03/09/11 romieu@fr.zoreil.com 1.1312 # [PATCH] (1/4) sdla - move out of Space.c # # Apply on top of 2.6.0-test5-bk1 + Stephen sdla patches. Compiles fine. # # # free_netdev() patrol. # # # drivers/net/wan/sdla.c | 2 +- # 1 files changed, 1 insertion(+), 1 deletion(-) # -------------------------------------------- # 03/09/11 Matt_Domsch@Dell.com 1.1283.1.2 # [PATCH] PCI: make new_id rely on CONFIG_HOTPLUG # # > > These either need to be marked __devinit and make "new_id" dependant on # > > CONFIG_HOTPLUG # # Patch below moves all the new_id code under CONFIG_HOTPLUG. Tested # with both CONFIG_HOTPLUG enabled and disabled. No significant code # changes, merely code moving, and in 2 cases, stub functions added. # -------------------------------------------- # 03/09/11 greg@kroah.com 1.1283.1.3 # [PATCH] PCI: remove compiler warning from previous new_id patch # # Also change the #define functions into inline functions to help # catch any future paramater mis-matches. # # And clean up a few minor style issue... # -------------------------------------------- # 03/09/11 greg@kroah.com 1.1283.1.4 # PCI: fix up some pci drivers that had marked their probe functions with __init # # This also required some other functions and variables to be marked as # __devinit # -------------------------------------------- # 03/09/11 torvalds@home.osdl.org 1.1313 # Merge dhcp-2:v2.5/linux into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/09/11 yoshfuji@linux-ipv6.org 1.1283.2.1 # [NET]: Various /proc/net/* files may drop some data. # -------------------------------------------- # 03/09/11 yoshfuji@linux-ipv6.org 1.1283.2.2 # [NET]: /proc/net/if_inet6 may drop some data. # -------------------------------------------- # 03/09/11 yoshfuji@linux-ipv6.org 1.1283.2.3 # [NET]: Clean up /proc/net/{anycast6/igmp6}. # -------------------------------------------- # 03/09/11 erlend-a@us.his.no 1.1283.2.4 # [CRYPTO]: Add alg. type to /proc/crypto output. # -------------------------------------------- # 03/09/11 laforge@netfilter.org 1.1283.2.5 # [NETFILTER]: Clear nf_debug in ipsec tunnel case. # -------------------------------------------- # 03/09/11 chas@cmf.nrl.navy.mil 1.1283.2.6 # [ATM]: Remove unnecessary GFP_ATOMIC allocation (from levon@movementarian.org) # -------------------------------------------- # 03/09/11 chas@cmf.nrl.navy.mil 1.1283.2.7 # [ATM]: Fix build failure with ATM_BR2684_IPFILTER enabled. # -------------------------------------------- # 03/09/11 hirofumi@mail.parknet.co.jp 1.1283.2.8 # [NETFILTER]: Fix typoe in ip_nat_tftp.c # -------------------------------------------- # 03/09/11 shemminger@osdl.org 1.1283.2.9 # [NET]: Remove some unnecessary proc_fs.h includes # -------------------------------------------- # 03/09/11 shemminger@osdl.org 1.1283.2.10 # [NET]: Convert packet scheduler API to seq_file. # -------------------------------------------- # 03/09/11 felipewd@terra.com.br 1.1283.2.11 # [NET]: Kill unneded version.h in net/sched. # -------------------------------------------- # 03/09/11 q@kampsax.dtu.dk 1.1283.2.12 # [IPV4]: Fix wrong IP address in icmp.c error message. # -------------------------------------------- # 03/09/11 herbert@gondor.apana.org.au 1.1283.2.13 # [XFRM]: Fix ALLOC_SPI for IPCOMP. # -------------------------------------------- # 03/09/11 akpm@osdl.org 1.1283.2.14 # [NET]: Remove spurious TASK_RUNNING setting after schedule_timeout(). # -------------------------------------------- # 03/09/11 yoshfuji@linux-ipv6.org 1.1283.2.15 # [NET]: Use proc_net_fops_create() and proc_net_remove() in net/core. # -------------------------------------------- # 03/09/11 yoshfuji@linux-ipv6.org 1.1283.2.16 # [NET]: Use proc_net_fops_create() and proc_net_remove() in net/ipv4. # -------------------------------------------- # 03/09/11 yoshfuji@linux-ipv6.org 1.1283.2.17 # [NET]: Use proc_net_fops_create() and proc_net_remove() in net/ipv6. # -------------------------------------------- # 03/09/11 shemminger@osdl.org 1.1283.2.18 # [BRIDGE]: Clear hw checksum flags when bridging. # -------------------------------------------- # 03/09/11 jfbeam@bluetronic.net 1.1283.3.1 # [SPARC64]: Fix VT/VT_CONSOLE Kconfig for headless operation. # -------------------------------------------- # 03/09/11 char@cmf.nrl.navy.mil 1.1283.2.19 # [ATM]: seq_file for /proc/net/atm (devices) [1/8] (from romieu@fr.zoreil.com) # # seq_file conversion for proc/atm/devices: # - code inspired from seq_file use in net/core/dev.c; # - atm_dev_lock taken/released in atm_dev_seq_{start/stop}; # - add a helper CREATE_SEQ_ENTRY() similar to CREATE_ENTRY() (both are removed # once conversion is done). # - atm_dev_seq_{start/stop/next} done in net/atm/resource.[ch] to ease # future handling of atm_devs and locking structure (per Chas suggestion) # -------------------------------------------- # 03/09/11 char@cmf.nrl.navy.mil 1.1283.2.20 # [ATM]: seq_file for /proc/net/atm (vc utils) [2/8] (from romieu@fr.zoreil.com) # # Helpers for seq_file conversion of proc/atm/{pvc/svc/vc}: # - struct vcc_state keeps # 1) the struct sock from which the current struct atm_vcc is deduced # 2) the family to which must belong the vcc (PF_ATM{SVC/PVC/any}) # 3) the availability of clip module # - vcc_seq{start/stop} are responsible for vcc_sklist locking # - __vcc_seq_open and vcc_seq_release take care of get/put for the clip module. # # Chas's suggestions applied since last version: # - atm_vc_xxx renamed to vcc_xxx # - atm_vc_common_seq_open renamed __vcc_seq_open (future name clashes # avoidance) # -------------------------------------------- # 03/09/11 char@cmf.nrl.navy.mil 1.1283.2.21 # [ATM]: seq_file for /proc/net/atm (pvc) [3/8] (from romieu@fr.zoreil.com) # # seq_file support for /proc/net/atm/pvc: # - pvc_info(): seq_printf/seq_putc replaces sprintf; # - atm_pvc_info() removal; # - the vc helpers (vcc__seq_xxx) do the remaining work. # # Chas's suggestions applied since last version: # - atm_pvc_xxx renamed to pvc_xxx # - atm_seq_pvc_fops renamed to pvc_seq_fops # -------------------------------------------- # 03/09/11 chas@cmf.nrl.navy.mil 1.1283.2.22 # [ATM]: seq_file for /proc/net/atm (svc) [4/8] (from romieu@fr.zoreil.com) # # seq_file support for /proc/net/atm/svc: # # Exactly same comments as pvc. Just s/p/s/ # -------------------------------------------- # 03/09/11 chas@cmf.nrl.navy.mil 1.1283.2.23 # [ATM]: seq_file for /proc/net/atm (vc) [5/8] (from romieu@fr.zoreil.com) # # seq_file support for /proc/net/atm/vc: # # Same comments as for pvc and svc. # # Extra Chas's suggestion applied since last version: # - atm_vc_xxx renamed to vcc_xxx. # -------------------------------------------- # 03/09/11 chas@cmf.nrl.navy.mil 1.1283.2.24 # [ATM]: seq_file for /proc/net/atm (arp) [6/8] (from romieu@fr.zoreil.com) # # seq_file support for /proc/net/atm/arp: # - svc_addr/atmarp_info(): seq_printf/seq_putc replace sprintf and friends; # - arp_getidx/arp_vcc_walk() take care of the usual seq_file cursor # positionning: they both return NULL until the cursor has reached its # position. struct atm_arp_state is updated accordingly; # - arp_seq_{stop/start} are responsible for clip_tbl_hook (un)locking; # - module refcounting is done in arp_seq_open()/arp_seq_release(); # - atm_lec_info() is removed. # # Chas's suggestions applied since last version: # - atm_arp_xxx renamed to arp_xxx; # - atm_seq_arp_fops renamed to arp_seq_fops. # # Chas didn't ask for it but I renamed arp_vc_walk to arp_vcc_walk. # -------------------------------------------- # 03/09/11 chas@cmf.nrl.navy.mil 1.1283.2.25 # [ATM]: seq_file conversion of /proc/net/atm [7/8] # # seq_file support for /proc/net/atm/lec: # - lec_info(): seq_printf/seq_putc replaces sprintf; # - traversal of the lec structure needs to walk: # -> the lec interfaces # -> the tables of arp tables(lec_arp_tables); # -> the arp tables themselves # -> the misc tables (lec_arp_empty_ones/lec_no_forward/mcast_fwds) # # Sum up of the call tree: # atm_lec_seq_start()/atm_lec_seq_next() # -> atm_lec_get_idx() # -> atm_lec_itf_walk() (responsible for dev_lec/dev_put handling) # -> atm_lec_priv_walk() (responsible for lec_priv locking) # -> atm_lec_arp_walk() # -> atm_lec_tbl_walk() # -> atm_lec_misc_walk() # -> atm_lec_tbl_walk() # # Each of the dedicated functions follows the same convention: return NULL # as long as the seq_file cursor hasn't been digested (i.e. until < 0). # Locking is only done when an entry (i.e. a lec_arp_table) is referenced. # atm_lec_seq_stop()/atm_lec_itf_walk()/atm_lec_priv_walk() are responsible # for getting this point right. # - module refcounting is done in atm_lec_seq_open()/atm_lec_seq_release(); # - atm_lec_info() is removed. # # Chas's suggestions applied since last version: # - atm_seq_lec_fops renamed to lec_seq_fops; # - change in state handling: it wasn't correctly set to its reset value # after a complete interface walk; # - lec_arp_get_status_string() bugfix. # -------------------------------------------- # 03/09/11 chas@cmf.nrl.navy.mil 1.1283.2.26 # [ATM]: seq_file conversion of /proc/net/atm [8/8] (from romieu@fr.zoreil.com) # # - introduction of the struct array 'atm_proc_ents': # - removal of code duplication in atm_proc_cleanup(); # - removal of code duplication in atm_proc_init(); # - removal of the macros CREATE_SEQ_ENTRY() and CREATE_ENTRY(); # - /proc/net/atm/vcc returns to /proc/net/atm/vc; # - credits at the top of the file; # - replaced proc_dev_atm_operations by proc_atm_dev_ops; # - atm_proc_dev_register: removal of tasteless "fail0/fail1" labels. # -------------------------------------------- # 03/09/11 chas@cmf.nrl.navy.mil 1.1283.2.27 # [ATM]: exporting llc_oui[] isn't worth it (from mitch@sfgoth.com) # -------------------------------------------- # 03/09/11 rob@osinvestor.com 1.1283.3.2 # [SPARC32]: Non-controversial gcc-3.3 build fixes. # -------------------------------------------- # 03/09/11 davej@redhat.com 1.1283.2.28 # [IPV6]: Fix non-CONFIG_PROC_FS build. # -------------------------------------------- # 03/09/11 wesolows@foobazco.org 1.1283.3.3 # [SPARC32]: Ignore btfixups in .text.exit # -------------------------------------------- # 03/09/11 dwmw2@infradead.org 1.1283.2.29 # [BLUETOOTH]: Fix bug in set_sk_owner() changes. # -------------------------------------------- # 03/09/11 mroos@linux.ee 1.1283.3.4 # [SPARC64]: BUG on positive addresses in vga.h # -------------------------------------------- # 03/09/11 rusty@rustcorp.com.au 1.1283.2.30 # [NETFILTER]: MASQUERADE target for mostly-static IP addresses. # # Herve Eychenne noted that many ADSL connections get the same # address when the interface comes back up, so some users use SNAT # instead of masquerade. The answer is that MASQUERADE should only # drop connections when the interface comes up, and then only if the # interface address has actually changed. # -------------------------------------------- # 03/09/11 rusty@rustcorp.com.au 1.1283.2.31 # [NETFILTER]: REJECT nonlinear fixes after sync with 2.4 # # Harald synced up ipt_REJECT.c from 2.4 route fixes, but it had # changed a fair bit because of the nonlinear fixes. This repairs it. # # 1) Copying of tcp header onto stack. # 2) ...which also checks length requirement. # 3) Skip checksum check: requires linear packet. # -------------------------------------------- # 03/09/11 davem@kernel.bkbits.net 1.1314 # Merge davem@nuts.ninka.net:/disk1/davem/BK/net-2.5 # into kernel.bkbits.net:/home/davem/net-2.5 # -------------------------------------------- # 03/09/11 davem@nuts.ninka.net 1.1283.3.5 # [SPARC64]: Update defconfig. # -------------------------------------------- # 03/09/11 davem@kernel.bkbits.net 1.1313.1.1 # Merge davem@nuts.ninka.net:/disk1/davem/BK/sparc-2.5 # into kernel.bkbits.net:/home/davem/sparc-2.5 # -------------------------------------------- # 03/09/11 torvalds@home.osdl.org 1.1315 # Merge bk://kernel.bkbits.net/davem/sparc-2.5 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # diff -Nru a/Documentation/00-INDEX b/Documentation/00-INDEX --- a/Documentation/00-INDEX Thu Sep 11 23:03:11 2003 +++ b/Documentation/00-INDEX Thu Sep 11 23:03:11 2003 @@ -116,8 +116,6 @@ - listing of various WWW + books that document kernel internals. kernel-parameters.txt - summary listing of command line / boot prompt args for the kernel. -kmod.txt - - info on the kernel module loader/unloader (kerneld replacement). ldm.txt - a brief description of LDM (Windows Dynamic Disks). locks.txt @@ -144,8 +142,6 @@ - script to make /dev entries for SMART controllers (see cciss.txt) mkdev.ida - script to make /dev entries for Intelligent Disk Array Controllers. -modules.txt - - short guide on how to make kernel parts into loadable modules moxa-smartio - info on installing/using Moxa multiport serial driver. mtrr.txt diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt --- a/Documentation/kernel-parameters.txt Thu Sep 11 23:03:14 2003 +++ b/Documentation/kernel-parameters.txt Thu Sep 11 23:03:14 2003 @@ -393,7 +393,7 @@ See Documentation/ide.txt. idle= [HW] - Format: poll + Format: idle=poll or idle=halt in2000= [HW,SCSI] See header of drivers/scsi/in2000.c. diff -Nru a/Documentation/modules.txt b/Documentation/modules.txt --- a/Documentation/modules.txt Thu Sep 11 23:03:11 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,264 +0,0 @@ -This file describes the strategy for dynamically loadable modules -in the Linux kernel. This is not a technical description on -the internals of module, but mostly a sample of how to compile -and use modules. - -Note: You should ensure that the module-init-tools-X.Y.Z.tar.gz you -are using is the most up to date one for this kernel. Some older -modules packages aren't aware of some of the newer modular features -that the kernel now supports. The current required version is listed -in the file linux/Documentation/Changes. - -In the beginning... -------------------- - -Anyway, your first step is to compile the kernel, as explained in the -file linux/README. It generally goes like: - - make *config <= usually menuconfig or xconfig - make clean - make zImage or make zlilo - -In "make config", you select what you want to include in the "resident" -kernel and what features you want to have available as loadable modules. -You will generally select the minimal resident set that is needed to boot: - - The filesystem of your root partition - A scsi driver, but see below for a list of SCSI modules! - Normal hard drive support - Net support (CONFIG_NET) - TCP/IP support (CONFIG_INET), but no drivers! - - plus those things that you just can't live without... - -The set of modules is constantly increasing, and you will be able to select -the option "m" in "make menuconfig" for those features that the current kernel -can offer as loadable modules. - -You also have a possibility to create modules that are less dependent on -the kernel version. This option can be selected during "make *config", by -enabling CONFIG_MODVERSIONS, and is most useful on "stable" kernel versions, -such as the kernels from the 2. series. -If you have modules that are based on sources that are not included in -the official kernel sources, you will certainly like this option... -See below how to compile modules outside the official kernel. - -Here is a sample of the available modules included in the kernel sources: - - Most filesystems: minix, msdos, umsdos, sysv, isofs, hpfs, - smbfs, nfs - - Mid-level SCSI support (required by top and low level scsi drivers). - Most low-level SCSI drivers: (i.e. aha1542, in2000) - All SCSI high-level drivers: disk, tape, cdrom, generic. - - Most Ethernet drivers: (too many to list, please see the file - ./Documentation/networking/net-modules.txt) - - Most CDROM drivers: - aztcd: Aztech,Orchid,Okano,Wearnes - cm206: Philips/LMS CM206 - gscd: Goldstar GCDR-420 - mcd, mcdx: Mitsumi LU005, FX001 - optcd: Optics Storage Dolphin 8000AT - sjcd: Sanyo CDR-H94A - sbpcd: Matsushita/Panasonic CR52x, CR56x, CD200, - Longshine LCS-7260, TEAC CD-55A - sonycd535: Sony CDU-531/535, CDU-510/515 - - And a lot of misc modules, such as: - lp: line printer - binfmt_elf: elf loader - binfmt_java: java loader - isp16: cdrom interface - serial: the serial (tty) interface - -When you have made the kernel, you create the modules by doing: - - make modules - -This will compile all modules. A module is identified by the -extension .ko, for kernel object. -Now, after you have created all your modules, you should also do: - - make modules_install - -This will copy all newly made modules into subdirectories under -"/lib/modules/kernel_release/", where "kernel_release" is something -like 2.5.54, or whatever the current kernel version is. -Note: Installing modules may require root privileges. - -As soon as you have rebooted the newly made kernel, you can install -and remove modules at will with the utilities: "insmod" and "rmmod". -After reading the man-page for insmod, you will also know how easy -it is to configure a module when you do "insmod" (hint: symbol=value). - -Installing modules in a non-standard location ---------------------------------------------- -When the modules needs to be installed under another directory -the INSTALL_MOD_PATH can be used to prefix "/lib/modules" as seen -in the following example: - -make INSTALL_MOD_PATH=/frodo modules_install - -This will install the modules in the directory /frodo/lib/modules. -/frodo can be a NFS mounted filesystem on another machine, allowing -out-of-the-box support for installation on remote machines. - - -Compiling modules outside the official kernel ---------------------------------------------- -Often modules are developed outside the official kernel. -To keep up with changes in the build system the most portable way -to compile a module outside the kernel is to use the following command-line: - -make -C path/to/kernel/src SUBDIRS=$PWD modules - -This requires that a makefile exits made in accordance to -Documentation/kbuild/makefiles.txt. - -Nifty features: ---------------- - -You also have access to two utilities: "modprobe" and "depmod", where -modprobe is a "wrapper" for (or extension to) "insmod". -These utilities use (and maintain) a set of files that describe all the -modules that are available for the current kernel in the /lib/modules -hierarchy as well as their interdependencies. - -Using the modprobe utility, you can load any module like this: - - /sbin/modprobe module - -without paying much attention to which kernel you are running, or what -other modules this module depends on. - -With the help of the modprobe configuration file: "/etc/modules.conf" -you can tune the behaviour of modprobe in many ways, including an -automatic setting of insmod options for each module. -And, yes, there _are_ man-pages for all this... - -To use modprobe successfully, you generally place the following -command in your /etc/rc.d/rc.S script. (Read more about this in the -"rc.hints" file in the module utilities package, -"module-init-tools-x.y.z.tar.gz".) - - /sbin/depmod -a - -This computes the dependencies between the different modules. -Then if you do, for example - - /sbin/modprobe umsdos - -you will automatically load _both_ the msdos and umsdos modules, -since umsdos runs piggyback on msdos. - - -Using modinfo: --------------- - -Sometimes you need to know what parameters are accepted by a -module or you've found a bug and want to contact the maintainer. -Then modinfo comes in very handy. - -Every module (normally) contains the author/maintainer, -a description and a list of parameters. - -For example "modinfo -a eepro100" will return: - - Maintainer: Andrey V. Savochkin - -and "modinfo -d eepro100" will return a description: - - Intel i82557/i82558 PCI EtherExpressPro driver - -and more important "modinfo -p eepro100" will return this list: - - debug int - options int array (min = 1, max = 8) - full_duplex int array (min = 1, max = 8) - congenb int - txfifo int - rxfifo int - txdmacount int - rxdmacount int - rx_copybreak int - max_interrupt_work int - multicast_filter_limit int - - -The "ultimate" utility: ------------------------ - -OK, you have read all of the above, and feel amply impressed... -Now, we tell you to forget all about how to install and remove -loadable modules... -With the kerneld daemon, all of these chores will be taken care of -automatically. Just answer "Y" to CONFIG_KERNELD in "make config", -and make sure that /sbin/kerneld is started as soon as possible -after boot and that "/sbin/depmod -a" has been executed for the -current kernel. (Read more about this in the module utilities package.) - -Whenever a program wants the kernel to use a feature that is only -available as a loadable module, and if the kernel hasn't got the -module installed yet, the kernel will ask the kerneld daemon to take -care of the situation and make the best of it. - -This is what happens: - - - The kernel notices that a feature is requested that is not - resident in the kernel. - - The kernel sends a message to kerneld, with a symbolic - description of the requested feature. - - The kerneld daemon asks e.g. modprobe to load a module that - fits this symbolic description. - - modprobe looks into its internal "alias" translation table - to see if there is a match. This table can be reconfigured - and expanded by having "alias" lines in "/etc/modules.conf". - - insmod is then asked to insert the module(s) that modprobe - has decided that the kernel needs. Every module will be - configured according to the "options" lines in "/etc/modules.conf". - - modprobe exits and kerneld tells the kernel that the request - succeeded (or failed...) - - The kernel uses the freshly installed feature just as if it - had been configured into the kernel as a "resident" part. - -The icing of the cake is that when an automatically installed module -has been unused for a period of time (usually 1 minute), the module -will be automatically removed from the kernel as well. - -This makes the kernel use the minimal amount of memory at any given time, -making it available for more productive use than as just a placeholder for -unused code. - -Actually, this is only a side-effect from the _real_ benefit of kerneld: -You only have to create a minimal kernel, that is more or less independent -of the actual hardware setup. The setup of the "virtual" kernel is -instead controlled by a configuration file as well as the actual usage -pattern of the current machine and its kernel. -This should be good news for maintainers of multiple machines as well as -for maintainers of distributions. - -To use kerneld with the least amount of "hassle", you need modprobe from -a release that can be considered "recent" w.r.t. your kernel, and also -a configuration file for modprobe ("/etc/modules.conf"). -Since modprobe already knows about most modules, the minimal configuration -file could look something like this: - - alias scsi_hostadapter aha1542 # or whatever SCSI adapter you have - alias eth0 3c509 # or whatever net adapter you have - # you might need an "options" line for some net adapters: - options 3c509 io=0x300 irq=10 - # you might also need an "options" line for some other module: - options cdu31a cdu31a_port=0x1f88 sony_pas_init=1 - -You could add these lines as well, but they are only "cosmetic": - - alias net-pf-3 off # no ax25 module available (yet) - alias net-pf-4 off # if you don't use the ipx module - alias net-pf-5 off # if you don't use the appletalk module - - -Written by: - Jacques Gelinas - Bjorn Ekwall diff -Nru a/Documentation/networking/ifenslave.c b/Documentation/networking/ifenslave.c --- a/Documentation/networking/ifenslave.c Thu Sep 11 23:03:11 2003 +++ b/Documentation/networking/ifenslave.c Thu Sep 11 23:03:11 2003 @@ -140,6 +140,7 @@ #include #include #include +#include #include #include #include diff -Nru a/arch/alpha/boot/misc.c b/arch/alpha/boot/misc.c --- a/arch/alpha/boot/misc.c Thu Sep 11 23:03:12 2003 +++ b/arch/alpha/boot/misc.c Thu Sep 11 23:03:12 2003 @@ -106,8 +106,8 @@ { void *p; - if (size <0) error("Malloc error\n"); - if (free_mem_ptr <= 0) error("Memory error\n"); + if (size <0) error("Malloc error"); + if (free_mem_ptr <= 0) error("Memory error"); free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ @@ -140,7 +140,7 @@ int fill_inbuf(void) { if (insize != 0) - error("ran out of input data\n"); + error("ran out of input data"); inbuf = input_data; insize = input_data_size; diff -Nru a/arch/arm/boot/compressed/head-sa1100.S b/arch/arm/boot/compressed/head-sa1100.S --- a/arch/arm/boot/compressed/head-sa1100.S Thu Sep 11 23:03:11 2003 +++ b/arch/arm/boot/compressed/head-sa1100.S Thu Sep 11 23:03:11 2003 @@ -34,6 +34,10 @@ @ REVISIT_PFS168: Temporary until firmware updated to use assigned machine number mov r7, #MACH_TYPE_PFS168 #endif +#ifdef CONFIG_SA1100_SIMPAD / + @ UNTIL we've something like an open bootldr + mov r7, #MACH_TYPE_SIMPAD @should be 87 +#endif #ifdef CONFIG_SA1100_VICTOR teq r7, #MACH_TYPE_VICTOR diff -Nru a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c --- a/arch/arm/boot/compressed/misc.c Thu Sep 11 23:03:13 2003 +++ b/arch/arm/boot/compressed/misc.c Thu Sep 11 23:03:13 2003 @@ -191,8 +191,8 @@ { void *p; - if (size <0) error("Malloc error\n"); - if (free_mem_ptr <= 0) error("Memory error\n"); + if (size <0) error("Malloc error"); + if (free_mem_ptr <= 0) error("Memory error"); free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ @@ -236,7 +236,7 @@ int fill_inbuf(void) { if (insize != 0) - error("ran out of input data\n"); + error("ran out of input data"); inbuf = input_data; insize = &input_data_end[0] - &input_data[0]; diff -Nru a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c --- a/arch/arm/common/sa1111.c Thu Sep 11 23:03:13 2003 +++ b/arch/arm/common/sa1111.c Thu Sep 11 23:03:13 2003 @@ -958,17 +958,6 @@ }; /* - * Register the SA1111 driver with LDM. - */ -static int sa1111_driver_init(void) -{ - driver_register(&sa1111_device_driver); - return 0; -} - -arch_initcall(sa1111_driver_init); - -/* * Get the parent device driver (us) structure * from a child function device */ @@ -1180,13 +1169,6 @@ .resume = sa1111_bus_resume, }; -static int sa1111_rab_bus_init(void) -{ - return bus_register(&sa1111_bus_type); -} - -postcore_initcall(sa1111_rab_bus_init); - int sa1111_driver_register(struct sa1111_driver *driver) { driver->drv.probe = sa1111_bus_probe; @@ -1199,6 +1181,26 @@ { driver_unregister(&driver->drv); } + +static int __init sa1111_init(void) +{ + int ret = bus_register(&sa1111_bus_type); + if (ret == 0) + driver_register(&sa1111_device_driver); + return ret; +} + +static void __exit sa1111_exit(void) +{ + driver_unregister(&sa1111_device_driver); + bus_unregister(&sa1111_bus_type); +} + +module_init(sa1111_init); +module_exit(sa1111_exit); + +MODULE_DESCRIPTION("Intel Corporation SA1111 core driver"); +MODULE_LICENSE("GPL"); EXPORT_SYMBOL(sa1111_check_dma_bug); EXPORT_SYMBOL(sa1111_select_audio_mode); diff -Nru a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c --- a/arch/arm/mach-sa1100/simpad.c Thu Sep 11 23:03:11 2003 +++ b/arch/arm/mach-sa1100/simpad.c Thu Sep 11 23:03:11 2003 @@ -9,24 +9,37 @@ #include #include #include +#include +#include #include #include +#include #include #include #include +#include +#include + #include +#include +#include #include "generic.h" long cs3_shadow; -long get_cs3_shadow() +long get_cs3_shadow(void) { return cs3_shadow; } +void set_cs3(long value) +{ + *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow = value; +} + void set_cs3_bit(int value) { cs3_shadow |= value; @@ -39,10 +52,15 @@ *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow; } +EXPORT_SYMBOL(set_cs3_bit); +EXPORT_SYMBOL(clear_cs3_bit); + static struct map_desc simpad_io_desc[] __initdata = { - /* virtual physical length type */ - { 0xf2800000, 0x4b800000, 0x00800000, MT_DEVICE }, /* MQ200 */ - { 0xf1000000, 0x18000000, 0x00100000, MT_DEVICE } /* Paules CS3, write only */ + /* virtual physical length type */ + /* MQ200 */ + { 0xf2800000, 0x4b800000, 0x00800000, MT_DEVICE }, + /* Paules CS3, write only */ + { 0xf1000000, 0x18000000, 0x00100000, MT_DEVICE }, }; @@ -50,32 +68,52 @@ { if (port->mapbase == (u_int)&Ser1UTCR0) { if (state) + { clear_cs3_bit(RS232_ON); - else + clear_cs3_bit(DECT_POWER_ON); + }else + { set_cs3_bit(RS232_ON); + set_cs3_bit(DECT_POWER_ON); + } } } static struct sa1100_port_fns simpad_port_fns __initdata = { - .pm = simpad_uart_pm, + .pm = simpad_uart_pm, }; static void __init simpad_map_io(void) { sa1100_map_io(); + iotable_init(simpad_io_desc, ARRAY_SIZE(simpad_io_desc)); - PSPR = 0xc0008000; - GPDR &= ~GPIO_GPIO0; - cs3_shadow = (EN1 | EN0 | LED2_ON | DISPLAY_ON | RS232_ON | - ENABLE_5V | RESET_SIMCARD); - *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow; + set_cs3_bit (EN1 | EN0 | LED2_ON | DISPLAY_ON | RS232_ON | + ENABLE_5V | RESET_SIMCARD | DECT_POWER_ON); + + + sa1100_register_uart_fns(&simpad_port_fns); + sa1100_register_uart(0, 3); /* serial interface */ + sa1100_register_uart(1, 1); /* DECT */ + + // Reassign UART 1 pins + GAFR |= GPIO_UART_TXD | GPIO_UART_RXD; + GPDR |= GPIO_UART_TXD | GPIO_LDD13 | GPIO_LDD15; + GPDR &= ~GPIO_UART_RXD; + PPAR |= PPAR_UPR; + + /* + * Set up registers for sleep mode. + */ + + + PWER = PWER_GPIO0| PWER_RTC; + PGSR = 0x818; + PCFR = 0; + PSDR = 0; - //It is only possible to register 3 UART in serial_sa1100.c - sa1100_register_uart(0, 3); - sa1100_register_uart(1, 1); - set_irq_type(IRQ_GPIO_UCB1300_IRQ, IRQT_RISING); } #ifdef CONFIG_PROC_FS @@ -105,7 +143,7 @@ char *p = page; int len, i; - p += sprintf(p, "Chipselect3 : %x\n", cs3_shadow); + p += sprintf(p, "Chipselect3 : %x\n", (uint)cs3_shadow); for (i = 0; i <= 15; i++) { if(cs3_shadow & (1<read_proc = proc_cs3_read; + proc_cs3->write_proc = (void*)proc_cs3_write; + } +#endif + + + return 0; } arch_initcall(cs3_init); -#endif // CONFIG_PROC_FS +static void simpad_power_off(void) +{ + local_irq_disable(); // was cli + set_cs3(0x800); /* only SD_MEDIAQ */ + + /* disable internal oscillator, float CS lines */ + PCFR = (PCFR_OPDE | PCFR_FP | PCFR_FS); + /* enable wake-up on GPIO0 (Assabet...) */ + PWER = GFER = GRER = 1; + /* + * set scratchpad to zero, just in case it is used as a + * restart address by the bootloader. + */ + PSPR = 0; + PGSR = 0; + /* enter sleep mode */ + PMCR = PMCR_SF; + while(1); + + local_irq_enable(); /* we won't ever call it */ + + +} + +static int __init simpad_init(void) +{ + set_power_off_handler( simpad_power_off ); + return 0; +} + +arch_initcall(simpad_init); + MACHINE_START(SIMPAD, "Simpad") MAINTAINER("Juergen Messerer") BOOT_MEM(0xc0000000, 0x80000000, 0xf8000000) + BOOT_PARAMS(0xc0000100) MAPIO(simpad_map_io) INITIRQ(sa1100_init_irq) MACHINE_END diff -Nru a/arch/arm26/boot/compressed/misc.c b/arch/arm26/boot/compressed/misc.c --- a/arch/arm26/boot/compressed/misc.c Thu Sep 11 23:03:11 2003 +++ b/arch/arm26/boot/compressed/misc.c Thu Sep 11 23:03:11 2003 @@ -191,8 +191,8 @@ { void *p; - if (size <0) error("Malloc error\n"); - if (free_mem_ptr <= 0) error("Memory error\n"); + if (size <0) error("Malloc error"); + if (free_mem_ptr <= 0) error("Memory error"); free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ @@ -236,7 +236,7 @@ int fill_inbuf(void) { if (insize != 0) - error("ran out of input data\n"); + error("ran out of input data"); inbuf = input_data; insize = &input_data_end[0] - &input_data[0]; diff -Nru a/arch/cris/arch-v10/boot/compressed/misc.c b/arch/cris/arch-v10/boot/compressed/misc.c --- a/arch/cris/arch-v10/boot/compressed/misc.c Thu Sep 11 23:03:13 2003 +++ b/arch/cris/arch-v10/boot/compressed/misc.c Thu Sep 11 23:03:13 2003 @@ -115,7 +115,7 @@ { void *p; - if (size <0) error("Malloc error\n"); + if (size <0) error("Malloc error"); free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig --- a/arch/i386/Kconfig Thu Sep 11 23:03:11 2003 +++ b/arch/i386/Kconfig Thu Sep 11 23:03:11 2003 @@ -454,6 +454,7 @@ config NR_CPUS int "Maximum number of CPUs (2-255)" depends on SMP + default "32" if X86_NUMAQ || X86_SUMMIT || X86_BIGSMP || X86_ES7000 default "8" help This allows you to specify the maximum number of CPUs which this diff -Nru a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c --- a/arch/i386/boot/compressed/misc.c Thu Sep 11 23:03:13 2003 +++ b/arch/i386/boot/compressed/misc.c Thu Sep 11 23:03:13 2003 @@ -132,8 +132,8 @@ { void *p; - if (size <0) error("Malloc error\n"); - if (free_mem_ptr <= 0) error("Memory error\n"); + if (size <0) error("Malloc error"); + if (free_mem_ptr <= 0) error("Memory error"); free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ @@ -141,7 +141,7 @@ free_mem_ptr += size; if (free_mem_ptr >= free_mem_end_ptr) - error("\nOut of memory\n"); + error("Out of memory"); return p; } @@ -232,7 +232,7 @@ static int fill_inbuf(void) { if (insize != 0) { - error("ran out of input data\n"); + error("ran out of input data"); } inbuf = input_data; @@ -306,9 +306,9 @@ static void setup_normal_output_buffer(void) { #ifdef STANDARD_MEMORY_BIOS_CALL - if (EXT_MEM_K < 1024) error("Less than 2MB of memory.\n"); + if (EXT_MEM_K < 1024) error("Less than 2MB of memory"); #else - if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory.\n"); + if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory"); #endif output_data = (char *)0x100000; /* Points to 1M */ free_mem_end_ptr = (long)real_mode; @@ -323,9 +323,9 @@ { high_buffer_start = (uch *)(((ulg)&end) + HEAP_SIZE); #ifdef STANDARD_MEMORY_BIOS_CALL - if (EXT_MEM_K < (3*1024)) error("Less than 4MB of memory.\n"); + if (EXT_MEM_K < (3*1024)) error("Less than 4MB of memory"); #else - if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory.\n"); + if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory"); #endif mv->low_buffer_start = output_data = (char *)LOW_BUFFER_START; low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX diff -Nru a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S --- a/arch/i386/boot/setup.S Thu Sep 11 23:03:12 2003 +++ b/arch/i386/boot/setup.S Thu Sep 11 23:03:12 2003 @@ -506,6 +506,17 @@ movw $0xAA, (0x1ff) # device present no_psmouse: +#if defined(CONFIG_X86_SPEEDSTEP_SMI) || defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE) + movl $0x0000E980, %eax # IST Support + movl $0x47534943, %edx # Request value + int $0x15 + + movl %eax, (96) + movl %ebx, (100) + movl %ecx, (104) + movl %edx, (108) +#endif + #if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) # Then check for an APM BIOS... # %ds points to the bootsector diff -Nru a/arch/i386/boot98/compressed/misc.c b/arch/i386/boot98/compressed/misc.c --- a/arch/i386/boot98/compressed/misc.c Thu Sep 11 23:03:11 2003 +++ b/arch/i386/boot98/compressed/misc.c Thu Sep 11 23:03:11 2003 @@ -132,8 +132,8 @@ { void *p; - if (size <0) error("Malloc error\n"); - if (free_mem_ptr <= 0) error("Memory error\n"); + if (size <0) error("Malloc error"); + if (free_mem_ptr <= 0) error("Memory error"); free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ @@ -141,7 +141,7 @@ free_mem_ptr += size; if (free_mem_ptr >= free_mem_end_ptr) - error("\nOut of memory\n"); + error("Out of memory"); return p; } @@ -232,7 +232,7 @@ static int fill_inbuf(void) { if (insize != 0) { - error("ran out of input data\n"); + error("ran out of input data"); } inbuf = input_data; @@ -306,9 +306,9 @@ static void setup_normal_output_buffer(void) { #ifdef STANDARD_MEMORY_BIOS_CALL - if (EXT_MEM_K < 1024) error("Less than 2MB of memory.\n"); + if (EXT_MEM_K < 1024) error("Less than 2MB of memory"); #else - if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory.\n"); + if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory"); #endif output_data = (char *)0x100000; /* Points to 1M */ free_mem_end_ptr = (long)real_mode; @@ -323,9 +323,9 @@ { high_buffer_start = (uch *)(((ulg)&end) + HEAP_SIZE); #ifdef STANDARD_MEMORY_BIOS_CALL - if (EXT_MEM_K < (3*1024)) error("Less than 4MB of memory.\n"); + if (EXT_MEM_K < (3*1024)) error("Less than 4MB of memory"); #else - if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory.\n"); + if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory"); #endif mv->low_buffer_start = output_data = (char *)LOW_BUFFER_START; low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX diff -Nru a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig --- a/arch/i386/kernel/cpu/cpufreq/Kconfig Thu Sep 11 23:03:11 2003 +++ b/arch/i386/kernel/cpu/cpufreq/Kconfig Thu Sep 11 23:03:11 2003 @@ -99,34 +99,46 @@ If in doubt, say N. +config X86_SPEEDSTEP_CENTRINO + tristate "Intel Enhanced SpeedStep" + depends on CPU_FREQ_TABLE + help + This adds the CPUFreq driver for Enhanced SpeedStep enabled + mobile CPUs. This means Intel Pentium M (Centrino) CPUs. + + For details, take a look at linux/Documentation/cpu-freq. + + If in doubt, say N. + config X86_SPEEDSTEP_ICH - tristate "Intel Speedstep" + tristate "Intel Speedstep on ICH-M chipsets (ioport interface)" depends on CPU_FREQ_TABLE help This adds the CPUFreq driver for certain mobile Intel Pentium III (Coppermine), all mobile Intel Pentium III-M (Tualatin) and all - mobile Intel Pentium 4 P4-Ms, with an Intel ICH2, ICH3, - or ICH4 southbridge. + mobile Intel Pentium 4 P4-M on systems which have an Intel ICH2, + ICH3 or ICH4 southbridge. For details, take a look at linux/Documentation/cpu-freq. If in doubt, say N. -config X86_SPEEDSTEP_CENTRINO - tristate "Intel Enhanced SpeedStep" - depends on CPU_FREQ_TABLE +config X86_SPEEDSTEP_SMI + tristate "Intel SpeedStep on 440BX/ZX/MX chipsets (SMI interface)" + depends on CPU_FREQ_TABLE && EXPERIMENTAL help - This adds the CPUFreq driver for Enhanced SpeedStep enabled - mobile CPUs. This means Intel Pentium M (Centrino) CPUs. - - For details, take a look at linux/Documentation/cpu-freq. - + This adds the CPUFreq driver for certain mobile Intel Pentium III + (Coppermine), all mobile Intel Pentium III-M (Tualatin) + on systems which have an Intel 440BX/ZX/MX southbridge. + + For details, take a look at linux/Documentation/cpu-freq. + If in doubt, say N. config X86_SPEEDSTEP_LIB - tristate - depends on X86_SPEEDSTEP_ICH - default X86_SPEEDSTEP_ICH + tristate + depends on (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI) + default (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI) config X86_P4_CLOCKMOD tristate "Intel Pentium 4 clock modulation" diff -Nru a/arch/i386/kernel/cpu/cpufreq/Makefile b/arch/i386/kernel/cpu/cpufreq/Makefile --- a/arch/i386/kernel/cpu/cpufreq/Makefile Thu Sep 11 23:03:12 2003 +++ b/arch/i386/kernel/cpu/cpufreq/Makefile Thu Sep 11 23:03:12 2003 @@ -9,6 +9,7 @@ obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o obj-$(CONFIG_X86_SPEEDSTEP_LIB) += speedstep-lib.o +obj-$(CONFIG_X86_SPEEDSTEP_SMI) += speedstep-smi.o ifdef CONFIG_X86_ACPI_CPUFREQ ifdef CONFIG_ACPI_DEBUG diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c Thu Sep 11 23:03:14 2003 @@ -0,0 +1,353 @@ +/* + * Intel SpeedStep SMI driver. + * + * (C) 2003 Hiroshi Miura + * + * Licensed under the terms of the GNU GPL License version 2. + * + */ + + +/********************************************************************* + * SPEEDSTEP - DEFINITIONS * + *********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "speedstep-lib.h" + +/* speedstep system management interface port/command. + * + * These parameters are got from IST-SMI BIOS call. + * If user gives it, these are used. + * + */ +static int smi_port = 0; +static int smi_cmd = 0; +static unsigned int smi_sig = 0; + + +/* + * There are only two frequency states for each processor. Values + * are in kHz for the time being. + */ +static struct cpufreq_frequency_table speedstep_freqs[] = { + {SPEEDSTEP_HIGH, 0}, + {SPEEDSTEP_LOW, 0}, + {0, CPUFREQ_TABLE_END}, +}; + +#define GET_SPEEDSTEP_OWNER 0 +#define GET_SPEEDSTEP_STATE 1 +#define SET_SPEEDSTEP_STATE 2 +#define GET_SPEEDSTEP_FREQS 4 + +/* DEBUG + * Define it if you want verbose debug output, e.g. for bug reporting + */ +#define SPEEDSTEP_DEBUG + +#ifdef SPEEDSTEP_DEBUG +#define dprintk(msg...) printk(msg) +#else +#define dprintk(msg...) do { } while(0) +#endif + +/** + * speedstep_smi_ownership + */ +static int speedstep_smi_ownership (void) +{ + u32 command, result, magic; + u32 function = GET_SPEEDSTEP_OWNER; + unsigned char magic_data[] = "Copyright (c) 1999 Intel Corporation"; + + command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); + magic = virt_to_phys(magic_data); + + __asm__ __volatile__( + "out %%al, (%%dx)\n" + : "=D" (result) + : "a" (command), "b" (function), "c" (0), "d" (smi_port), "D" (0), "S" (magic) + ); + + return result; +} +/** + * speedstep_smi_get_freqs - get SpeedStep preferred & current freq. + * + */ +static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high) +{ + u32 command, result, edi, high_mhz, low_mhz; + u32 state=0; + u32 function = GET_SPEEDSTEP_FREQS; + + command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); + + __asm__ __volatile__("movl $0, %%edi\n" + "out %%al, (%%dx)\n" + : "=a" (result), "=b" (high_mhz), "=c" (low_mhz), "=d" (state), "=D" (edi) + : "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0) + ); + *high = high_mhz * 1000; + *low = low_mhz * 1000; + + return result; +} +/** + * speedstep_get_state - set the SpeedStep state + * @state: processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) + * + */ +static int speedstep_get_state (void) +{ + u32 function=GET_SPEEDSTEP_STATE; + u32 result, state, edi, command; + + command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); + + __asm__ __volatile__("movl $0, %%edi\n" + "out %%al, (%%dx)\n" + : "=a" (result), "=b" (state), "=D" (edi) + : "a" (command), "b" (function), "c" (0), "d" (smi_port), "S" (0) + ); + + return state; +} + +/** + * speedstep_set_state - set the SpeedStep state + * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) + * + */ +static void speedstep_set_state (unsigned int state, unsigned int notify) +{ + unsigned int old_state, result, command, new_state; + unsigned long flags; + struct cpufreq_freqs freqs; + unsigned int function=SET_SPEEDSTEP_STATE; + + if (state > 0x1) + return; + + old_state = speedstep_get_state(); + freqs.old = speedstep_freqs[old_state].frequency; + freqs.new = speedstep_freqs[state].frequency; + freqs.cpu = 0; /* speedstep.c is UP only driver */ + + if (old_state == state) + return; + + if (notify) + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); + + /* Disable IRQs */ + local_irq_save(flags); + + command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff); + __asm__ __volatile__( + "movl $0, %%edi\n" + "out %%al, (%%dx)\n" + : "=b" (new_state), "=D" (result) + : "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0) + ); + + /* enable IRQs */ + local_irq_restore(flags); + + if (new_state == state) { + dprintk(KERN_INFO "cpufreq: change to %u MHz succeded\n", (freqs.new / 1000)); + } else { + printk(KERN_ERR "cpufreq: change failed\n"); + } + + if (notify) + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + + return; +} + + +/** + * speedstep_target - set a new CPUFreq policy + * @policy: new policy + * @target_freq: new freq + * @relation: + * + * Sets a new CPUFreq policy/freq. + */ +static int speedstep_target (struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + unsigned int newstate = 0; + + if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate)) + return -EINVAL; + + speedstep_set_state(newstate, 1); + + return 0; +} + + +/** + * speedstep_verify - verifies a new CPUFreq policy + * @freq: new policy + * + * Limit must be within speedstep_low_freq and speedstep_high_freq, with + * at least one border included. + */ +static int speedstep_verify (struct cpufreq_policy *policy) +{ + return cpufreq_frequency_table_verify(policy, &speedstep_freqs[0]); +} + + +static int speedstep_cpu_init(struct cpufreq_policy *policy) +{ + int result; + unsigned int speed,state; + + /* capability check */ + if (policy->cpu != 0) + return -ENODEV; + + result = speedstep_smi_ownership(); + + if (result) + dprintk(KERN_INFO "cpufreq: fails an aquiring ownership of a SMI interface.\n"); + + /* detect low and high frequency */ + result = speedstep_smi_get_freqs(&speedstep_freqs[SPEEDSTEP_LOW].frequency, + &speedstep_freqs[SPEEDSTEP_HIGH].frequency); + if (result) { + /* fall back to speedstep_lib.c dection mechanism: try both states out */ + unsigned int speedstep_processor = speedstep_detect_processor(); + + dprintk(KERN_INFO "speedstep-smi: could not detect low and high frequencies by SMI call.\n"); + if (!speedstep_processor) + return -ENODEV; + + result = speedstep_get_freqs(speedstep_processor, + &speedstep_freqs[SPEEDSTEP_LOW].frequency, + &speedstep_freqs[SPEEDSTEP_HIGH].frequency, + &speedstep_set_state); + + if (result) { + dprintk(KERN_INFO "speedstep-smi: could not detect two different speeds -- aborting.\n"); + return result; + } else + dprintk(KERN_INFO "speedstep-smi: workaround worked.\n"); + } + + /* get current speed setting */ + state = speedstep_get_state(); + speed = speedstep_freqs[state].frequency; + + dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n", + (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? "low" : "high", + (speed / 1000)); + + /* cpuinfo and default policy values */ + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + policy->cur = speed; + + return cpufreq_frequency_table_cpuinfo(policy, &speedstep_freqs[0]); +} + + +static int speedstep_resume(struct cpufreq_policy *policy) +{ + int result = speedstep_smi_ownership(); + + if (result) + dprintk(KERN_INFO "cpufreq: fails an aquiring ownership of a SMI interface.\n"); + + return result; +} + + +static struct cpufreq_driver speedstep_driver = { + .name = "speedstep-smi", + .verify = speedstep_verify, + .target = speedstep_target, + .init = speedstep_cpu_init, + .resume = speedstep_resume, +}; + +/** + * speedstep_init - initializes the SpeedStep CPUFreq driver + * + * Initializes the SpeedStep support. Returns -ENODEV on unsupported + * BIOS, -EINVAL on problems during initiatization, and zero on + * success. + */ +static int __init speedstep_init(void) +{ + + dprintk("speedstep-smi: signature:0%.8lx, command:0lx%.8lx, event:0x%.8lx, perf_level:0x%.8lx.\n", + ist_info.signature, ist_info.command, ist_info.event, ist_info.perf_level); + + + /* Error if no IST-SMI BIOS or no PARM + sig= 'ISGE' aka 'Intel Speedstep Gate E' */ + if ((ist_info.signature != 0x47534943) && ( + (smi_port == 0) || (smi_cmd == 0))) + return -ENODEV; + + if (smi_sig == 1) + smi_sig = 0x47534943; + else + smi_sig = ist_info.signature; + + /* setup smi_port from MODLULE_PARM or BIOS */ + if ((smi_port > 0xff) || (smi_port < 0)) { + return -EINVAL; + } else if (smi_port == 0) { + smi_port = ist_info.command & 0xff; + } + + if ((smi_cmd > 0xff) || (smi_cmd < 0)) { + return -EINVAL; + } else if (smi_cmd == 0) { + smi_cmd = (ist_info.command >> 16) & 0xff; + } + + return cpufreq_register_driver(&speedstep_driver); +} + + +/** + * speedstep_exit - unregisters SpeedStep support + * + * Unregisters SpeedStep support. + */ +static void __exit speedstep_exit(void) +{ + cpufreq_unregister_driver(&speedstep_driver); +} + +module_param(smi_port, int, 0444); +module_param(smi_cmd, int, 0444); +module_param(smi_sig, uint, 0444); + +MODULE_PARM_DESC(smi_port, "Override the BIOS-given IST port with this value -- Intel's default setting is 0xb2"); +MODULE_PARM_DESC(smi_cmd, "Override the BIOS-given IST command with this value -- Intel's default setting is 0x82"); +MODULE_PARM_DESC(smi_sig, "Set to 1 to fake the IST signature when using the SMI interface."); + +MODULE_AUTHOR ("Hiroshi Miura"); +MODULE_DESCRIPTION ("Speedstep driver for IST applet SMI interface."); +MODULE_LICENSE ("GPL"); + +module_init(speedstep_init); +module_exit(speedstep_exit); diff -Nru a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c --- a/arch/i386/kernel/cpu/intel.c Thu Sep 11 23:03:12 2003 +++ b/arch/i386/kernel/cpu/intel.c Thu Sep 11 23:03:12 2003 @@ -164,7 +164,7 @@ } #endif - + select_idle_routine(c); if (c->cpuid_level > 1) { /* supports eax=2 call */ int i, j, n; diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c --- a/arch/i386/kernel/i386_ksyms.c Thu Sep 11 23:03:14 2003 +++ b/arch/i386/kernel/i386_ksyms.c Thu Sep 11 23:03:14 2003 @@ -33,6 +33,7 @@ #include #include #include +#include extern void dump_thread(struct pt_regs *, struct user *); extern spinlock_t rtc_lock; @@ -208,4 +209,8 @@ #ifdef CONFIG_EDD_MODULE EXPORT_SYMBOL(edd); EXPORT_SYMBOL(eddnr); +#endif + +#if defined(CONFIG_X86_SPEEDSTEP_SMI) || defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE) +EXPORT_SYMBOL(ist_info); #endif diff -Nru a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c --- a/arch/i386/kernel/mpparse.c Thu Sep 11 23:03:12 2003 +++ b/arch/i386/kernel/mpparse.c Thu Sep 11 23:03:12 2003 @@ -167,6 +167,11 @@ boot_cpu_logical_apicid = apicid; } + if (num_processors >= NR_CPUS) { + printk(KERN_WARNING "NR_CPUS limit of %i reached. Cannot " + "boot CPU(apicid 0x%d).\n", NR_CPUS, m->mpc_apicid); + return; + } num_processors++; if (MAX_APICS - m->mpc_apicid <= 0) { diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c --- a/arch/i386/kernel/process.c Thu Sep 11 23:03:11 2003 +++ b/arch/i386/kernel/process.c Thu Sep 11 23:03:11 2003 @@ -151,11 +151,57 @@ } } +/* + * This uses new MONITOR/MWAIT instructions on P4 processors with PNI, + * which can obviate IPI to trigger checking of need_resched. + * We execute MONITOR against need_resched and enter optimized wait state + * through MWAIT. Whenever someone changes need_resched, we would be woken + * up from MWAIT (without an IPI). + */ +static void mwait_idle(void) +{ + local_irq_enable(); + + if (!need_resched()) { + set_thread_flag(TIF_POLLING_NRFLAG); + do { + __monitor((void *)¤t_thread_info()->flags, 0, 0); + if (need_resched()) + break; + __mwait(0, 0); + } while (!need_resched()); + clear_thread_flag(TIF_POLLING_NRFLAG); + } +} + +void __init select_idle_routine(const struct cpuinfo_x86 *c) +{ + if (cpu_has(c, X86_FEATURE_MWAIT)) { + printk("monitor/mwait feature present.\n"); + /* + * Skip, if setup has overridden idle. + * Also, take care of system with asymmetric CPUs. + * Use, mwait_idle only if all cpus support it. + * If not, we fallback to default_idle() + */ + if (!pm_idle) { + printk("using mwait in idle threads.\n"); + pm_idle = mwait_idle; + } + return; + } + pm_idle = default_idle; + return; +} + static int __init idle_setup (char *str) { if (!strncmp(str, "poll", 4)) { printk("using polling idle threads.\n"); pm_idle = poll_idle; + } else if (!strncmp(str, "halt", 4)) { + printk("using halt in idle threads.\n"); + pm_idle = default_idle; } return 1; diff -Nru a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c --- a/arch/i386/kernel/reboot.c Thu Sep 11 23:03:12 2003 +++ b/arch/i386/kernel/reboot.c Thu Sep 11 23:03:12 2003 @@ -251,7 +251,7 @@ * other OSs see a clean IRQ state. */ smp_send_stop(); -#elif CONFIG_X86_LOCAL_APIC +#elif defined(CONFIG_X86_LOCAL_APIC) if (cpu_has_apic) { local_irq_disable(); disable_local_APIC(); diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c --- a/arch/i386/kernel/setup.c Thu Sep 11 23:03:12 2003 +++ b/arch/i386/kernel/setup.c Thu Sep 11 23:03:12 2003 @@ -44,6 +44,7 @@ #include #include #include +#include #include "setup_arch_pre.h" #include "mach_resources.h" @@ -102,6 +103,7 @@ unsigned char table[0]; }; struct edid_info edid_info; +struct ist_info ist_info; struct e820map e820; unsigned char aux_device_present; @@ -960,6 +962,7 @@ screen_info = SCREEN_INFO; edid_info = EDID_INFO; apm_info.bios = APM_BIOS_INFO; + ist_info = IST_INFO; saved_videomode = VIDEO_MODE; printk("Video mode to be used for restore is %lx\n", saved_videomode); if( SYS_DESC_TABLE.length != 0 ) { diff -Nru a/arch/i386/kernel/timers/Makefile b/arch/i386/kernel/timers/Makefile --- a/arch/i386/kernel/timers/Makefile Thu Sep 11 23:03:11 2003 +++ b/arch/i386/kernel/timers/Makefile Thu Sep 11 23:03:11 2003 @@ -2,7 +2,7 @@ # Makefile for x86 timers # -obj-y := timer.o timer_none.o timer_tsc.o timer_pit.o +obj-y := timer.o timer_none.o timer_tsc.o timer_pit.o common.o obj-$(CONFIG_X86_CYCLONE_TIMER) += timer_cyclone.o obj-$(CONFIG_HPET_TIMER) += timer_hpet.o diff -Nru a/arch/i386/kernel/timers/common.c b/arch/i386/kernel/timers/common.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/kernel/timers/common.c Thu Sep 11 23:03:14 2003 @@ -0,0 +1,139 @@ +/* + * Common functions used across the timers go here + */ + +#include +#include +#include + +#include +#include +#include + +#include "mach_timer.h" + +/* ------ Calibrate the TSC ------- + * Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset(). + * Too much 64-bit arithmetic here to do this cleanly in C, and for + * accuracy's sake we want to keep the overhead on the CTC speaker (channel 2) + * output busy loop as low as possible. We avoid reading the CTC registers + * directly because of the awkward 8-bit access mechanism of the 82C54 + * device. + */ + +#define CALIBRATE_TIME (5 * 1000020/HZ) + +unsigned long __init calibrate_tsc(void) +{ + mach_prepare_counter(); + + { + unsigned long startlow, starthigh; + unsigned long endlow, endhigh; + unsigned long count; + + rdtsc(startlow,starthigh); + mach_countup(&count); + rdtsc(endlow,endhigh); + + + /* Error: ECTCNEVERSET */ + if (count <= 1) + goto bad_ctc; + + /* 64-bit subtract - gcc just messes up with long longs */ + __asm__("subl %2,%0\n\t" + "sbbl %3,%1" + :"=a" (endlow), "=d" (endhigh) + :"g" (startlow), "g" (starthigh), + "0" (endlow), "1" (endhigh)); + + /* Error: ECPUTOOFAST */ + if (endhigh) + goto bad_ctc; + + /* Error: ECPUTOOSLOW */ + if (endlow <= CALIBRATE_TIME) + goto bad_ctc; + + __asm__("divl %2" + :"=a" (endlow), "=d" (endhigh) + :"r" (endlow), "0" (0), "1" (CALIBRATE_TIME)); + + return endlow; + } + + /* + * The CTC wasn't reliable: we got a hit on the very first read, + * or the CPU was so fast/slow that the quotient wouldn't fit in + * 32 bits.. + */ +bad_ctc: + return 0; +} + +#ifdef CONFIG_HPET_TIMER +/* ------ Calibrate the TSC using HPET ------- + * Return 2^32 * (1 / (TSC clocks per usec)) for getting the CPU freq. + * Second output is parameter 1 (when non NULL) + * Set 2^32 * (1 / (tsc per HPET clk)) for delay_hpet(). + * calibrate_tsc() calibrates the processor TSC by comparing + * it to the HPET timer of known frequency. + * Too much 64-bit arithmetic here to do this cleanly in C + */ +#define CALIBRATE_CNT_HPET (5 * hpet_tick) +#define CALIBRATE_TIME_HPET (5 * KERNEL_TICK_USEC) + +unsigned long __init calibrate_tsc_hpet(unsigned long *tsc_hpet_quotient_ptr) +{ + unsigned long tsc_startlow, tsc_starthigh; + unsigned long tsc_endlow, tsc_endhigh; + unsigned long hpet_start, hpet_end; + unsigned long result, remain; + + hpet_start = hpet_readl(HPET_COUNTER); + rdtsc(tsc_startlow, tsc_starthigh); + do { + hpet_end = hpet_readl(HPET_COUNTER); + } while ((hpet_end - hpet_start) < CALIBRATE_CNT_HPET); + rdtsc(tsc_endlow, tsc_endhigh); + + /* 64-bit subtract - gcc just messes up with long longs */ + __asm__("subl %2,%0\n\t" + "sbbl %3,%1" + :"=a" (tsc_endlow), "=d" (tsc_endhigh) + :"g" (tsc_startlow), "g" (tsc_starthigh), + "0" (tsc_endlow), "1" (tsc_endhigh)); + + /* Error: ECPUTOOFAST */ + if (tsc_endhigh) + goto bad_calibration; + + /* Error: ECPUTOOSLOW */ + if (tsc_endlow <= CALIBRATE_TIME_HPET) + goto bad_calibration; + + ASM_DIV64_REG(result, remain, tsc_endlow, 0, CALIBRATE_TIME_HPET); + if (remain > (tsc_endlow >> 1)) + result++; /* rounding the result */ + + if (tsc_hpet_quotient_ptr) { + unsigned long tsc_hpet_quotient; + + ASM_DIV64_REG(tsc_hpet_quotient, remain, tsc_endlow, 0, + CALIBRATE_CNT_HPET); + if (remain > (tsc_endlow >> 1)) + tsc_hpet_quotient++; /* rounding the result */ + *tsc_hpet_quotient_ptr = tsc_hpet_quotient; + } + + return result; +bad_calibration: + /* + * the CPU was so fast/slow that the quotient wouldn't fit in + * 32 bits.. + */ + return 0; +} +#endif + diff -Nru a/arch/i386/kernel/timers/timer_cyclone.c b/arch/i386/kernel/timers/timer_cyclone.c --- a/arch/i386/kernel/timers/timer_cyclone.c Thu Sep 11 23:03:13 2003 +++ b/arch/i386/kernel/timers/timer_cyclone.c Thu Sep 11 23:03:13 2003 @@ -19,7 +19,6 @@ #include extern spinlock_t i8253_lock; -extern unsigned long calibrate_tsc(void); /* Number of usecs that the last interrupt was delayed */ static int delay_at_last_interrupt; diff -Nru a/arch/i386/kernel/timers/timer_hpet.c b/arch/i386/kernel/timers/timer_hpet.c --- a/arch/i386/kernel/timers/timer_hpet.c Thu Sep 11 23:03:13 2003 +++ b/arch/i386/kernel/timers/timer_hpet.c Thu Sep 11 23:03:13 2003 @@ -131,63 +131,6 @@ } while ((hpet_end - hpet_start) < (loops)); } -/* ------ Calibrate the TSC ------- - * Return 2^32 * (1 / (TSC clocks per usec)) for getting the CPU freq. - * Set 2^32 * (1 / (tsc per HPET clk)) for delay_hpet(). - * calibrate_tsc() calibrates the processor TSC by comparing - * it to the HPET timer of known frequency. - * Too much 64-bit arithmetic here to do this cleanly in C - */ -#define CALIBRATE_CNT_HPET (5 * hpet_tick) -#define CALIBRATE_TIME_HPET (5 * KERNEL_TICK_USEC) - -static unsigned long __init calibrate_tsc(void) -{ - unsigned long tsc_startlow, tsc_starthigh; - unsigned long tsc_endlow, tsc_endhigh; - unsigned long hpet_start, hpet_end; - unsigned long result, remain; - - hpet_start = hpet_readl(HPET_COUNTER); - rdtsc(tsc_startlow, tsc_starthigh); - do { - hpet_end = hpet_readl(HPET_COUNTER); - } while ((hpet_end - hpet_start) < CALIBRATE_CNT_HPET); - rdtsc(tsc_endlow, tsc_endhigh); - - /* 64-bit subtract - gcc just messes up with long longs */ - __asm__("subl %2,%0\n\t" - "sbbl %3,%1" - :"=a" (tsc_endlow), "=d" (tsc_endhigh) - :"g" (tsc_startlow), "g" (tsc_starthigh), - "0" (tsc_endlow), "1" (tsc_endhigh)); - - /* Error: ECPUTOOFAST */ - if (tsc_endhigh) - goto bad_calibration; - - /* Error: ECPUTOOSLOW */ - if (tsc_endlow <= CALIBRATE_TIME_HPET) - goto bad_calibration; - - ASM_DIV64_REG(result, remain, tsc_endlow, 0, CALIBRATE_TIME_HPET); - if (remain > (tsc_endlow >> 1)) - result++; /* rounding the result */ - - ASM_DIV64_REG(tsc_hpet_quotient, remain, tsc_endlow, 0, - CALIBRATE_CNT_HPET); - if (remain > (tsc_endlow >> 1)) - tsc_hpet_quotient++; /* rounding the result */ - - return result; -bad_calibration: - /* - * the CPU was so fast/slow that the quotient wouldn't fit in - * 32 bits.. - */ - return 0; -} - static int __init init_hpet(char* override) { unsigned long result, remain; @@ -201,7 +144,7 @@ printk("Using HPET for gettimeofday\n"); if (cpu_has_tsc) { - unsigned long tsc_quotient = calibrate_tsc(); + unsigned long tsc_quotient = calibrate_tsc_hpet(&tsc_hpet_quotient); if (tsc_quotient) { /* report CPU clock rate in Hz. * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) = diff -Nru a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c --- a/arch/i386/kernel/timers/timer_tsc.c Thu Sep 11 23:03:13 2003 +++ b/arch/i386/kernel/timers/timer_tsc.c Thu Sep 11 23:03:13 2003 @@ -230,67 +230,6 @@ } while ((now-bclock) < loops); } -/* ------ Calibrate the TSC ------- - * Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset(). - * Too much 64-bit arithmetic here to do this cleanly in C, and for - * accuracy's sake we want to keep the overhead on the CTC speaker (channel 2) - * output busy loop as low as possible. We avoid reading the CTC registers - * directly because of the awkward 8-bit access mechanism of the 82C54 - * device. - */ - -#define CALIBRATE_TIME (5 * 1000020/HZ) - -static unsigned long __init calibrate_tsc(void) -{ - mach_prepare_counter(); - - { - unsigned long startlow, starthigh; - unsigned long endlow, endhigh; - unsigned long count; - - rdtsc(startlow,starthigh); - mach_countup(&count); - rdtsc(endlow,endhigh); - - last_tsc_low = endlow; - - /* Error: ECTCNEVERSET */ - if (count <= 1) - goto bad_ctc; - - /* 64-bit subtract - gcc just messes up with long longs */ - __asm__("subl %2,%0\n\t" - "sbbl %3,%1" - :"=a" (endlow), "=d" (endhigh) - :"g" (startlow), "g" (starthigh), - "0" (endlow), "1" (endhigh)); - - /* Error: ECPUTOOFAST */ - if (endhigh) - goto bad_ctc; - - /* Error: ECPUTOOSLOW */ - if (endlow <= CALIBRATE_TIME) - goto bad_ctc; - - __asm__("divl %2" - :"=a" (endlow), "=d" (endhigh) - :"r" (endlow), "0" (0), "1" (CALIBRATE_TIME)); - - return endlow; - } - - /* - * The CTC wasn't reliable: we got a hit on the very first read, - * or the CPU was so fast/slow that the quotient wouldn't fit in - * 32 bits.. - */ -bad_ctc: - return 0; -} - #ifdef CONFIG_HPET_TIMER static void mark_offset_tsc_hpet(void) { @@ -339,58 +278,6 @@ ASM_MUL64_REG(temp, delay_at_last_interrupt, hpet_usec_quotient, delay_at_last_interrupt); } - -/* ------ Calibrate the TSC based on HPET timer ------- - * Return 2^32 * (1 / (TSC clocks per usec)) for do_fast_gettimeoffset(). - * calibrate_tsc() calibrates the processor TSC by comparing - * it to the HPET timer of known frequency. - * Too much 64-bit arithmetic here to do this cleanly in C - */ - -#define CALIBRATE_CNT_HPET (5 * hpet_tick) -#define CALIBRATE_TIME_HPET (5 * KERNEL_TICK_USEC) - -unsigned long __init calibrate_tsc_hpet(void) -{ - unsigned long tsc_startlow, tsc_starthigh; - unsigned long tsc_endlow, tsc_endhigh; - unsigned long hpet_start, hpet_end; - unsigned long result, remain; - - hpet_start = hpet_readl(HPET_COUNTER); - rdtsc(tsc_startlow, tsc_starthigh); - do { - hpet_end = hpet_readl(HPET_COUNTER); - } while ((hpet_end - hpet_start) < CALIBRATE_CNT_HPET); - rdtsc(tsc_endlow, tsc_endhigh); - - /* 64-bit subtract - gcc just messes up with long longs */ - __asm__("subl %2,%0\n\t" - "sbbl %3,%1" - :"=a" (tsc_endlow), "=d" (tsc_endhigh) - :"g" (tsc_startlow), "g" (tsc_starthigh), - "0" (tsc_endlow), "1" (tsc_endhigh)); - - /* Error: ECPUTOOFAST */ - if (tsc_endhigh) - goto bad_calibration; - - /* Error: ECPUTOOSLOW */ - if (tsc_endlow <= CALIBRATE_TIME_HPET) - goto bad_calibration; - - ASM_DIV64_REG(result, remain, tsc_endlow, 0, CALIBRATE_TIME_HPET); - if (remain > (tsc_endlow >> 1)) - result++; /* rounding the result */ - - return result; -bad_calibration: - /* - * the CPU was so fast/slow that the quotient wouldn't fit in - * 32 bits.. - */ - return 0; -} #endif #ifdef CONFIG_CPU_FREQ @@ -425,6 +312,7 @@ if (use_tsc) { fast_gettimeoffset_quotient = cpufreq_scale(fast_gettimeoffset_ref, freq->new, ref_freq); cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new); + set_cyc2ns_scale(cpu_khz/1000); } #endif } @@ -491,7 +379,7 @@ if (is_hpet_enabled()){ unsigned long result, remain; printk("Using TSC for gettimeofday\n"); - tsc_quotient = calibrate_tsc_hpet(); + tsc_quotient = calibrate_tsc_hpet(NULL); timer_tsc.mark_offset = &mark_offset_tsc_hpet; /* * Math to calculate hpet to usec multiplier diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig --- a/arch/ia64/Kconfig Thu Sep 11 23:03:14 2003 +++ b/arch/ia64/Kconfig Thu Sep 11 23:03:14 2003 @@ -267,7 +267,7 @@ unsure, answer Y. config PM - bool + bool "Power Management support" depends on IA64_GENERIC || IA64_DIG || IA64_HP_ZX1 default y ---help--- @@ -569,6 +569,7 @@ source "arch/ia64/hp/sim/Kconfig" +source "arch/ia64/oprofile/Kconfig" menu "Kernel hacking" diff -Nru a/arch/ia64/Makefile b/arch/ia64/Makefile --- a/arch/ia64/Makefile Thu Sep 11 23:03:11 2003 +++ b/arch/ia64/Makefile Thu Sep 11 23:03:11 2003 @@ -65,6 +65,7 @@ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ +drivers-$(CONFIG_OPROFILE) += arch/ia64/oprofile/ boot := arch/ia64/hp/sim/boot diff -Nru a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c --- a/arch/ia64/hp/common/sba_iommu.c Thu Sep 11 23:03:11 2003 +++ b/arch/ia64/hp/common/sba_iommu.c Thu Sep 11 23:03:11 2003 @@ -227,12 +227,7 @@ static struct ioc *ioc_list; static int reserve_sba_gart = 1; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #define sba_sg_address(sg) (page_address((sg)->page) + (sg)->offset) -#else -#define sba_sg_address(sg) ((sg)->address ? (sg)->address : \ - page_address((sg)->page) + (sg)->offset) -#endif #ifdef FULL_VALID_PDIR static u64 prefetch_spill_page; diff -Nru a/arch/ia64/hp/sim/boot/boot_head.S b/arch/ia64/hp/sim/boot/boot_head.S --- a/arch/ia64/hp/sim/boot/boot_head.S Thu Sep 11 23:03:12 2003 +++ b/arch/ia64/hp/sim/boot/boot_head.S Thu Sep 11 23:03:12 2003 @@ -27,6 +27,14 @@ br.call.sptk.many rp=start_bootloader END(_start) +/* + * Set a break point on this function so that symbols are available to set breakpoints in + * the kernel being debugged. + */ +GLOBAL_ENTRY(debug_break) + br.ret.sptk.many b0 +END(debug_break) + GLOBAL_ENTRY(ssc) .regstk 5,0,0,0 mov r15=in4 diff -Nru a/arch/ia64/hp/sim/boot/bootloader.c b/arch/ia64/hp/sim/boot/bootloader.c --- a/arch/ia64/hp/sim/boot/bootloader.c Thu Sep 11 23:03:13 2003 +++ b/arch/ia64/hp/sim/boot/bootloader.c Thu Sep 11 23:03:13 2003 @@ -37,15 +37,7 @@ extern void jmp_to_kernel (unsigned long bp, unsigned long e_entry); extern struct ia64_boot_param *sys_fw_init (const char *args, int arglen); - -/* - * Set a break point on this function so that symbols are available to set breakpoints in - * the kernel being debugged. - */ -static void -debug_break (void) -{ -} +extern void debug_break (void); static void cons_write (const char *buf) diff -Nru a/arch/ia64/ia32/elfcore32.h b/arch/ia64/ia32/elfcore32.h --- a/arch/ia64/ia32/elfcore32.h Thu Sep 11 23:03:12 2003 +++ b/arch/ia64/ia32/elfcore32.h Thu Sep 11 23:03:12 2003 @@ -8,6 +8,8 @@ #ifndef _ELFCORE32_H_ #define _ELFCORE32_H_ +#include + #define USE_ELF_CORE_DUMP 1 /* Override elfcore.h */ @@ -79,8 +81,7 @@ pr_reg[11] = regs->r1; \ pr_reg[12] = regs->cr_iip; \ pr_reg[13] = regs->r17 & 0xffff; \ - asm volatile ("mov %0=ar.eflag ;;" \ - : "=r"(pr_reg[14])); \ + pr_reg[14] = ia64_getreg(_IA64_REG_AR_EFLAG); \ pr_reg[15] = regs->r12; \ pr_reg[16] = (regs->r17 >> 16) & 0xffff; diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c --- a/arch/ia64/kernel/acpi.c Thu Sep 11 23:03:12 2003 +++ b/arch/ia64/kernel/acpi.c Thu Sep 11 23:03:12 2003 @@ -603,11 +603,13 @@ printk(KERN_ERR PREFIX "Can't find FADT\n"); #ifdef CONFIG_SMP - smp_boot_data.cpu_count = available_cpus; if (available_cpus == 0) { printk(KERN_INFO "ACPI: Found 0 CPUS; assuming 1\n"); + printk(KERN_INFO "CPU 0 (0x%04x)", hard_smp_processor_id()); + smp_boot_data.cpu_phys_id[available_cpus] = hard_smp_processor_id(); available_cpus = 1; /* We've got at least one of these, no? */ } + smp_boot_data.cpu_count = available_cpus; smp_build_cpu_map(); # ifdef CONFIG_NUMA diff -Nru a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c --- a/arch/ia64/kernel/efi.c Thu Sep 11 23:03:11 2003 +++ b/arch/ia64/kernel/efi.c Thu Sep 11 23:03:11 2003 @@ -324,7 +324,7 @@ check_md = q; if (check_md->attribute & EFI_MEMORY_WB) - trim_bottom(md, granule_addr); + trim_bottom(check_md, granule_addr); if (check_md->phys_addr < granule_addr) continue; diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S --- a/arch/ia64/kernel/entry.S Thu Sep 11 23:03:11 2003 +++ b/arch/ia64/kernel/entry.S Thu Sep 11 23:03:11 2003 @@ -1448,7 +1448,7 @@ data8 sys_sched_setaffinity data8 sys_sched_getaffinity data8 sys_set_tid_address - data8 sys_fadvise64 + data8 sys_fadvise64_64 data8 sys_tgkill // 1235 data8 sys_exit_group data8 sys_lookup_dcookie @@ -1473,7 +1473,7 @@ data8 sys_clock_nanosleep data8 sys_fstatfs64 data8 sys_statfs64 - data8 sys_fadvise64_64 + data8 ia64_ni_syscall data8 ia64_ni_syscall // 1260 data8 ia64_ni_syscall data8 ia64_ni_syscall diff -Nru a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S --- a/arch/ia64/kernel/fsys.S Thu Sep 11 23:03:11 2003 +++ b/arch/ia64/kernel/fsys.S Thu Sep 11 23:03:11 2003 @@ -655,7 +655,7 @@ data8 0 // sched_setaffinity data8 0 // sched_getaffinity data8 fsys_set_tid_address // set_tid_address - data8 0 // fadvise64 + data8 0 // fadvise64_64 data8 0 // tgkill // 1235 data8 0 // exit_group data8 0 // lookup_dcookie @@ -680,7 +680,7 @@ data8 0 // clock_nanosleep data8 0 // fstatfs64 data8 0 // statfs64 - data8 0 // fadvise64_64 + data8 0 data8 0 // 1260 data8 0 data8 0 diff -Nru a/arch/ia64/kernel/init_task.c b/arch/ia64/kernel/init_task.c --- a/arch/ia64/kernel/init_task.c Thu Sep 11 23:03:14 2003 +++ b/arch/ia64/kernel/init_task.c Thu Sep 11 23:03:14 2003 @@ -28,15 +28,13 @@ */ #define init_thread_info init_task_mem.s.thread_info -static union { +union { struct { struct task_struct task; struct thread_info thread_info; } s; unsigned long stack[KERNEL_STACK_SIZE/sizeof (unsigned long)]; -} init_task_mem asm ("init_task_mem") __attribute__((section(".data.init_task"))) = {{ +} init_task_mem asm ("init_task") __attribute__((section(".data.init_task"))) = {{ .task = INIT_TASK(init_task_mem.s.task), .thread_info = INIT_THREAD_INFO(init_task_mem.s.task) }}; - -extern struct task_struct init_task __attribute__ ((alias("init_task_mem"))); diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c --- a/arch/ia64/kernel/perfmon.c Thu Sep 11 23:03:13 2003 +++ b/arch/ia64/kernel/perfmon.c Thu Sep 11 23:03:14 2003 @@ -58,23 +58,8 @@ #define PFM_CTX_ZOMBIE 4 /* owner of the context is closing it */ #define PFM_CTX_TERMINATED 5 /* the task the context was loaded onto is gone */ -#define CTX_LOADED(c) (c)->ctx_state = PFM_CTX_LOADED -#define CTX_UNLOADED(c) (c)->ctx_state = PFM_CTX_UNLOADED -#define CTX_ZOMBIE(c) (c)->ctx_state = PFM_CTX_ZOMBIE -#define CTX_DESTROYED(c) (c)->ctx_state = PFM_CTX_DESTROYED -#define CTX_MASKED(c) (c)->ctx_state = PFM_CTX_MASKED -#define CTX_TERMINATED(c) (c)->ctx_state = PFM_CTX_TERMINATED - -#define CTX_IS_UNLOADED(c) ((c)->ctx_state == PFM_CTX_UNLOADED) -#define CTX_IS_LOADED(c) ((c)->ctx_state == PFM_CTX_LOADED) -#define CTX_IS_ZOMBIE(c) ((c)->ctx_state == PFM_CTX_ZOMBIE) -#define CTX_IS_MASKED(c) ((c)->ctx_state == PFM_CTX_MASKED) -#define CTX_IS_TERMINATED(c) ((c)->ctx_state == PFM_CTX_TERMINATED) -#define CTX_IS_DEAD(c) ((c)->ctx_state == PFM_CTX_TERMINATED || (c)->ctx_state == PFM_CTX_ZOMBIE) - #define PFM_INVALID_ACTIVATION (~0UL) - /* * depth of message queue */ @@ -155,7 +140,7 @@ * in UP: * - we need to protect against PMU overflow interrupts (local_irq_disable) * - * spin_lock_irqsave()/spin_lock_irqrestore(): + * spin_lock_irqsave()/spin_unlock_irqrestore(): * in SMP: local_irq_disable + spin_lock * in UP : local_irq_disable * @@ -649,6 +634,7 @@ DEFINE_PER_CPU(pfm_context_t *, pmu_ctx); DEFINE_PER_CPU(unsigned long, pmu_activation_number); + /* forward declaration */ static struct file_operations pfm_file_ops; @@ -659,7 +645,13 @@ static void pfm_lazy_save_regs (struct task_struct *ta); #endif -#if defined(CONFIG_ITANIUM) +/* + * the HP simulator must be first because + * CONFIG_IA64_HP_SIM is independent of CONFIG_MCKINLEY or CONFIG_ITANIUM + */ +#if defined(CONFIG_IA64_HP_SIM) +#include "perfmon_hpsim.h" +#elif defined(CONFIG_ITANIUM) #include "perfmon_itanium.h" #elif defined(CONFIG_MCKINLEY) #include "perfmon_mckinley.h" @@ -953,13 +945,15 @@ struct thread_struct *th = &task->thread; unsigned long mask; unsigned long psr, val; - int i; + int i, is_system; + + is_system = ctx->ctx_fl_system; if (task != current) { printk(KERN_ERR "perfmon.%d: invalid task[%d] current[%d]\n", __LINE__, task->pid, current->pid); return; } - if (CTX_IS_MASKED(ctx) == 0) { + if (ctx->ctx_state != PFM_CTX_MASKED) { printk(KERN_ERR "perfmon.%d: task[%d] current[%d] invalid state=%d\n", __LINE__, task->pid, current->pid, ctx->ctx_state); return; @@ -975,7 +969,7 @@ * * system-wide session are pinned and self-monitoring */ - if (ctx->ctx_fl_system && (PFM_CPUINFO_GET() & PFM_CPUINFO_DCR_PP)) { + if (is_system && (PFM_CPUINFO_GET() & PFM_CPUINFO_DCR_PP)) { /* disable dcr pp */ ia64_setreg(_IA64_REG_CR_DCR, ia64_getreg(_IA64_REG_CR_DCR) & ~IA64_DCR_PP); pfm_clear_psr_pp(); @@ -1022,7 +1016,7 @@ /* * now restore PSR */ - if (ctx->ctx_fl_system && (PFM_CPUINFO_GET() & PFM_CPUINFO_DCR_PP)) { + if (is_system && (PFM_CPUINFO_GET() & PFM_CPUINFO_DCR_PP)) { /* enable dcr pp */ ia64_setreg(_IA64_REG_CR_DCR, ia64_getreg(_IA64_REG_CR_DCR) | IA64_DCR_PP); ia64_srlz_i(); @@ -1825,6 +1819,7 @@ void *smpl_buf_vaddr = NULL; void *smpl_buf_addr = NULL; int free_possible = 1; + int state, is_system; { u64 psr = pfm_get_psr(); BUG_ON((psr & IA64_PSR_I) == 0UL); @@ -1850,6 +1845,11 @@ PROTECT_CTX(ctx, flags); + state = ctx->ctx_state; + is_system = ctx->ctx_fl_system; + + task = PFM_CTX_TASK(ctx); + /* * remove our file from the async queue, if we use it */ @@ -1859,11 +1859,10 @@ DPRINT(("[%d] after async_queue=%p\n", current->pid, ctx->ctx_async_queue)); } - task = PFM_CTX_TASK(ctx); - DPRINT(("[%d] ctx_state=%d\n", current->pid, ctx->ctx_state)); + DPRINT(("[%d] ctx_state=%d\n", current->pid, state)); - if (CTX_IS_UNLOADED(ctx) || CTX_IS_TERMINATED(ctx)) { + if (state == PFM_CTX_UNLOADED || state == PFM_CTX_TERMINATED) { goto doit; } @@ -1884,7 +1883,7 @@ * * We need to release the resource on the ORIGINAL cpu. */ - if (ctx->ctx_fl_system && ctx->ctx_cpu != smp_processor_id()) { + if (is_system && ctx->ctx_cpu != smp_processor_id()) { DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); @@ -1900,9 +1899,10 @@ task->thread.pfm_context = NULL; ctx->ctx_task = NULL; - CTX_UNLOADED(ctx); + ctx->ctx_state = state = PFM_CTX_UNLOADED; pfm_unreserve_session(ctx, 1 , ctx->ctx_cpu); + } else #endif /* CONFIG_SMP */ { @@ -1914,19 +1914,20 @@ */ pfm_context_unload(ctx, NULL, 0, regs); - CTX_TERMINATED(ctx); + ctx->ctx_state = PFM_CTX_TERMINATED; - DPRINT(("[%d] ctx_state=%d\n", current->pid, ctx->ctx_state)); + DPRINT(("[%d] ctx_state=%d\n", current->pid, state)); } goto doit; } + /* * The task is currently blocked or will block after an overflow. * we must force it to wakeup to get out of the * MASKED state and transition to the unloaded state by itself */ - if (CTX_IS_MASKED(ctx) && CTX_OVFL_NOBLOCK(ctx) == 0) { + if (state == PFM_CTX_MASKED && CTX_OVFL_NOBLOCK(ctx) == 0) { /* * set a "partial" zombie state to be checked @@ -1949,7 +1950,7 @@ */ up(&ctx->ctx_restart_sem); - DPRINT(("waking up ctx_state=%d for [%d]\n", ctx->ctx_state, current->pid)); + DPRINT(("waking up ctx_state=%d for [%d]\n", state, current->pid)); /* * put ourself to sleep waiting for the other @@ -1971,24 +1972,24 @@ */ schedule(); - DPRINT(("woken up ctx_state=%d for [%d]\n", ctx->ctx_state, current->pid)); PROTECT_CTX(ctx, flags); + remove_wait_queue(&ctx->ctx_zombieq, &wait); set_current_state(TASK_RUNNING); /* * context is terminated at this point */ - DPRINT(("after zombie wakeup ctx_state=%d for [%d]\n", ctx->ctx_state, current->pid)); + DPRINT(("after zombie wakeup ctx_state=%d for [%d]\n", state, current->pid)); } else { #ifdef CONFIG_SMP /* * switch context to zombie state */ - CTX_ZOMBIE(ctx); + ctx->ctx_state = PFM_CTX_ZOMBIE; DPRINT(("zombie ctx for [%d]\n", task->pid)); /* @@ -2002,6 +2003,10 @@ } doit: /* cannot assume task is defined from now on */ + + /* reload state, may have changed during opening of critical section */ + state = ctx->ctx_state; + /* * the context is still attached to a task (possibly current) * we cannot destroy it right now @@ -2032,10 +2037,9 @@ ctx->ctx_smpl_hdr = NULL; } - DPRINT(("[%d] ctx_state=%d free_possible=%d vaddr=%p addr=%p size=%lu\n", current->pid, - ctx->ctx_state, + state, free_possible, smpl_buf_vaddr, smpl_buf_addr, @@ -2047,7 +2051,7 @@ * UNLOADED and TERMINATED mean that the session has already been * unreserved. */ - if (CTX_IS_ZOMBIE(ctx)) { + if (state == PFM_CTX_ZOMBIE) { pfm_unreserve_session(ctx, ctx->ctx_fl_system , ctx->ctx_cpu); } @@ -2360,10 +2364,23 @@ static int pfm_bad_permissions(struct task_struct *task) { - /* stolen from bad_signal() */ - return (current->session != task->session) - && (current->euid ^ task->suid) && (current->euid ^ task->uid) - && (current->uid ^ task->suid) && (current->uid ^ task->uid); + /* inspired by ptrace_attach() */ + DPRINT(("[%d] cur: uid=%d gid=%d task: euid=%d suid=%d uid=%d egid=%d sgid=%d\n", + current->pid, + current->uid, + current->gid, + task->euid, + task->suid, + task->uid, + task->egid, + task->sgid)); + + return ((current->uid != task->euid) + || (current->uid != task->suid) + || (current->uid != task->uid) + || (current->gid != task->egid) + || (current->gid != task->sgid) + || (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE); } static int @@ -2655,7 +2672,7 @@ /* * context is unloaded */ - CTX_UNLOADED(ctx); + ctx->ctx_state = PFM_CTX_UNLOADED; /* * initialization of context's flags @@ -2787,7 +2804,7 @@ if (flag == PFM_PMD_NO_RESET) return; - if (CTX_IS_MASKED(ctx)) { + if (ctx->ctx_state == PFM_CTX_MASKED) { pfm_reset_regs_masked(ctx, ovfl_regs, flag); return; } @@ -2836,27 +2853,30 @@ unsigned long value; unsigned long smpl_pmds, reset_pmds; unsigned int cnum, reg_flags, flags; - int i, can_access_pmu = 0, is_loaded; - int is_monitor, is_counting; + int i, can_access_pmu = 0, is_loaded, is_system; + int is_monitor, is_counting, state; int ret = -EINVAL; #define PFM_CHECK_PMC_PM(x, y, z) ((x)->ctx_fl_system ^ PMC_PM(y, z)) - if (CTX_IS_DEAD(ctx)) return -EINVAL; + state = ctx->ctx_state; + is_loaded = state == PFM_CTX_LOADED ? 1 : 0; + is_system = ctx->ctx_fl_system; + + if (state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE) return -EINVAL; - is_loaded = CTX_IS_LOADED(ctx); if (is_loaded) { thread = &ctx->ctx_task->thread; - can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task ? 1 : 0; /* * In system wide and when the context is loaded, access can only happen * when the caller is running on the CPU being monitored by the session. * It does not have to be the owner (ctx_task) of the context per se. */ - if (ctx->ctx_fl_system && ctx->ctx_cpu != smp_processor_id()) { + if (is_system && ctx->ctx_cpu != smp_processor_id()) { DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); return -EBUSY; } + can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task || is_system ? 1 : 0; } for (i = 0; i < count; i++, req++) { @@ -2893,7 +2913,6 @@ goto error; } - if (is_counting) { pfm_monitor_t *p = (pfm_monitor_t *)&value; /* @@ -2975,7 +2994,7 @@ * make sure we do not try to reset on * restart because we have established new values */ - if (CTX_IS_MASKED(ctx)) ctx->ctx_ovfl_regs[0] &= ~1UL << cnum; + if (state == PFM_CTX_MASKED) ctx->ctx_ovfl_regs[0] &= ~1UL << cnum; } /* * Needed in case the user does not initialize the equivalent @@ -3007,7 +3026,7 @@ /* * write thread state */ - if (ctx->ctx_fl_system == 0) thread->pmcs[cnum] = value; + if (is_system == 0) thread->pmcs[cnum] = value; /* * write hardware register if we can @@ -3067,13 +3086,16 @@ pfarg_reg_t *req = (pfarg_reg_t *)arg; unsigned long value, hw_value; unsigned int cnum; - int i, can_access_pmu = 0; - int is_counting, is_loaded; + int i, can_access_pmu = 0, state; + int is_counting, is_loaded, is_system; int ret = -EINVAL; - if (CTX_IS_DEAD(ctx)) return -EINVAL; - is_loaded = CTX_IS_LOADED(ctx); + state = ctx->ctx_state; + is_loaded = state == PFM_CTX_LOADED ? 1 : 0; + is_system = ctx->ctx_fl_system; + + if (state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE) return -EINVAL; /* * on both UP and SMP, we can only write to the PMC when the task is @@ -3081,16 +3103,16 @@ */ if (is_loaded) { thread = &ctx->ctx_task->thread; - can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task ? 1 : 0; /* * In system wide and when the context is loaded, access can only happen * when the caller is running on the CPU being monitored by the session. * It does not have to be the owner (ctx_task) of the context per se. */ - if (ctx->ctx_fl_system && ctx->ctx_cpu != smp_processor_id()) { + if (is_system && ctx->ctx_cpu != smp_processor_id()) { DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); return -EBUSY; } + can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task || is_system ? 1 : 0; } for (i = 0; i < count; i++, req++) { @@ -3179,7 +3201,7 @@ * make sure we do not try to reset on * restart because we have established new values */ - if (is_counting && CTX_IS_MASKED(ctx)) { + if (is_counting && state == PFM_CTX_MASKED) { ctx->ctx_ovfl_regs[0] &= ~1UL << cnum; } @@ -3187,7 +3209,7 @@ /* * write thread state */ - if (ctx->ctx_fl_system == 0) thread->pmds[cnum] = hw_value; + if (is_system == 0) thread->pmds[cnum] = hw_value; /* * write hardware register if we can @@ -3265,35 +3287,40 @@ unsigned long val = 0UL, lval ; pfarg_reg_t *req = (pfarg_reg_t *)arg; unsigned int cnum, reg_flags = 0; - int i, is_loaded, can_access_pmu = 0; + int i, can_access_pmu = 0, state; + int is_loaded, is_system; int ret = -EINVAL; - if (CTX_IS_ZOMBIE(ctx)) return -EINVAL; - /* * access is possible when loaded only for * self-monitoring tasks or in UP mode */ - is_loaded = CTX_IS_LOADED(ctx); + + state = ctx->ctx_state; + is_loaded = state == PFM_CTX_LOADED ? 1 : 0; + is_system = ctx->ctx_fl_system; + + if (state == PFM_CTX_ZOMBIE) return -EINVAL; if (is_loaded) { thread = &ctx->ctx_task->thread; /* - * this can be true when not self-monitoring only in UP - */ - can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task? 1 : 0; - - if (can_access_pmu) ia64_srlz_d(); - /* * In system wide and when the context is loaded, access can only happen * when the caller is running on the CPU being monitored by the session. * It does not have to be the owner (ctx_task) of the context per se. */ - if (ctx->ctx_fl_system && ctx->ctx_cpu != smp_processor_id()) { + if (is_system && ctx->ctx_cpu != smp_processor_id()) { DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); return -EBUSY; } + /* + * this can be true when not self-monitoring only in UP + */ + can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task || is_system ? 1 : 0; + + if (can_access_pmu) ia64_srlz_d(); } + DPRINT(("enter loaded=%d access_pmu=%d ctx_state=%d\n", is_loaded, can_access_pmu, @@ -3334,7 +3361,7 @@ * if context is zombie, then task does not exist anymore. * In this case, we use the full value saved in the context (pfm_flush_regs()). */ - val = CTX_IS_LOADED(ctx) ? thread->pmds[cnum] : 0UL; + val = state == PFM_CTX_LOADED ? thread->pmds[cnum] : 0UL; } if (PMD_IS_COUNTING(cnum)) { @@ -3628,7 +3655,7 @@ if (rst_ctrl.bits.mask_monitoring == 0) { DPRINT(("resuming monitoring for [%d]\n", task->pid)); - if (CTX_IS_MASKED(ctx)) pfm_restore_monitoring(task); + if (state == PFM_CTX_MASKED) pfm_restore_monitoring(task); } else { DPRINT(("keeping monitoring stopped for [%d]\n", task->pid)); @@ -3643,7 +3670,7 @@ /* * back to LOADED state */ - CTX_LOADED(ctx); + ctx->ctx_state = PFM_CTX_LOADED; return 0; } @@ -3706,30 +3733,34 @@ dbreg_t dbreg; unsigned int rnum; int first_time; - int ret = 0; - int i, can_access_pmu = 0, is_loaded; + int ret = 0, state; + int i, can_access_pmu = 0; + int is_system, is_loaded; if (pmu_conf.use_rr_dbregs == 0) return -EINVAL; - if (CTX_IS_DEAD(ctx)) return -EINVAL; + state = ctx->ctx_state; + is_loaded = state == PFM_CTX_LOADED ? 1 : 0; + is_system = ctx->ctx_fl_system; + + if (state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE) return -EINVAL; - is_loaded = CTX_IS_LOADED(ctx); /* * on both UP and SMP, we can only write to the PMC when the task is * the owner of the local PMU. */ if (is_loaded) { thread = &ctx->ctx_task->thread; - can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task ? 1 : 0; /* * In system wide and when the context is loaded, access can only happen * when the caller is running on the CPU being monitored by the session. * It does not have to be the owner (ctx_task) of the context per se. */ - if (ctx->ctx_fl_system && ctx->ctx_cpu != smp_processor_id()) { + if (is_system && ctx->ctx_cpu != smp_processor_id()) { DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); return -EBUSY; } + can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task || is_system ? 1 : 0; } /* @@ -3758,7 +3789,7 @@ */ LOCK_PFS(); - if (first_time && ctx->ctx_fl_system) { + if (first_time && is_system) { if (pfm_sessions.pfs_ptrace_use_dbregs) ret = -EBUSY; else @@ -3906,16 +3937,19 @@ { struct pt_regs *tregs; struct task_struct *task = PFM_CTX_TASK(ctx); + int state, is_system; + state = ctx->ctx_state; + is_system = ctx->ctx_fl_system; - if (CTX_IS_LOADED(ctx) == 0 && CTX_IS_MASKED(ctx) == 0) return -EINVAL; + if (state != PFM_CTX_LOADED && state != PFM_CTX_MASKED) return -EINVAL; /* * In system wide and when the context is loaded, access can only happen * when the caller is running on the CPU being monitored by the session. * It does not have to be the owner (ctx_task) of the context per se. */ - if (ctx->ctx_fl_system && ctx->ctx_cpu != smp_processor_id()) { + if (is_system && ctx->ctx_cpu != smp_processor_id()) { DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); return -EBUSY; } @@ -3925,7 +3959,7 @@ * and the user level state of the caller, which may not * necessarily be the creator of the context. */ - if (ctx->ctx_fl_system) { + if (is_system) { /* * Update local PMU first * @@ -3985,15 +4019,19 @@ pfm_start(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) { struct pt_regs *tregs; + int state, is_system; + + state = ctx->ctx_state; + is_system = ctx->ctx_fl_system; - if (CTX_IS_LOADED(ctx) == 0) return -EINVAL; + if (state != PFM_CTX_LOADED) return -EINVAL; /* * In system wide and when the context is loaded, access can only happen * when the caller is running on the CPU being monitored by the session. * It does not have to be the owner (ctx_task) of the context per se. */ - if (ctx->ctx_fl_system && ctx->ctx_cpu != smp_processor_id()) { + if (is_system && ctx->ctx_cpu != smp_processor_id()) { DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); return -EBUSY; } @@ -4003,7 +4041,7 @@ * and the user level state of the caller, which may not * necessarily be the creator of the context. */ - if (ctx->ctx_fl_system) { + if (is_system) { /* * set user level psr.pp for the caller @@ -4055,7 +4093,6 @@ */ ia64_psr(tregs)->up = 1; } - return 0; } @@ -4121,11 +4158,14 @@ unsigned long *pmcs_source, *pmds_source; int the_cpu; int ret = 0; + int state, is_system; + state = ctx->ctx_state; + is_system = ctx->ctx_fl_system; /* * can only load from unloaded or terminated state */ - if (CTX_IS_UNLOADED(ctx) == 0 && CTX_IS_TERMINATED(ctx) == 0) { + if (state != PFM_CTX_UNLOADED && state != PFM_CTX_TERMINATED) { DPRINT(("[%d] cannot load to [%d], invalid ctx_state=%d\n", current->pid, req->load_pid, @@ -4151,7 +4191,7 @@ /* * system wide is self monitoring only */ - if (ctx->ctx_fl_system && task != current) { + if (is_system && task != current) { DPRINT(("system wide is self monitoring only current=%d load_pid=%d\n", current->pid, req->load_pid)); @@ -4191,7 +4231,7 @@ /* * now reserve the session */ - ret = pfm_reserve_session(current, ctx->ctx_fl_system, the_cpu); + ret = pfm_reserve_session(current, is_system, the_cpu); if (ret) goto error; ret = -EBUSY; @@ -4216,15 +4256,14 @@ pfm_reset_msgq(ctx); - CTX_LOADED(ctx); + ctx->ctx_state = PFM_CTX_LOADED; /* * link context to task */ ctx->ctx_task = task; - if (ctx->ctx_fl_system) { - + if (is_system) { /* * we load as stopped */ @@ -4250,7 +4289,7 @@ */ if (task == current) { - if (ctx->ctx_fl_system == 0) { + if (is_system == 0) { /* allow user level control */ ia64_psr(regs)->sp = 0; @@ -4318,14 +4357,14 @@ /* * release task, there is now a link with the context */ - if (ctx->ctx_fl_system == 0 && task != current) { + if (is_system == 0 && task != current) { pfm_put_task(task); if (ret == 0) { ret = pfm_check_task_exist(ctx); if (ret) { - CTX_UNLOADED(ctx); - ctx->ctx_task = NULL; + ctx->ctx_state = PFM_CTX_UNLOADED; + ctx->ctx_task = NULL; } } } @@ -4347,40 +4386,34 @@ { struct task_struct *task = PFM_CTX_TASK(ctx); struct pt_regs *tregs; + int state, is_system; DPRINT(("ctx_state=%d task [%d]\n", ctx->ctx_state, task ? task->pid : -1)); + state = ctx->ctx_state; + is_system = ctx->ctx_fl_system; + /* * unload only when necessary */ - if (CTX_IS_TERMINATED(ctx) || CTX_IS_UNLOADED(ctx)) { + if (state == PFM_CTX_TERMINATED || state == PFM_CTX_UNLOADED) { DPRINT(("[%d] ctx_state=%d, nothing to do\n", current->pid, ctx->ctx_state)); return 0; } /* - * In system wide and when the context is loaded, access can only happen - * when the caller is running on the CPU being monitored by the session. - * It does not have to be the owner (ctx_task) of the context per se. - */ - if (ctx->ctx_fl_system && ctx->ctx_cpu != smp_processor_id()) { - DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu)); - return -EBUSY; - } - - /* * clear psr and dcr bits */ pfm_stop(ctx, NULL, 0, regs); - CTX_UNLOADED(ctx); + ctx->ctx_state = state = PFM_CTX_UNLOADED; /* * in system mode, we need to update the PMU directly * and the user level state of the caller, which may not * necessarily be the creator of the context. */ - if (ctx->ctx_fl_system) { + if (is_system) { /* * Update cpuinfo @@ -4524,7 +4557,7 @@ if (ret) { printk(KERN_ERR "perfmon: pfm_exit_thread [%d] state=%d unload failed %d\n", task->pid, ctx->ctx_state, ret); } - CTX_TERMINATED(ctx); + ctx->ctx_state = PFM_CTX_TERMINATED; DPRINT(("ctx terminated by [%d]\n", task->pid)); pfm_end_notify_user(ctx); @@ -4606,16 +4639,19 @@ pfm_check_task_state(pfm_context_t *ctx, int cmd, unsigned long flags) { struct task_struct *task; + int state; + + state = ctx->ctx_state; task = PFM_CTX_TASK(ctx); if (task == NULL) { - DPRINT(("context %d no task, state=%d\n", ctx->ctx_fd, ctx->ctx_state)); + DPRINT(("context %d no task, state=%d\n", ctx->ctx_fd, state)); return 0; } DPRINT(("context %d state=%d [%d] task_state=%ld must_stop=%d\n", ctx->ctx_fd, - ctx->ctx_state, + state, task->pid, task->state, PFM_CMD_STOPPED(cmd))); @@ -4631,9 +4667,9 @@ /* * context is UNLOADED, MASKED, TERMINATED we are safe to go */ - if (CTX_IS_LOADED(ctx) == 0) return 0; + if (state != PFM_CTX_LOADED == 0) return 0; - if (CTX_IS_ZOMBIE(ctx)) return -EINVAL; + if (state == PFM_CTX_ZOMBIE) return -EINVAL; /* * context is loaded, we must make sure the task is stopped @@ -4653,6 +4689,7 @@ pfm_wait_task_inactive(task); PROTECT_CTX(ctx, flags); + return 0; } @@ -4830,12 +4867,12 @@ } if (rst_ctrl.bits.mask_monitoring == 0) { DPRINT(("resuming monitoring\n")); - if (CTX_IS_MASKED(ctx)) pfm_restore_monitoring(current); + if (ctx->ctx_state == PFM_CTX_MASKED) pfm_restore_monitoring(current); } else { DPRINT(("stopping monitoring\n")); //pfm_stop_monitoring(current, regs); } - CTX_LOADED(ctx); + ctx->ctx_state = PFM_CTX_LOADED; } } @@ -4869,7 +4906,7 @@ /* * switch to terminated state */ - CTX_TERMINATED(ctx); + ctx->ctx_state = PFM_CTX_TERMINATED; DPRINT(("context <%d> terminated for [%d]\n", ctx->ctx_fd, current->pid)); @@ -4922,7 +4959,7 @@ /* * must be done before we check non-blocking mode */ - if (ctx->ctx_fl_going_zombie || CTX_IS_ZOMBIE(ctx)) goto do_zombie; + if (ctx->ctx_fl_going_zombie || ctx->ctx_state == PFM_CTX_ZOMBIE) goto do_zombie; ovfl_regs = ctx->ctx_ovfl_regs[0]; @@ -4966,7 +5003,7 @@ static int pfm_notify_user(pfm_context_t *ctx, pfm_msg_t *msg) { - if (CTX_IS_ZOMBIE(ctx)) { + if (ctx->ctx_state == PFM_CTX_ZOMBIE) { DPRINT(("ignoring overflow notification, owner is zombie\n")); return 0; } @@ -5049,13 +5086,13 @@ pfm_ovfl_arg_t ovfl_arg; unsigned long mask; unsigned long old_val; - unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL; + unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL, smpl_pmds = 0UL; unsigned long tstamp; pfm_ovfl_ctrl_t ovfl_ctrl; unsigned int i, has_smpl; int must_notify = 0; - if (unlikely(CTX_IS_ZOMBIE(ctx))) goto stop_monitoring; + if (unlikely(ctx->ctx_state == PFM_CTX_ZOMBIE)) goto stop_monitoring; /* * sanity test. Should never happen @@ -5106,10 +5143,9 @@ if (PMC_OVFL_NOTIFY(ctx, i)) ovfl_notify |= 1UL << i; } - DPRINT_ovfl(("ctx_pmd[%d].val=0x%lx old_val=0x%lx pmd=0x%lx ovfl_pmds=0x%lx " - "ovfl_notify=0x%lx\n", - i, ctx->ctx_pmds[i].val, old_val, - ia64_get_pmd(i) & pmu_conf.ovfl_val, ovfl_pmds, ovfl_notify)); + DPRINT_ovfl(("ctx_pmd[%d].val=0x%lx old_val=0x%lx pmd=0x%lx ovfl_pmds=0x%lx ovfl_notify=0x%lx smpl_pmds=0x%lx\n", + i, ctx->ctx_pmds[i].val, old_val, + ia64_get_pmd(i) & pmu_conf.ovfl_val, ovfl_pmds, ovfl_notify, smpl_pmds)); } /* @@ -5128,7 +5164,7 @@ */ if (has_smpl) { unsigned long start_cycles, end_cycles; - unsigned long pmd_mask, smpl_pmds; + unsigned long pmd_mask; int j, k, ret = 0; int this_cpu = smp_processor_id(); @@ -5257,7 +5293,7 @@ */ if (ovfl_ctrl.bits.mask_monitoring) { pfm_mask_monitoring(task); - CTX_MASKED(ctx); + ctx->ctx_state = PFM_CTX_MASKED; } /* @@ -5553,19 +5589,18 @@ pfm_set_psr_pp(); ia64_srlz_i(); } - { unsigned long val; - val = ia64_get_pmc(4); - if ((val & (1UL<<23)) == 0UL) printk("perfmon: PMU off: pmc4=0x%lx\n", val); - } } void pfm_syst_wide_update_task(struct task_struct *task, unsigned long info, int is_ctxswin) { unsigned long start, end; + pfm_stats[smp_processor_id()].pfm_sysupdt_count++; start = ia64_get_itc(); + pfm_do_syst_wide_update_task(task, info, is_ctxswin); + end = ia64_get_itc(); pfm_stats[smp_processor_id()].pfm_sysupdt_cycles += end-start; } @@ -5591,7 +5626,7 @@ */ flags = pfm_protect_ctx_ctxsw(ctx); - if (CTX_IS_ZOMBIE(ctx)) { + if (ctx->ctx_state == PFM_CTX_ZOMBIE) { struct pt_regs *regs = ia64_task_regs(task); pfm_clear_psr_up(); @@ -5840,7 +5875,7 @@ BUG_ON(psr & IA64_PSR_I); #endif - if (unlikely(CTX_IS_ZOMBIE(ctx))) { + if (unlikely(ctx->ctx_state == PFM_CTX_ZOMBIE)) { struct pt_regs *regs = ia64_task_regs(task); BUG_ON(ctx->ctx_smpl_hdr); diff -Nru a/arch/ia64/kernel/perfmon_hpsim.h b/arch/ia64/kernel/perfmon_hpsim.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/kernel/perfmon_hpsim.h Thu Sep 11 23:03:14 2003 @@ -0,0 +1,75 @@ +/* + * This file contains the HP SKI Simulator PMU register description tables + * and pmc checkers used by perfmon.c. + * + * Copyright (C) 2002-2003 Hewlett Packard Co + * Stephane Eranian + * + * File mostly contributed by Ian Wienand + * + * This file is included as a dummy template so the kernel does not + * try to initalize registers the simulator can't handle. + * + * Note the simulator does not (currently) implement these registers, i.e., + * they do not count anything. But you can read/write them. + */ + +#define RDEP(x) (1UL<<(x)) + +#ifndef CONFIG_IA64_HP_SIM +#error "This file should only be included for the HP Simulator" +#endif + +static pfm_reg_desc_t pfm_hpsim_pmc_desc[PMU_MAX_PMCS]={ +/* pmc0 */ { PFM_REG_CONTROL , 0, 0x1UL, -1UL, NULL, NULL, {0UL, 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc1 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL, 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc2 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL, 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc3 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL, 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc4 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(4), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc5 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(5), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc6 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(6), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc7 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(7), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc8 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(8), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc9 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(9), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc10 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(10), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc11 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(11), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc12 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(12), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc13 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(13), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc14 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(14), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc15 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {RDEP(15), 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, + { PFM_REG_END , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */ +}; + +static pfm_reg_desc_t pfm_hpsim_pmd_desc[PMU_MAX_PMDS]={ +/* pmd0 */ { PFM_REG_BUFFER, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmd1 */ { PFM_REG_BUFFER, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmd2 */ { PFM_REG_BUFFER, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmd3 */ { PFM_REG_BUFFER, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmd4 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(4),0UL, 0UL, 0UL}}, +/* pmd5 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(5),0UL, 0UL, 0UL}}, +/* pmd6 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(6),0UL, 0UL, 0UL}}, +/* pmd7 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(7),0UL, 0UL, 0UL}}, +/* pmd8 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(8),0UL, 0UL, 0UL}}, +/* pmd9 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(9),0UL, 0UL, 0UL}}, +/* pmd10 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}}, +/* pmd11 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}}, +/* pmd12 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}}, +/* pmd13 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(13),0UL, 0UL, 0UL}}, +/* pmd14 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(14),0UL, 0UL, 0UL}}, +/* pmd15 */ { PFM_REG_COUNTING, 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(15),0UL, 0UL, 0UL}}, + { PFM_REG_END , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */ +}; + +/* + * impl_pmcs, impl_pmds are computed at runtime to minimize errors! + */ +static pmu_config_t pmu_conf={ + .pmu_name = "hpsim", + .pmu_family = 0x7, /* ski emulator reports as Itanium */ + .enabled = 0, + .ovfl_val = (1UL << 32) - 1, + .num_ibrs = 0, /* does not use */ + .num_dbrs = 0, /* does not use */ + .pmd_desc = pfm_hpsim_pmd_desc, + .pmc_desc = pfm_hpsim_pmc_desc +}; diff -Nru a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c --- a/arch/ia64/kernel/smpboot.c Thu Sep 11 23:03:11 2003 +++ b/arch/ia64/kernel/smpboot.c Thu Sep 11 23:03:11 2003 @@ -534,8 +534,8 @@ printk(KERN_INFO "SMP mode deactivated.\n"); cpus_clear(cpu_online_map); cpus_clear(phys_cpu_present_map); - cpu_set(1, cpu_online_map); - cpu_set(1, phys_cpu_present_map); + cpu_set(0, cpu_online_map); + cpu_set(0, phys_cpu_present_map); return; } } diff -Nru a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c --- a/arch/ia64/kernel/time.c Thu Sep 11 23:03:11 2003 +++ b/arch/ia64/kernel/time.c Thu Sep 11 23:03:11 2003 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -39,29 +40,6 @@ #endif static void -do_profile (unsigned long ip) -{ - extern cpumask_t prof_cpu_mask; - - if (!prof_buffer) - return; - - if (!cpu_isset(smp_processor_id(), prof_cpu_mask)) - return; - - ip -= (unsigned long) _stext; - ip >>= prof_shift; - /* - * Don't ignore out-of-bounds IP values silently, put them into the last - * histogram slot, so if present, they will show up as a sharp peak. - */ - if (ip > prof_len - 1) - ip = prof_len - 1; - - atomic_inc((atomic_t *) &prof_buffer[ip]); -} - -static void itc_reset (void) { } @@ -199,6 +177,52 @@ tv->tv_usec = usec; } +/* + * The profiling function is SMP safe. (nothing can mess + * around with "current", and the profiling counters are + * updated with atomic operations). This is especially + * useful with a profiling multiplier != 1 + */ +static inline void +ia64_do_profile (struct pt_regs * regs) +{ + unsigned long ip, slot; + extern unsigned long prof_cpu_mask; + + profile_hook(regs); + + if (user_mode(regs)) + return; + + if (!prof_buffer) + return; + + ip = instruction_pointer(regs); + /* Conserve space in histogram by encoding slot bits in address + * bits 2 and 3 rather than bits 0 and 1. + */ + slot = ip & 3; + ip = (ip & ~3UL) + 4*slot; + + /* + * Only measure the CPUs specified by /proc/irq/prof_cpu_mask. + * (default is all CPUs.) + */ + if (!cpu_isset(smp_processor_id(), prof_cpu_mask)) + return; + + ip -= (unsigned long) &_stext; + ip >>= prof_shift; + /* + * Don't ignore out-of-bounds IP values silently, + * put them into the last histogram slot, so if + * present, they will show up as a sharp peak. + */ + if (ip > prof_len-1) + ip = prof_len-1; + atomic_inc((atomic_t *)&prof_buffer[ip]); +} + static irqreturn_t timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) { @@ -210,14 +234,9 @@ printk(KERN_ERR "Oops: timer tick before it's due (itc=%lx,itm=%lx)\n", ia64_get_itc(), new_itm); + ia64_do_profile(regs); + while (1) { - /* - * Do kernel PC profiling here. We multiply the instruction number by - * four so that we can use a prof_shift of 2 to get instruction-level - * instead of just bundle-level accuracy. - */ - if (!user_mode(regs)) - do_profile(regs->cr_iip + 4*ia64_psr(regs)->ri); #ifdef CONFIG_SMP smp_do_timer(regs); diff -Nru a/arch/ia64/oprofile/Kconfig b/arch/ia64/oprofile/Kconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/oprofile/Kconfig Thu Sep 11 23:03:14 2003 @@ -0,0 +1,22 @@ + +menu "Profiling support" + depends on EXPERIMENTAL + +config PROFILING + bool "Profiling support (EXPERIMENTAL)" + help + Say Y here to enable the extended profiling support mechanisms used + by profilers such as OProfile. + +config OPROFILE + tristate "OProfile system profiling (EXPERIMENTAL)" + depends on PROFILING + help + OProfile is a profiling system capable of profiling the + whole system, include the kernel, kernel modules, libraries, + and applications. + + If unsure, say N. + +endmenu + diff -Nru a/arch/ia64/oprofile/Makefile b/arch/ia64/oprofile/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/oprofile/Makefile Thu Sep 11 23:03:14 2003 @@ -0,0 +1,9 @@ +obj-$(CONFIG_OPROFILE) += oprofile.o + +DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \ + oprof.o cpu_buffer.o buffer_sync.o \ + event_buffer.o oprofile_files.o \ + oprofilefs.o oprofile_stats.o \ + timer_int.o ) + +oprofile-y := $(DRIVER_OBJS) init.o diff -Nru a/arch/ia64/oprofile/init.c b/arch/ia64/oprofile/init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/oprofile/init.c Thu Sep 11 23:03:14 2003 @@ -0,0 +1,25 @@ +/** + * @file init.c + * + * @remark Copyright 2002 OProfile authors + * @remark Read the file COPYING + * + * @author John Levon + */ + +#include +#include +#include +#include + +extern void timer_init(struct oprofile_operations ** ops); + +int __init oprofile_arch_init(struct oprofile_operations ** ops) +{ + return -ENODEV; +} + + +void oprofile_arch_exit(void) +{ +} diff -Nru a/arch/ia64/scripts/toolchain-flags b/arch/ia64/scripts/toolchain-flags --- a/arch/ia64/scripts/toolchain-flags Thu Sep 11 23:03:14 2003 +++ b/arch/ia64/scripts/toolchain-flags Thu Sep 11 23:03:14 2003 @@ -20,7 +20,7 @@ EOF fi -if ! $CC -c $dir/check-model.c -o $out 2>&1 | grep -q 'attribute directive ignored' +if ! $CC -c $dir/check-model.c -o $out 2>&1 | grep __model__ | grep -q attrib then CPPFLAGS="$CPPFLAGS -DHAVE_MODEL_SMALL_ATTRIBUTE" fi diff -Nru a/arch/ia64/sn/io/drivers/ioconfig_bus.c b/arch/ia64/sn/io/drivers/ioconfig_bus.c --- a/arch/ia64/sn/io/drivers/ioconfig_bus.c Thu Sep 11 23:03:13 2003 +++ b/arch/ia64/sn/io/drivers/ioconfig_bus.c Thu Sep 11 23:03:13 2003 @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include @@ -157,7 +157,7 @@ char *name; char *temp; char *next; - char *current; + char *curr; char *line; struct ascii_moduleid *moduleid; @@ -166,10 +166,10 @@ name = kmalloc(125, GFP_KERNEL); memset(name, 0, 125); moduleid = table; - current = file_contents; - while (nextline(current, &next, line)){ + curr = file_contents; + while (nextline(curr, &next, line)){ - DBG("current 0x%lx next 0x%lx\n", current, next); + DBG("curr 0x%lx next 0x%lx\n", curr, next); temp = line; /* @@ -182,7 +182,7 @@ break; if (*temp == '\n') { - current = next; + curr = next; memset(line, 0, 256); continue; } @@ -191,7 +191,7 @@ * Skip comment lines */ if (*temp == '#') { - current = next; + curr = next; memset(line, 0, 256); continue; } @@ -204,7 +204,7 @@ DBG("Found %s\n", name); moduleid++; free_entry++; - current = next; + curr = next; memset(line, 0, 256); } diff -Nru a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c --- a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c Thu Sep 11 23:03:13 2003 +++ b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c Thu Sep 11 23:03:13 2003 @@ -544,7 +544,7 @@ pci_read_config_byte(device_dev, PCI_INTERRUPT_PIN, (unsigned char *)&lines); - irqpdaindr->current = device_dev; + irqpdaindr->curr = device_dev; intr_handle = pciio_intr_alloc(device_vertex, NULL, lines, device_vertex); irq = intr_handle->pi_irq; diff -Nru a/arch/ia64/sn/io/machvec/pci_dma.c b/arch/ia64/sn/io/machvec/pci_dma.c --- a/arch/ia64/sn/io/machvec/pci_dma.c Thu Sep 11 23:03:12 2003 +++ b/arch/ia64/sn/io/machvec/pci_dma.c Thu Sep 11 23:03:12 2003 @@ -597,7 +597,7 @@ if (!sn_dma_supported(dev, dma_mask)) return 0; - dev->dma_mask = dma_mask; + *dev->dma_mask = dma_mask; return 1; } EXPORT_SYMBOL(sn_dma_set_mask); diff -Nru a/arch/ia64/sn/io/sn2/ml_SN_intr.c b/arch/ia64/sn/io/sn2/ml_SN_intr.c --- a/arch/ia64/sn/io/sn2/ml_SN_intr.c Thu Sep 11 23:03:13 2003 +++ b/arch/ia64/sn/io/sn2/ml_SN_intr.c Thu Sep 11 23:03:13 2003 @@ -174,8 +174,8 @@ min_shared = 256; for (i=IA64_SN2_FIRST_DEVICE_VECTOR; i < IA64_SN2_LAST_DEVICE_VECTOR; i++) { /* Share with the same device class */ - if (irqpdaindr->current->vendor == irqpdaindr->device_dev[i]->vendor && - irqpdaindr->current->device == irqpdaindr->device_dev[i]->device && + if (irqpdaindr->curr->vendor == irqpdaindr->device_dev[i]->vendor && + irqpdaindr->curr->device == irqpdaindr->device_dev[i]->device && irqpdaindr->share_count[i] < min_shared) { min_shared = irqpdaindr->share_count[i]; bit = i; diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c --- a/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c Thu Sep 11 23:03:11 2003 +++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c Thu Sep 11 23:03:11 2003 @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c --- a/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c Thu Sep 11 23:03:13 2003 +++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c Thu Sep 11 23:03:13 2003 @@ -27,7 +27,6 @@ #include #include #include -#include #include #include diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c --- a/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c Thu Sep 11 23:03:14 2003 +++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c Thu Sep 11 23:03:14 2003 @@ -31,7 +31,6 @@ #include #include #include -#include #include #include diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_error.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_error.c --- a/arch/ia64/sn/io/sn2/pcibr/pcibr_error.c Thu Sep 11 23:03:11 2003 +++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_error.c Thu Sep 11 23:03:11 2003 @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_hints.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_hints.c --- a/arch/ia64/sn/io/sn2/pcibr/pcibr_hints.c Thu Sep 11 23:03:13 2003 +++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_hints.c Thu Sep 11 23:03:13 2003 @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c --- a/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c Thu Sep 11 23:03:13 2003 +++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c Thu Sep 11 23:03:13 2003 @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c --- a/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c Thu Sep 11 23:03:14 2003 +++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c Thu Sep 11 23:03:14 2003 @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c --- a/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c Thu Sep 11 23:03:12 2003 +++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c Thu Sep 11 23:03:12 2003 @@ -27,7 +27,6 @@ #include #include #include -#include #include #include diff -Nru a/arch/ia64/sn/io/sn2/pic.c b/arch/ia64/sn/io/sn2/pic.c --- a/arch/ia64/sn/io/sn2/pic.c Thu Sep 11 23:03:13 2003 +++ b/arch/ia64/sn/io/sn2/pic.c Thu Sep 11 23:03:13 2003 @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff -Nru a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c --- a/arch/mips/kernel/irixelf.c Thu Sep 11 23:03:14 2003 +++ b/arch/mips/kernel/irixelf.c Thu Sep 11 23:03:14 2003 @@ -1088,6 +1088,7 @@ elf.e_ident[EI_CLASS] = ELFCLASS32; elf.e_ident[EI_DATA] = ELFDATA2LSB; elf.e_ident[EI_VERSION] = EV_CURRENT; + elf.e_ident[EI_OSABI] = ELF_OSABI; memset(elf.e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD); elf.e_type = ET_CORE; diff -Nru a/arch/parisc/Kconfig b/arch/parisc/Kconfig --- a/arch/parisc/Kconfig Thu Sep 11 23:03:13 2003 +++ b/arch/parisc/Kconfig Thu Sep 11 23:03:13 2003 @@ -184,7 +184,7 @@ source "drivers/md/Kconfig" -#source drivers/message/fusion/Kconfig +source drivers/message/fusion/Kconfig #source drivers/ieee1394/Kconfig diff -Nru a/arch/parisc/Makefile b/arch/parisc/Makefile --- a/arch/parisc/Makefile Thu Sep 11 23:03:13 2003 +++ b/arch/parisc/Makefile Thu Sep 11 23:03:13 2003 @@ -16,7 +16,7 @@ # Modified for PA-RISC Linux by Paul Lahaie, Alex deVries, # Mike Shaver, Helge Deller and Martin K. Petersen # - +NM = sh arch/parisc/nm ifdef CONFIG_PARISC64 CROSS_COMPILE := hppa64-linux- UTS_MACHINE := parisc64 diff -Nru a/arch/parisc/defconfig b/arch/parisc/defconfig --- a/arch/parisc/defconfig Thu Sep 11 23:03:11 2003 +++ b/arch/parisc/defconfig Thu Sep 11 23:03:11 2003 @@ -150,24 +150,25 @@ CONFIG_SCSI_LASI700=y CONFIG_53C700_MEM_MAPPED=y CONFIG_53C700_LE_ON_BE=y -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set CONFIG_SCSI_ZALON=y -# CONFIG_SCSI_NCR53C8XX is not set -CONFIG_SCSI_SYM53C8XX=y CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 CONFIG_SCSI_NCR53C8XX_SYNC=20 # CONFIG_SCSI_NCR53C8XX_PROFILE is not set -# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set # CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set # CONFIG_SCSI_PCI2000 is not set # CONFIG_SCSI_PCI2220I is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_SIM710 is not set +# CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_U14_34F is not set # CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set @@ -374,7 +375,6 @@ # CONFIG_SERIO_CT82C710 is not set # CONFIG_SERIO_PARKBD is not set CONFIG_HP_SDC=y -CONFIG_HIL_MLC=y # # Input Device Drivers diff -Nru a/arch/parisc/hpux/wrappers.S b/arch/parisc/hpux/wrappers.S --- a/arch/parisc/hpux/wrappers.S Thu Sep 11 23:03:13 2003 +++ b/arch/parisc/hpux/wrappers.S Thu Sep 11 23:03:13 2003 @@ -21,17 +21,20 @@ */ #ifdef __LP64__ -#warning Must be changed for PA64 +#warning PA64 support needs more work...did first cut #endif #include +#include +#include +#ifdef __LP64__ + .level 2.0w +#else .level 1.1 +#endif .text -#include -#include - /* These should probably go in a header file somewhere. * They are duplicated in kernel/wrappers.S * Possibly we should consider consolidating these @@ -41,41 +44,41 @@ #ifdef __LP64__ #warning NEEDS WORK for 64-bit #endif - stw %r3, PT_GR3(\regs) - stw %r4, PT_GR4(\regs) - stw %r5, PT_GR5(\regs) - stw %r6, PT_GR6(\regs) - stw %r7, PT_GR7(\regs) - stw %r8, PT_GR8(\regs) - stw %r9, PT_GR9(\regs) - stw %r10,PT_GR10(\regs) - stw %r11,PT_GR11(\regs) - stw %r12,PT_GR12(\regs) - stw %r13,PT_GR13(\regs) - stw %r14,PT_GR14(\regs) - stw %r15,PT_GR15(\regs) - stw %r16,PT_GR16(\regs) - stw %r17,PT_GR17(\regs) - stw %r18,PT_GR18(\regs) + STREG %r3, PT_GR3(\regs) + STREG %r4, PT_GR4(\regs) + STREG %r5, PT_GR5(\regs) + STREG %r6, PT_GR6(\regs) + STREG %r7, PT_GR7(\regs) + STREG %r8, PT_GR8(\regs) + STREG %r9, PT_GR9(\regs) + STREG %r10,PT_GR10(\regs) + STREG %r11,PT_GR11(\regs) + STREG %r12,PT_GR12(\regs) + STREG %r13,PT_GR13(\regs) + STREG %r14,PT_GR14(\regs) + STREG %r15,PT_GR15(\regs) + STREG %r16,PT_GR16(\regs) + STREG %r17,PT_GR17(\regs) + STREG %r18,PT_GR18(\regs) .endm .macro reg_restore regs - ldw PT_GR3(\regs), %r3 - ldw PT_GR4(\regs), %r4 - ldw PT_GR5(\regs), %r5 - ldw PT_GR6(\regs), %r6 - ldw PT_GR7(\regs), %r7 - ldw PT_GR8(\regs), %r8 - ldw PT_GR9(\regs), %r9 - ldw PT_GR10(\regs),%r10 - ldw PT_GR11(\regs),%r11 - ldw PT_GR12(\regs),%r12 - ldw PT_GR13(\regs),%r13 - ldw PT_GR14(\regs),%r14 - ldw PT_GR15(\regs),%r15 - ldw PT_GR16(\regs),%r16 - ldw PT_GR17(\regs),%r17 - ldw PT_GR18(\regs),%r18 + LDREG PT_GR3(\regs), %r3 + LDREG PT_GR4(\regs), %r4 + LDREG PT_GR5(\regs), %r5 + LDREG PT_GR6(\regs), %r6 + LDREG PT_GR7(\regs), %r7 + LDREG PT_GR8(\regs), %r8 + LDREG PT_GR9(\regs), %r9 + LDREG PT_GR10(\regs),%r10 + LDREG PT_GR11(\regs),%r11 + LDREG PT_GR12(\regs),%r12 + LDREG PT_GR13(\regs),%r13 + LDREG PT_GR14(\regs),%r14 + LDREG PT_GR15(\regs),%r15 + LDREG PT_GR16(\regs),%r16 + LDREG PT_GR17(\regs),%r17 + LDREG PT_GR18(\regs),%r18 .endm @@ -88,18 +91,18 @@ ;! pointer in task reg_save %r1 - stw %r2,-20(%r30) + STREG %r2,-20(%r30) ldo 64(%r30),%r30 - stw %r2,PT_GR19(%r1) ;! save for child - stw %r30,PT_GR21(%r1) ;! save for child + STREG %r2,PT_GR19(%r1) ;! save for child + STREG %r30,PT_GR21(%r1) ;! save for child - ldw PT_GR30(%r1),%r25 - mtctl %r25,%cr29 + LDREG PT_GR30(%r1),%r25 + mtctl %r25,%cr29 copy %r1,%r24 bl sys_clone,%r2 ldi SIGCHLD,%r26 - ldw -84(%r30),%r2 + LDREG -84(%r30),%r2 fork_return: ldo -64(%r30),%r30 ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs @@ -116,14 +119,14 @@ * know the difference. We can fix this later if necessary. */ - ldo -1024(%r0),%r1 + ldo -1024(%r0),%r1 comb,>>=,n %r28,%r1,fork_exit /* just let the syscall exit handle it */ - or,= %r28,%r0,%r0 - or,tr %r0,%r0,%r29 /* r28 <> 0, we are parent, set r29 to 0 */ - ldo 1(%r0),%r29 /* r28 == 0, we are child, set r29 to 1 */ + or,= %r28,%r0,%r0 + or,tr %r0,%r0,%r29 /* r28 <> 0, we are parent, set r29 to 0 */ + ldo 1(%r0),%r29 /* r28 == 0, we are child, set r29 to 1 */ fork_exit: - bv %r0(%r2) + bv %r0(%r2) nop /* Set the return value for the child */ @@ -134,7 +137,7 @@ nop #endif - ldw TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2 + LDREG TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2 b fork_return copy %r0,%r28 @@ -157,17 +160,17 @@ /* Store arg0, arg1 and arg2 so that hpux_execve will find them */ - stw %r26,PT_GR26(%r1) - stw %r25,PT_GR25(%r1) - stw %r24,PT_GR24(%r1) + STREG %r26,PT_GR26(%r1) + STREG %r25,PT_GR25(%r1) + STREG %r24,PT_GR24(%r1) - stw %r2,-20(%r30) + STREG %r2,-20(%r30) ldo 64(%r30),%r30 bl hpux_execve,%r2 copy %r1,%arg0 ldo -64(%r30),%r30 - ldw -20(%r30),%r2 + LDREG -20(%r30),%r2 /* If exec succeeded we need to load the args */ @@ -175,10 +178,10 @@ comb,>>= %r28,%r1,exec_error copy %r2,%r19 ldo -TASK_SZ_ALGN-64(%r30),%r1 ;! get task ptr - ldw TASK_PT_GR26(%r1),%r26 - ldw TASK_PT_GR25(%r1),%r25 - ldw TASK_PT_GR24(%r1),%r24 - ldw TASK_PT_GR23(%r1),%r23 + LDREG TASK_PT_GR26(%r1),%r26 + LDREG TASK_PT_GR25(%r1),%r25 + LDREG TASK_PT_GR24(%r1),%r24 + LDREG TASK_PT_GR23(%r1),%r23 copy %r0,%r2 /* Flag to syscall_exit not to clear args */ exec_error: @@ -191,7 +194,7 @@ /* HP-UX expects pipefd's returned in r28 & r29 */ hpux_pipe_wrapper: - stw %r2,-20(%r30) + STREG %r2,-20(%r30) ldo 64(%r30),%r30 bl hpux_pipe,%r2 ldo -56(%r30),%r26 /* pass local array to hpux_pipe */ @@ -199,12 +202,12 @@ ldo -1024(%r0),%r1 comb,>>= %r28,%r1,pipe_exit /* let syscall exit handle it */ - ldw -84(%r30),%r2 + LDREG -84(%r30),%r2 /* if success, load fd's from stack array */ - ldw -56(%r30),%r28 - ldw -52(%r30),%r29 + LDREG -56(%r30),%r28 + LDREG -52(%r30),%r29 pipe_exit: bv %r0(%r2) @@ -251,4 +254,4 @@ hpux_unimplemented_wrapper: b hpux_unimplemented - stw %r22,-64(%r30) /* overwrite arg8 with syscall number */ + STREG %r22,-64(%r30) /* overwrite arg8 with syscall number */ diff -Nru a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c --- a/arch/parisc/kernel/cache.c Thu Sep 11 23:03:12 2003 +++ b/arch/parisc/kernel/cache.c Thu Sep 11 23:03:12 2003 @@ -232,7 +232,8 @@ if (!page->mapping) return; - + /* check shared list first if it's not empty...it's usually + * the shortest */ list_for_each(l, &page->mapping->i_mmap_shared) { struct vm_area_struct *mpnt; unsigned long off; @@ -243,6 +244,33 @@ * If this VMA is not in our MM, we can ignore it. */ if (mpnt->vm_mm != mm) + continue; + + if (page->index < mpnt->vm_pgoff) + continue; + + off = page->index - mpnt->vm_pgoff; + if (off >= (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT) + continue; + + flush_cache_page(mpnt, mpnt->vm_start + (off << PAGE_SHIFT)); + + /* All user shared mappings should be equivalently mapped, + * so once we've flushed one we should be ok + */ + return; + } + + /* then check private mapping list for read only shared mappings + * which are flagged by VM_MAYSHARE */ + list_for_each(l, &page->mapping->i_mmap) { + struct vm_area_struct *mpnt; + unsigned long off; + + mpnt = list_entry(l, struct vm_area_struct, shared); + + + if (mpnt->vm_mm != mm || !(mpnt->vm_flags & VM_MAYSHARE)) continue; if (page->index < mpnt->vm_pgoff) diff -Nru a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c --- a/arch/parisc/kernel/drivers.c Thu Sep 11 23:03:13 2003 +++ b/arch/parisc/kernel/drivers.c Thu Sep 11 23:03:13 2003 @@ -447,7 +447,7 @@ #define MAX_NATIVE_DEVICES 64 #define NATIVE_DEVICE_OFFSET 0x1000 -#define FLEX_MASK (unsigned long)0xfffffffffffc0000 +#define FLEX_MASK F_EXTEND(0xfffc0000) #define IO_IO_LOW offsetof(struct bc_module, io_io_low) #define IO_IO_HIGH offsetof(struct bc_module, io_io_high) #define READ_IO_IO_LOW(dev) (unsigned long)(signed int)__raw_readl(dev->hpa + IO_IO_LOW) @@ -514,7 +514,7 @@ } while(!devices_found && hpa < io_io_high); } -#define CENTRAL_BUS_ADDR (unsigned long) 0xfffffffffff80000 +#define CENTRAL_BUS_ADDR F_EXTEND(0xfff80000) /** * walk_central_bus - Find devices attached to the central bus diff -Nru a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c --- a/arch/parisc/kernel/irq.c Thu Sep 11 23:03:12 2003 +++ b/arch/parisc/kernel/irq.c Thu Sep 11 23:03:12 2003 @@ -842,6 +842,10 @@ return irq_found; } +unsigned int probe_irq_mask(unsigned long irqs) +{ + return 0; +} void __init init_IRQ(void) { diff -Nru a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c --- a/arch/parisc/kernel/module.c Thu Sep 11 23:03:14 2003 +++ b/arch/parisc/kernel/module.c Thu Sep 11 23:03:14 2003 @@ -41,6 +41,13 @@ return -ENOEXEC; \ } +/* Maximum number of GOT entries. We use a long displacement ldd from + * the bottom of the table, which has a maximum signed displacement of + * 0x3fff; however, since we're only going forward, this becomes + * 0x1fff, and thus, since each GOT entry is 8 bytes long we can have + * at most 1023 entries */ +#define MAX_GOTS 1023 + /* three functions to determine where in the module core * or init pieces the location is */ static inline int is_init(struct module *me, void *loc) @@ -300,11 +307,14 @@ got = me->module_core + me->arch.got_offset; for (i = 0; got[i].addr; i++) if (got[i].addr == value) - return i * sizeof(struct got_entry); + goto out; BUG_ON(++me->arch.got_count > me->arch.got_max); got[i].addr = value; + out: + DEBUGP("GOT ENTRY %d[%x] val %lx\n", i, i*sizeof(struct got_entry), + value); return i * sizeof(struct got_entry); } #endif /* __LP64__ */ @@ -387,7 +397,7 @@ stub->insns[2] = 0xe820d000; /* bve (%r1) */ stub->insns[3] = 0x537b0030; /* ldd 18(%dp),%dp */ - stub->insns[0] |= reassemble_14(rrsel(get_got(me, value, addend),0)); + stub->insns[0] |= reassemble_14(get_got(me, value, addend) & 0x3fff); } else { @@ -516,6 +526,9 @@ case R_PARISC_PCREL22F: /* 22-bit PC relative address; only defined for pa20 */ val = get_stub(me, val, addend, 0, is_init(me, loc)); + DEBUGP("STUB FOR %s loc %lx+%lx at %lx\n", + strtab + sym->st_name, (unsigned long)loc, addend, + val) val = (val - dot - 8)/4; CHECK_RELOC(val, 22); *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); @@ -618,6 +631,9 @@ val = get_stub(me, val, addend, 0, is_init(me, loc)); } + DEBUGP("STUB FOR %s loc %lx, val %lx+%lx at %lx\n", + strtab + sym->st_name, loc, sym->st_value, + addend, val); /* FIXME: local symbols work as long as the * core and init pieces aren't separated too * far. If this is ever broken, you will trip @@ -646,6 +662,9 @@ /* 64-bit function address */ if(is_local(me, (void *)(val + addend))) { *loc64 = get_fdesc(me, val+addend); + DEBUGP("FDESC for %s at %p points to %lx\n", + strtab + sym->st_name, *loc64, + ((struct fdesc_entry *)*loc64)->addr); } else { /* if the symbol is not local to this * module then val+addend is a pointer @@ -711,8 +730,13 @@ } } - printk("module %s: strtab %p, symhdr %p\n", + DEBUGP("module %s: strtab %p, symhdr %p\n", me->name, strtab, symhdr); + + if(me->arch.got_count > MAX_GOTS) { + printk(KERN_ERR "%s: Global Offset Table overflow (used %ld, allowed %d\n", me->name, me->arch.got_count, MAX_GOTS); + return -EINVAL; + } /* no symbol table */ if(symhdr == NULL) diff -Nru a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c --- a/arch/parisc/kernel/parisc_ksyms.c Thu Sep 11 23:03:14 2003 +++ b/arch/parisc/kernel/parisc_ksyms.c Thu Sep 11 23:03:14 2003 @@ -37,6 +37,7 @@ #include EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); +EXPORT_SYMBOL(probe_irq_mask); #include EXPORT_SYMBOL(kernel_thread); @@ -200,6 +201,9 @@ EXPORT_SYMBOL(__ashldi3); EXPORT_SYMBOL(__lshrdi3); EXPORT_SYMBOL(__muldi3); + +asmlinkage void * __canonicalize_funcptr_for_compare(void *); +EXPORT_SYMBOL(__canonicalize_funcptr_for_compare); #ifdef __LP64__ extern void __divdi3(void); diff -Nru a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c --- a/arch/parisc/kernel/pci.c Thu Sep 11 23:03:11 2003 +++ b/arch/parisc/kernel/pci.c Thu Sep 11 23:03:11 2003 @@ -25,7 +25,7 @@ #define DEBUG_CONFIG 0 #if DEBUG_CONFIG -# define DBGC(x...) printk(KERN_DEBUG x) +# define DBGC(x...) printk(KERN_DEBUG x) #else # define DBGC(x...) #endif @@ -38,13 +38,15 @@ #endif /* To be used as: mdelay(pci_post_reset_delay); -** -** post_reset is the time the kernel should stall to prevent anyone from -** accessing the PCI bus once #RESET is de-asserted. -** PCI spec somewhere says 1 second but with multi-PCI bus systems, -** this makes the boot time much longer than necessary. -** 20ms seems to work for all the HP PCI implementations to date. -*/ + * + * post_reset is the time the kernel should stall to prevent anyone from + * accessing the PCI bus once #RESET is de-asserted. + * PCI spec somewhere says 1 second but with multi-PCI bus systems, + * this makes the boot time much longer than necessary. + * 20ms seems to work for all the HP PCI implementations to date. + * + * XXX: turn into a #defined constant in ? + */ int pci_post_reset_delay = 50; struct pci_port_ops *pci_port; @@ -52,9 +54,7 @@ int pci_hba_count = 0; -/* -** parisc_pci_hba used by pci_port->in/out() ops to lookup bus data. -*/ +/* parisc_pci_hba used by pci_port->in/out() ops to lookup bus data. */ #define PCI_HBA_MAX 32 struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX]; @@ -129,8 +129,6 @@ /* Called from pci_do_scan_bus() *after* walking a bus but before walking PPBs. */ void pcibios_fixup_bus(struct pci_bus *bus) { - ASSERT(pci_bios != NULL); - if (pci_bios->fixup_bus) { pci_bios->fixup_bus(bus); } else { @@ -145,64 +143,26 @@ } -/* -** Used in drivers/pci/quirks.c -*/ +/* Used in drivers/pci/quirks.c */ struct pci_fixup pcibios_fixups[] = { {0} }; /* -** called by drivers/pci/setup.c:pdev_fixup_irq() -*/ -void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) -{ -/* -** updates IRQ_LINE cfg register to reflect PCI-PCI bridge skewing. -** -** Calling path for Alpha is: -** alpha/kernel/pci.c:common_init_pci(swizzle_func, pci_map_irq_func ) -** drivers/pci/setup.c:pci_fixup_irqs() -** drivers/pci/setup.c:pci_fixup_irq() (for each PCI device) -** invoke swizzle and map functions -** alpha/kernel/pci.c:pcibios_update_irq() -** -** Don't need this for PA legacy PDC systems. -** -** On PAT PDC systems, We only support one "swizzle" for any number -** of PCI-PCI bridges deep. That's how bit3 PCI expansion chassis -** are implemented. The IRQ lines are "skewed" for all devices but -** *NOT* routed through the PCI-PCI bridge. Ie any device "0" will -** share an IRQ line. Legacy PDC is expecting this IRQ line routing -** as well. -** -** Unfortunately, PCI spec allows the IRQ lines to be routed -** around the PCI bridge as long as the IRQ lines are skewed -** based on the device number...... -** -** Lastly, dino.c might be able to use pci_fixup_irq() to -** support RS-232 and PS/2 children. Not sure how but it's -** something to think about. -*/ -} - - -/* -** Called by pci_set_master() - a driver interface. -** -** Legacy PDC guarantees to set: -** Map Memory BAR's into PA IO space. -** Map Expansion ROM BAR into one common PA IO space per bus. -** Map IO BAR's into PCI IO space. -** Command (see below) -** Cache Line Size -** Latency Timer -** Interrupt Line -** PPB: secondary latency timer, io/mmio base/limit, -** bus numbers, bridge control -** -*/ -void -pcibios_set_master(struct pci_dev *dev) + * Called by pci_set_master() - a driver interface. + * + * Legacy PDC guarantees to set: + * Map Memory BAR's into PA IO space. + * Map Expansion ROM BAR into one common PA IO space per bus. + * Map IO BAR's into PCI IO space. + * Command (see below) + * Cache Line Size + * Latency Timer + * Interrupt Line + * PPB: secondary latency timer, io/mmio base/limit, + * bus numbers, bridge control + * + */ +void pcibios_set_master(struct pci_dev *dev) { u8 lat; @@ -214,43 +174,36 @@ ** HP generally has fewer devices on the bus than other architectures. ** upper byte is PCI_LATENCY_TIMER. */ - pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, + pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, (0x80 << 8) | (L1_CACHE_BYTES / sizeof(u32))); } -void __init -pcibios_init_bus(struct pci_bus *bus) +void __init pcibios_init_bus(struct pci_bus *bus) { struct pci_dev *dev = bus->self; + unsigned short bridge_ctl; /* We deal only with pci controllers and pci-pci bridges. */ - if (dev && (dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) + if (!dev || (dev->class >> 8) != PCI_CLASS_BRIDGE_PCI) return; - - if (dev) { - unsigned short bridge_ctl; - - /* PCI-PCI bridge - set the cache line and default latency - (32) for primary and secondary buses. */ - pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 32); - - /* Read bridge control */ - pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bridge_ctl); - pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bridge_ctl - | PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR); - } + /* PCI-PCI bridge - set the cache line and default latency + (32) for primary and secondary buses. */ + pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 32); + + pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bridge_ctl); + bridge_ctl |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR; + pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bridge_ctl); } -/* -** KLUGE: Link the child and parent resources - generic PCI didn't -*/ +/* KLUGE: Link the child and parent resources - generic PCI didn't */ static void pcibios_link_hba_resources( struct resource *hba_res, struct resource *r) { if (!r->parent) { + printk(KERN_EMERG "PCI: Tell willy he's wrong\n"); r->parent = hba_res; /* reverse link is harder *sigh* */ @@ -268,14 +221,9 @@ } } -/* -** called by drivers/pci/setup-res.c:pci_setup_bridge(). -*/ -void __devinit pcibios_resource_to_bus( - struct pci_dev *dev, - struct pci_bus_region *region, - struct resource *res - ) +/* called by drivers/pci/setup-bus.c:pci_setup_bridge(). */ +void __devinit pcibios_resource_to_bus(struct pci_dev *dev, + struct pci_bus_region *region, struct resource *res) { struct pci_bus *bus = dev->bus; struct pci_hba_data *hba = HBA_DATA(bus->dev->platform_data); @@ -313,17 +261,16 @@ #endif /* -** pcibios align resources() is called everytime generic PCI code -** wants to generate a new address. The process of looking for -** an available address, each candidate is first "aligned" and -** then checked if the resource is available until a match is found. -** -** Since we are just checking candidates, don't use any fields other -** than res->start. -*/ -void __devinit -pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long alignment) + * pcibios align resources() is called every time generic PCI code + * wants to generate a new address. The process of looking for + * an available address, each candidate is first "aligned" and + * then checked if the resource is available until a match is found. + * + * Since we are just checking candidates, don't use any fields other + * than res->start. + */ +void pcibios_align_resource(void *data, struct resource *res, + unsigned long size, unsigned long alignment) { unsigned long mask, align; @@ -332,10 +279,6 @@ res->parent, res->start, res->end, (int) res->flags, size, alignment); - /* has resource already been aligned/assigned? */ - if (res->parent) - return; - /* If it's not IO, then it's gotta be MEM */ align = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; @@ -344,32 +287,26 @@ res->start += mask; res->start &= ~mask; - /* - ** WARNING : caller is expected to update "end" field. - ** We can't since it might really represent the *size*. - ** The difference is "end = start + size" vs "end += start". - */ + /* The caller updates the end field, we don't. */ } -int __devinit -pcibios_enable_device(struct pci_dev *dev, int mask) +/* + * A driver is enabling the device. We make sure that all the appropriate + * bits are set to allow the device to operate as the driver is expecting. + * We enable the port IO and memory IO bits if the device has any BARs of + * that type, and we enable the PERR and SERR bits unconditionally. + * Drivers that do not need parity (eg graphics and possibly networking) + * can clear these bits if they want. + */ +int pcibios_enable_device(struct pci_dev *dev, int mask) { u16 cmd; int idx; - /* - ** The various platform PDC's (aka "BIOS" for PCs) don't - ** enable all the same bits. We just make sure they are here. - */ pci_read_config_word(dev, PCI_COMMAND, &cmd); - /* - ** See if any resources have been allocated - ** While "regular" PCI devices only use 0-5, Bridges use a few - ** beyond that for window registers. - */ - for (idx=0; idxresource[idx]; /* only setup requested resources */ @@ -382,14 +319,6 @@ cmd |= PCI_COMMAND_MEMORY; } - /* - ** Enable System error and Parity Error reporting by default. - ** Devices that do NOT want those behaviors should clear them - ** (eg PCI graphics, possibly networking). - ** Interfaces like SCSI certainly should not. We want the - ** system to crash if a system or parity error is detected. - ** At least until the device driver can recover from such an error. - */ cmd |= (PCI_COMMAND_SERR | PCI_COMMAND_PARITY); #if 0 @@ -402,30 +331,15 @@ return 0; } -void __init -pcibios_setup_host_bridge(struct pci_bus *bus) -{ - ASSERT(pci_bios != NULL); -#if 0 - if (pci_bios) - { - if (pci_bios->setup_host_bridge) { - (*pci_bios->setup_host_bridge)(bus); - } - } -#endif -} - - -/* -** PARISC specific (unfortunately) -*/ +/* PA-RISC specific */ void pcibios_register_hba(struct pci_hba_data *hba) { - ASSERT(pci_hba_count < PCI_HBA_MAX); + if (pci_hba_count >= PCI_HBA_MAX) { + printk(KERN_ERR "PCI: Too many Host Bus Adapters\n"); + return; + } - /* pci_port->in/out() uses parisc_pci_hba to lookup parameter. */ parisc_pci_hba[pci_hba_count] = hba; hba->hba_num = pci_hba_count++; } diff -Nru a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c --- a/arch/parisc/kernel/process.c Thu Sep 11 23:03:14 2003 +++ b/arch/parisc/kernel/process.c Thu Sep 11 23:03:14 2003 @@ -19,7 +19,6 @@ #include #include #include -#include #include #include diff -Nru a/arch/parisc/kernel/real2.S b/arch/parisc/kernel/real2.S --- a/arch/parisc/kernel/real2.S Thu Sep 11 23:03:12 2003 +++ b/arch/parisc/kernel/real2.S Thu Sep 11 23:03:12 2003 @@ -123,7 +123,7 @@ nop restore_control_regs: - load32 PA(save_cr_space + (N_SAVED_REGS * REG_SZ)), %r26 + load32 PA(save_cr_space+(N_SAVED_REGS*REG_SZ)), %r26 POP_CR(%cr15, %r26) POP_CR(%cr31, %r26) POP_CR(%cr30, %r26) @@ -275,6 +275,7 @@ nop #endif + .export pc_in_user_space .text /* Doesn't belong here but I couldn't find a nicer spot. */ @@ -283,3 +284,17 @@ bv,n 0(%rp) nop + + .export __canonicalize_funcptr_for_compare + .text + /* http://lists.parisc-linux.org/hypermail/parisc-linux/10916.html + ** GCC 3.3 and later has a new function in libgcc.a for + ** comparing function pointers. + */ +__canonicalize_funcptr_for_compare: +#ifdef __LP64__ + bve (%r2) +#else + bv %r0(%r2) +#endif + copy %r26,%r28 diff -Nru a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c --- a/arch/parisc/kernel/signal.c Thu Sep 11 23:03:14 2003 +++ b/arch/parisc/kernel/signal.c Thu Sep 11 23:03:14 2003 @@ -13,7 +13,6 @@ * arch/parisc/hpux/signal.c when we figure out how to do them. */ -#include #include #include #include @@ -458,6 +457,8 @@ if (in_syscall) { /* Check the return code */ switch (regs->gr[28]) { + case -ERESTART_RESTARTBLOCK: + current_thread_info()->restart_block.fn = do_no_restart_syscall; case -ERESTARTNOHAND: DBG(("ERESTARTNOHAND: returning -EINTR\n")); regs->gr[28] = -EINTR; @@ -495,7 +496,8 @@ /* Did we come from a system call? */ if (in_syscall) { /* Restart the system call - no handlers present */ - if (regs->gr[28] == -ERESTARTNOHAND || + if (regs->gr[28] == -ERESTART_RESTARTBLOCK || + regs->gr[28] == -ERESTARTNOHAND || regs->gr[28] == -ERESTARTSYS || regs->gr[28] == -ERESTARTNOINTR) { /* Hooray for delayed branching. We don't diff -Nru a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c --- a/arch/parisc/kernel/sys_parisc.c Thu Sep 11 23:03:13 2003 +++ b/arch/parisc/kernel/sys_parisc.c Thu Sep 11 23:03:13 2003 @@ -30,8 +30,6 @@ { struct vm_area_struct *vma; - if (!addr) - addr = TASK_UNMAPPED_BASE; addr = PAGE_ALIGN(addr); for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { @@ -46,17 +44,38 @@ #define DCACHE_ALIGN(addr) (((addr) + (SHMLBA - 1)) &~ (SHMLBA - 1)) -static unsigned long get_shared_area(struct inode *inode, unsigned long addr, - unsigned long len, unsigned long pgoff) +/* + * We need to know the offset to use. Old scheme was to look for + * existing mapping and use the same offset. New scheme is to use the + * address of the kernel data structure as the seed for the offset. + * We'll see how that works... + */ +#if 0 +static int get_offset(struct address_space *mapping) { - struct vm_area_struct *vma, *first_vma; - int offset; + struct vm_area_struct *vma = list_entry(mapping->i_mmap_shared.next, + struct vm_area_struct, shared); + return (vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT)) & + (SHMLBA - 1); +} +#else +/* The mapping is cacheline aligned, so there's no information in the bottom + * few bits of the address. We're looking for 10 bits (4MB / 4k), so let's + * drop the bottom 8 bits and use bits 8-17. + */ +static int get_offset(struct address_space *mapping) +{ + int offset = (int) mapping << (PAGE_SHIFT - 8); + return offset & 0x3FF000; +} +#endif - first_vma = list_entry(inode->i_mapping->i_mmap_shared.next, struct vm_area_struct, shared); - offset = (first_vma->vm_start + ((pgoff - first_vma->vm_pgoff) << PAGE_SHIFT)) & (SHMLBA - 1); +static unsigned long get_shared_area(struct address_space *mapping, + unsigned long addr, unsigned long len, unsigned long pgoff) +{ + struct vm_area_struct *vma; + int offset = get_offset(mapping); - if (!addr) - addr = TASK_UNMAPPED_BASE; addr = DCACHE_ALIGN(addr - offset) + offset; for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { @@ -74,17 +93,17 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) { - struct inode *inode = NULL; + struct inode *inode; if (len > TASK_SIZE) return -ENOMEM; + if (!addr) + addr = TASK_UNMAPPED_BASE; - if (filp) { - inode = filp->f_dentry->d_inode; - } + inode = filp ? filp->f_dentry->d_inode : NULL; - if (inode && (flags & MAP_SHARED) && (!list_empty(&inode->i_mapping->i_mmap_shared))) { - addr = get_shared_area(inode, addr, len, pgoff); + if (inode && (flags & MAP_SHARED)) { + addr = get_shared_area(inode->i_mapping, addr, len, pgoff); } else { addr = get_unshared_area(addr, len); } @@ -185,6 +204,7 @@ size_t count, loff_t pos); extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char *buf, size_t count, loff_t pos); +extern asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count); asmlinkage ssize_t parisc_pread64(unsigned int fd, char *buf, size_t count, unsigned int high, unsigned int low) @@ -198,6 +218,11 @@ return sys_pwrite64(fd, buf, count, (loff_t)high << 32 | low); } +asmlinkage ssize_t parisc_readahead(int fd, unsigned int high, unsigned int low, + size_t count) +{ + return sys_readahead(fd, (loff_t)high << 32 | low, count); +} /* * FIXME, please remove this crap as soon as possible @@ -271,7 +296,7 @@ tbuf.shm_cpid = sbuf->shm_cpid; tbuf.shm_lpid = sbuf->shm_lpid; tbuf.shm_nattch = sbuf->shm_nattch; - return copy_to_user(buf, &tbuf, sizeof tbuf); + return copy_to_user(buf, &tbuf, sizeof tbuf) ? -EFAULT : 0; } int sys_msgctl_broken(int msqid, int cmd, struct msqid_ds *buf) diff -Nru a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c --- a/arch/parisc/kernel/sys_parisc32.c Thu Sep 11 23:03:12 2003 +++ b/arch/parisc/kernel/sys_parisc32.c Thu Sep 11 23:03:12 2003 @@ -46,6 +46,7 @@ #include #include #include +#include #include #include @@ -373,18 +374,16 @@ return copy_to_user(u, &t32, sizeof t32); } -static int -get_compat_timeval(struct compat_timeval *u, struct timeval *t) +static inline long get_ts32(struct timespec *o, struct compat_timeval *i) { - int err; - struct compat_timeval t32; + long usec; - if ((err = copy_from_user(&t32, u, sizeof t32)) == 0) - { - t->tv_sec = t32.tv_sec; - t->tv_usec = t32.tv_usec; - } - return err; + if (__get_user(o->tv_sec, &i->tv_sec)) + return -EFAULT; + if (__get_user(usec, &i->tv_usec)) + return -EFAULT; + o->tv_nsec = usec * 1000; + return 0; } asmlinkage long sys32_time(compat_time_t *tloc) @@ -418,23 +417,22 @@ return 0; } -asmlinkage int -sys32_settimeofday(struct compat_timespec *tv, struct timezone *tz) +asmlinkage +int sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz) { - struct timeval ktv; - struct timezone ktz; - extern int do_sys_settimeofday(struct timespec *tv, struct timezone *tz); + struct timespec kts; + struct timezone ktz; - if (tv) { - if (get_compat_timeval(tv, &ktv)) - return -EFAULT; - } - if (tz) { - if (copy_from_user(&ktz, tz, sizeof(ktz))) - return -EFAULT; - } + if (tv) { + if (get_ts32(&kts, tv)) + return -EFAULT; + } + if (tz) { + if (copy_from_user(&ktz, tz, sizeof(ktz))) + return -EFAULT; + } - return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL); + return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); } int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf) @@ -1087,6 +1085,27 @@ kfree(mb); return err; +} + + +extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count); +asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 count) +{ + mm_segment_t old_fs = get_fs(); + int ret; + off_t of; + + if (offset && get_user(of, offset)) + return -EFAULT; + + set_fs(KERNEL_DS); + ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count); + set_fs(old_fs); + + if (offset && put_user(of, offset)) + return -EFAULT; + + return ret; } /* EXPORT/UNEXPORT */ diff -Nru a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S --- a/arch/parisc/kernel/syscall.S Thu Sep 11 23:03:14 2003 +++ b/arch/parisc/kernel/syscall.S Thu Sep 11 23:03:14 2003 @@ -483,7 +483,7 @@ ENTRY_SAME(madvise) ENTRY_SAME(clone_wrapper) /* 120 */ ENTRY_SAME(setdomainname) - ENTRY_SAME(sendfile) + ENTRY_DIFF(sendfile) /* struct sockaddr... */ ENTRY_SAME(recvfrom) /* struct timex contains longs */ @@ -592,7 +592,7 @@ ENTRY_SAME(ni_syscall) ENTRY_SAME(ni_syscall) /* 205 */ ENTRY_SAME(gettid) - ENTRY_SAME(readahead) + ENTRY_OURS(readahead) ENTRY_SAME(ni_syscall) /* tkill */ ENTRY_SAME(sendfile64) diff -Nru a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c --- a/arch/parisc/kernel/traps.c Thu Sep 11 23:03:14 2003 +++ b/arch/parisc/kernel/traps.c Thu Sep 11 23:03:14 2003 @@ -221,6 +221,8 @@ return; } + oops_in_progress = 1; + /* Amuse the user in a SPARC fashion */ printk( " _______________________________ \n" @@ -413,6 +415,8 @@ void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long offset) { static spinlock_t terminate_lock = SPIN_LOCK_UNLOCKED; + + oops_in_progress = 1; set_eiem(0); local_irq_disable(); diff -Nru a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/parisc/kernel/vmlinux.lds.S Thu Sep 11 23:03:11 2003 @@ -0,0 +1,125 @@ +#include +#include + +/* ld script to make hppa Linux kernel */ +#ifndef CONFIG_PARISC64 +OUTPUT_FORMAT("elf32-hppa-linux") +OUTPUT_ARCH(hppa) +#else +OUTPUT_FORMAT("elf64-hppa-linux") +OUTPUT_ARCH(hppa:hppa2.0w) +#endif + +ENTRY(_stext) +#ifndef CONFIG_PARISC64 +jiffies = jiffies_64 + 4; +#else +jiffies = jiffies_64; +#endif +SECTIONS +{ + + . = 0x10100000; + + _text = .; /* Text and read-only data */ + .text BLOCK(16) : { + *(.text*) + *(.PARISC.unwind) + *(.fixup) + *(.lock.text) /* out-of-line lock text */ + *(.gnu.warning) + } = 0 + + _etext = .; /* End of text section */ + + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + RODATA + + .data BLOCK(8192) : { /* Data without special */ + data_start = .; + *(.data) + } + +#ifdef CONFIG_PARISC64 + . = ALIGN(16); /* Linkage tables */ + .opd : { *(.opd) } PROVIDE (__gp = .); + .plt : { *(.plt) } + .dlt : { *(.dlt) } +#endif + + . = ALIGN(16384); + __init_begin = .; + .init.text : { + _sinittext = .; + *(.init.text) + _einittext = .; + } + .init.data : { *(.init.data) } + . = ALIGN(16); + __setup_start = .; + .init.setup : { *(.init.setup) } + __setup_end = .; + __start___param =.; + __param : { *(__param) } + __stop___param = .; + __initcall_start = .; + .initcall.init : { + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + } + __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; + SECURITY_INIT + . = ALIGN(4096); + __initramfs_start = .; + .init.ramfs : { *(.init.ramfs) } + __initramfs_end = .; + . = ALIGN(32); + __per_cpu_start = .; + .data.percpu : { *(.data.percpu) } + __per_cpu_end = .; + . = ALIGN(4096); + __init_end = .; + + init_task BLOCK(16384) : { *(init_task) } /* The initial task and kernel stack */ + + _edata = .; /* End of data section */ + + + .bss : { *(.bss) *(COMMON) } /* BSS */ + + + _end = . ; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .note 0 : { *(.note) } + +#ifdef CONFIG_PARISC64 + /* temporary hack until binutils is fixed to not emit these + for static binaries */ + /DISCARD/ : { + *(.dynsym) + *(.dynstr) + *(.dynamic) + *(.hash) + } +#endif +} diff -Nru a/arch/parisc/nm b/arch/parisc/nm --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/parisc/nm Thu Sep 11 23:03:14 2003 @@ -0,0 +1,6 @@ +#!/bin/sh +## +# Hack to have an nm which removes the local symbols. We also rely +# on this nm being hidden out of the ordinarily executable path +## +${CROSS_COMPILE}nm $* | grep -v '.LC*[0-9]*$' diff -Nru a/arch/parisc/vmlinux.lds.S b/arch/parisc/vmlinux.lds.S --- a/arch/parisc/vmlinux.lds.S Thu Sep 11 23:03:11 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,125 +0,0 @@ -#include -#include - -/* ld script to make hppa Linux kernel */ -#ifndef CONFIG_PARISC64 -OUTPUT_FORMAT("elf32-hppa-linux") -OUTPUT_ARCH(hppa) -#else -OUTPUT_FORMAT("elf64-hppa-linux") -OUTPUT_ARCH(hppa:hppa2.0w) -#endif - -ENTRY(_stext) -#ifndef CONFIG_PARISC64 -jiffies = jiffies_64 + 4; -#else -jiffies = jiffies_64; -#endif -SECTIONS -{ - - . = 0x10100000; - - _text = .; /* Text and read-only data */ - .text BLOCK(16) : { - *(.text*) - *(.PARISC.unwind) - *(.fixup) - *(.lock.text) /* out-of-line lock text */ - *(.gnu.warning) - } = 0 - - _etext = .; /* End of text section */ - - . = ALIGN(16); /* Exception table */ - __start___ex_table = .; - __ex_table : { *(__ex_table) } - __stop___ex_table = .; - - RODATA - - .data BLOCK(8192) : { /* Data without special */ - data_start = .; - *(.data) - } - -#ifdef CONFIG_PARISC64 - . = ALIGN(16); /* Linkage tables */ - .opd : { *(.opd) } PROVIDE (__gp = .); - .plt : { *(.plt) } - .dlt : { *(.dlt) } -#endif - - . = ALIGN(16384); - __init_begin = .; - .init.text : { - _sinittext = .; - *(.init.text) - _einittext = .; - } - .init.data : { *(.init.data) } - . = ALIGN(16); - __setup_start = .; - .init.setup : { *(.init.setup) } - __setup_end = .; - __start___param =.; - __param : { *(__param) } - __stop___param = .; - __initcall_start = .; - .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) - } - __initcall_end = .; - __con_initcall_start = .; - .con_initcall.init : { *(.con_initcall.init) } - __con_initcall_end = .; - SECURITY_INIT - . = ALIGN(4096); - __initramfs_start = .; - .init.ramfs : { *(.init.ramfs) } - __initramfs_end = .; - . = ALIGN(32); - __per_cpu_start = .; - .data.percpu : { *(.data.percpu) } - __per_cpu_end = .; - . = ALIGN(4096); - __init_end = .; - - init_task BLOCK(16384) : { *(init_task) } /* The initial task and kernel stack */ - - _edata = .; /* End of data section */ - - - .bss : { *(.bss) *(COMMON) } /* BSS */ - - - _end = . ; - - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - .note 0 : { *(.note) } - -#ifdef CONFIG_PARISC64 - /* temporary hack until binutils is fixed to not emit these - for static binaries */ - /DISCARD/ : { - *(.dynsym) - *(.dynstr) - *(.dynamic) - *(.hash) - } -#endif -} diff -Nru a/arch/ppc/kernel/align.c b/arch/ppc/kernel/align.c --- a/arch/ppc/kernel/align.c Thu Sep 11 23:03:11 2003 +++ b/arch/ppc/kernel/align.c Thu Sep 11 23:03:11 2003 @@ -21,11 +21,11 @@ unsigned char flags; }; -#if defined(CONFIG_4xx) +#if defined(CONFIG_4xx) || defined(CONFIG_POWER4) #define OPCD(inst) (((inst) & 0xFC000000) >> 26) #define RS(inst) (((inst) & 0x03E00000) >> 21) #define RA(inst) (((inst) & 0x001F0000) >> 16) -#define IS_DFORM(code) ((code) >= 32 && (code) <= 55) +#define IS_XFORM(code) ((code) == 31) #endif #define INVALID { 0, 0 } @@ -61,9 +61,9 @@ { 4, ST+F+S }, /* 00 0 1010: stfs */ { 8, ST+F }, /* 00 0 1011: stfd */ INVALID, /* 00 0 1100 */ - INVALID, /* 00 0 1101 */ + INVALID, /* 00 0 1101: ld/ldu/lwa */ INVALID, /* 00 0 1110 */ - INVALID, /* 00 0 1111 */ + INVALID, /* 00 0 1111: std/stdu */ { 4, LD+U }, /* 00 1 0000: lwzu */ INVALID, /* 00 1 0001 */ { 4, ST+U }, /* 00 1 0010: stwu */ @@ -80,12 +80,12 @@ INVALID, /* 00 1 1101 */ INVALID, /* 00 1 1110 */ INVALID, /* 00 1 1111 */ - INVALID, /* 01 0 0000 */ + INVALID, /* 01 0 0000: ldx */ INVALID, /* 01 0 0001 */ - INVALID, /* 01 0 0010 */ + INVALID, /* 01 0 0010: stdx */ INVALID, /* 01 0 0011 */ INVALID, /* 01 0 0100 */ - INVALID, /* 01 0 0101: lwax?? */ + INVALID, /* 01 0 0101: lwax */ INVALID, /* 01 0 0110 */ INVALID, /* 01 0 0111 */ { 0, LD+HARD }, /* 01 0 1000: lswx */ @@ -96,12 +96,12 @@ INVALID, /* 01 0 1101 */ INVALID, /* 01 0 1110 */ INVALID, /* 01 0 1111 */ - INVALID, /* 01 1 0000 */ + INVALID, /* 01 1 0000: ldux */ INVALID, /* 01 1 0001 */ - INVALID, /* 01 1 0010 */ + INVALID, /* 01 1 0010: stdux */ INVALID, /* 01 1 0011 */ INVALID, /* 01 1 0100 */ - INVALID, /* 01 1 0101: lwaux?? */ + INVALID, /* 01 1 0101: lwaux */ INVALID, /* 01 1 0110 */ INVALID, /* 01 1 0111 */ INVALID, /* 01 1 1000 */ @@ -157,9 +157,9 @@ { 4, ST+F+S }, /* 11 0 1010: stfsx */ { 8, ST+F }, /* 11 0 1011: stfdx */ INVALID, /* 11 0 1100 */ - INVALID, /* 11 0 1101 */ + INVALID, /* 11 0 1101: lmd */ INVALID, /* 11 0 1110 */ - INVALID, /* 11 0 1111 */ + INVALID, /* 11 0 1111: stmd */ { 4, LD+U }, /* 11 1 0000: lwzux */ INVALID, /* 11 1 0001 */ { 4, ST+U }, /* 11 1 0010: stwux */ @@ -184,7 +184,7 @@ fix_alignment(struct pt_regs *regs) { int instr, nb, flags; -#if defined(CONFIG_4xx) +#if defined(CONFIG_4xx) || defined(CONFIG_POWER4) int opcode, f1, f2, f3; #endif int i, t; @@ -199,9 +199,11 @@ CHECK_FULL_REGS(regs); -#if defined(CONFIG_4xx) +#if defined(CONFIG_4xx) || defined(CONFIG_POWER4) /* The 4xx-family processors have no DSISR register, * so we emulate it. + * The POWER4 has a DSISR register but doesn't set it on + * an alignment fault. -- paulus */ instr = *((unsigned int *)regs->nip); @@ -209,7 +211,7 @@ reg = RS(instr); areg = RA(instr); - if (IS_DFORM(opcode)) { + if (!IS_XFORM(opcode)) { f1 = 0; f2 = (instr & 0x04000000) >> 26; f3 = (instr & 0x78000000) >> 27; diff -Nru a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c --- a/arch/ppc/kernel/asm-offsets.c Thu Sep 11 23:03:12 2003 +++ b/arch/ppc/kernel/asm-offsets.c Thu Sep 11 23:03:12 2003 @@ -52,6 +52,7 @@ DEFINE(THREAD_VR0, offsetof(struct thread_struct, vr[0])); DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave)); DEFINE(THREAD_VSCR, offsetof(struct thread_struct, vscr)); + DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr)); #endif /* CONFIG_ALTIVEC */ /* Interrupt register frame */ DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD); @@ -101,7 +102,7 @@ DEFINE(_XER, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, xer)); DEFINE(_DAR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dar)); DEFINE(_DSISR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr)); - /* The PowerPC 400-class processors have neither the DAR nor the DSISR + /* The PowerPC 400-class & Book-E processors have neither the DAR nor the DSISR * SPRs. Hence, we overload them to hold the similar DEAR and ESR SPRs * for such processors. For critical interrupts we use them to * hold SRR0 and SRR1. diff -Nru a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S --- a/arch/ppc/kernel/head.S Thu Sep 11 23:03:12 2003 +++ b/arch/ppc/kernel/head.S Thu Sep 11 23:03:12 2003 @@ -915,7 +915,9 @@ /* enable use of AltiVec after return */ oris r9,r9,MSR_VEC@h mfspr r5,SPRG3 /* current task's THREAD (phys) */ + li r4,1 li r10,THREAD_VSCR + stw r4,THREAD_USED_VR(r5) lvx vr0,r10,r5 mtvscr vr0 REST_32VR(0,r10,r5) diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S --- a/arch/ppc/kernel/misc.S Thu Sep 11 23:03:13 2003 +++ b/arch/ppc/kernel/misc.S Thu Sep 11 23:03:13 2003 @@ -1379,7 +1379,7 @@ .long sys_clock_gettime .long sys_clock_getres .long sys_clock_nanosleep - .long sys_ni_syscall /* reserved for swapcontext */ + .long sys_swapcontext .long sys_tgkill /* 250 */ .long sys_utimes .long sys_statfs64 diff -Nru a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c --- a/arch/ppc/kernel/process.c Thu Sep 11 23:03:12 2003 +++ b/arch/ppc/kernel/process.c Thu Sep 11 23:03:12 2003 @@ -415,6 +415,7 @@ memset(current->thread.vr, 0, sizeof(current->thread.vr)); memset(¤t->thread.vscr, 0, sizeof(current->thread.vscr)); current->thread.vrsave = 0; + current->thread.used_vr = 0; #endif /* CONFIG_ALTIVEC */ } diff -Nru a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c --- a/arch/ppc/kernel/signal.c Thu Sep 11 23:03:14 2003 +++ b/arch/ppc/kernel/signal.c Thu Sep 11 23:03:14 2003 @@ -41,18 +41,6 @@ #define GP_REGS_SIZE min(sizeof(elf_gregset_t), sizeof(struct pt_regs)) -/* - * 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. - */ -#define MSR_USERCHANGE (MSR_FE0 | MSR_FE1) - int do_signal(sigset_t *oldset, struct pt_regs *regs); /* @@ -72,8 +60,8 @@ spin_unlock_irq(¤t->sighand->siglock); regs->result = -EINTR; - regs->ccr |= 0x10000000; regs->gpr[3] = EINTR; + regs->ccr |= 0x10000000; while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); @@ -103,8 +91,8 @@ spin_unlock_irq(¤t->sighand->siglock); regs->result = -EINTR; - regs->ccr |= 0x10000000; regs->gpr[3] = EINTR; + regs->ccr |= 0x10000000; while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); @@ -164,305 +152,389 @@ * */ struct sigregs { - elf_gregset_t gp_regs; - double fp_regs[ELF_NFPREG]; - unsigned long tramp[2]; + struct mcontext mctx; /* all the register values */ /* Programs using the rs6000/xcoff abi can save up to 19 gp regs and 18 fp regs below sp before decrementing it. */ int abigap[56]; }; -struct rt_sigframe -{ - unsigned long _unused[2]; - struct siginfo *pinfo; - void *puc; - struct siginfo info; - struct ucontext uc; -}; - +/* We use the mc_pad field for the signal return trampoline. */ +#define tramp mc_pad /* * 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 + * one rt_sigframe struct (siginfo + ucontext + ABI gap) + * a gap of __SIGNAL_FRAMESIZE+16 bytes + * (the +16 is to get the siginfo and ucontext in the same + * positions as in older kernels). * * Each of these things must be a multiple of 16 bytes in size. * */ -int sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, - struct pt_regs *regs) +struct rt_sigframe { - struct rt_sigframe __user *rt_sf; - struct sigcontext sigctx; - struct sigregs __user *sr; - elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */ - sigset_t set; - stack_t st; + struct siginfo info; + struct ucontext uc; + /* Programs using the rs6000/xcoff abi can save up to 19 gp regs + and 18 fp regs below sp before decrementing it. */ + int abigap[56]; +}; - rt_sf = (struct rt_sigframe __user *)(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); +/* + * Save the current user registers on the user stack. + * We only save the altivec registers if the process has used + * altivec instructions at some point. + */ +static int +save_user_regs(struct pt_regs *regs, struct mcontext *frame, int sigret) +{ + /* save general and floating-point registers */ + CHECK_FULL_REGS(regs); if (regs->msr & MSR_FP) giveup_fpu(current); + if (__copy_to_user(&frame->mc_gregs, regs, GP_REGS_SIZE) + || __copy_to_user(&frame->mc_fregs, current->thread.fpr, + ELF_NFPREG * sizeof(double))) + return 1; - /* restore registers - - * sigctx is initialized to point to the - * preamble frame (where registers are stored) - * see handle_signal() + current->thread.fpscr = 0; /* turn off all fp exceptions */ + +#ifdef CONFIG_ALTIVEC + /* save altivec registers */ + if (current->thread.used_vr) { + if (regs->msr & MSR_VEC) + giveup_altivec(current); + if (__copy_to_user(&frame->mc_vregs, current->thread.vr, + ELF_NVRREG * sizeof(vector128))) + return 1; + /* set MSR_VEC in the saved MSR value to indicate that + frame->mc_vregs contains valid data */ + if (__put_user(regs->msr | MSR_VEC, &frame->mc_gregs[PT_MSR])) + return 1; + } + /* else assert((regs->msr & MSR_VEC) == 0) */ + + /* We always copy to/from vrsave, it's 0 if we don't have or don't + * use altivec. Since VSCR only contains 32 bits saved in the least + * significant bits of a vector, we "cheat" and stuff VRSAVE in the + * most significant bits of that same vector. --BenH */ - sr = (struct sigregs __user *) 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); - memcpy(regs, saved_regs, GP_REGS_SIZE); - if (copy_from_user(current->thread.fpr, &sr->fp_regs, - sizeof(sr->fp_regs))) - goto badframe; + if (__put_user(current->thread.vrsave, (u32 *)&frame->mc_vregs[32])) + return 1; +#endif /* CONFIG_ALTIVEC */ + + if (sigret) { + /* Set up the sigreturn trampoline: li r0,sigret; sc */ + if (__put_user(0x38000000UL + sigret, &frame->tramp[0]) + || __put_user(0x44000002UL, &frame->tramp[1])) + return 1; + flush_icache_range((unsigned long) &frame->tramp[0], + (unsigned long) &frame->tramp[2]); + } - sigreturn_exit(regs); /* doesn't return here */ return 0; +} -badframe: - do_exit(SIGSEGV); +/* + * Restore the current user register values from the user stack, + * (except for MSR). + */ +static int +restore_user_regs(struct pt_regs *regs, struct mcontext __user *sr) +{ +#ifdef CONFIG_ALTIVEC + unsigned long msr; +#endif + + /* copy up to but not including MSR */ + if (__copy_from_user(regs, &sr->mc_gregs, PT_MSR * sizeof(elf_greg_t))) + return 1; + /* copy from orig_r3 (the word after the MSR) up to the end */ + if (__copy_from_user(®s->orig_gpr3, &sr->mc_gregs[PT_ORIG_R3], + GP_REGS_SIZE - PT_ORIG_R3 * sizeof(elf_greg_t))) + return 1; + + /* force the process to reload the FP registers from + current->thread when it next does FP instructions */ + regs->msr &= ~MSR_FP; + if (__copy_from_user(current->thread.fpr, &sr->mc_fregs, + sizeof(sr->mc_fregs))) + return 1; + +#ifdef CONFIG_ALTIVEC + /* force the process to reload the altivec registers from + current->thread when it next does altivec instructions */ + regs->msr &= ~MSR_VEC; + if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_VEC) != 0) { + /* restore altivec registers from the stack */ + if (__copy_from_user(current->thread.vr, &sr->mc_vregs, + sizeof(sr->mc_vregs))) + return 1; + } else if (current->thread.used_vr) + memset(¤t->thread.vr, 0, sizeof(current->thread.vr)); + + /* Always get VRSAVE back */ + if (__get_user(current->thread.vrsave, (u32 *)&sr->mc_vregs[32])) + return 1; +#endif /* CONFIG_ALTIVEC */ + + return 0; } +/* + * Restore the user process's signal mask + */ static void -setup_rt_frame(struct pt_regs *regs, struct sigregs __user *frame, - signed long newsp) +restore_sigmask(sigset_t *set) { - struct rt_sigframe __user *rt_sf = (struct rt_sigframe __user *) newsp; + sigdelsetmask(set, ~_BLOCKABLE); + spin_lock_irq(¤t->sighand->siglock); + current->blocked = *set; + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); +} - /* Set up preamble frame */ - if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) +/* + * Set up a signal frame for a "real-time" signal handler + * (one which gets siginfo). + */ +static void +handle_rt_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs * regs, + unsigned long newsp) +{ + struct rt_sigframe __user *rt_sf; + struct mcontext __user *frame; + unsigned long origsp = newsp; + + /* Set up Signal Frame */ + /* Put a Real Time Context onto stack */ + newsp -= sizeof(*rt_sf); + rt_sf = (struct rt_sigframe __user *) newsp; + + /* create a stack frame for the caller of the handler */ + newsp -= __SIGNAL_FRAMESIZE + 16; + + if (verify_area(VERIFY_WRITE, (void __user *) newsp, origsp - newsp)) goto badframe; - CHECK_FULL_REGS(regs); - 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)) - /* Set up to return from user space. - It calls the sc exception at offset 0x9999 - for sys_rt_sigreturn(). - */ - || __put_user(0x38000000UL + __NR_rt_sigreturn, &frame->tramp[0]) - || __put_user(0x44000002UL, &frame->tramp[1])) /* sc */ + + /* Put the siginfo & fill in most of the ucontext */ + if (copy_siginfo_to_user(&rt_sf->info, info) + || __put_user(0, &rt_sf->uc.uc_flags) + || __put_user(0, &rt_sf->uc.uc_link) + || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp) + || __put_user(sas_ss_flags(regs->gpr[1]), + &rt_sf->uc.uc_stack.ss_flags) + || __put_user(current->sas_ss_size, &rt_sf->uc.uc_stack.ss_size) + || __put_user(&rt_sf->uc.uc_mcontext, &rt_sf->uc.uc_regs) + || __copy_to_user(&rt_sf->uc.uc_oldsigmask, oldset, sizeof(*oldset)) + || __copy_to_user(&rt_sf->uc.uc_sigmask, oldset, sizeof(*oldset))) 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; - if (put_user(regs->gpr[1], (unsigned long __user *)newsp) - || get_user(regs->nip, &rt_sf->uc.uc_mcontext.handler) - || get_user(regs->gpr[3], &rt_sf->uc.uc_mcontext.signal) - || get_user(regs->gpr[4], (unsigned long __user *)&rt_sf->pinfo) - || get_user(regs->gpr[5], (unsigned long __user *)&rt_sf->puc)) + /* Save user registers on the stack */ + frame = &rt_sf->uc.uc_mcontext; + if (save_user_regs(regs, frame, __NR_rt_sigreturn)) goto badframe; + if (put_user(regs->gpr[1], (unsigned long __user *)newsp)) + goto badframe; regs->gpr[1] = newsp; + regs->gpr[3] = sig; + regs->gpr[4] = (unsigned long) &rt_sf->info; + regs->gpr[5] = (unsigned long) &rt_sf->uc; regs->gpr[6] = (unsigned long) rt_sf; + regs->nip = (unsigned long) ka->sa.sa_handler; regs->link = (unsigned long) frame->tramp; + regs->trap = 0; return; badframe: #if DEBUG_SIG - printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", + printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif - do_exit(SIGSEGV); + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); } -/* - * Do a signal return; undo the signal stack. - */ -int sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, - struct pt_regs *regs) +static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs) { - struct sigcontext __user *sc; - struct sigcontext sigctx; - struct sigregs __user *sr; - elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */ sigset_t set; - sc = (struct sigcontext __user *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); - if (copy_from_user(&sigctx, sc, sizeof(sigctx))) - goto badframe; + if (__copy_from_user(&set, &ucp->uc_sigmask, sizeof(set))) + return -EFAULT; + restore_sigmask(&set); - set.sig[0] = sigctx.oldmask; -#if _NSIG_WORDS > 1 - set.sig[1] = sigctx._unused[3]; -#endif - 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); + if (restore_user_regs(regs, &ucp->uc_mcontext)) + return -EFAULT; - /* restore registers */ - sr = (struct sigregs __user *) 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); - memcpy(regs, saved_regs, GP_REGS_SIZE); + return 0; +} - if (copy_from_user(current->thread.fpr, &sr->fp_regs, - sizeof(sr->fp_regs))) - goto badframe; +int sys_swapcontext(struct ucontext __user *old_ctx, + struct ucontext __user *new_ctx, + int r5, int r6, int r7, int r8, struct pt_regs *regs) +{ + unsigned char tmp; + + if (old_ctx != NULL) { + if (verify_area(VERIFY_WRITE, old_ctx, sizeof(*old_ctx)) + || save_user_regs(regs, &old_ctx->uc_mcontext, 0) + || __copy_to_user(&old_ctx->uc_sigmask, + ¤t->blocked, sizeof(sigset_t)) + /* the next 2 things aren't strictly necessary */ + || __copy_to_user(&old_ctx->uc_oldsigmask, + ¤t->blocked, sizeof(sigset_t)) + || __put_user(&old_ctx->uc_mcontext, &old_ctx->uc_regs)) + return -EFAULT; + } + if (new_ctx == NULL) + return 0; + if (verify_area(VERIFY_READ, new_ctx, sizeof(*new_ctx)) + || __get_user(tmp, (u8 *) new_ctx) + || __get_user(tmp, (u8 *) (new_ctx + 1) - 1)) + return -EFAULT; + + /* + * If we get a fault copying the context into the kernel's + * image of the user's registers, we can't just return -EFAULT + * because the user's registers will be corrupted. For instance + * the NIP value may have been updated but not some of the + * other registers. Given that we have done the verify_area + * and successfully read the first and last bytes of the region + * above, this should only happen in an out-of-memory situation + * or if another thread unmaps the region containing the context. + * We kill the task with a SIGSEGV in this situation. + */ + if (do_setcontext(new_ctx, regs)) + do_exit(SIGSEGV); + sigreturn_exit(regs); + /* doesn't actually return back to here */ + return 0; +} + +int sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, + struct pt_regs *regs) +{ + struct rt_sigframe __user *rt_sf; + + rt_sf = (struct rt_sigframe __user *) + (regs->gpr[1] + __SIGNAL_FRAMESIZE + 16); + if (verify_area(VERIFY_READ, rt_sf, sizeof(struct rt_sigframe))) + goto bad; + if (do_setcontext(&rt_sf->uc, regs)) + goto bad; + + /* + * It's not clear whether or why it is desirable to save the + * sigaltstack setting on signal delivery and restore it on + * signal return. But other architectures do this and we have + * always done it up until now so it is probably better not to + * change it. -- paulus + */ + do_sigaltstack(&rt_sf->uc.uc_stack, NULL, regs->gpr[1]); sigreturn_exit(regs); /* doesn't return here */ return 0; -badframe: - do_exit(SIGSEGV); -} + bad: + force_sig(SIGSEGV, current); + return 0; +} /* - * Set up a signal frame. + * OK, we're invoking a handler */ static void -setup_frame(struct pt_regs *regs, struct sigregs __user *frame, - unsigned long newsp) +handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs * regs, + unsigned long newsp) { - struct sigcontext __user *sc = (struct sigcontext __user *) newsp; + struct sigcontext __user *sc; + struct sigregs __user *frame; + unsigned long origsp = newsp; - if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) + /* Set up Signal Frame */ + newsp -= sizeof(struct sigregs); + frame = (struct sigregs __user *) newsp; + + /* Put a sigcontext on the stack */ + newsp -= sizeof(*sc); + sc = (struct sigcontext __user *) newsp; + + /* create a stack frame for the caller of the handler */ + newsp -= __SIGNAL_FRAMESIZE; + + if (verify_area(VERIFY_WRITE, (void *) newsp, origsp - newsp)) goto badframe; - CHECK_FULL_REGS(regs); - 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)) - || __put_user(0x38000000UL + __NR_sigreturn, &frame->tramp[0]) - || __put_user(0x44000002UL, &frame->tramp[1])) /* sc */ + +#if _NSIG != 64 +#error "Please adjust handle_signal()" +#endif + if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler) + || __put_user(oldset->sig[0], &sc->oldmask) + || __put_user(oldset->sig[1], &sc->_unused[3]) + || __put_user((struct pt_regs *)frame, &sc->regs) + || __put_user(sig, &sc->signal)) goto badframe; - flush_icache_range((unsigned long) &frame->tramp[0], - (unsigned long) &frame->tramp[2]); - current->thread.fpscr = 0; /* turn off all fp exceptions */ - newsp -= __SIGNAL_FRAMESIZE; - if (put_user(regs->gpr[1], (unsigned long __user *)newsp) - || get_user(regs->nip, &sc->handler) - || get_user(regs->gpr[3], &sc->signal)) + if (save_user_regs(regs, &frame->mctx, __NR_sigreturn)) + goto badframe; + + if (put_user(regs->gpr[1], (unsigned long *)newsp)) goto badframe; regs->gpr[1] = newsp; + regs->gpr[3] = sig; regs->gpr[4] = (unsigned long) sc; - regs->link = (unsigned long) frame->tramp; + regs->nip = (unsigned long) ka->sa.sa_handler; + regs->link = (unsigned long) frame->mctx.tramp; + regs->trap = 0; return; badframe: #if DEBUG_SIG - printk("badframe in setup_frame, regs=%p frame=%p newsp=%lx\n", - regs, frame, newsp); + printk("badframe in handle_signal, regs=%p frame=%lx newsp=%lx\n", + regs, frame, *newspp); #endif - do_exit(SIGSEGV); + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); } /* - * OK, we're invoking a handler + * Do a signal return; undo the signal stack. */ -static void -handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs, unsigned long *newspp, unsigned long frame) +int sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, + struct pt_regs *regs) { struct sigcontext __user *sc; - struct rt_sigframe __user *rt_sf; - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; + struct sigcontext sigctx; + struct mcontext __user *sr; + sigset_t set; - if (TRAP(regs) == 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; - regs->gpr[3] = EINTR; - regs->ccr |= 0x10000000; - } + sc = (struct sigcontext __user *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); + if (copy_from_user(&sigctx, sc, sizeof(sigctx))) + goto badframe; - /* 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 __user *) *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 __user *) *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; - } + set.sig[0] = sigctx.oldmask; + set.sig[1] = sigctx._unused[3]; + restore_sigmask(&set); - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; + sr = (struct mcontext *) sigctx.regs; + if (verify_area(VERIFY_READ, sr, sizeof(*sr)) + || restore_user_regs(regs, sr)) + goto badframe; - if (!(ka->sa.sa_flags & SA_NODEFER)) { - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); - sigaddset(¤t->blocked,sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - } - return; + sigreturn_exit(regs); /* doesn't return */ + return 0; 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); + force_sig(SIGSEGV, current); + return 0; } /* @@ -475,7 +547,7 @@ siginfo_t info; struct k_sigaction *ka; unsigned long frame, newsp; - int signr; + int signr, ret; if (!oldset) oldset = ¤t->blocked; @@ -483,40 +555,65 @@ 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); - /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, oldset, regs, &newsp, frame); - } + ka = (signr == 0)? NULL: ¤t->sighand->action[signr-1]; - if (TRAP(regs) == 0x0C00) { /* System Call! */ - if ((int)regs->result == -ERESTARTNOHAND || - (int)regs->result == -ERESTARTSYS || - (int)regs->result == -ERESTARTNOINTR) { - regs->gpr[3] = regs->orig_gpr3; + if (TRAP(regs) == 0x0C00 /* System Call! */ + && regs->ccr & 0x10000000 /* error signalled */ + && ((ret = regs->gpr[3]) == ERESTARTSYS + || ret == ERESTARTNOHAND || ret == ERESTARTNOINTR + || ret == ERESTART_RESTARTBLOCK)) { + + if (signr > 0 + && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK + || (ret == ERESTARTSYS + && !(ka->sa.sa_flags & SA_RESTART)))) { + /* make the system call return an EINTR error */ + regs->result = -EINTR; + regs->gpr[3] = EINTR; + /* note that the cr0.SO bit is already set */ + /* clear any restart function that was set */ + if (ret == ERESTART_RESTARTBLOCK) + current_thread_info()->restart_block.fn + = do_no_restart_syscall; + } else { regs->nip -= 4; /* Back up & retry system call */ regs->result = 0; - } else if ((int)regs->result == -ERESTART_RESTARTBLOCK) { - regs->gpr[0] = __NR_restart_syscall; - regs->nip -= 4; - regs->result = 0; + regs->trap = 0; + if (ret == ERESTART_RESTARTBLOCK) + regs->gpr[0] = __NR_restart_syscall; + else + regs->gpr[3] = regs->orig_gpr3; } } - if (newsp == frame) + if (signr == 0) return 0; /* no signals delivered */ + if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size + && !on_sig_stack(regs->gpr[1])) + newsp = current->sas_ss_sp + current->sas_ss_size; + else + newsp = regs->gpr[1]; + newsp &= ~0xfUL; + + /* Whee! Actually deliver the signal. */ if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame(regs, (struct sigregs __user *) frame, newsp); + handle_rt_signal(signr, ka, &info, oldset, regs, newsp); else - setup_frame(regs, (struct sigregs __user *) frame, newsp); + handle_signal(signr, ka, &info, oldset, regs, newsp); + + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + + if (!(ka->sa.sa_flags & SA_NODEFER)) { + spin_lock_irq(¤t->sighand->siglock); + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigaddset(¤t->blocked, signr); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + } + return 1; } diff -Nru a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c --- a/arch/ppc/kernel/traps.c Thu Sep 11 23:03:11 2003 +++ b/arch/ppc/kernel/traps.c Thu Sep 11 23:03:11 2003 @@ -95,14 +95,19 @@ } void -_exception(int signr, struct pt_regs *regs) +_exception(int signr, struct pt_regs *regs, int code, unsigned long addr) { - if (!user_mode(regs)) - { + siginfo_t info; + + if (!user_mode(regs)) { debugger(regs); die("Exception in kernel mode", regs, signr); } - force_sig(signr, current); + info.si_signo = signr; + info.si_errno = 0; + info.si_code = code; + info.si_addr = (void *) addr; + force_sig_info(signr, &info, current); } /* @@ -154,12 +159,40 @@ return 0; } +#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) +/* On 4xx, the reason for the machine check or program exception + is in the ESR. */ +#define get_reason(regs) ((regs)->dsisr) +#define REASON_FP 0 +#define REASON_ILLEGAL ESR_PIL +#define REASON_PRIVILEGED ESR_PPR +#define REASON_TRAP ESR_PTR + +/* single-step stuff */ +#define single_stepping(regs) (current->thread.dbcr0 & DBCR0_IC) +#define clear_single_step(regs) (current->thread.dbcr0 &= ~DBCR0_IC) + +#else +/* On non-4xx, the reason for the machine check or program + exception is in the MSR. */ +#define get_reason(regs) ((regs)->msr) +#define REASON_FP 0x100000 +#define REASON_ILLEGAL 0x80000 +#define REASON_PRIVILEGED 0x40000 +#define REASON_TRAP 0x20000 + +#define single_stepping(regs) ((regs)->msr & MSR_SE) +#define clear_single_step(regs) ((regs)->msr &= ~MSR_SE) +#endif + void MachineCheckException(struct pt_regs *regs) { + unsigned long reason = get_reason(regs); + if (user_mode(regs)) { regs->msr |= MSR_RI; - _exception(SIGSEGV, regs); + _exception(SIGBUS, regs, BUS_ADRERR, regs->nip); return; } @@ -178,10 +211,18 @@ if (check_io_access(regs)) return; -#ifndef CONFIG_4xx - printk(KERN_CRIT "Machine check in kernel mode.\n"); - printk(KERN_CRIT "Caused by (from SRR1=%lx): ", regs->msr); - switch (regs->msr & 0x601F0000) { +#ifdef CONFIG_4xx + if (reason & ESR_IMCP) { + printk("Instruction"); + mtspr(SPRN_ESR, reason & ~ESR_IMCP); + } else + printk("Data"); + printk(" machine check in kernel mode.\n"); + +#else /* !CONFIG_4xx */ + printk("Machine check in kernel mode.\n"); + printk("Caused by (from SRR1=%lx): ", reason); + switch (reason & 0x601F0000) { case 0x80000: printk("Machine check signal\n"); break; @@ -208,15 +249,6 @@ default: printk("Unknown values in msr\n"); } - -#else /* CONFIG_4xx */ - /* Note that the ESR gets stored in regs->dsisr on 4xx. */ - if (regs->dsisr & ESR_MCI) { - printk(KERN_CRIT "Instruction"); - mtspr(SPRN_ESR, regs->dsisr & ~ESR_MCI); - } else - printk(KERN_CRIT "Data"); - printk(" machine check in kernel mode.\n"); #endif /* CONFIG_4xx */ debugger(regs); @@ -238,7 +270,7 @@ { printk("Bad trap at PC: %lx, MSR: %lx, vector=%lx %s\n", regs->nip, regs->msr, regs->trap, print_tainted()); - _exception(SIGTRAP, regs); + _exception(SIGTRAP, regs, 0, 0); } void @@ -246,13 +278,13 @@ { if (debugger_iabr_match(regs)) return; - _exception(SIGTRAP, regs); + _exception(SIGTRAP, regs, TRAP_BRKPT, 0); } void RunModeException(struct pt_regs *regs) { - _exception(SIGTRAP, regs); + _exception(SIGTRAP, regs, 0, 0); } /* Illegal instruction emulation support. Originally written to @@ -271,17 +303,17 @@ static int emulate_instruction(struct pt_regs *regs) { - uint instword; - uint rd; - uint retval; + u32 instword; + u32 rd; + int retval; - retval = EINVAL; + retval = -EINVAL; if (!user_mode(regs)) return retval; CHECK_FULL_REGS(regs); - if (get_user(instword, (uint __user *)(regs->nip))) + if (get_user(instword, (u32 __user *)(regs->nip))) return -EFAULT; /* Emulate the mfspr rD, PVR. @@ -290,10 +322,23 @@ rd = (instword >> 21) & 0x1f; regs->gpr[rd] = mfspr(PVR); retval = 0; - } - if (retval == 0) regs->nip += 4; - return(retval); + } + return retval; +} + +/* + * After we have successfully emulated an instruction, we have to + * check if the instruction was being single-stepped, and if so, + * pretend we got a single-step exception. This was pointed out + * by Kumar Gala. -- paulus + */ +static void emulate_single_step(struct pt_regs *regs) +{ + if (single_stepping(regs)) { + clear_single_step(regs); + _exception(SIGTRAP, regs, TRAP_TRACE, 0); + } } /* @@ -349,29 +394,47 @@ void ProgramCheckException(struct pt_regs *regs) { - int errcode; - -#if defined(CONFIG_4xx) - unsigned int esr = regs->dsisr; - int isbpt = esr & ESR_PTR; + unsigned int reason = get_reason(regs); extern int do_mathemu(struct pt_regs *regs); #ifdef CONFIG_MATH_EMULATION - if (!isbpt && do_mathemu(regs) == 0) + /* (reason & REASON_ILLEGAL) would be the obvious thing here, + * but there seems to be a hardware bug on the 405GP (RevD) + * that means ESR is sometimes set incorrectly - either to + * ESR_DST (!?) or 0. In the process of chasing this with the + * hardware people - not sure if it can happen on any illegal + * instruction or only on FP instructions, whether there is a + * pattern to occurences etc. -dgibson 31/Mar/2003 */ + if (!(reason & REASON_TRAP) && do_mathemu(regs) == 0) { + emulate_single_step(regs); return; + } #endif /* CONFIG_MATH_EMULATION */ -#else /* ! CONFIG_4xx */ - int isbpt = regs->msr & 0x20000; - - if (regs->msr & 0x100000) { + if (reason & REASON_FP) { /* IEEE FP exception */ - _exception(SIGFPE, regs); + int code = 0; + u32 fpscr; + + if (regs->msr & MSR_FP) + giveup_fpu(current); + fpscr = current->thread.fpscr; + fpscr &= fpscr << 22; /* mask summary bits with enables */ + if (fpscr & FPSCR_VX) + code = FPE_FLTINV; + else if (fpscr & FPSCR_OX) + code = FPE_FLTOVF; + else if (fpscr & FPSCR_UX) + code = FPE_FLTUND; + else if (fpscr & FPSCR_ZX) + code = FPE_FLTDIV; + else if (fpscr & FPSCR_XX) + code = FPE_FLTRES; + _exception(SIGFPE, regs, code, regs->nip); return; } -#endif /* ! CONFIG_4xx */ - if (isbpt) { + if (reason & REASON_TRAP) { /* trap exception */ if (debugger_bpt(regs)) return; @@ -379,17 +442,21 @@ regs->nip += 4; return; } - _exception(SIGTRAP, regs); + _exception(SIGTRAP, regs, TRAP_BRKPT, 0); return; } - /* Try to emulate it if we should. */ - if ((errcode = emulate_instruction(regs))) { - if (errcode == -EFAULT) - _exception(SIGBUS, regs); - else - _exception(SIGILL, regs); + if (reason & REASON_PRIVILEGED) { + /* Try to emulate it if we should. */ + if (emulate_instruction(regs) == 0) { + emulate_single_step(regs); + return; + } + _exception(SIGILL, regs, ILL_PRVOPC, regs->nip); + return; } + + _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); } void @@ -398,7 +465,7 @@ regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */ if (debugger_sstep(regs)) return; - _exception(SIGTRAP, regs); + _exception(SIGTRAP, regs, TRAP_TRACE, 0); } void @@ -414,12 +481,12 @@ if (fixed == -EFAULT) { /* fixed == -EFAULT means the operand address was bad */ if (user_mode(regs)) - force_sig(SIGSEGV, current); + _exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar); else bad_page_fault(regs, regs->dar, SIGSEGV); return; } - _exception(SIGBUS, regs); + _exception(SIGBUS, regs, BUS_ADRALN, regs->dar); } void @@ -470,16 +537,17 @@ #endif if (errcode) { if (errcode > 0) - _exception(SIGFPE, regs); + _exception(SIGFPE, regs, 0, 0); else if (errcode == -EFAULT) - _exception(SIGSEGV, regs); + _exception(SIGSEGV, regs, 0, 0); else - _exception(SIGILL, regs); - } + _exception(SIGILL, regs, ILL_ILLOPC, regs->nip); + } else + emulate_single_step(regs); } #endif /* CONFIG_8xx */ -#if defined(CONFIG_4xx) +#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) void DebugException(struct pt_regs *regs, unsigned long debug_status) { @@ -487,7 +555,7 @@ if (debug_status & DBSR_TIE) { /* trap instruction*/ if (!user_mode(regs) && debugger_bpt(regs)) return; - _exception(SIGTRAP, regs); + _exception(SIGTRAP, regs, 0, 0); } #endif @@ -495,10 +563,10 @@ if (!user_mode(regs) && debugger_sstep(regs)) return; current->thread.dbcr0 &= ~DBCR0_IC; - _exception(SIGTRAP, regs); + _exception(SIGTRAP, regs, TRAP_TRACE, 0); } } -#endif /* CONFIG_4xx */ +#endif /* CONFIG_4xx || CONFIG_BOOKE */ #if !defined(CONFIG_TAU_INT) void diff -Nru a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig --- a/arch/ppc64/Kconfig Thu Sep 11 23:03:12 2003 +++ b/arch/ppc64/Kconfig Thu Sep 11 23:03:12 2003 @@ -72,6 +72,17 @@ bool default y +config HUGETLB_PAGE + bool "Huge TLB Page Support" + help + This enables support for huge pages. User space applications + can make use of this support with the sys_alloc_hugepages and + sys_free_hugepages system calls. If your applications are + huge page aware and your processor supports this (only POWER4, + then say Y here. + + Otherwise, say N. + config SMP bool "Symmetric multi-processing support" ---help--- diff -Nru a/arch/ppc64/Makefile b/arch/ppc64/Makefile --- a/arch/ppc64/Makefile Thu Sep 11 23:03:11 2003 +++ b/arch/ppc64/Makefile Thu Sep 11 23:03:11 2003 @@ -18,7 +18,13 @@ LDFLAGS := -m elf64ppc LDFLAGS_vmlinux := -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD) CFLAGS += -msoft-float -pipe -Wno-uninitialized -mminimal-toc \ - -mtraceback=full -mcpu=power4 + -mcpu=power4 + +have_zero_bss := $(shell if $(CC) -fno-zero-initialized-in-bss -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi) + +ifeq ($(have_zero_bss),y) +CFLAGS += -fno-zero-initialized-in-bss +endif head-y := arch/ppc64/kernel/head.o @@ -38,6 +44,12 @@ %_config: arch/ppc64/configs/%_defconfig rm -f .config arch/ppc64/defconfig cp -f arch/ppc64/configs/$(@:config=defconfig) arch/ppc64/defconfig + +bootimage-$(CONFIG_PPC_PSERIES) := zImage +bootimage-$(CONFIG_PPC_ISERIES) := vmlinux.sm +BOOTIMAGE := $(bootimage-y) +install: vmlinux + $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@ archclean: $(Q)$(MAKE) $(clean)=$(boot) diff -Nru a/arch/ppc64/boot/Makefile b/arch/ppc64/boot/Makefile --- a/arch/ppc64/boot/Makefile Thu Sep 11 23:03:13 2003 +++ b/arch/ppc64/boot/Makefile Thu Sep 11 23:03:13 2003 @@ -122,5 +122,7 @@ awk '{printf "unsigned long vmlinux_memsize = 0x%s;\n", substr($$1,8)}' \ >> $(obj)/imagesize.c +install: $(CONFIGURE) $(obj)/$(BOOTIMAGE) + sh -x $(src)/install.sh "$(KERNELRELEASE)" "$(obj)/$(BOOTIMAGE)" "$(TOPDIR)/System.map" "$(INSTALL_PATH)" clean-files := $(patsubst $(obj)/%,%, $(obj-boot)) diff -Nru a/arch/ppc64/boot/install.sh b/arch/ppc64/boot/install.sh --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/boot/install.sh Thu Sep 11 23:03:14 2003 @@ -0,0 +1,41 @@ +#!/bin/sh +# +# arch/ppc64/boot/install.sh +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 1995 by Linus Torvalds +# +# Blatantly stolen from in arch/i386/boot/install.sh by Dave Hansen +# +# "make install" script for ppc64 architecture +# +# Arguments: +# $1 - kernel version +# $2 - kernel image file +# $3 - kernel map file +# $4 - default install path (blank if root directory) +# + +# User may have a custom install script + +if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi +if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi + +# Default install + +# this should work for both the pSeries zImage and the iSeries vmlinux.sm +image_name=`basename $2` + +if [ -f $4/$image_name ]; then + mv $4/$image_name $4/$image_name.old +fi + +if [ -f $4/System.map ]; then + mv $4/System.map $4/System.old +fi + +cat $2 > $4/$image_name +cp $3 $4/System.map diff -Nru a/arch/ppc64/defconfig b/arch/ppc64/defconfig --- a/arch/ppc64/defconfig Thu Sep 11 23:03:11 2003 +++ b/arch/ppc64/defconfig Thu Sep 11 23:03:12 2003 @@ -8,11 +8,13 @@ CONFIG_EARLY_PRINTK=y CONFIG_COMPAT=y CONFIG_FRAME_POINTER=y +CONFIG_FORCE_MAX_ZONEORDER=13 # # Code maturity level options # CONFIG_EXPERIMENTAL=y +# CONFIG_BROKEN is not set # # General setup @@ -21,11 +23,14 @@ CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y -CONFIG_LOG_BUF_SHIFT=15 +CONFIG_LOG_BUF_SHIFT=16 +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y CONFIG_FUTEX=y CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y @@ -72,7 +77,6 @@ # # Generic Driver Options # -# CONFIG_FW_LOADER is not set # # Memory Technology Devices (MTD) @@ -99,7 +103,7 @@ # CONFIG_BLK_DEV_UMEM is not set CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set -CONFIG_BLK_DEV_NBD=y +CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y @@ -127,9 +131,9 @@ # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_REPORT_LUNS is not set -# CONFIG_SCSI_CONSTANTS is not set +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_REPORT_LUNS=y +CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_LOGGING is not set # @@ -178,7 +182,8 @@ CONFIG_MD_RAID1=y CONFIG_MD_RAID5=y # CONFIG_MD_MULTIPATH is not set -# CONFIG_BLK_DEV_DM is not set +CONFIG_BLK_DEV_DM=y +CONFIG_DM_IOCTL_V4=y # # Fusion MPT device support @@ -206,9 +211,8 @@ CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set # CONFIG_NETLINK_DEV is not set -# CONFIG_NETFILTER is not set CONFIG_UNIX=y -# CONFIG_NET_KEY is not set +CONFIG_NET_KEY=m CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set @@ -217,13 +221,17 @@ # CONFIG_NET_IPGRE is not set # CONFIG_IP_MROUTE is not set # CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set +CONFIG_INET_ECN=y CONFIG_SYN_COOKIES=y -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m # CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +CONFIG_XFRM_USER=m # # SCTP Configuration (EXPERIMENTAL) @@ -233,8 +241,6 @@ # CONFIG_ATM is not set # CONFIG_VLAN_8021Q is not set # CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_NET_DIVERT is not set @@ -258,10 +264,10 @@ # ARCnet devices # # CONFIG_ARCNET is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set +CONFIG_DUMMY=m +CONFIG_BONDING=m # CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set +CONFIG_TUN=m # CONFIG_ETHERTAP is not set # @@ -312,6 +318,7 @@ # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set +# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -321,7 +328,14 @@ # CONFIG_IXGB is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set -# CONFIG_PPP is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPPOE=m # CONFIG_SLIP is not set # @@ -489,26 +503,32 @@ # File systems # CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +# CONFIG_EXT2_FS_SECURITY is not set CONFIG_EXT3_FS=y -# CONFIG_EXT3_FS_XATTR is not set +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +# CONFIG_EXT3_FS_SECURITY is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y CONFIG_REISERFS_FS=y # CONFIG_REISERFS_CHECK is not set # CONFIG_REISERFS_PROC_INFO is not set CONFIG_JFS_FS=y -# CONFIG_JFS_POSIX_ACL is not set +CONFIG_JFS_POSIX_ACL=y # CONFIG_JFS_DEBUG is not set # CONFIG_JFS_STATISTICS is not set -CONFIG_XFS_FS=y +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m # CONFIG_XFS_RT is not set # CONFIG_XFS_QUOTA is not set -# CONFIG_XFS_POSIX_ACL is not set +CONFIG_XFS_POSIX_ACL=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS_FS=m # CONFIG_AUTOFS4_FS is not set # @@ -517,7 +537,7 @@ CONFIG_ISO9660_FS=y # CONFIG_JOLIET is not set # CONFIG_ZISOFS is not set -# CONFIG_UDF_FS is not set +CONFIG_UDF_FS=m # # DOS/FAT/NT Filesystems @@ -533,8 +553,9 @@ CONFIG_PROC_FS=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS=y -# CONFIG_DEVPTS_FS_XATTR is not set -# CONFIG_TMPFS is not set +CONFIG_DEVPTS_FS_XATTR=y +# CONFIG_DEVPTS_FS_SECURITY is not set +CONFIG_TMPFS=y CONFIG_RAMFS=y # @@ -546,7 +567,7 @@ # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set +CONFIG_CRAMFS=y # CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set @@ -561,15 +582,16 @@ CONFIG_NFS_V4=y CONFIG_NFSD=y CONFIG_NFSD_V3=y -# CONFIG_NFSD_V4 is not set +CONFIG_NFSD_V4=y CONFIG_NFSD_TCP=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m # CONFIG_SMB_FS is not set -CONFIG_CIFS=y +CONFIG_CIFS=m # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_INTERMEZZO_FS is not set @@ -705,6 +727,7 @@ CONFIG_XMON=y CONFIG_XMON_DEFAULT=y # CONFIG_PPCDBG is not set +# CONFIG_DEBUG_INFO is not set # # Security options @@ -714,9 +737,27 @@ # # Cryptographic options # -# CONFIG_CRYPTO is not set +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_TEST=m # # Library routines # CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m diff -Nru a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c --- a/arch/ppc64/kernel/asm-offsets.c Thu Sep 11 23:03:13 2003 +++ b/arch/ppc64/kernel/asm-offsets.c Thu Sep 11 23:03:13 2003 @@ -83,9 +83,7 @@ DEFINE(PACALPQUEUE, offsetof(struct paca_struct, lpQueuePtr)); DEFINE(PACATOC, offsetof(struct paca_struct, xTOC)); DEFINE(PACAEXCSP, offsetof(struct paca_struct, exception_sp)); - DEFINE(PACAHRDWINTSTACK, offsetof(struct paca_struct, xHrdIntStack)); DEFINE(PACAPROCENABLED, offsetof(struct paca_struct, xProcEnabled)); - DEFINE(PACAHRDWINTCOUNT, offsetof(struct paca_struct, xHrdIntCount)); DEFINE(PACADEFAULTDECR, offsetof(struct paca_struct, default_decr)); DEFINE(PACAPROFENABLED, offsetof(struct paca_struct, prof_enabled)); DEFINE(PACAPROFLEN, offsetof(struct paca_struct, prof_len)); diff -Nru a/arch/ppc64/kernel/chrp_setup.c b/arch/ppc64/kernel/chrp_setup.c --- a/arch/ppc64/kernel/chrp_setup.c Thu Sep 11 23:03:11 2003 +++ b/arch/ppc64/kernel/chrp_setup.c Thu Sep 11 23:03:11 2003 @@ -72,6 +72,7 @@ extern void find_and_init_phbs(void); +extern void pSeries_get_boot_time(struct rtc_time *rtc_time); extern void pSeries_get_rtc_time(struct rtc_time *rtc_time); extern int pSeries_set_rtc_time(struct rtc_time *rtc_time); void pSeries_calibrate_decr(void); @@ -256,7 +257,7 @@ ppc_md.power_off = rtas_power_off; ppc_md.halt = rtas_halt; - ppc_md.get_boot_time = pSeries_get_rtc_time; + ppc_md.get_boot_time = pSeries_get_boot_time; ppc_md.get_rtc_time = pSeries_get_rtc_time; ppc_md.set_rtc_time = pSeries_set_rtc_time; ppc_md.calibrate_decr = pSeries_calibrate_decr; diff -Nru a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c --- a/arch/ppc64/kernel/eeh.c Thu Sep 11 23:03:13 2003 +++ b/arch/ppc64/kernel/eeh.c Thu Sep 11 23:03:13 2003 @@ -115,8 +115,17 @@ ret = rtas_call(ibm_read_slot_reset_state, 3, 3, rets, dn->eeh_config_addr, BUID_HI(dn->phb->buid), BUID_LO(dn->phb->buid)); if (ret == 0 && rets[1] == 1 && rets[0] >= 2) { - panic("EEH: MMIO failure (%ld) on device:\n %s %s\n", - rets[0], pci_name(dev), dev->dev.name); + /* + * XXX We should create a separate sysctl for this. + * + * Since the panic_on_oops sysctl is used to halt + * the system in light of potential corruption, we + * can use it here. + */ + if (panic_on_oops) + panic("EEH: MMIO failure (%ld) on device:\n%s\n", rets[0], pci_name(dev)); + else + printk("EEH: MMIO failure (%ld) on device:\n%s\n", rets[0], pci_name(dev)); } } eeh_false_positives++; diff -Nru a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S --- a/arch/ppc64/kernel/head.S Thu Sep 11 23:03:12 2003 +++ b/arch/ppc64/kernel/head.S Thu Sep 11 23:03:12 2003 @@ -40,6 +40,15 @@ #define DO_SOFT_DISABLE #endif +/* copy saved SOFTE bit or EE bit from saved MSR depending + * if we are doing soft-disable or not + */ +#ifdef DO_SOFT_DISABLE +#define DO_COPY_EE() ld r20,SOFTE(r1) +#else +#define DO_COPY_EE() rldicl r20,r23,49,63 +#endif + /* * hcall interface to pSeries LPAR */ @@ -618,11 +627,7 @@ ld r4,_DAR(r1) ld r5,_DSISR(r1) addi r3,r1,STACK_FRAME_OVERHEAD -#ifdef DO_SOFT_DISABLE - ld r20,SOFTE(r1) /* Copy saved SOFTE bit */ -#else - rldicl r20,r23,49,63 /* copy EE bit from saved MSR */ -#endif + DO_COPY_EE() li r6,0x300 bl .save_remaining_regs bl .do_page_fault @@ -644,12 +649,9 @@ or. r3,r3,r3 /* Check return code */ beq fast_exception_return /* Return if we succeeded */ 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 + DO_COPY_EE() li r6,0x380 + li r5,0 bl .save_remaining_regs bl .do_page_fault b .ret_from_except @@ -670,13 +672,9 @@ bl .do_hash_page_ISI /* Try to handle as hpte fault */ 1: mr r4,r22 - mr r5,r23 + rlwinm r5,r23,0,4,4 /* We only care about PR in error_code */ 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 + DO_COPY_EE() li r6,0x400 bl .save_remaining_regs bl .do_page_fault @@ -692,12 +690,9 @@ beq+ fast_exception_return /* Return if we succeeded */ 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 + DO_COPY_EE() li r6,0x480 + li r5,0 bl .save_remaining_regs bl .do_page_fault b .ret_from_except @@ -710,70 +705,14 @@ li r20,0 li r6,0x500 bl .save_remaining_regs - /* Determine if need to run do_irq on a hardware interrupt stack */ - /* The first invocation of do_irq will occur on the kernel */ - /* stack in the current stack */ - /* All other invocations of do_irq will run on the hardware */ - /* interrupt stack associated with the PACA of the current */ - /* processor. */ - /* */ - /* The call to do_irq will preserve the value of r14 - r31 */ - /* */ -/* - * XXX turn off interrupt stacks until the thread_info stuff is fixed. - * Otherwise we end up setting need_resched etc bits in the interrupt - * stack and they never get seen when we return to the process stack - Anton - */ -#if 0 - lbz r21,PACAHRDWINTCOUNT(r13) /* get hardware interrupt cnt */ - cmpi 0,r21,1 /* */ - addi r21,r21,1 /* incr hardware interrupt cnt*/ - stb r21,PACAHRDWINTCOUNT(r13) /* */ - bne 2f /* */ - - mr r14,r1 /* preserve current r1 */ - ld r1,PACAHRDWINTSTACK(r13) /* */ - std r14,0(r1) /* set the back chain */ bl .do_IRQ - lbz r22,PACAHRDWINTCOUNT(r13) /* get hardware interrupt cnt */ - cmp 0,r22,r21 /* debug test */ - bne 3f - subi r21,r21,1 - stb r21,PACAHRDWINTCOUNT(r13) /* */ - mr r1,r14 /* */ b .ret_from_except -#endif - -2: - bl .do_IRQ - -#if 0 - lbz r22,PACAHRDWINTCOUNT(r13) /* get hardware interrupt cnt */ - cmp 0,r22,r21 /* debug test */ - bne 3f /* */ - subi r21,r21,1 /* decr hardware interrupt cnt*/ - stb r21,PACAHRDWINTCOUNT(r13) /* */ -#endif - - b .ret_from_except - -3: - /* error - counts out of sync */ -#ifdef CONFIG_XMON - bl .xmon -#endif -4: b 4b - .globl Alignment_common Alignment_common: EXCEPTION_PROLOG_COMMON 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 + DO_COPY_EE() li r6,0x600 bl .save_remaining_regs bl .AlignmentException @@ -783,11 +722,7 @@ ProgramCheck_common: EXCEPTION_PROLOG_COMMON 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 + DO_COPY_EE() li r6,0x700 bl .save_remaining_regs bl .ProgramCheckException @@ -798,11 +733,7 @@ EXCEPTION_PROLOG_COMMON bne .load_up_fpu /* if from user, just load it up */ 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 + DO_COPY_EE() li r6,0x800 bl .save_remaining_regs bl .KernelFPUnavailableException @@ -818,11 +749,7 @@ beq+ HardwareInterrupt_entry 1: #endif -#ifdef DO_SOFT_DISABLE - ld r20,SOFTE(r1) -#else - rldicl r20,r23,49,63 /* copy EE bit from saved MSR */ -#endif + DO_COPY_EE() li r6,0xC00 bl .save_remaining_regs bl .DoSyscall @@ -1866,18 +1793,6 @@ li r5,0 std r0,PACAKSAVE(r13) - /* ptr to hardware interrupt stack for boot processor */ - LOADADDR(r3, hardware_int_paca0) - li r5,PAGE_SIZE - sldi r5,r5,3 - subi r5,r5,STACK_FRAME_OVERHEAD - - add r3,r3,r5 - std r3,PACAHRDWINTSTACK(r13) - - li r3,0 - stb r3,PACAHRDWINTCOUNT(r13) - /* Restore the parms passed in from the bootloader. */ mr r3,r31 mr r4,r30 @@ -1998,10 +1913,6 @@ .globl ioremap_dir ioremap_dir: .space 4096 - - .globl hardware_int_paca0 -hardware_int_paca0: - .space 8*PAGE_SIZE /* 1 page segment table per cpu (max 48, cpu0 allocated at STAB0_PHYS_ADDR) */ .globl stab_array diff -Nru a/arch/ppc64/kernel/htab.c b/arch/ppc64/kernel/htab.c --- a/arch/ppc64/kernel/htab.c Thu Sep 11 23:03:13 2003 +++ b/arch/ppc64/kernel/htab.c Thu Sep 11 23:03:13 2003 @@ -197,7 +197,7 @@ if (!pgd_none(*pg)) { pm = pmd_offset(pg, ea); - if (!pmd_none(*pm)) { + if (pmd_present(*pm)) { pt = pte_offset_kernel(pm, ea); pte = *pt; if (!pte_present(pte)) @@ -436,8 +436,12 @@ if (user_region && cpus_equal(mm->cpu_vm_mask, tmp)) local = 1; - ptep = find_linux_pte(pgdir, ea); - ret = __hash_page(ea, access, vsid, ptep, trap, local); + ret = hash_huge_page(mm, access, ea, vsid, local); + if (ret < 0) { + ptep = find_linux_pte(pgdir, ea); + ret = __hash_page(ea, access, vsid, ptep, trap, local); + } + spin_unlock(&mm->page_table_lock); return ret; diff -Nru a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c --- a/arch/ppc64/kernel/irq.c Thu Sep 11 23:03:12 2003 +++ b/arch/ppc64/kernel/irq.c Thu Sep 11 23:03:12 2003 @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -350,14 +351,11 @@ return 0; } -extern char *ppc_find_proc_name(unsigned *p, char *buf, unsigned buflen); - -static inline void handle_irq_event(int irq, struct pt_regs *regs, - struct irqaction *action) +static inline int handle_irq_event(int irq, struct pt_regs *regs, + struct irqaction *action) { int status = 0; int retval = 0; - struct irqaction *first_action = action; if (!(action->flags & SA_INTERRUPT)) local_irq_enable(); @@ -370,30 +368,90 @@ if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); local_irq_disable(); - if (retval != 1) { - static int count = 100; - char name_buf[256]; - if (count) { - count--; - if (retval) { - printk("irq event %d: bogus retval mask %x\n", - irq, retval); - } else { - printk("irq %d: nobody cared!\n", irq); - } - dump_stack(); - printk("handlers:\n"); - action = first_action; - do { - printk("[<%p>]", action->handler); - printk(" (%s)\n", - ppc_find_proc_name((unsigned *)action->handler, name_buf, 256)); - action = action->next; - } while (action); - } + return retval; +} + +static void __report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret) +{ + struct irqaction *action; + + if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) { + printk(KERN_ERR "irq event %d: bogus return value %x\n", + irq, action_ret); + } else { + printk(KERN_ERR "irq %d: nobody cared!\n", irq); + } + dump_stack(); + printk(KERN_ERR "handlers:\n"); + action = desc->action; + do { + printk(KERN_ERR "[<%p>]", action->handler); + print_symbol(" (%s)", + (unsigned long)action->handler); + printk("\n"); + action = action->next; + } while (action); +} + +static void report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret) +{ + static int count = 100; + + if (count) { + count--; + __report_bad_irq(irq, desc, action_ret); } } +static int noirqdebug; + +static int __init noirqdebug_setup(char *str) +{ + noirqdebug = 1; + printk("IRQ lockup detection disabled\n"); + return 1; +} + +__setup("noirqdebug", noirqdebug_setup); + +/* + * If 99,900 of the previous 100,000 interrupts have not been handled then + * assume that the IRQ is stuck in some manner. Drop a diagnostic and try to + * turn the IRQ off. + * + * (The other 100-of-100,000 interrupts may have been a correctly-functioning + * device sharing an IRQ with the failing one) + * + * Called under desc->lock + */ +static void note_interrupt(int irq, irq_desc_t *desc, irqreturn_t action_ret) +{ + if (action_ret != IRQ_HANDLED) { + desc->irqs_unhandled++; + if (action_ret != IRQ_NONE) + report_bad_irq(irq, desc, action_ret); + } + + desc->irq_count++; + if (desc->irq_count < 100000) + return; + + desc->irq_count = 0; + if (desc->irqs_unhandled > 99900) { + /* + * The interrupt is stuck + */ + __report_bad_irq(irq, desc, action_ret); + /* + * Now kill the IRQ + */ + printk(KERN_EMERG "Disabling IRQ #%d\n", irq); + desc->status |= IRQ_DISABLED; + desc->handler->disable(irq); + } + desc->irqs_unhandled = 0; +} + /* * Eventually, this should take an array of interrupts and an array size * so it can dispatch multiple interrupts. @@ -462,10 +520,13 @@ * SMP environment. */ for (;;) { + irqreturn_t action_ret; + spin_unlock(&desc->lock); - handle_irq_event(irq, regs, action); + action_ret = handle_irq_event(irq, regs, action); spin_lock(&desc->lock); - + if (!noirqdebug) + note_interrupt(irq, desc, action_ret); if (likely(!(desc->status & IRQ_PENDING))) break; desc->status &= ~IRQ_PENDING; diff -Nru a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c --- a/arch/ppc64/kernel/pSeries_lpar.c Thu Sep 11 23:03:14 2003 +++ b/arch/ppc64/kernel/pSeries_lpar.c Thu Sep 11 23:03:14 2003 @@ -36,18 +36,6 @@ #include #include - -long plpar_pte_enter(unsigned long flags, - unsigned long ptex, - unsigned long new_pteh, unsigned long new_ptel, - unsigned long *old_pteh_ret, unsigned long *old_ptel_ret) -{ - unsigned long dummy, ret; - ret = plpar_hcall(H_ENTER, flags, ptex, new_pteh, new_ptel, - old_pteh_ret, old_ptel_ret, &dummy); - return(ret); -} - long plpar_pte_remove(unsigned long flags, unsigned long ptex, unsigned long avpn, @@ -83,7 +71,6 @@ tce_ret, &dummy, &dummy); } - long plpar_tce_put(unsigned long liobn, unsigned long ioba, unsigned long tceval) @@ -104,10 +91,9 @@ unsigned long len, const char *buffer) { - unsigned long dummy; unsigned long *lbuf = (unsigned long *)buffer; /* ToDo: alignment? */ - return plpar_hcall(H_PUT_TERM_CHAR, termno, len, - lbuf[0], lbuf[1], &dummy, &dummy, &dummy); + return plpar_hcall_norets(H_PUT_TERM_CHAR, termno, len, lbuf[0], + lbuf[1]); } static void tce_build_pSeriesLP(struct TceTable *tbl, long tcenum, @@ -287,12 +273,11 @@ int hvc_put_chars(int index, const char *buf, int count) { - unsigned long dummy; unsigned long *lbuf = (unsigned long *) buf; long ret; - ret = plpar_hcall(H_PUT_TERM_CHAR, index, count, lbuf[0], lbuf[1], - &dummy, &dummy, &dummy); + ret = plpar_hcall_norets(H_PUT_TERM_CHAR, index, count, lbuf[0], + lbuf[1]); if (ret == H_Success) return count; if (ret == H_Busy) @@ -318,7 +303,6 @@ - long pSeries_lpar_hpte_insert(unsigned long hpte_group, unsigned long va, unsigned long prpn, int secondary, unsigned long hpteflags, @@ -329,6 +313,7 @@ unsigned long flags; unsigned long slot; HPTE lhpte; + unsigned long dummy0, dummy1; /* Fill in the local HPTE with absolute rpn, avpn and flags */ lhpte.dw1.dword1 = 0; @@ -348,7 +333,6 @@ /* Now fill in the actual HPTE */ /* Set CEC cookie to 0 */ - /* Large page = 0 */ /* Zero page = 0 */ /* I-cache Invalidate = 0 */ /* I-cache synchronize = 0 */ @@ -359,19 +343,8 @@ if (hpteflags & (_PAGE_GUARDED|_PAGE_NO_CACHE)) lhpte.dw1.flags.flags &= ~_PAGE_COHERENT; - __asm__ __volatile__ ( - H_ENTER_r3 - "mr 4, %2\n" - "mr 5, %3\n" - "mr 6, %4\n" - "mr 7, %5\n" - HSC - "mr %0, 3\n" - "mr %1, 4\n" - : "=r" (lpar_rc), "=r" (slot) - : "r" (flags), "r" (hpte_group), "r" (lhpte.dw0.dword0), - "r" (lhpte.dw1.dword1) - : "r3", "r4", "r5", "r6", "r7", "cc"); + lpar_rc = plpar_hcall(H_ENTER, flags, hpte_group, lhpte.dw0.dword0, + lhpte.dw1.dword1, &slot, &dummy0, &dummy1); if (lpar_rc == H_PTEG_Full) return -1; diff -Nru a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c --- a/arch/ppc64/kernel/pSeries_pci.c Thu Sep 11 23:03:14 2003 +++ b/arch/ppc64/kernel/pSeries_pci.c Thu Sep 11 23:03:14 2003 @@ -427,6 +427,7 @@ void pcibios_name_device(struct pci_dev *dev) { +#if 0 struct device_node *dn; /* @@ -446,6 +447,7 @@ } } } +#endif } void __init pcibios_fixup_device_resources(struct pci_dev *dev, diff -Nru a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c --- a/arch/ppc64/kernel/ppc_ksyms.c Thu Sep 11 23:03:11 2003 +++ b/arch/ppc64/kernel/ppc_ksyms.c Thu Sep 11 23:03:11 2003 @@ -49,8 +49,6 @@ extern int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); extern int do_signal(sigset_t *, struct pt_regs *); -extern int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *)); -extern int unregister_ioctl32_conversion(unsigned int cmd); int abs(int); @@ -65,9 +63,6 @@ #ifdef CONFIG_SMP EXPORT_SYMBOL(synchronize_irq); #endif /* CONFIG_SMP */ - -EXPORT_SYMBOL(register_ioctl32_conversion); -EXPORT_SYMBOL(unregister_ioctl32_conversion); EXPORT_SYMBOL(isa_io_base); EXPORT_SYMBOL(pci_io_base); diff -Nru a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c --- a/arch/ppc64/kernel/process.c Thu Sep 11 23:03:13 2003 +++ b/arch/ppc64/kernel/process.c Thu Sep 11 23:03:13 2003 @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -130,12 +131,9 @@ return last; } -char *ppc_find_proc_name(unsigned *p, char *buf, unsigned buflen); - void show_regs(struct pt_regs * regs) { int i; - char name_buf[256]; printk("NIP: %016lX XER: %016lX LR: %016lX\n", regs->nip, regs->xer, regs->link); @@ -170,8 +168,7 @@ * above info out without failing */ printk("NIP [%016lx] ", regs->nip); - printk("%s\n", ppc_find_proc_name((unsigned *)regs->nip, - name_buf, 256)); + print_symbol("%s\n", regs->nip); show_stack(current, (unsigned long *)regs->gpr[1]); } @@ -385,102 +382,6 @@ return error; } -void initialize_paca_hardware_interrupt_stack(void) -{ - int i; - unsigned long stack; - unsigned long end_of_stack =0; - - for (i=1; i < NR_CPUS; i++) { - if (!cpu_possible(i)) - continue; - /* Carve out storage for the hardware interrupt stack */ - stack = __get_free_pages(GFP_ATOMIC, get_order(8*PAGE_SIZE)); - - if ( !stack ) { - printk("ERROR, cannot find space for hardware stack.\n"); - panic(" no hardware stack "); - } - - - /* Store the stack value in the PACA for the processor */ - paca[i].xHrdIntStack = stack + (8*PAGE_SIZE) - STACK_FRAME_OVERHEAD; - paca[i].xHrdIntCount = 0; - - } - - /* - * __get_free_pages() might give us a page > KERNBASE+256M which - * is mapped with large ptes so we can't set up the guard page. - */ - if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) - return; - - for (i=0; i < NR_CPUS; i++) { - if (!cpu_possible(i)) - continue; - /* set page at the top of stack to be protected - prevent overflow */ - end_of_stack = paca[i].xHrdIntStack - (8*PAGE_SIZE - STACK_FRAME_OVERHEAD); - ppc_md.hpte_updateboltedpp(PP_RXRX,end_of_stack); - } -} - -char *ppc_find_proc_name(unsigned *p, char *buf, unsigned buflen) -{ - unsigned long tb_flags; - unsigned short name_len; - unsigned long tb_start, code_start, code_ptr, code_offset; - unsigned int code_len; - unsigned long end; - - strcpy(buf, "Unknown"); - code_ptr = (unsigned long)p; - code_offset = 0; - - /* handle functions in text and init sections */ - if (((unsigned long)p >= (unsigned long)_stext) && - ((unsigned long)p < (unsigned long)_etext)) - end = (unsigned long)_etext; - else if (((unsigned long)p >= (unsigned long)__init_begin) && - ((unsigned long)p < (unsigned long)__init_end)) - end = (unsigned long)__init_end; - else - return buf; - - while ((unsigned long)p < end) { - if (*p == 0) { - tb_start = (unsigned long)p; - ++p; /* Point to traceback flags */ - tb_flags = *((unsigned long *)p); - p += 2; /* Skip over traceback flags */ - if (tb_flags & TB_NAME_PRESENT) { - if (tb_flags & TB_PARMINFO) - ++p; /* skip over parminfo data */ - if (tb_flags & TB_HAS_TBOFF) { - code_len = *p; /* get code length */ - code_start = tb_start - code_len; - code_offset = code_ptr - code_start + 1; - if (code_offset > 0x100000) - break; - ++p; /* skip over code size */ - } - name_len = *((unsigned short *)p); - if (name_len > (buflen-20)) - name_len = buflen-20; - memcpy(buf, ((char *)p)+2, name_len); - buf[name_len] = 0; - if (code_offset) - sprintf(buf+name_len, "+0x%lx", - code_offset-1); - } - break; - } - ++p; - } - - return buf; -} - /* * These bracket the sleeping functions.. */ @@ -520,7 +421,6 @@ unsigned long ip; unsigned long stack_page = (unsigned long)p->thread_info; int count = 0; - char name_buf[256]; unsigned long sp = (unsigned long)_sp; if (!p) @@ -539,8 +439,7 @@ if (__get_user(ip, (unsigned long *)(sp + 16))) break; printk("[%016lx] ", ip); - printk("%s\n", ppc_find_proc_name((unsigned *)ip, - name_buf, 256)); + print_symbol("%s\n", ip); } while (count++ < 32); } diff -Nru a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c --- a/arch/ppc64/kernel/rtas.c Thu Sep 11 23:03:11 2003 +++ b/arch/ppc64/kernel/rtas.c Thu Sep 11 23:03:11 2003 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -176,6 +177,26 @@ for (i = 0; i < nret-1; ++i) outputs[i] = rtas_args->rets[i+1]; return (ulong)((nret > 0) ? rtas_args->rets[0] : 0); +} + +/* Given an RTAS status code of 990n compute the hinted delay of 10^n + * (last digit) milliseconds. For now we bound at n=3 (1 sec). + */ +unsigned int +rtas_extended_busy_delay_time(int status) +{ + int order = status - 9900; + unsigned int ms; + + if (order < 0) + order = 0; /* RTC depends on this for -2 clock busy */ + else if (order > 3) + order = 3; /* bound */ + + /* Use microseconds for reasonable accuracy */ + for (ms = 1000; order > 0; order--) + ms = ms * 10; + return ms / (1000000/HZ); /* round down is fine */ } #define FLASH_BLOCK_LIST_VERSION (1UL) diff -Nru a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c --- a/arch/ppc64/kernel/rtc.c Thu Sep 11 23:03:12 2003 +++ b/arch/ppc64/kernel/rtc.c Thu Sep 11 23:03:12 2003 @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -340,20 +341,63 @@ #endif #ifdef CONFIG_PPC_PSERIES +#define MAX_RTC_WAIT 5000 /* 5 sec */ +#define RTAS_CLOCK_BUSY (-2) +void pSeries_get_boot_time(struct rtc_time *rtc_tm) +{ + unsigned long ret[8]; + int error, wait_time; + unsigned long max_wait_tb; + + max_wait_tb = __get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; + do { + error = rtas_call(rtas_token("get-time-of-day"), 0, 8, (void *)&ret); + if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { + wait_time = rtas_extended_busy_delay_time(error); + /* This is boot time so we spin. */ + udelay(wait_time*1000); + error = RTAS_CLOCK_BUSY; + } + } while (error == RTAS_CLOCK_BUSY && (__get_tb() < max_wait_tb)); + + if (error != 0) { + printk(KERN_WARNING "error: reading the clock failed (%d)\n", + error); + return; + } + + rtc_tm->tm_sec = ret[5]; + rtc_tm->tm_min = ret[4]; + rtc_tm->tm_hour = ret[3]; + rtc_tm->tm_mday = ret[2]; + rtc_tm->tm_mon = ret[1] - 1; + rtc_tm->tm_year = ret[0] - 1900; +} + +/* NOTE: get_rtc_time will get an error if executed in interrupt context + * and if a delay is needed to read the clock. In this case we just + * silently return without updating rtc_tm. + */ void pSeries_get_rtc_time(struct rtc_time *rtc_tm) { unsigned long ret[8]; - int error; - int count; + int error, wait_time; + unsigned long max_wait_tb; - /* - * error -2 is clock busy, we keep retrying a few times to see - * if it will come good -- paulus - */ - count = 0; + max_wait_tb = __get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; do { error = rtas_call(rtas_token("get-time-of-day"), 0, 8, (void *)&ret); - } while (error == -2 && ++count < 1000); + if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { + if (in_interrupt()) { + printk(KERN_WARNING "error: reading clock would delay interrupt\n"); + return; /* delay not allowed */ + } + wait_time = rtas_extended_busy_delay_time(error); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(wait_time); + error = RTAS_CLOCK_BUSY; + } + } while (error == RTAS_CLOCK_BUSY && (__get_tb() < max_wait_tb)); if (error != 0) { printk(KERN_WARNING "error: reading the clock failed (%d)\n", @@ -371,20 +415,24 @@ int pSeries_set_rtc_time(struct rtc_time *tm) { - int error; - int count; + int error, wait_time; + unsigned long max_wait_tb; - /* - * error -2 is clock busy, we keep retrying a few times to see - * if it will come good -- paulus - */ - count = 0; + max_wait_tb = __get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; do { error = rtas_call(rtas_token("set-time-of-day"), 7, 1, NULL, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, 0); - } while (error == -2 && ++count < 1000); + if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { + if (in_interrupt()) + return 1; /* probably decrementer */ + wait_time = rtas_extended_busy_delay_time(error); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(wait_time); + error = RTAS_CLOCK_BUSY; + } + } while (error == RTAS_CLOCK_BUSY && (__get_tb() < max_wait_tb)); if (error != 0) printk(KERN_WARNING "error: setting the clock failed (%d)\n", diff -Nru a/arch/ppc64/kernel/semaphore.c b/arch/ppc64/kernel/semaphore.c --- a/arch/ppc64/kernel/semaphore.c Thu Sep 11 23:03:11 2003 +++ b/arch/ppc64/kernel/semaphore.c Thu Sep 11 23:03:11 2003 @@ -75,9 +75,8 @@ struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); - tsk->state = TASK_UNINTERRUPTIBLE; + __set_task_state(tsk, TASK_UNINTERRUPTIBLE); add_wait_queue_exclusive(&sem->wait, &wait); - smp_wmb(); /* * Try to get the semaphore. If the count is > 0, then we've @@ -87,10 +86,10 @@ */ while (__sem_update_count(sem, -1) <= 0) { schedule(); - tsk->state = TASK_UNINTERRUPTIBLE; + set_task_state(tsk, TASK_UNINTERRUPTIBLE); } remove_wait_queue(&sem->wait, &wait); - tsk->state = TASK_RUNNING; + __set_task_state(tsk, TASK_RUNNING); /* * If there are any more sleepers, wake one of them up so @@ -106,9 +105,8 @@ struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); - tsk->state = TASK_INTERRUPTIBLE; + __set_task_state(tsk, TASK_INTERRUPTIBLE); add_wait_queue_exclusive(&sem->wait, &wait); - smp_wmb(); while (__sem_update_count(sem, -1) <= 0) { if (signal_pending(current)) { @@ -122,10 +120,11 @@ break; } schedule(); - tsk->state = TASK_INTERRUPTIBLE; + set_task_state(tsk, TASK_INTERRUPTIBLE); } - tsk->state = TASK_RUNNING; remove_wait_queue(&sem->wait, &wait); + __set_task_state(tsk, TASK_RUNNING); + wake_up(&sem->wait); return retval; } diff -Nru a/arch/ppc64/kernel/stab.c b/arch/ppc64/kernel/stab.c --- a/arch/ppc64/kernel/stab.c Thu Sep 11 23:03:13 2003 +++ b/arch/ppc64/kernel/stab.c Thu Sep 11 23:03:13 2003 @@ -221,15 +221,18 @@ } static inline void __ste_allocate(unsigned long esid, unsigned long vsid, - int kernel_segment) + int kernel_segment, mm_context_t context) { if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) { + int large = 0; + #ifndef CONFIG_PPC_ISERIES if (REGION_ID(esid << SID_SHIFT) == KERNEL_REGION_ID) - make_slbe(esid, vsid, 1, kernel_segment); - else + large = 1; + else if (REGION_ID(esid << SID_SHIFT) == USER_REGION_ID) + large = in_hugepage_area(context, esid << SID_SHIFT); #endif - make_slbe(esid, vsid, 0, kernel_segment); + make_slbe(esid, vsid, large, kernel_segment); } else { unsigned char top_entry, stab_entry, *segments; @@ -255,6 +258,7 @@ { unsigned long vsid, esid; int kernel_segment = 0; + mm_context_t context; PMC_SW_PROCESSOR(stab_faults); @@ -266,16 +270,18 @@ if (REGION_ID(ea) >= KERNEL_REGION_ID) { kernel_segment = 1; vsid = get_kernel_vsid(ea); + context = REGION_ID(ea); } else { - struct mm_struct *mm = current->mm; - if (mm) - vsid = get_vsid(mm->context, ea); - else + if (! current->mm) return 1; + + context = current->mm->context; + + vsid = get_vsid(context, ea); } esid = GET_ESID(ea); - __ste_allocate(esid, vsid, kernel_segment); + __ste_allocate(esid, vsid, kernel_segment, context); if (!(cur_cpu_spec->cpu_features & CPU_FTR_SLB)) { /* Order update */ asm volatile("sync":::"memory"); @@ -302,7 +308,7 @@ for (esid = 0; esid < 16; esid++) { unsigned long ea = esid << SID_SHIFT; vsid = get_vsid(mm->context, ea); - __ste_allocate(esid, vsid, 0); + __ste_allocate(esid, vsid, 0, mm->context); } } else { unsigned long pc = KSTK_EIP(tsk); @@ -316,7 +322,7 @@ (REGION_ID(pc) >= KERNEL_REGION_ID)) return; vsid = get_vsid(mm->context, pc); - __ste_allocate(GET_ESID(pc), vsid, 0); + __ste_allocate(GET_ESID(pc), vsid, 0, mm->context); } if (stack && (pc_segment != stack_segment)) { @@ -324,7 +330,7 @@ (REGION_ID(stack) >= KERNEL_REGION_ID)) return; vsid = get_vsid(mm->context, stack); - __ste_allocate(GET_ESID(stack), vsid, 0); + __ste_allocate(GET_ESID(stack), vsid, 0, mm->context); } } diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c --- a/arch/ppc64/kernel/sys_ppc32.c Thu Sep 11 23:03:13 2003 +++ b/arch/ppc64/kernel/sys_ppc32.c Thu Sep 11 23:03:13 2003 @@ -1243,16 +1243,19 @@ } -struct msgbuf32 { s32 mtype; char mtext[1]; }; +struct msgbuf32 { + compat_long_t mtype; + char mtext[1]; +}; struct semid_ds32 { struct ipc_perm sem_perm; compat_time_t sem_otime; compat_time_t sem_ctime; - u32 sem_base; - u32 sem_pending; - u32 sem_pending_last; - u32 undo; + compat_uptr_t sem_base; + compat_uptr_t sem_pending; + compat_uptr_t sem_pending_last; + compat_uptr_t undo; unsigned short sem_nsems; }; @@ -1262,21 +1265,20 @@ compat_time_t sem_otime; unsigned int __unused2; compat_time_t sem_ctime; - u32 sem_nsems; - u32 __unused3; - u32 __unused4; + compat_ulong_t sem_nsems; + compat_ulong_t __unused3; + compat_ulong_t __unused4; }; -struct msqid_ds32 -{ +struct msqid_ds32 { struct ipc_perm msg_perm; - u32 msg_first; - u32 msg_last; + compat_uptr_t msg_first; + compat_uptr_t msg_last; compat_time_t msg_stime; compat_time_t msg_rtime; compat_time_t msg_ctime; - u32 msg_lcbytes; - u32 msg_lqbytes; + compat_ulong_t msg_lcbytes; + compat_ulong_t msg_lqbytes; unsigned short msg_cbytes; unsigned short msg_qnum; unsigned short msg_qbytes; @@ -1292,13 +1294,13 @@ compat_time_t msg_rtime; unsigned int __unused3; compat_time_t msg_ctime; - unsigned int msg_cbytes; - unsigned int msg_qnum; - unsigned int msg_qbytes; + compat_ulong_t msg_cbytes; + compat_ulong_t msg_qnum; + compat_ulong_t msg_qbytes; compat_pid_t msg_lspid; compat_pid_t msg_lrpid; - unsigned int __unused4; - unsigned int __unused5; + compat_ulong_t __unused4; + compat_ulong_t __unused5; }; struct shmid_ds32 { @@ -1311,8 +1313,8 @@ compat_ipc_pid_t shm_lpid; unsigned short shm_nattch; unsigned short __unused; - unsigned int __unused2; - unsigned int __unused3; + compat_uptr_t __unused2; + compat_uptr_t __unused3; }; struct shmid64_ds32 { @@ -1327,9 +1329,9 @@ compat_size_t shm_segsz; compat_pid_t shm_cpid; compat_pid_t shm_lpid; - unsigned int shm_nattch; - unsigned int __unused5; - unsigned int __unused6; + compat_ulong_t shm_nattch; + compat_ulong_t __unused5; + compat_ulong_t __unused6; }; /* @@ -1350,7 +1352,7 @@ err = -EFAULT; if (get_user(pad, (u32 *)uptr)) return err; - if (third == SETVAL) + if ((third & ~IPC_64) == SETVAL) fourth.val = (int)pad; else fourth.__pad = (void *)A(pad); diff -Nru a/arch/ppc64/kernel/syscalls.c b/arch/ppc64/kernel/syscalls.c --- a/arch/ppc64/kernel/syscalls.c Thu Sep 11 23:03:13 2003 +++ b/arch/ppc64/kernel/syscalls.c Thu Sep 11 23:03:13 2003 @@ -1,5 +1,5 @@ /* - * linux/arch/ppc/kernel/sys_ppc.c + * linux/arch/ppc64/kernel/sys_ppc.c * * PowerPC version * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) @@ -40,7 +40,6 @@ #include #include #include -#include #include extern unsigned long wall_jiffies; @@ -79,6 +78,7 @@ case SEMCTL: { union semun fourth; + ret = -EINVAL; if (!ptr) break; if ((ret = get_user(fourth.__pad, (void **)ptr))) @@ -94,6 +94,7 @@ case 0: { struct ipc_kludge tmp; + ret = -EINVAL; if (!ptr) break; if ((ret = copy_from_user(&tmp, @@ -127,6 +128,7 @@ break; } case 1: /* iBCS2 emulator entry point */ + ret = -EINVAL; if (!segment_eq(get_fs(), get_ds())) break; ret = sys_shmat (first, (char *) ptr, second, diff -Nru a/arch/ppc64/kernel/vmlinux.lds.S b/arch/ppc64/kernel/vmlinux.lds.S --- a/arch/ppc64/kernel/vmlinux.lds.S Thu Sep 11 23:03:13 2003 +++ b/arch/ppc64/kernel/vmlinux.lds.S Thu Sep 11 23:03:13 2003 @@ -137,4 +137,9 @@ . = ALIGN(4096); _end = . ; PROVIDE (end = .); + + /* Sections to be discarded. */ + /DISCARD/ : { + *(.exitcall.exit) + } } diff -Nru a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c --- a/arch/ppc64/kernel/xics.c Thu Sep 11 23:03:12 2003 +++ b/arch/ppc64/kernel/xics.c Thu Sep 11 23:03:12 2003 @@ -267,6 +267,15 @@ irq, call_status); return; } + + /* Have to set XIVE to 0xff to be able to remove a slot */ + call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, default_server, + 0xff); + if (call_status != 0) { + printk("xics_disable_irq: irq=%x: ibm_set_xive(0xff) returned %lx\n", + irq, call_status); + return; + } } void xics_end_irq(u_int irq) @@ -375,12 +384,12 @@ int i; unsigned long intr_size = 0; struct device_node *np; - uint *ireg, ilen, indx=0; + 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]; + unsigned long addr; + unsigned long size; + } inodes[NR_CPUS]; ppc64_boot_msg(0x20, "XICS Init"); diff -Nru a/arch/ppc64/mm/Makefile b/arch/ppc64/mm/Makefile --- a/arch/ppc64/mm/Makefile Thu Sep 11 23:03:11 2003 +++ b/arch/ppc64/mm/Makefile Thu Sep 11 23:03:11 2003 @@ -6,3 +6,4 @@ obj-y := fault.o init.o extable.o imalloc.o obj-$(CONFIG_DISCONTIGMEM) += numa.o +obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o diff -Nru a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c --- a/arch/ppc64/mm/fault.c Thu Sep 11 23:03:13 2003 +++ b/arch/ppc64/mm/fault.c Thu Sep 11 23:03:13 2003 @@ -46,8 +46,10 @@ void bad_page_fault(struct pt_regs *, unsigned long, int); /* - * For 600- and 800-family processors, the error_code parameter is DSISR - * for a data fault, SRR1 for an instruction fault. + * The error_code parameter is + * - DSISR for a non-SLB data access fault, + * - SRR1 & 0x08000000 for a non-SLB instruction access fault + * - 0 any SLB fault. */ void do_page_fault(struct pt_regs *regs, unsigned long address, unsigned long error_code) @@ -57,17 +59,6 @@ siginfo_t info; unsigned long code = SEGV_MAPERR; unsigned long is_write = error_code & 0x02000000; - - /* - * Fortunately the bit assignments in SRR1 for an instruction - * fault and DSISR for a data fault are mostly the same for the - * bits we are interested in. But there are some bits which - * indicate errors in DSISR but can validly be set in SRR1. - */ - if (regs->trap == 0x400) - error_code &= 0x48200000; - else if (regs->trap != 0x300) /* ensure error_code is 0 on SLB miss */ - error_code = 0; #ifdef CONFIG_DEBUG_KERNEL if (debugger_fault_handler && (regs->trap == 0x300 || diff -Nru a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/mm/hugetlbpage.c Thu Sep 11 23:03:14 2003 @@ -0,0 +1,925 @@ +/* + * PPC64 (POWER4) Huge TLB Page Support for Kernel. + * + * Copyright (C) 2003 David Gibson, IBM Corporation. + * + * Based on the IA-32 version: + * Copyright (C) 2002, Rohit Seth + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +int htlbpage_max; + +/* This lock protects the two counters and list below */ +static spinlock_t htlbpage_lock = SPIN_LOCK_UNLOCKED; + +static int htlbpage_free; /* = 0 */ +static int htlbpage_total; /* = 0 */ +static struct list_head hugepage_freelists[MAX_NUMNODES]; + +static void enqueue_huge_page(struct page *page) +{ + list_add(&page->list, + &hugepage_freelists[page_zone(page)->zone_pgdat->node_id]); +} + +/* XXX make this a sysctl */ +unsigned long largepage_roundrobin = 1; + +static struct page *dequeue_huge_page(void) +{ + static int nid = 0; + struct page *page = NULL; + int i; + + if (!largepage_roundrobin) + nid = numa_node_id(); + + for (i = 0; i < numnodes; i++) { + if (!list_empty(&hugepage_freelists[nid])) + break; + nid = (nid + 1) % numnodes; + } + + if (!list_empty(&hugepage_freelists[nid])) { + page = list_entry(hugepage_freelists[nid].next, struct page, list); + list_del(&page->list); + } + + if (largepage_roundrobin) + nid = (nid + 1) % numnodes; + + return page; +} + +static struct page *alloc_fresh_huge_page(void) +{ + static int nid = 0; + struct page *page; + + page = alloc_pages_node(nid, GFP_HIGHUSER, HUGETLB_PAGE_ORDER); + if (!page) + return NULL; + + nid = page_zone(page)->zone_pgdat->node_id; + nid = (nid + 1) % numnodes; + return page; +} + +/* HugePTE layout: + * + * 31 30 ... 15 14 13 12 10 9 8 7 6 5 4 3 2 1 0 + * PFN>>12..... - - - - - - HASH_IX.... 2ND HASH RW - HG=1 + */ + +#define HUGEPTE_SHIFT 15 +#define _HUGEPAGE_PFN 0xffff8000 +#define _HUGEPAGE_BAD 0x00007f00 +#define _HUGEPAGE_HASHPTE 0x00000008 +#define _HUGEPAGE_SECONDARY 0x00000010 +#define _HUGEPAGE_GROUP_IX 0x000000e0 +#define _HUGEPAGE_HPTEFLAGS (_HUGEPAGE_HASHPTE | _HUGEPAGE_SECONDARY | \ + _HUGEPAGE_GROUP_IX) +#define _HUGEPAGE_RW 0x00000004 + +typedef struct {unsigned int val;} hugepte_t; +#define hugepte_val(hugepte) ((hugepte).val) +#define __hugepte(x) ((hugepte_t) { (x) } ) +#define hugepte_pfn(x) \ + ((unsigned long)(hugepte_val(x)>>HUGEPTE_SHIFT) << HUGETLB_PAGE_ORDER) +#define mk_hugepte(page,wr) __hugepte( \ + ((page_to_pfn(page)>>HUGETLB_PAGE_ORDER) << HUGEPTE_SHIFT ) \ + | (!!(wr) * _HUGEPAGE_RW) | _PMD_HUGEPAGE ) + +#define hugepte_bad(x) ( !(hugepte_val(x) & _PMD_HUGEPAGE) || \ + (hugepte_val(x) & _HUGEPAGE_BAD) ) +#define hugepte_page(x) pfn_to_page(hugepte_pfn(x)) +#define hugepte_none(x) (!(hugepte_val(x) & _HUGEPAGE_PFN)) + + +static void free_huge_page(struct page *page); +static void flush_hash_hugepage(mm_context_t context, unsigned long ea, + hugepte_t pte, int local); + +static inline unsigned int hugepte_update(hugepte_t *p, unsigned int clr, + unsigned int set) +{ + unsigned int old, tmp; + + __asm__ __volatile__( + "1: lwarx %0,0,%3 # pte_update\n\ + andc %1,%0,%4 \n\ + or %1,%1,%5 \n\ + stwcx. %1,0,%3 \n\ + bne- 1b" + : "=&r" (old), "=&r" (tmp), "=m" (*p) + : "r" (p), "r" (clr), "r" (set), "m" (*p) + : "cc" ); + return old; +} + +static inline void set_hugepte(hugepte_t *ptep, hugepte_t pte) +{ + hugepte_update(ptep, ~_HUGEPAGE_HPTEFLAGS, + hugepte_val(pte) & ~_HUGEPAGE_HPTEFLAGS); +} + +static struct page *alloc_hugetlb_page(void) +{ + int i; + struct page *page; + + spin_lock(&htlbpage_lock); + page = dequeue_huge_page(); + if (!page) { + spin_unlock(&htlbpage_lock); + return NULL; + } + + htlbpage_free--; + spin_unlock(&htlbpage_lock); + set_page_count(page, 1); + page->lru.prev = (void *)free_huge_page; + for (i = 0; i < (HPAGE_SIZE/PAGE_SIZE); ++i) + clear_highpage(&page[i]); + return page; +} + +static hugepte_t *hugepte_alloc(struct mm_struct *mm, unsigned long addr) +{ + pgd_t *pgd; + pmd_t *pmd = NULL; + + BUG_ON(!in_hugepage_area(mm->context, addr)); + + pgd = pgd_offset(mm, addr); + pmd = pmd_alloc(mm, pgd, addr); + + /* We shouldn't find a (normal) PTE page pointer here */ + BUG_ON(!pmd_none(*pmd) && !pmd_hugepage(*pmd)); + + return (hugepte_t *)pmd; +} + +static hugepte_t *hugepte_offset(struct mm_struct *mm, unsigned long addr) +{ + pgd_t *pgd; + pmd_t *pmd = NULL; + + BUG_ON(!in_hugepage_area(mm->context, addr)); + + pgd = pgd_offset(mm, addr); + pmd = pmd_offset(pgd, addr); + + /* We shouldn't find a (normal) PTE page pointer here */ + BUG_ON(!pmd_none(*pmd) && !pmd_hugepage(*pmd)); + + return (hugepte_t *)pmd; +} + +static void setup_huge_pte(struct mm_struct *mm, struct page *page, + hugepte_t *ptep, int write_access) +{ + hugepte_t entry; + int i; + + mm->rss += (HPAGE_SIZE / PAGE_SIZE); + entry = mk_hugepte(page, write_access); + for (i = 0; i < HUGEPTE_BATCH_SIZE; i++) + set_hugepte(ptep+i, entry); +} + +static void teardown_huge_pte(hugepte_t *ptep) +{ + int i; + + for (i = 0; i < HUGEPTE_BATCH_SIZE; i++) + pmd_clear((pmd_t *)(ptep+i)); +} + +/* + * This function checks for proper alignment of input addr and len parameters. + */ +int is_aligned_hugepage_range(unsigned long addr, unsigned long len) +{ + if (len & ~HPAGE_MASK) + return -EINVAL; + if (addr & ~HPAGE_MASK) + return -EINVAL; + if (! is_hugepage_only_range(addr, len)) + return -EINVAL; + return 0; +} + +static void do_slbia(void *unused) +{ + asm volatile ("isync; slbia; isync":::"memory"); +} + +/* Activate the low hpage region for 32bit processes. mmap_sem must + * be held*/ +static int open_32bit_htlbpage_range(struct mm_struct *mm) +{ + struct vm_area_struct *vma; + unsigned long addr; + + if (mm->context & CONTEXT_LOW_HPAGES) + return 0; /* The window is already open */ + + /* Check no VMAs are in the region */ + vma = find_vma(mm, TASK_HPAGE_BASE_32); + + if (vma && (vma->vm_start < TASK_HPAGE_END_32)) + return -EBUSY; + + /* Clean up any leftover PTE pages in the region */ + spin_lock(&mm->page_table_lock); + for (addr = TASK_HPAGE_BASE_32; addr < TASK_HPAGE_END_32; + addr += PMD_SIZE) { + pgd_t *pgd = pgd_offset(mm, addr); + pmd_t *pmd = pmd_offset(pgd, addr); + + if (! pmd_none(*pmd)) { + struct page *page = pmd_page(*pmd); + pte_t *pte = (pte_t *)pmd_page_kernel(*pmd); + int i; + + /* No VMAs, so there should be no PTEs, check + * just in case. */ + for (i = 0; i < PTRS_PER_PTE; i++) { + BUG_ON(! pte_none(*pte)); + pte++; + } + + pmd_clear(pmd); + pgtable_remove_rmap(page); + pte_free(page); + } + } + spin_unlock(&mm->page_table_lock); + + /* FIXME: do we need to scan for PTEs too? */ + + mm->context |= CONTEXT_LOW_HPAGES; + + /* the context change must make it to memory before the slbia, + * so that further SLB misses do the right thing. */ + mb(); + + on_each_cpu(do_slbia, NULL, 0, 1); + + return 0; +} + +int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, + struct vm_area_struct *vma) +{ + hugepte_t *src_pte, *dst_pte, entry; + struct page *ptepage; + unsigned long addr = vma->vm_start; + unsigned long end = vma->vm_end; + + while (addr < end) { + BUG_ON(! in_hugepage_area(src->context, addr)); + BUG_ON(! in_hugepage_area(dst->context, addr)); + + dst_pte = hugepte_alloc(dst, addr); + if (!dst_pte) + return -ENOMEM; + + src_pte = hugepte_offset(src, addr); + entry = *src_pte; + + if ((addr % HPAGE_SIZE) == 0) { + /* This is the first hugepte in a batch */ + ptepage = hugepte_page(entry); + get_page(ptepage); + dst->rss += (HPAGE_SIZE / PAGE_SIZE); + } + set_hugepte(dst_pte, entry); + + + addr += PMD_SIZE; + } + return 0; +} + +int +follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, + struct page **pages, struct vm_area_struct **vmas, + unsigned long *position, int *length, int i) +{ + unsigned long vpfn, vaddr = *position; + int remainder = *length; + + WARN_ON(!is_vm_hugetlb_page(vma)); + + vpfn = vaddr/PAGE_SIZE; + while (vaddr < vma->vm_end && remainder) { + BUG_ON(!in_hugepage_area(mm->context, vaddr)); + + if (pages) { + hugepte_t *pte; + struct page *page; + + pte = hugepte_offset(mm, vaddr); + + /* hugetlb should be locked, and hence, prefaulted */ + WARN_ON(!pte || hugepte_none(*pte)); + + page = &hugepte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)]; + + WARN_ON(!PageCompound(page)); + + get_page(page); + pages[i] = page; + } + + if (vmas) + vmas[i] = vma; + + vaddr += PAGE_SIZE; + ++vpfn; + --remainder; + ++i; + } + + *length = remainder; + *position = vaddr; + + return i; +} + +struct page * +follow_huge_addr(struct mm_struct *mm, + struct vm_area_struct *vma, unsigned long address, int write) +{ + return NULL; +} + +struct vm_area_struct *hugepage_vma(struct mm_struct *mm, unsigned long addr) +{ + return NULL; +} + +int pmd_huge(pmd_t pmd) +{ + return pmd_hugepage(pmd); +} + +struct page * +follow_huge_pmd(struct mm_struct *mm, unsigned long address, + pmd_t *pmd, int write) +{ + struct page *page; + + BUG_ON(! pmd_hugepage(*pmd)); + + page = hugepte_page(*(hugepte_t *)pmd); + if (page) { + page += ((address & ~HPAGE_MASK) >> PAGE_SHIFT); + get_page(page); + } + return page; +} + +static void free_huge_page(struct page *page) +{ + BUG_ON(page_count(page)); + BUG_ON(page->mapping); + + INIT_LIST_HEAD(&page->list); + + spin_lock(&htlbpage_lock); + enqueue_huge_page(page); + htlbpage_free++; + spin_unlock(&htlbpage_lock); +} + +void huge_page_release(struct page *page) +{ + if (!put_page_testzero(page)) + return; + + free_huge_page(page); +} + +void unmap_hugepage_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) +{ + struct mm_struct *mm = vma->vm_mm; + unsigned long addr; + hugepte_t *ptep; + struct page *page; + int local = 0; + cpumask_t tmp; + + WARN_ON(!is_vm_hugetlb_page(vma)); + BUG_ON((start % HPAGE_SIZE) != 0); + BUG_ON((end % HPAGE_SIZE) != 0); + + /* XXX are there races with checking cpu_vm_mask? - Anton */ + tmp = cpumask_of_cpu(smp_processor_id()); + if (cpus_equal(vma->vm_mm->cpu_vm_mask, tmp)) + local = 1; + + for (addr = start; addr < end; addr += HPAGE_SIZE) { + hugepte_t pte; + + BUG_ON(!in_hugepage_area(mm->context, addr)); + + ptep = hugepte_offset(mm, addr); + if (!ptep || hugepte_none(*ptep)) + continue; + + pte = *ptep; + page = hugepte_page(pte); + teardown_huge_pte(ptep); + + if (hugepte_val(pte) & _HUGEPAGE_HASHPTE) + flush_hash_hugepage(mm->context, addr, + pte, local); + + huge_page_release(page); + } + + mm->rss -= (end - start) >> PAGE_SHIFT; +} + +void zap_hugepage_range(struct vm_area_struct *vma, + unsigned long start, unsigned long length) +{ + struct mm_struct *mm = vma->vm_mm; + + spin_lock(&mm->page_table_lock); + unmap_hugepage_range(vma, start, start + length); + spin_unlock(&mm->page_table_lock); +} + +int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma) +{ + struct mm_struct *mm = current->mm; + unsigned long addr; + int ret = 0; + + WARN_ON(!is_vm_hugetlb_page(vma)); + BUG_ON((vma->vm_start % HPAGE_SIZE) != 0); + BUG_ON((vma->vm_end % HPAGE_SIZE) != 0); + + spin_lock(&mm->page_table_lock); + for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) { + unsigned long idx; + hugepte_t *pte = hugepte_alloc(mm, addr); + struct page *page; + + BUG_ON(!in_hugepage_area(mm->context, addr)); + + if (!pte) { + ret = -ENOMEM; + goto out; + } + if (!hugepte_none(*pte)) + continue; + + idx = ((addr - vma->vm_start) >> HPAGE_SHIFT) + + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT)); + page = find_get_page(mapping, idx); + if (!page) { + page = alloc_hugetlb_page(); + if (!page) { + ret = -ENOMEM; + goto out; + } + ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC); + unlock_page(page); + if (ret) { + free_huge_page(page); + goto out; + } + } + setup_huge_pte(mm, page, pte, vma->vm_flags & VM_WRITE); + } +out: + spin_unlock(&mm->page_table_lock); + return ret; +} + +/* Because we have an exclusive hugepage region which lies within the + * normal user address space, we have to take special measures to make + * non-huge mmap()s evade the hugepage reserved region. */ +unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, + unsigned long flags) +{ + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + unsigned long start_addr; + + if (len > TASK_SIZE) + return -ENOMEM; + + if (addr) { + addr = PAGE_ALIGN(addr); + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && + (!vma || addr + len <= vma->vm_start) && + !is_hugepage_only_range(addr,len)) + return addr; + } + start_addr = addr = mm->free_area_cache; + +full_search: + for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { + /* At this point: (!vma || addr < vma->vm_end). */ + if (TASK_SIZE - len < addr) { + /* + * Start a new search - just in case we missed + * some holes. + */ + if (start_addr != TASK_UNMAPPED_BASE) { + start_addr = addr = TASK_UNMAPPED_BASE; + goto full_search; + } + return -ENOMEM; + } + if (!vma || addr + len <= vma->vm_start) { + if (is_hugepage_only_range(addr, len)) { + if (addr < TASK_HPAGE_END_32) + addr = TASK_HPAGE_END_32; + else + addr = TASK_HPAGE_END; + + continue; + } + /* + * Remember the place where we stopped the search: + */ + mm->free_area_cache = addr + len; + return addr; + } + addr = vma->vm_end; + } +} + + +unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, + unsigned long len, unsigned long pgoff, + unsigned long flags) +{ + struct vm_area_struct *vma; + unsigned long base, end; + + if (len & ~HPAGE_MASK) + return -EINVAL; + + if (!(cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)) + return -EINVAL; + + if (test_thread_flag(TIF_32BIT)) { + int err; + + err = open_32bit_htlbpage_range(current->mm); + if (err) + return err; /* Should this just be EINVAL? */ + + base = TASK_HPAGE_BASE_32; + end = TASK_HPAGE_END_32; + } else { + base = TASK_HPAGE_BASE; + end = TASK_HPAGE_END; + } + + if (!in_hugepage_area(current->mm->context, addr) + || (addr & (HPAGE_SIZE - 1))) + addr = base; + + for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { + /* At this point: (!vma || addr < vma->vm_end). */ + if (addr + len > end) + return -ENOMEM; + if (!vma || (addr + len) <= vma->vm_start) + return addr; + addr = ALIGN(vma->vm_end, HPAGE_SIZE); + + /* Because we're in an exclusively hugepage region, + * this alignment shouldn't have skipped over any + * other vmas */ + } +} + +static inline unsigned long computeHugeHptePP(unsigned int hugepte) +{ + unsigned long flags = 0x2; + + if (! (hugepte & _HUGEPAGE_RW)) + flags |= 0x1; + return flags; +} + +int hash_huge_page(struct mm_struct *mm, unsigned long access, + unsigned long ea, unsigned long vsid, int local) +{ + hugepte_t *ptep; + unsigned long va, vpn; + int is_write; + hugepte_t old_pte, new_pte; + unsigned long hpteflags, prpn; + long slot; + + /* Is this for us? */ + if (!in_hugepage_area(mm->context, ea)) + return -1; + + ea &= ~(HPAGE_SIZE-1); + + /* We have to find the first hugepte in the batch, since + * that's the one that will store the HPTE flags */ + ptep = hugepte_offset(mm, ea); + + /* Search the Linux page table for a match with va */ + va = (vsid << 28) | (ea & 0x0fffffff); + vpn = va >> HPAGE_SHIFT; + + /* + * If no pte found or not present, send the problem up to + * do_page_fault + */ + if (unlikely(!ptep || hugepte_none(*ptep))) + return 1; + + BUG_ON(hugepte_bad(*ptep)); + + /* + * Check the user's access rights to the page. If access should be + * prevented then send the problem up to do_page_fault. + */ + is_write = access & _PAGE_RW; + if (unlikely(is_write && !(hugepte_val(*ptep) & _HUGEPAGE_RW))) + return 1; + + /* + * At this point, we have a pte (old_pte) which can be used to build + * or update an HPTE. There are 2 cases: + * + * 1. There is a valid (present) pte with no associated HPTE (this is + * the most common case) + * 2. There is a valid (present) pte with an associated HPTE. The + * current values of the pp bits in the HPTE prevent access + * because we are doing software DIRTY bit management and the + * page is currently not DIRTY. + */ + + old_pte = *ptep; + new_pte = old_pte; + + hpteflags = computeHugeHptePP(hugepte_val(new_pte)); + + /* Check if pte already has an hpte (case 2) */ + if (unlikely(hugepte_val(old_pte) & _HUGEPAGE_HASHPTE)) { + /* There MIGHT be an HPTE for this pte */ + unsigned long hash, slot; + + hash = hpt_hash(vpn, 1); + if (hugepte_val(old_pte) & _HUGEPAGE_SECONDARY) + hash = ~hash; + slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP; + slot += (hugepte_val(old_pte) & _HUGEPAGE_GROUP_IX) >> 5; + + if (ppc_md.hpte_updatepp(slot, hpteflags, va, 1, local) == -1) + hugepte_val(old_pte) &= ~_HUGEPAGE_HPTEFLAGS; + } + + if (likely(!(hugepte_val(old_pte) & _HUGEPAGE_HASHPTE))) { + unsigned long hash = hpt_hash(vpn, 1); + unsigned long hpte_group; + + prpn = hugepte_pfn(old_pte); + +repeat: + hpte_group = ((hash & htab_data.htab_hash_mask) * + HPTES_PER_GROUP) & ~0x7UL; + + /* Update the linux pte with the HPTE slot */ + hugepte_val(new_pte) &= ~_HUGEPAGE_HPTEFLAGS; + hugepte_val(new_pte) |= _HUGEPAGE_HASHPTE; + + /* Add in WIMG bits */ + /* XXX We should store these in the pte */ + hpteflags |= _PAGE_COHERENT; + + slot = ppc_md.hpte_insert(hpte_group, va, prpn, 0, + hpteflags, 0, 1); + + /* Primary is full, try the secondary */ + if (unlikely(slot == -1)) { + hugepte_val(new_pte) |= _HUGEPAGE_SECONDARY; + hpte_group = ((~hash & htab_data.htab_hash_mask) * + HPTES_PER_GROUP) & ~0x7UL; + slot = ppc_md.hpte_insert(hpte_group, va, prpn, + 1, hpteflags, 0, 1); + if (slot == -1) { + if (mftb() & 0x1) + hpte_group = ((hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; + + ppc_md.hpte_remove(hpte_group); + goto repeat; + } + } + + if (unlikely(slot == -2)) + panic("hash_huge_page: pte_insert failed\n"); + + hugepte_val(new_pte) |= (slot<<5) & _HUGEPAGE_GROUP_IX; + + /* + * No need to use ldarx/stdcx here because all who + * might be updating the pte will hold the + * page_table_lock or the hash_table_lock + * (we hold both) + */ + *ptep = new_pte; + } + + return 0; +} + +static void flush_hash_hugepage(mm_context_t context, unsigned long ea, + hugepte_t pte, int local) +{ + unsigned long vsid, vpn, va, hash, secondary, slot; + + BUG_ON(hugepte_bad(pte)); + BUG_ON(!in_hugepage_area(context, ea)); + + vsid = get_vsid(context, ea); + + va = (vsid << 28) | (ea & 0x0fffffff); + vpn = va >> LARGE_PAGE_SHIFT; + hash = hpt_hash(vpn, 1); + secondary = !!(hugepte_val(pte) & _HUGEPAGE_SECONDARY); + if (secondary) + hash = ~hash; + slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP; + slot += (hugepte_val(pte) & _HUGEPAGE_GROUP_IX) >> 5; + + ppc_md.hpte_invalidate(slot, va, 1, local); +} + +static void split_and_free_hugepage(struct page *page) +{ + int j; + struct page *map; + + map = page; + htlbpage_total--; + for (j = 0; j < (HPAGE_SIZE / PAGE_SIZE); j++) { + map->flags &= ~(1 << PG_locked | 1 << PG_error | 1 << PG_referenced | + 1 << PG_dirty | 1 << PG_active | 1 << PG_reserved | + 1 << PG_private | 1<< PG_writeback); + set_page_count(map, 0); + map++; + } + set_page_count(page, 1); + __free_pages(page, HUGETLB_PAGE_ORDER); +} + +int set_hugetlb_mem_size(int count) +{ + int lcount; + struct page *page; + + if (!(cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)) + return 0; + + if (count < 0) + lcount = count; + else + lcount = count - htlbpage_total; + + if (lcount == 0) + return htlbpage_total; + if (lcount > 0) { /* Increase the mem size. */ + while (lcount--) { + page = alloc_fresh_huge_page(); + if (page == NULL) + break; + spin_lock(&htlbpage_lock); + enqueue_huge_page(page); + htlbpage_free++; + htlbpage_total++; + spin_unlock(&htlbpage_lock); + } + return htlbpage_total; + } + /* Shrink the memory size. */ + while (lcount++) { + page = alloc_hugetlb_page(); + if (page == NULL) + break; + spin_lock(&htlbpage_lock); + split_and_free_hugepage(page); + spin_unlock(&htlbpage_lock); + } + return htlbpage_total; +} + +int hugetlb_sysctl_handler(ctl_table *table, int write, + struct file *file, void *buffer, size_t *length) +{ + proc_dointvec(table, write, file, buffer, length); + htlbpage_max = set_hugetlb_mem_size(htlbpage_max); + return 0; +} + +static int __init hugetlb_setup(char *s) +{ + if (sscanf(s, "%d", &htlbpage_max) <= 0) + htlbpage_max = 0; + return 1; +} +__setup("hugepages=", hugetlb_setup); + +static int __init hugetlb_init(void) +{ + int i; + struct page *page; + + if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) { + for (i = 0; i < MAX_NUMNODES; ++i) + INIT_LIST_HEAD(&hugepage_freelists[i]); + + for (i = 0; i < htlbpage_max; ++i) { + page = alloc_fresh_huge_page(); + if (!page) + break; + spin_lock(&htlbpage_lock); + enqueue_huge_page(page); + spin_unlock(&htlbpage_lock); + } + htlbpage_max = htlbpage_free = htlbpage_total = i; + printk("Total HugeTLB memory allocated, %d\n", htlbpage_free); + } else { + htlbpage_max = 0; + printk("CPU does not support HugeTLB\n"); + } + + return 0; +} +module_init(hugetlb_init); + +int hugetlb_report_meminfo(char *buf) +{ + return sprintf(buf, + "HugePages_Total: %5d\n" + "HugePages_Free: %5d\n" + "Hugepagesize: %5lu kB\n", + htlbpage_total, + htlbpage_free, + HPAGE_SIZE/1024); +} + +/* This is advisory only, so we can get away with accesing + * htlbpage_free without taking the lock. */ +int is_hugepage_mem_enough(size_t size) +{ + return (size + ~HPAGE_MASK)/HPAGE_SIZE <= htlbpage_free; +} + +/* + * We cannot handle pagefaults against hugetlb pages at all. They cause + * handle_mm_fault() to try to instantiate regular-sized pages in the + * hugegpage VMA. do_page_fault() is supposed to trap this, so BUG is we get + * this far. + */ +static struct page *hugetlb_nopage(struct vm_area_struct *vma, + unsigned long address, int unused) +{ + BUG(); + return NULL; +} + +struct vm_operations_struct hugetlb_vm_ops = { + .nopage = hugetlb_nopage, +}; diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c --- a/arch/ppc64/mm/init.c Thu Sep 11 23:03:13 2003 +++ b/arch/ppc64/mm/init.c Thu Sep 11 23:03:13 2003 @@ -290,7 +290,7 @@ if (!pgd_none(*pgd)) { pmd = pmd_offset(pgd, vmaddr); - if (!pmd_none(*pmd)) { + if (pmd_present(*pmd)) { ptep = pte_offset_kernel(pmd, vmaddr); /* Check if HPTE might exist and flush it if so */ pte = __pte(pte_update(ptep, _PAGE_HPTEFLAGS, 0)); @@ -298,6 +298,7 @@ flush_hash_page(context, vmaddr, pte, local); } } + WARN_ON(pmd_hugepage(*pmd)); } } @@ -348,7 +349,7 @@ pmd_end = (start + PMD_SIZE) & PMD_MASK; if (pmd_end > end) pmd_end = end; - if (!pmd_none(*pmd)) { + if (pmd_present(*pmd)) { ptep = pte_offset_kernel(pmd, start); do { if (pte_val(*ptep) & _PAGE_HASHPTE) { @@ -367,6 +368,7 @@ ++ptep; } while (start < pmd_end); } else { + WARN_ON(pmd_hugepage(*pmd)); start = pmd_end; } ++pmd; @@ -540,8 +542,6 @@ } module_init(setup_kcore); -void initialize_paca_hardware_interrupt_stack(void); - void __init mem_init(void) { #ifndef CONFIG_DISCONTIGMEM @@ -607,9 +607,6 @@ PAGE_OFFSET, (unsigned long)__va(lmb_end_of_DRAM())); #endif mem_init_done = 1; - - /* set the last page of each hardware interrupt stack to be protected */ - initialize_paca_hardware_interrupt_stack(); #ifdef CONFIG_PPC_ISERIES create_virtual_bus_tce_table(); diff -Nru a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c --- a/arch/ppc64/mm/numa.c Thu Sep 11 23:03:13 2003 +++ b/arch/ppc64/mm/numa.c Thu Sep 11 23:03:13 2003 @@ -24,18 +24,21 @@ 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}; -unsigned long numa_cpumask_lookup_table[MAX_NUMNODES]; +cpumask_t numa_cpumask_lookup_table[MAX_NUMNODES]; int nr_cpus_in_node[MAX_NUMNODES] = { [0 ... (MAX_NUMNODES -1)] = 0}; struct pglist_data node_data[MAX_NUMNODES]; bootmem_data_t plat_node_bdata[MAX_NUMNODES]; +EXPORT_SYMBOL(node_data); +EXPORT_SYMBOL(numa_memory_lookup_table); + 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; - if (!(numa_cpumask_lookup_table[node] & 1UL << cpu)) { - numa_cpumask_lookup_table[node] |= 1UL << cpu; + if (!(cpu_isset(cpu, numa_cpumask_lookup_table[node]))) { + cpu_set(cpu, numa_cpumask_lookup_table[node]); nr_cpus_in_node[node]++; } } diff -Nru a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c --- a/arch/ppc64/xmon/xmon.c Thu Sep 11 23:03:13 2003 +++ b/arch/ppc64/xmon/xmon.c Thu Sep 11 23:03:13 2003 @@ -15,6 +15,8 @@ #include #include #include +#include + #include #include #include @@ -27,6 +29,7 @@ #include #include #include + #include "nonstdio.h" #include "privinst.h" @@ -59,7 +62,6 @@ unsigned instr; unsigned long count; unsigned char enabled; - char funcname[64]; /* function name for humans */ }; #define NBPTS 16 @@ -79,14 +81,9 @@ static int bsesc(void); static void dump(void); static void prdump(unsigned long, long); -#ifdef __MWERKS__ -static void prndump(unsigned, int); -static int nvreadb(unsigned); -#endif static int ppc_inst_dump(unsigned long, long); void print_address(unsigned long); static int getsp(void); -static void dump_hash_table(void); static void backtrace(struct pt_regs *); static void excprint(struct pt_regs *); static void prregs(struct pt_regs *); @@ -106,7 +103,6 @@ static unsigned long read_spr(int); static void write_spr(int, unsigned long); static void super_regs(void); -static void print_sysmap(void); static void remove_bpts(void); static void insert_bpts(void); static struct bpt *at_breakpoint(unsigned long pc); @@ -158,7 +154,6 @@ dd dump double values\n\ e print exception information\n\ f flush cache\n\ - h dump hash table\n\ m examine/change memory\n\ mm move a block of memory\n\ ms set a block of memory\n\ @@ -183,6 +178,13 @@ static struct pt_regs *xmon_regs[NR_CPUS]; +void __xmon_print_symbol(const char *fmt, unsigned long address); +#define xmon_print_symbol(fmt, addr) \ +do { \ + __check_printsym_format(fmt, ""); \ + __xmon_print_symbol(fmt, addr); \ +} while(0) + /* * Stuff for reading and writing memory safely */ @@ -211,42 +213,6 @@ no functions have been called from the current function. */ -/* - A traceback table typically follows each function. - The find_tb_table() func will fill in this struct. Note that the struct - is not an exact match with the encoded table defined by the ABI. It is - defined here more for programming convenience. - */ -struct tbtable { - unsigned long flags; /* flags: */ -#define TBTAB_FLAGSGLOBALLINK (1L<<47) -#define TBTAB_FLAGSISEPROL (1L<<46) -#define TBTAB_FLAGSHASTBOFF (1L<<45) -#define TBTAB_FLAGSINTPROC (1L<<44) -#define TBTAB_FLAGSHASCTL (1L<<43) -#define TBTAB_FLAGSTOCLESS (1L<<42) -#define TBTAB_FLAGSFPPRESENT (1L<<41) -#define TBTAB_FLAGSNAMEPRESENT (1L<<38) -#define TBTAB_FLAGSUSESALLOCA (1L<<37) -#define TBTAB_FLAGSSAVESCR (1L<<33) -#define TBTAB_FLAGSSAVESLR (1L<<32) -#define TBTAB_FLAGSSTORESBC (1L<<31) -#define TBTAB_FLAGSFIXUP (1L<<30) -#define TBTAB_FLAGSPARMSONSTK (1L<<0) - unsigned char fp_saved; /* num fp regs saved f(32-n)..f31 */ - unsigned char gpr_saved; /* num gpr's saved */ - unsigned char fixedparms; /* num fixed point parms */ - unsigned char floatparms; /* num float parms */ - unsigned char parminfo[32]; /* types of args. null terminated */ -#define TBTAB_PARMFIXED 1 -#define TBTAB_PARMSFLOAT 2 -#define TBTAB_PARMDFLOAT 3 - unsigned int tb_offset; /* offset from start of func */ - unsigned long funcstart; /* addr of start of function */ - char name[64]; /* name of function (null terminated)*/ -}; -static int find_tb_table(unsigned long codeaddr, struct tbtable *tab); - #define SURVEILLANCE_TOKEN 9000 static inline void disable_surveillance(void) @@ -304,8 +270,7 @@ std 29,232(%0)\n\ std 30,240(%0)\n\ std 31,248(%0)" : : "b" (®s)); - /* Fetch the link reg for this stack frame. - NOTE: the prev printf fills in the lr. */ + regs.nip = regs.link = ((unsigned long *)(regs.gpr[1]))[2]; regs.msr = get_msr(); regs.ctr = get_ctr(); @@ -380,7 +345,9 @@ xmon_trace[smp_processor_id()] = BRSTEP; regs->msr |= MSR_SE; } else { - printf("Stopped at breakpoint %x (%lx %s)\n", (bp - bpts)+1, bp->address, bp->funcname); + printf("Stopped at breakpoint %x (%lx ", (bp - bpts) + 1, + bp->address); + xmon_print_symbol("%s)\n", bp->address); xmon(regs); } return 1; @@ -578,9 +545,6 @@ else excprint(excp); break; - case 'M': - print_sysmap(); - break; case 'S': super_regs(); break; @@ -590,9 +554,6 @@ case 'f': cacheflush(); break; - case 'h': - dump_hash_table(); - break; case 's': case 'x': case EOF: @@ -773,7 +734,6 @@ unsigned long a; int mode, i; struct bpt *bp; - struct tbtable tab; cmd = inchar(); switch (cmd) { @@ -829,7 +789,9 @@ if (bp == 0) { printf("No breakpoint at %x\n", a); } else { - printf("Cleared breakpoint %x (%lx %s)\n", (bp - bpts)+1, bp->address, bp->funcname); + printf("Cleared breakpoint %x (%lx ", + (bp - bpts) + 1, bp->address); + xmon_print_symbol("%s)\n", bp->address); bp->enabled = 0; } } @@ -863,8 +825,11 @@ printf(" inst %.16lx %8x\n", iabr.address & ~3, iabr.count); for (bp = bpts, bpnum = 1; bp < &bpts[NBPTS]; ++bp, ++bpnum) - if (bp->enabled) - printf("%2x trap %.16lx %8x %s\n", bpnum, bp->address, bp->count, bp->funcname); + if (bp->enabled) { + printf("%2x trap %.16lx %8x ", + bpnum, bp->address, bp->count); + xmon_print_symbol("%s\n", bp->address); + } break; } bp = at_breakpoint(a); @@ -881,14 +846,9 @@ bp->address = a; bp->count = 0; scanhex(&bp->count); - /* Find the function name just once. */ - bp->funcname[0] = '\0'; - if (find_tb_table(bp->address, &tab) && tab.name[0]) { - /* Got a nice name for it. */ - int delta = bp->address - tab.funcstart; - sprintf(bp->funcname, "%s+0x%x", tab.name, delta); - } - printf("Set breakpoint %2x trap %.16lx %8x %s\n", (bp-bpts)+1, bp->address, bp->count, bp->funcname); + printf("Set breakpoint %2x trap %.16lx %8x ", (bp-bpts) + 1, + bp->address, bp->count); + xmon_print_symbol("%s\n", bp->address); break; } } @@ -925,7 +885,6 @@ unsigned long lr; unsigned long stack[3]; struct pt_regs regs; - struct tbtable tab; int framecount; char *funcname; /* declare these as raw ptrs so we don't get func descriptors */ @@ -971,17 +930,11 @@ break; printf("exception: %lx %s regs %lx\n", regs.trap, getvecname(regs.trap), sp+112); printf(" %.16lx", regs.nip); - if ((regs.nip & 0xffffffff00000000UL) && - find_tb_table(regs.nip, &tab)) { - int delta = regs.nip-tab.funcstart; - if (delta < 0) - printf(" "); - else - printf(" %s+0x%x", tab.name, delta); - } + if (regs.nip & 0xffffffff00000000UL) + xmon_print_symbol(" %s", regs.nip); printf("\n"); if (regs.gpr[1] < sp) { - printf("\n", regs.gpr[1]); + printf("\n", regs.gpr[1]); break; } @@ -989,13 +942,8 @@ if (mread(sp, stack, sizeof(stack)) != sizeof(stack)) break; } else { - if (stack[2] && find_tb_table(stack[2], &tab)) { - int delta = stack[2]-tab.funcstart; - if (delta < 0) - printf(" "); - else - printf(" %s+0x%x", tab.name, delta); - } + if (stack[2]) + xmon_print_symbol(" %s", stack[2]); printf("\n"); } if (stack[0] && stack[0] <= sp) { @@ -1024,8 +972,6 @@ void excprint(struct pt_regs *fp) { - struct task_struct *c; - struct tbtable tab; unsigned long flags; spin_lock_irqsave(&exception_print_lock, flags); @@ -1034,21 +980,13 @@ printf("cpu %d: ", smp_processor_id()); #endif /* CONFIG_SMP */ - printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(fp->trap), fp); + printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(fp->trap), fp); printf(" pc: %lx", fp->nip); - if (find_tb_table(fp->nip, &tab) && tab.name[0]) { - /* Got a nice name for it */ - int delta = fp->nip - tab.funcstart; - printf(" (%s+0x%x)", tab.name, delta); - } - printf("\n"); + xmon_print_symbol(" (%s)\n", fp->nip); + printf(" lr: %lx", fp->link); - if (find_tb_table(fp->link, &tab) && tab.name[0]) { - /* Got a nice name for it */ - int delta = fp->link - tab.funcstart; - printf(" (%s+0x%x)", tab.name, delta); - } - printf("\n"); + xmon_print_symbol(" (%s)\n", fp->link); + printf(" sp: %lx\n", fp->gpr[1]); printf(" msr: %lx\n", fp->msr); @@ -1057,13 +995,11 @@ printf(" dsisr: %lx\n", fp->dsisr); } - /* XXX: need to copy current or we die. Why? */ - c = current; - printf(" current = 0x%lx\n", c); + printf(" current = 0x%lx\n", current); printf(" paca = 0x%lx\n", get_paca()); - if (c) { - printf(" current = %lx, pid = %ld, comm = %s\n", - c, c->pid, c->comm); + if (current) { + printf(" pid = %ld, comm = %s\n", + current->pid, current->comm); } spin_unlock_irqrestore(&exception_print_lock, flags); @@ -1153,14 +1089,6 @@ extern char dec_exc; void -print_sysmap(void) -{ - extern char *sysmap; - if ( sysmap ) - printf("System.map: \n%s", sysmap); -} - -void super_regs() { int i, cmd; @@ -1228,152 +1156,6 @@ scannl(); } -#ifndef CONFIG_PPC64BRIDGE -static void -dump_hash_table_seg(unsigned seg, unsigned start, unsigned end) -{ - extern void *Hash; - extern unsigned long Hash_size; - unsigned *htab = Hash; - unsigned hsize = Hash_size; - unsigned v, hmask, va, last_va; - int found, last_found, i; - unsigned *hg, w1, last_w2, last_va0; - - last_found = 0; - hmask = hsize / 64 - 1; - va = start; - start = (start >> 12) & 0xffff; - end = (end >> 12) & 0xffff; - for (v = start; v < end; ++v) { - found = 0; - hg = htab + (((v ^ seg) & hmask) * 16); - w1 = 0x80000000 | (seg << 7) | (v >> 10); - for (i = 0; i < 8; ++i, hg += 2) { - if (*hg == w1) { - found = 1; - break; - } - } - if (!found) { - w1 ^= 0x40; - hg = htab + ((~(v ^ seg) & hmask) * 16); - for (i = 0; i < 8; ++i, hg += 2) { - if (*hg == w1) { - found = 1; - break; - } - } - } - if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) { - if (last_found) { - if (last_va != last_va0) - printf(" ... %x", last_va); - printf("\n"); - } - if (found) { - printf("%x to %x", va, hg[1]); - last_va0 = va; - } - last_found = found; - } - if (found) { - last_w2 = hg[1] & ~0x180; - last_va = va; - } - va += 4096; - } - if (last_found) - printf(" ... %x\n", last_va); -} - -#else /* CONFIG_PPC64BRIDGE */ -static void -dump_hash_table_seg(unsigned seg, unsigned start, unsigned end) -{ - extern void *Hash; - extern unsigned long Hash_size; - unsigned *htab = Hash; - unsigned hsize = Hash_size; - unsigned v, hmask, va, last_va; - int found, last_found, i; - unsigned *hg, w1, last_w2, last_va0; - - last_found = 0; - hmask = hsize / 128 - 1; - va = start; - start = (start >> 12) & 0xffff; - end = (end >> 12) & 0xffff; - for (v = start; v < end; ++v) { - found = 0; - hg = htab + (((v ^ seg) & hmask) * 32); - w1 = 1 | (seg << 12) | ((v & 0xf800) >> 4); - for (i = 0; i < 8; ++i, hg += 4) { - if (hg[1] == w1) { - found = 1; - break; - } - } - if (!found) { - w1 ^= 2; - hg = htab + ((~(v ^ seg) & hmask) * 32); - for (i = 0; i < 8; ++i, hg += 4) { - if (hg[1] == w1) { - found = 1; - break; - } - } - } - if (!(last_found && found && (hg[3] & ~0x180) == last_w2 + 4096)) { - if (last_found) { - if (last_va != last_va0) - printf(" ... %x", last_va); - printf("\n"); - } - if (found) { - printf("%x to %x", va, hg[3]); - last_va0 = va; - } - last_found = found; - } - if (found) { - last_w2 = hg[3] & ~0x180; - last_va = va; - } - va += 4096; - } - if (last_found) - printf(" ... %x\n", last_va); -} -#endif /* CONFIG_PPC64BRIDGE */ - -static unsigned long hash_ctx; -static unsigned long hash_start; -static unsigned long hash_end; - -static void -dump_hash_table() -{ - int seg; - unsigned seg_start, seg_end; - - hash_ctx = 0; - hash_start = 0; - hash_end = 0xfffff000; - scanhex(&hash_ctx); - scanhex(&hash_start); - scanhex(&hash_end); - printf("Mappings for context %x\n", hash_ctx); - seg_start = hash_start; - for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) { - seg_end = (seg << 28) | 0x0ffff000; - if (seg_end > hash_end) - seg_end = hash_end; - dump_hash_table_seg((hash_ctx << 4) + seg, seg_start, seg_end); - seg_start = seg_end + 0x1000; - } -} - int mread(unsigned long adrs, void *buf, int size) { @@ -2073,111 +1855,52 @@ lineptr = str; } - -/* Starting at codeaddr scan forward for a tbtable and fill in the - given table. Return non-zero if successful at doing something. - */ -static int -find_tb_table(unsigned long codeaddr, struct tbtable *tab) +/* xmon version of __print_symbol */ +void __xmon_print_symbol(const char *fmt, unsigned long address) { - unsigned long codeaddr_max; - unsigned long tbtab_start; - int nr; - int instr; - int num_parms; + char *modname; + const char *name; + unsigned long offset, size; + char namebuf[128]; - /* don't look for traceback table in userspace */ - if (codeaddr < PAGE_OFFSET) - return 0; + if (setjmp(bus_error_jmp) == 0) { + debugger_fault_handler = handle_fault; + sync(); + name = kallsyms_lookup(address, &size, &offset, &modname, + namebuf); + sync(); + /* wait a little while to see if we get a machine check */ + __delay(200); + } else { + name = "symbol lookup failed"; + } - if (tab == NULL) - return 0; - memset(tab, 0, sizeof(tab)); + debugger_fault_handler = 0; - /* Scan instructions starting at codeaddr for 128k max */ - for (codeaddr_max = codeaddr + 128*1024*4; - codeaddr < codeaddr_max; - codeaddr += 4) { - nr = mread(codeaddr, &instr, 4); - if (nr != 4) - return 0; /* Bad read. Give up promptly. */ - if (instr == 0) { - /* table should follow. */ - int version; - unsigned long flags; - tbtab_start = codeaddr; /* save it to compute func start addr */ - codeaddr += 4; - nr = mread(codeaddr, &flags, 8); - if (nr != 8) - return 0; /* Bad read or no tb table. */ - tab->flags = flags; - version = (flags >> 56) & 0xff; - if (version != 0) - continue; /* No tb table here. */ - /* Now, like the version, some of the flags are values - that are more conveniently extracted... */ - tab->fp_saved = (flags >> 24) & 0x3f; - tab->gpr_saved = (flags >> 16) & 0x3f; - tab->fixedparms = (flags >> 8) & 0xff; - tab->floatparms = (flags >> 1) & 0x7f; - codeaddr += 8; - num_parms = tab->fixedparms + tab->floatparms; - if (num_parms) { - unsigned int parminfo; - int parm; - if (num_parms > 32) - return 1; /* incomplete */ - nr = mread(codeaddr, &parminfo, 4); - if (nr != 4) - return 1; /* incomplete */ - /* decode parminfo...32 bits. - A zero means fixed. A one means float and the - following bit determines single (0) or double (1). - */ - for (parm = 0; parm < num_parms; parm++) { - if (parminfo & 0x80000000) { - parminfo <<= 1; - if (parminfo & 0x80000000) - tab->parminfo[parm] = TBTAB_PARMDFLOAT; - else - tab->parminfo[parm] = TBTAB_PARMSFLOAT; - } else { - tab->parminfo[parm] = TBTAB_PARMFIXED; - } - parminfo <<= 1; - } - codeaddr += 4; - } - if (flags & TBTAB_FLAGSHASTBOFF) { - nr = mread(codeaddr, &tab->tb_offset, 4); - if (nr != 4) - return 1; /* incomplete */ - if (tab->tb_offset > 0) { - tab->funcstart = tbtab_start - tab->tb_offset; - } - codeaddr += 4; - } - /* hand_mask appears to be always be omitted. */ - if (flags & TBTAB_FLAGSHASCTL) { - /* Assume this will never happen for C or asm */ - return 1; /* incomplete */ - } - if (flags & TBTAB_FLAGSNAMEPRESENT) { - short namlen; - nr = mread(codeaddr, &namlen, 2); - if (nr != 2) - return 1; /* incomplete */ - if (namlen >= sizeof(tab->name)) - namlen = sizeof(tab->name)-1; - codeaddr += 2; - nr = mread(codeaddr, tab->name, namlen); - tab->name[namlen] = '\0'; - codeaddr += namlen; - } - return 1; - } + if (!name) { + char addrstr[sizeof("0x%lx") + (BITS_PER_LONG*3/10)]; + + sprintf(addrstr, "0x%lx", address); + printf(fmt, addrstr); + return; + } + + if (modname) { + /* This is pretty small. */ + char buffer[sizeof("%s+%#lx/%#lx [%s]") + + strlen(name) + 2*(BITS_PER_LONG*3/10) + + strlen(modname)]; + + sprintf(buffer, "%s+%#lx/%#lx [%s]", + name, offset, size, modname); + printf(fmt, buffer); + } else { + char buffer[sizeof("%s+%#lx/%#lx") + + strlen(name) + 2*(BITS_PER_LONG*3/10)]; + + sprintf(buffer, "%s+%#lx/%#lx", name, offset, size); + printf(fmt, buffer); } - return 0; /* hit max...sorry. */ } void diff -Nru a/arch/sh/boot/compressed/misc.c b/arch/sh/boot/compressed/misc.c --- a/arch/sh/boot/compressed/misc.c Thu Sep 11 23:03:11 2003 +++ b/arch/sh/boot/compressed/misc.c Thu Sep 11 23:03:11 2003 @@ -105,8 +105,8 @@ { void *p; - if (size <0) error("Malloc error\n"); - if (free_mem_ptr == 0) error("Memory error\n"); + if (size <0) error("Malloc error"); + if (free_mem_ptr == 0) error("Memory error"); free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ @@ -114,7 +114,7 @@ free_mem_ptr += size; if (free_mem_ptr >= free_mem_end_ptr) - error("\nOut of memory\n"); + error("Out of memory"); return p; } @@ -180,7 +180,7 @@ static int fill_inbuf(void) { if (insize != 0) { - error("ran out of input data\n"); + error("ran out of input data"); } inbuf = input_data; diff -Nru a/arch/sparc/boot/btfixupprep.c b/arch/sparc/boot/btfixupprep.c --- a/arch/sparc/boot/btfixupprep.c Thu Sep 11 23:03:13 2003 +++ b/arch/sparc/boot/btfixupprep.c Thu Sep 11 23:03:13 2003 @@ -171,6 +171,8 @@ } } else if (buffer[nbase+4] != '_') continue; + if (!strcmp (sect, ".text.exit")) + continue; if (strcmp (sect, ".text") && strcmp (sect, ".init.text") && strcmp (sect, ".fixup") && diff -Nru a/arch/sparc/lib/checksum.S b/arch/sparc/lib/checksum.S --- a/arch/sparc/lib/checksum.S Thu Sep 11 23:03:12 2003 +++ b/arch/sparc/lib/checksum.S Thu Sep 11 23:03:12 2003 @@ -145,36 +145,39 @@ .globl C_LABEL(__csum_partial_copy_start), C_LABEL(__csum_partial_copy_end) C_LABEL(__csum_partial_copy_start): -#define EX(x,y,a,b,z) \ +/* Work around cpp -rob */ +#define ALLOC #alloc +#define EXECINSTR #execinstr +#define EX(x,y,a,b) \ 98: x,y; \ - .section .fixup,z##alloc,z##execinstr; \ + .section .fixup,ALLOC,EXECINSTR; \ .align 4; \ 99: ba 30f; \ a, b, %o3; \ - .section __ex_table,z##alloc; \ + .section __ex_table,ALLOC; \ .align 4; \ .word 98b, 99b; \ .text; \ .align 4 -#define EX2(x,y,z) \ +#define EX2(x,y) \ 98: x,y; \ - .section __ex_table,z##alloc; \ + .section __ex_table,ALLOC; \ .align 4; \ .word 98b, 30f; \ .text; \ .align 4 -#define EX3(x,y,z) \ +#define EX3(x,y) \ 98: x,y; \ - .section __ex_table,z##alloc; \ + .section __ex_table,ALLOC; \ .align 4; \ .word 98b, 96f; \ .text; \ .align 4 -#define EXT(start,end,handler,z) \ - .section __ex_table,z##alloc; \ +#define EXT(start,end,handler) \ + .section __ex_table,ALLOC; \ .align 4; \ .word start, 0, end, handler; \ .text; \ @@ -247,21 +250,21 @@ cc_end_cruft: be 1f andcc %o3, 4, %g0 - EX(ldd [%o0 + 0x00], %g2, and %o3, 0xf,#) + EX(ldd [%o0 + 0x00], %g2, and %o3, 0xf) add %o1, 8, %o1 addcc %g2, %g7, %g7 add %o0, 8, %o0 addxcc %g3, %g7, %g7 - EX2(st %g2, [%o1 - 0x08],#) + EX2(st %g2, [%o1 - 0x08]) addx %g0, %g7, %g7 andcc %o3, 4, %g0 - EX2(st %g3, [%o1 - 0x04],#) + EX2(st %g3, [%o1 - 0x04]) 1: be 1f andcc %o3, 3, %o3 - EX(ld [%o0 + 0x00], %g2, add %o3, 4,#) + EX(ld [%o0 + 0x00], %g2, add %o3, 4) add %o1, 4, %o1 addcc %g2, %g7, %g7 - EX2(st %g2, [%o1 - 0x04],#) + EX2(st %g2, [%o1 - 0x04]) addx %g0, %g7, %g7 andcc %o3, 3, %g0 add %o0, 4, %o0 @@ -271,14 +274,14 @@ subcc %o3, 2, %o3 b 4f or %g0, %g0, %o4 -2: EX(lduh [%o0 + 0x00], %o4, add %o3, 2,#) +2: EX(lduh [%o0 + 0x00], %o4, add %o3, 2) add %o0, 2, %o0 - EX2(sth %o4, [%o1 + 0x00],#) + EX2(sth %o4, [%o1 + 0x00]) be 6f add %o1, 2, %o1 sll %o4, 16, %o4 -4: EX(ldub [%o0 + 0x00], %o5, add %g0, 1,#) - EX2(stb %o5, [%o1 + 0x00],#) +4: EX(ldub [%o0 + 0x00], %o5, add %g0, 1) + EX2(stb %o5, [%o1 + 0x00]) sll %o5, 8, %o5 or %o5, %o4, %o4 6: addcc %o4, %g7, %g7 @@ -295,9 +298,9 @@ andcc %o0, 0x2, %g0 be 1f andcc %o0, 0x4, %g0 - EX(lduh [%o0 + 0x00], %g4, add %g1, 0,#) + EX(lduh [%o0 + 0x00], %g4, add %g1, 0) sub %g1, 2, %g1 - EX2(sth %g4, [%o1 + 0x00],#) + EX2(sth %g4, [%o1 + 0x00]) add %o0, 2, %o0 sll %g4, 16, %g4 addcc %g4, %g7, %g7 @@ -311,9 +314,9 @@ or %g3, %g7, %g7 1: be 3f andcc %g1, 0xffffff80, %g0 - EX(ld [%o0 + 0x00], %g4, add %g1, 0,#) + EX(ld [%o0 + 0x00], %g4, add %g1, 0) sub %g1, 4, %g1 - EX2(st %g4, [%o1 + 0x00],#) + EX2(st %g4, [%o1 + 0x00]) add %o0, 4, %o0 addcc %g4, %g7, %g7 add %o1, 4, %o1 @@ -342,7 +345,7 @@ CSUMCOPY_BIGCHUNK(%o0,%o1,%g7,0x20,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) CSUMCOPY_BIGCHUNK(%o0,%o1,%g7,0x40,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) CSUMCOPY_BIGCHUNK(%o0,%o1,%g7,0x60,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) -10: EXT(5b, 10b, 20f,#) ! note for exception handling +10: EXT(5b, 10b, 20f) ! note for exception handling sub %g1, 128, %g1 ! detract from length addx %g0, %g7, %g7 ! add in last carry bit andcc %g1, 0xffffff80, %g0 ! more to csum? @@ -367,7 +370,7 @@ CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x28,%g2,%g3,%g4,%g5) CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x18,%g2,%g3,%g4,%g5) CSUMCOPY_LASTCHUNK(%o0,%o1,%g7,0x08,%g2,%g3,%g4,%g5) -12: EXT(cctbl, 12b, 22f,#) ! note for exception table handling +12: EXT(cctbl, 12b, 22f) ! note for exception table handling addx %g0, %g7, %g7 andcc %o3, 0xf, %g0 ! check for low bits set ccte: bne cc_end_cruft ! something left, handle it out of band @@ -378,7 +381,7 @@ CSUMCOPY_BIGCHUNK_ALIGNED(%o0,%o1,%g7,0x20,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) CSUMCOPY_BIGCHUNK_ALIGNED(%o0,%o1,%g7,0x40,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) CSUMCOPY_BIGCHUNK_ALIGNED(%o0,%o1,%g7,0x60,%o4,%o5,%g2,%g3,%g4,%g5,%o2,%o3) -11: EXT(ccdbl, 11b, 21f,#) ! note for exception table handling +11: EXT(ccdbl, 11b, 21f) ! note for exception table handling sub %g1, 128, %g1 ! detract from length addx %g0, %g7, %g7 ! add in last carry bit andcc %g1, 0xffffff80, %g0 ! more to csum? @@ -395,9 +398,9 @@ be,a 1f srl %g1, 1, %g4 sub %g1, 1, %g1 - EX(ldub [%o0], %g5, add %g1, 1,#) + EX(ldub [%o0], %g5, add %g1, 1) add %o0, 1, %o0 - EX2(stb %g5, [%o1],#) + EX2(stb %g5, [%o1]) srl %g1, 1, %g4 add %o1, 1, %o1 1: cmp %g4, 0 @@ -406,34 +409,34 @@ andcc %o0, 2, %g0 be,a 1f srl %g4, 1, %g4 - EX(lduh [%o0], %o4, add %g1, 0,#) + EX(lduh [%o0], %o4, add %g1, 0) sub %g1, 2, %g1 srl %o4, 8, %g2 sub %g4, 1, %g4 - EX2(stb %g2, [%o1],#) + EX2(stb %g2, [%o1]) add %o4, %g5, %g5 - EX2(stb %o4, [%o1 + 1],#) + EX2(stb %o4, [%o1 + 1]) add %o0, 2, %o0 srl %g4, 1, %g4 add %o1, 2, %o1 1: cmp %g4, 0 be,a 2f andcc %g1, 2, %g0 - EX3(ld [%o0], %o4,#) + EX3(ld [%o0], %o4) 5: srl %o4, 24, %g2 srl %o4, 16, %g3 - EX2(stb %g2, [%o1],#) + EX2(stb %g2, [%o1]) srl %o4, 8, %g2 - EX2(stb %g3, [%o1 + 1],#) + EX2(stb %g3, [%o1 + 1]) add %o0, 4, %o0 - EX2(stb %g2, [%o1 + 2],#) + EX2(stb %g2, [%o1 + 2]) addcc %o4, %g5, %g5 - EX2(stb %o4, [%o1 + 3],#) + EX2(stb %o4, [%o1 + 3]) addx %g5, %g0, %g5 ! I am now to lazy to optimize this (question it add %o1, 4, %o1 ! is worthy). Maybe some day - with the sll/srl subcc %g4, 1, %g4 ! tricks bne,a 5b - EX3(ld [%o0], %o4,#) + EX3(ld [%o0], %o4) sll %g5, 16, %g2 srl %g5, 16, %g5 srl %g2, 16, %g2 @@ -441,19 +444,19 @@ add %g2, %g5, %g5 2: be,a 3f andcc %g1, 1, %g0 - EX(lduh [%o0], %o4, and %g1, 3,#) + EX(lduh [%o0], %o4, and %g1, 3) andcc %g1, 1, %g0 srl %o4, 8, %g2 add %o0, 2, %o0 - EX2(stb %g2, [%o1],#) + EX2(stb %g2, [%o1]) add %g5, %o4, %g5 - EX2(stb %o4, [%o1 + 1],#) + EX2(stb %o4, [%o1 + 1]) add %o1, 2, %o1 3: be,a 1f sll %g5, 16, %o4 - EX(ldub [%o0], %g2, add %g0, 1,#) + EX(ldub [%o0], %g2, add %g0, 1) sll %g2, 8, %o4 - EX2(stb %g2, [%o1],#) + EX2(stb %g2, [%o1]) add %g5, %o4, %g5 sll %g5, 16, %o4 1: addcc %o4, %g5, %g5 diff -Nru a/arch/sparc/lib/copy_user.S b/arch/sparc/lib/copy_user.S --- a/arch/sparc/lib/copy_user.S Thu Sep 11 23:03:12 2003 +++ b/arch/sparc/lib/copy_user.S Thu Sep 11 23:03:12 2003 @@ -16,41 +16,44 @@ #include #include -#define EX(x,y,a,b,z) \ +/* Work around cpp -rob */ +#define ALLOC #alloc +#define EXECINSTR #execinstr +#define EX(x,y,a,b) \ 98: x,y; \ - .section .fixup,z##alloc,z##execinstr; \ + .section .fixup,ALLOC,EXECINSTR; \ .align 4; \ 99: ba fixupretl; \ a, b, %g3; \ - .section __ex_table,z##alloc; \ + .section __ex_table,ALLOC; \ .align 4; \ .word 98b, 99b; \ .text; \ .align 4 -#define EX2(x,y,c,d,e,a,b,z) \ +#define EX2(x,y,c,d,e,a,b) \ 98: x,y; \ - .section .fixup,z##alloc,z##execinstr; \ + .section .fixup,ALLOC,EXECINSTR; \ .align 4; \ 99: c, d, e; \ ba fixupretl; \ a, b, %g3; \ - .section __ex_table,z##alloc; \ + .section __ex_table,ALLOC; \ .align 4; \ .word 98b, 99b; \ .text; \ .align 4 -#define EXO2(x,y,z) \ -98: x,##y; \ - .section __ex_table,z##alloc; \ +#define EXO2(x,y) \ +98: x, y; \ + .section __ex_table,ALLOC; \ .align 4; \ .word 98b, 97f; \ .text; \ .align 4 -#define EXT(start,end,handler,z) \ - .section __ex_table,z##alloc; \ +#define EXT(start,end,handler) \ + .section __ex_table,ALLOC; \ .align 4; \ .word start, 0, end, handler; \ .text; \ @@ -121,23 +124,23 @@ be 4f andcc %o1, 2, %g0 - EXO2(ldub [%o1], %g2,#) + EXO2(ldub [%o1], %g2) add %o1, 1, %o1 - EXO2(stb %g2, [%o0],#) + EXO2(stb %g2, [%o0]) sub %o2, 1, %o2 bne 3f add %o0, 1, %o0 - EXO2(lduh [%o1], %g2,#) + EXO2(lduh [%o1], %g2) add %o1, 2, %o1 - EXO2(sth %g2, [%o0],#) + EXO2(sth %g2, [%o0]) sub %o2, 2, %o2 b 3f add %o0, 2, %o0 4: - EXO2(lduh [%o1], %g2,#) + EXO2(lduh [%o1], %g2) add %o1, 2, %o1 - EXO2(sth %g2, [%o0],#) + EXO2(sth %g2, [%o0]) sub %o2, 2, %o2 b 3f add %o0, 2, %o0 @@ -160,9 +163,9 @@ be 2f mov %o2, %g1 - EXO2(ld [%o1], %o4,#) + EXO2(ld [%o1], %o4) sub %g1, 4, %g1 - EXO2(st %o4, [%o0],#) + EXO2(st %o4, [%o0]) add %o1, 4, %o1 add %o0, 4, %o0 2: @@ -177,7 +180,7 @@ MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5) MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5) 80: - EXT(5b, 80b, 50f,#) + EXT(5b, 80b, 50f) subcc %g7, 128, %g7 add %o1, 128, %o1 bne 5b @@ -204,37 +207,37 @@ MOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5) MOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5) copy_user_table_end: - EXT(copy_user_table, copy_user_table_end, 51f,#) + EXT(copy_user_table, copy_user_table_end, 51f) be copy_user_last7 andcc %g1, 4, %g0 - EX(ldd [%o1], %g2, and %g1, 0xf,#) + EX(ldd [%o1], %g2, and %g1, 0xf) add %o0, 8, %o0 add %o1, 8, %o1 - EX(st %g2, [%o0 - 0x08], and %g1, 0xf,#) - EX2(st %g3, [%o0 - 0x04], and %g1, 0xf, %g1, sub %g1, 4,#) + EX(st %g2, [%o0 - 0x08], and %g1, 0xf) + EX2(st %g3, [%o0 - 0x04], and %g1, 0xf, %g1, sub %g1, 4) copy_user_last7: be 1f andcc %g1, 2, %g0 - EX(ld [%o1], %g2, and %g1, 7,#) + EX(ld [%o1], %g2, and %g1, 7) add %o1, 4, %o1 - EX(st %g2, [%o0], and %g1, 7,#) + EX(st %g2, [%o0], and %g1, 7) add %o0, 4, %o0 1: be 1f andcc %g1, 1, %g0 - EX(lduh [%o1], %g2, and %g1, 3,#) + EX(lduh [%o1], %g2, and %g1, 3) add %o1, 2, %o1 - EX(sth %g2, [%o0], and %g1, 3,#) + EX(sth %g2, [%o0], and %g1, 3) add %o0, 2, %o0 1: be 1f nop - EX(ldub [%o1], %g2, add %g0, 1,#) - EX(stb %g2, [%o0], add %g0, 1,#) + EX(ldub [%o1], %g2, add %g0, 1) + EX(stb %g2, [%o0], add %g0, 1) 1: retl clr %o0 @@ -245,7 +248,7 @@ MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5) MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5) 81: - EXT(ldd_std, 81b, 52f,#) + EXT(ldd_std, 81b, 52f) subcc %g7, 128, %g7 add %o1, 128, %o1 bne ldd_std @@ -274,9 +277,9 @@ be 10f nop - EXO2(ldub [%o1], %g2,#) + EXO2(ldub [%o1], %g2) add %o1, 1, %o1 - EXO2(stb %g2, [%o0],#) + EXO2(stb %g2, [%o0]) sub %o2, 1, %o2 andcc %o2, 0xfffffff0, %o3 be short_end @@ -285,7 +288,7 @@ MOVE_HALFCHUNK(o1, o0, 0x00, g2, g3, g4, g5) MOVE_HALFCHUNK(o1, o0, 0x08, g2, g3, g4, g5) 82: - EXT(10b, 82b, 53f,#) + EXT(10b, 82b, 53f) subcc %o3, 0x10, %o3 add %o1, 0x10, %o1 bne 10b @@ -303,7 +306,7 @@ MOVE_SHORTCHUNK(o1, o0, -0x0e, g2, g3) MOVE_SHORTCHUNK(o1, o0, -0x10, g2, g3) 83: - EXT(byte_chunk, 83b, 54f,#) + EXT(byte_chunk, 83b, 54f) subcc %o3, 0x10, %o3 add %o1, 0x10, %o1 bne byte_chunk @@ -328,11 +331,11 @@ MOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3) MOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3) short_table_end: - EXT(84b, short_table_end, 55f,#) + EXT(84b, short_table_end, 55f) be 1f nop - EX(ldub [%o1], %g2, add %g0, 1,#) - EX(stb %g2, [%o0], add %g0, 1,#) + EX(ldub [%o1], %g2, add %g0, 1) + EX(stb %g2, [%o0], add %g0, 1) 1: retl clr %o0 @@ -344,11 +347,11 @@ be 1f andcc %o2, 4, %g0 - EXO2(ld [%o1 + 0x00], %g2,#) - EXO2(ld [%o1 + 0x04], %g3,#) + EXO2(ld [%o1 + 0x00], %g2) + EXO2(ld [%o1 + 0x04], %g3) add %o1, 8, %o1 - EXO2(st %g2, [%o0 + 0x00],#) - EX(st %g3, [%o0 + 0x04], sub %o2, 4,#) + EXO2(st %g2, [%o0 + 0x00]) + EX(st %g3, [%o0 + 0x04], sub %o2, 4) add %o0, 8, %o0 1: b copy_user_last7 diff -Nru a/arch/sparc/lib/memset.S b/arch/sparc/lib/memset.S --- a/arch/sparc/lib/memset.S Thu Sep 11 23:03:11 2003 +++ b/arch/sparc/lib/memset.S Thu Sep 11 23:03:11 2003 @@ -10,20 +10,23 @@ #include #include -#define EX(x,y,a,b,z) \ +/* Work around cpp -rob */ +#define ALLOC #alloc +#define EXECINSTR #execinstr +#define EX(x,y,a,b) \ 98: x,y; \ - .section .fixup,z##alloc,z##execinstr; \ + .section .fixup,ALLOC,EXECINSTR; \ .align 4; \ 99: ba 30f; \ a, b, %o0; \ - .section __ex_table,z##alloc; \ + .section __ex_table,ALLOC; \ .align 4; \ .word 98b, 99b; \ .text; \ .align 4 -#define EXT(start,end,handler,z) \ - .section __ex_table,z##alloc; \ +#define EXT(start,end,handler) \ + .section __ex_table,ALLOC; \ .align 4; \ .word start, 0, end, handler; \ .text; \ @@ -74,13 +77,13 @@ 3: cmp %o2, 3 be 2f - EX(stb %g3, [%o0], sub %o1, 0,#) + EX(stb %g3, [%o0], sub %o1, 0) cmp %o2, 2 be 2f - EX(stb %g3, [%o0 + 0x01], sub %o1, 1,#) + EX(stb %g3, [%o0 + 0x01], sub %o1, 1) - EX(stb %g3, [%o0 + 0x02], sub %o1, 2,#) + EX(stb %g3, [%o0 + 0x02], sub %o1, 2) 2: sub %o2, 4, %o2 add %o1, %o2, %o1 @@ -101,7 +104,7 @@ be 2f mov %g3, %g2 - EX(st %g3, [%o0], sub %o1, 0,#) + EX(st %g3, [%o0], sub %o1, 0) sub %o1, 4, %o1 add %o0, 4, %o0 2: @@ -113,7 +116,7 @@ subcc %o3, 128, %o3 ZERO_BIG_BLOCK(%o0, 0x40, %g2) 11: - EXT(10b, 11b, 20f,#) + EXT(10b, 11b, 20f) bne 10b add %o0, 128, %o0 @@ -138,17 +141,17 @@ be 1f andcc %o1, 2, %g0 - EX(st %g3, [%o0], and %o1, 7,#) + EX(st %g3, [%o0], and %o1, 7) add %o0, 4, %o0 1: be 1f andcc %o1, 1, %g0 - EX(sth %g3, [%o0], and %o1, 3,#) + EX(sth %g3, [%o0], and %o1, 3) add %o0, 2, %o0 1: bne,a 8f - EX(stb %g3, [%o0], and %o1, 1,#) + EX(stb %g3, [%o0], and %o1, 1) 8: retl clr %o0 @@ -161,7 +164,7 @@ add %o0, 1, %o0 subcc %o1, 1, %o1 bne,a 8b - EX(stb %g3, [%o0 - 1], add %o1, 1,#) + EX(stb %g3, [%o0 - 1], add %o1, 1) 0: retl clr %o0 diff -Nru a/arch/sparc/math-emu/sfp-util.h b/arch/sparc/math-emu/sfp-util.h --- a/arch/sparc/math-emu/sfp-util.h Thu Sep 11 23:03:14 2003 +++ b/arch/sparc/math-emu/sfp-util.h Thu Sep 11 23:03:14 2003 @@ -4,8 +4,8 @@ #include #define add_ssaaaa(sh, sl, ah, al, bh, bl) \ - __asm__ ("addcc %r4,%5,%1 - addx %r2,%3,%0" \ + __asm__ ("addcc %r4,%5,%1\n\t" \ + "addx %r2,%3,%0\n" \ : "=r" ((USItype)(sh)), \ "=&r" ((USItype)(sl)) \ : "%rJ" ((USItype)(ah)), \ @@ -14,8 +14,8 @@ "rI" ((USItype)(bl)) \ : "cc") #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ - __asm__ ("subcc %r4,%5,%1 - subx %r2,%3,%0" \ + __asm__ ("subcc %r4,%5,%1\n\t" \ + "subx %r2,%3,%0\n" \ : "=r" ((USItype)(sh)), \ "=&r" ((USItype)(sl)) \ : "rJ" ((USItype)(ah)), \ @@ -25,46 +25,46 @@ : "cc") #define umul_ppmm(w1, w0, u, v) \ - __asm__ ("! Inlined umul_ppmm - wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr - sra %3,31,%%g2 ! Don't move this insn - and %2,%%g2,%%g2 ! Don't move this insn - andcc %%g0,0,%%g1 ! Don't move this insn - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,%3,%%g1 - mulscc %%g1,0,%%g1 - add %%g1,%%g2,%0 - rd %%y,%1" \ + __asm__ ("! Inlined umul_ppmm\n\t" \ + "wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr\n\t" \ + "sra %3,31,%%g2 ! Don't move this insn\n\t" \ + "and %2,%%g2,%%g2 ! Don't move this insn\n\t" \ + "andcc %%g0,0,%%g1 ! Don't move this insn\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,%3,%%g1\n\t" \ + "mulscc %%g1,0,%%g1\n\t" \ + "add %%g1,%%g2,%0\n\t" \ + "rd %%y,%1\n" \ : "=r" ((USItype)(w1)), \ "=r" ((USItype)(w0)) \ : "%rI" ((USItype)(u)), \ @@ -74,30 +74,30 @@ /* It's quite necessary to add this much assembler for the sparc. The default udiv_qrnnd (in C) is more than 10 times slower! */ #define udiv_qrnnd(q, r, n1, n0, d) \ - __asm__ ("! Inlined udiv_qrnnd - mov 32,%%g1 - subcc %1,%2,%%g0 -1: bcs 5f - addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb - sub %1,%2,%1 ! this kills msb of n - addx %1,%1,%1 ! so this can't give carry - subcc %%g1,1,%%g1 -2: bne 1b - subcc %1,%2,%%g0 - bcs 3f - addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb - b 3f - sub %1,%2,%1 ! this kills msb of n -4: sub %1,%2,%1 -5: addxcc %1,%1,%1 - bcc 2b - subcc %%g1,1,%%g1 -! Got carry from n. Subtract next step to cancel this carry. - bne 4b - addcc %0,%0,%0 ! shift n1n0 and a 0-bit in lsb - sub %1,%2,%1 -3: xnor %0,0,%0 - ! End of inline udiv_qrnnd" \ + __asm__ ("! Inlined udiv_qrnnd\n\t" \ + "mov 32,%%g1\n\t" \ + "subcc %1,%2,%%g0\n\t" \ + "1: bcs 5f\n\t" \ + "addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n\t" \ + "sub %1,%2,%1 ! this kills msb of n\n\t" \ + "addx %1,%1,%1 ! so this can't give carry\n\t" \ + "subcc %%g1,1,%%g1\n\t" \ + "2: bne 1b\n\t" \ + "subcc %1,%2,%%g0\n\t" \ + "bcs 3f\n\t" \ + "addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n\t" \ + "b 3f\n\t" \ + "sub %1,%2,%1 ! this kills msb of n\n\t" \ + "4: sub %1,%2,%1\n\t" \ + "5: addxcc %1,%1,%1\n\t" \ + "bcc 2b\n\t" \ + "subcc %%g1,1,%%g1\n\t" \ + "! Got carry from n. Subtract next step to cancel this carry.\n\t" \ + "bne 4b\n\t" \ + "addcc %0,%0,%0 ! shift n1n0 and a 0-bit in lsb\n\t" \ + "sub %1,%2,%1\n\t" \ + "3: xnor %0,0,%0\n\t" \ + "! End of inline udiv_qrnnd\n" \ : "=&r" ((USItype)(q)), \ "=&r" ((USItype)(r)) \ : "r" ((USItype)(d)), \ diff -Nru a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig --- a/arch/sparc64/Kconfig Thu Sep 11 23:03:13 2003 +++ b/arch/sparc64/Kconfig Thu Sep 11 23:03:13 2003 @@ -29,7 +29,8 @@ smartcard reader, if present. Say Y to enable support for these. config VT - bool + bool "Virtual terminal" if EMBEDDED + select INPUT default y ---help--- If you say Y here, you will get support for terminal devices with @@ -59,7 +60,8 @@ shiny Linux system :-) config VT_CONSOLE - bool + bool "Support for console on virtual terminal" if EMBEDDED + depends on VT default y ---help--- The system console is the device which receives all kernel messages diff -Nru a/arch/sparc64/defconfig b/arch/sparc64/defconfig --- a/arch/sparc64/defconfig Thu Sep 11 23:03:12 2003 +++ b/arch/sparc64/defconfig Thu Sep 11 23:03:12 2003 @@ -1,13 +1,15 @@ # # Automatically generated make config: don't edit # +CONFIG_64BIT=y CONFIG_MMU=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y -CONFIG_BROKEN=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y # # General setup @@ -17,6 +19,7 @@ # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y CONFIG_LOG_BUF_SHIFT=15 +# CONFIG_IKCONFIG is not set # CONFIG_EMBEDDED is not set CONFIG_KALLSYMS=y CONFIG_FUTEX=y @@ -51,6 +54,10 @@ CONFIG_US3_FREQ=m CONFIG_US2E_FREQ=m CONFIG_CPU_FREQ_PROC_INTF=y +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m CONFIG_CPU_FREQ_GOV_USERSPACE=m # CONFIG_CPU_FREQ_24_API is not set CONFIG_SPARC64=y @@ -67,7 +74,6 @@ # CONFIG_PCI_LEGACY_PROC is not set # CONFIG_PCI_NAMES is not set CONFIG_SUN_OPENPROMFS=m -CONFIG_KCORE_ELF=y CONFIG_SPARC32_COMPAT=y CONFIG_COMPAT=y CONFIG_BINFMT_ELF32=y @@ -102,8 +108,6 @@ # Graphics support # CONFIG_FB=y -# CONFIG_FB_CIRRUS is not set -# CONFIG_FB_PM2 is not set # CONFIG_FB_CYBER2000 is not set # CONFIG_FB_IMSTT is not set # CONFIG_FB_BW2 is not set @@ -119,7 +123,6 @@ # CONFIG_FB_3DFX is not set # CONFIG_FB_VOODOO1 is not set # CONFIG_FB_TRIDENT is not set -# CONFIG_FB_PM3 is not set CONFIG_FB_SBUS=y CONFIG_FB_FFB=y # CONFIG_FB_TCX is not set @@ -274,6 +277,7 @@ # SCSI device support # CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y # # SCSI support type (disk, tape, CD-ROM) @@ -309,7 +313,6 @@ # CONFIG_AIC79XX_DEBUG_ENABLE is not set CONFIG_AIC79XX_DEBUG_MASK=0 # CONFIG_AIC79XX_REG_PRETTY_PRINT is not set -# CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_BUSLOGIC is not set @@ -319,7 +322,7 @@ CONFIG_SCSI_EATA_PIO=m # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_INITIO is not set +CONFIG_SCSI_IPS=m CONFIG_SCSI_INIA100=m CONFIG_SCSI_PPA=m CONFIG_SCSI_IMM=m @@ -330,15 +333,12 @@ CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set CONFIG_SCSI_QLOGIC_ISP=m CONFIG_SCSI_QLOGIC_FC=y CONFIG_SCSI_QLOGIC_FC_FIRMWARE=y # CONFIG_SCSI_QLOGIC_1280 is not set CONFIG_SCSI_QLOGICPTI=m CONFIG_SCSI_DC395x=m -# CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_NSP32 is not set CONFIG_SCSI_DEBUG=m CONFIG_SCSI_SUNESP=y @@ -474,6 +474,7 @@ CONFIG_BRIDGE=m CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set +CONFIG_BRIDGE_NETFILTER=y # # IP: Netfilter Configuration @@ -486,6 +487,7 @@ CONFIG_IP_NF_QUEUE=m CONFIG_IP_NF_IPTABLES=m CONFIG_IP_NF_MATCH_LIMIT=m +CONFIG_IP_NF_MATCH_IPRANGE=m CONFIG_IP_NF_MATCH_MAC=m CONFIG_IP_NF_MATCH_PKTTYPE=m CONFIG_IP_NF_MATCH_MARK=m @@ -501,16 +503,16 @@ CONFIG_IP_NF_MATCH_HELPER=m CONFIG_IP_NF_MATCH_STATE=m CONFIG_IP_NF_MATCH_CONNTRACK=m -CONFIG_IP_NF_MATCH_UNCLEAN=m CONFIG_IP_NF_MATCH_OWNER=m CONFIG_IP_NF_MATCH_PHYSDEV=m CONFIG_IP_NF_FILTER=m CONFIG_IP_NF_TARGET_REJECT=m -CONFIG_IP_NF_TARGET_MIRROR=m CONFIG_IP_NF_NAT=m CONFIG_IP_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_SAME=m CONFIG_IP_NF_NAT_LOCAL=y CONFIG_IP_NF_NAT_SNMP_BASIC=m CONFIG_IP_NF_NAT_IRC=m @@ -522,6 +524,7 @@ CONFIG_IP_NF_TARGET_ECN=m CONFIG_IP_NF_TARGET_DSCP=m CONFIG_IP_NF_TARGET_MARK=m +CONFIG_IP_NF_TARGET_CLASSIFY=m CONFIG_IP_NF_TARGET_LOG=m CONFIG_IP_NF_TARGET_ULOG=m CONFIG_IP_NF_TARGET_TCPMSS=m @@ -558,21 +561,27 @@ # DECnet: Netfilter Configuration # CONFIG_DECNET_NF_GRABULATOR=m + +# +# Bridge: Netfilter Configuration +# CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m CONFIG_BRIDGE_EBT_T_FILTER=m CONFIG_BRIDGE_EBT_T_NAT=m -CONFIG_BRIDGE_EBT_BROUTE=m -CONFIG_BRIDGE_EBT_LOG=m -CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_802_3=m CONFIG_BRIDGE_EBT_ARP=m -CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_IP=m CONFIG_BRIDGE_EBT_MARK=m CONFIG_BRIDGE_EBT_PKTTYPE=m CONFIG_BRIDGE_EBT_STP=m -CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m CONFIG_BRIDGE_EBT_DNAT=m -CONFIG_BRIDGE_EBT_REDIRECT=m CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m CONFIG_XFRM=y CONFIG_XFRM_USER=m @@ -781,7 +790,6 @@ # Token Ring devices (depends on LLC=y) # CONFIG_NET_FC=y -# CONFIG_IPHASE5526 is not set # CONFIG_RCPCI is not set CONFIG_SHAPER=m @@ -830,8 +838,6 @@ # # AX.25 network device drivers # -# CONFIG_MKISS is not set -# CONFIG_6PACK is not set # CONFIG_BPQETHER is not set # CONFIG_BAYCOM_SER_FDX is not set # CONFIG_BAYCOM_SER_HDX is not set @@ -875,7 +881,6 @@ # # Old SIR device drivers # -# CONFIG_IRTTY_OLD is not set # CONFIG_IRPORT_SIR is not set # @@ -886,7 +891,6 @@ # FIR device drivers # # CONFIG_USB_IRDA is not set -# CONFIG_TOSHIBA_OLD is not set # CONFIG_TOSHIBA_FIR is not set # CONFIG_VLSI_FIR is not set @@ -896,11 +900,6 @@ CONFIG_ISDN_BOOL=y # -# Old ISDN4Linux -# -# CONFIG_ISDN is not set - -# # CAPI subsystem # CONFIG_ISDN_CAPI=m @@ -1000,7 +999,6 @@ CONFIG_I2C_PHILIPSPAR=m CONFIG_SCx200_ACB=m CONFIG_I2C_ALGOPCF=m -# CONFIG_I2C_ELEKTOR is not set CONFIG_I2C_CHARDEV=m # @@ -1198,7 +1196,6 @@ # # Video For Linux # -CONFIG_VIDEO_PROC_FS=y # # Video Adapters @@ -1214,7 +1211,6 @@ CONFIG_TUNER_3036=m # CONFIG_VIDEO_STRADIS is not set # CONFIG_VIDEO_ZORAN is not set -# CONFIG_VIDEO_ZR36120 is not set CONFIG_VIDEO_SAA7134=m CONFIG_VIDEO_MXB=m CONFIG_VIDEO_DPC=m @@ -1247,7 +1243,6 @@ CONFIG_DVB_GRUNDIG_29504_401=m CONFIG_DVB_MT312=m CONFIG_DVB_VES1820=m -# CONFIG_DVB_TDA1004X is not set # # Supported SAA7146 based PCI Adapters @@ -1262,7 +1257,6 @@ # Supported USB Adapters # # CONFIG_DVB_TTUSB_BUDGET is not set -# CONFIG_DVB_TTUSB_DEC is not set # # Supported FlexCopII (B2C2) Adapters @@ -1430,7 +1424,7 @@ # # USB Network adaptors # -CONFIG_USB_AX8817X=m +CONFIG_USB_AX8817X_STANDALONE=m CONFIG_USB_CATC=m CONFIG_USB_KAWETH=m CONFIG_USB_PEGASUS=m @@ -1453,6 +1447,11 @@ CONFIG_USB_EPSON2888=y CONFIG_USB_ZAURUS=y CONFIG_USB_CDCETHER=y + +# +# USB Network Adapters +# +CONFIG_USB_AX8817X=y # # USB port drivers diff -Nru a/arch/x86_64/boot/compressed/misc.c b/arch/x86_64/boot/compressed/misc.c --- a/arch/x86_64/boot/compressed/misc.c Thu Sep 11 23:03:12 2003 +++ b/arch/x86_64/boot/compressed/misc.c Thu Sep 11 23:03:12 2003 @@ -116,8 +116,8 @@ { void *p; - if (size <0) error("Malloc error\n"); - if (free_mem_ptr <= 0) error("Memory error\n"); + if (size <0) error("Malloc error"); + if (free_mem_ptr <= 0) error("Memory error"); free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ @@ -125,7 +125,7 @@ free_mem_ptr += size; if (free_mem_ptr >= free_mem_end_ptr) - error("\nOut of memory\n"); + error("Out of memory"); return p; } @@ -215,7 +215,7 @@ static int fill_inbuf(void) { if (insize != 0) { - error("ran out of input data\n"); + error("ran out of input data"); } inbuf = input_data; @@ -280,9 +280,9 @@ void setup_normal_output_buffer(void) { #ifdef STANDARD_MEMORY_BIOS_CALL - if (EXT_MEM_K < 1024) error("Less than 2MB of memory.\n"); + if (EXT_MEM_K < 1024) error("Less than 2MB of memory"); #else - if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory.\n"); + if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory"); #endif output_data = (char *)0x100000; /* Points to 1M */ free_mem_end_ptr = (long)real_mode; @@ -297,9 +297,9 @@ { high_buffer_start = (uch *)(((ulg)&end) + HEAP_SIZE); #ifdef STANDARD_MEMORY_BIOS_CALL - if (EXT_MEM_K < (3*1024)) error("Less than 4MB of memory.\n"); + if (EXT_MEM_K < (3*1024)) error("Less than 4MB of memory"); #else - if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory.\n"); + if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory"); #endif mv->low_buffer_start = output_data = (char *)LOW_BUFFER_START; low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX diff -Nru a/crypto/proc.c b/crypto/proc.c --- a/crypto/proc.c Thu Sep 11 23:03:12 2003 +++ b/crypto/proc.c Thu Sep 11 23:03:12 2003 @@ -57,6 +57,7 @@ switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { case CRYPTO_ALG_TYPE_CIPHER: + seq_printf(m, "type : cipher\n"); seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); seq_printf(m, "min keysize : %u\n", alg->cra_cipher.cia_min_keysize); @@ -65,9 +66,16 @@ break; case CRYPTO_ALG_TYPE_DIGEST: + seq_printf(m, "type : digest\n"); seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); seq_printf(m, "digestsize : %u\n", alg->cra_digest.dia_digestsize); + break; + case CRYPTO_ALG_TYPE_COMPRESS: + seq_printf(m, "type : compression\n"); + break; + default: + seq_printf(m, "type : unknown\n"); break; } diff -Nru a/drivers/atm/Kconfig b/drivers/atm/Kconfig --- a/drivers/atm/Kconfig Thu Sep 11 23:03:12 2003 +++ b/drivers/atm/Kconfig Thu Sep 11 23:03:12 2003 @@ -241,7 +241,7 @@ config ATM_AMBASSADOR tristate "Madge Ambassador (Collage PCI 155 Server)" - depends on PCI && ATM && BROKEN_ON_SMP + depends on PCI && ATM help This is a driver for ATMizer based ATM card produced by Madge Networks Ltd. Say Y (or M to compile as a module named ambassador) diff -Nru a/drivers/atm/firestream.c b/drivers/atm/firestream.c --- a/drivers/atm/firestream.c Thu Sep 11 23:03:11 2003 +++ b/drivers/atm/firestream.c Thu Sep 11 23:03:11 2003 @@ -250,7 +250,7 @@ }; -struct reginit_item PHY_NTC_INIT[] __initdata = { +struct reginit_item PHY_NTC_INIT[] __devinitdata = { { PHY_CLEARALL, 0x40 }, { 0x12, 0x0001 }, { 0x13, 0x7605 }, @@ -1296,7 +1296,7 @@ }; -static void __init undocumented_pci_fix (struct pci_dev *pdev) +static void __devinit undocumented_pci_fix (struct pci_dev *pdev) { int tint; @@ -1320,13 +1320,13 @@ * PHY routines * **************************************************************************/ -static void __init write_phy (struct fs_dev *dev, int regnum, int val) +static void __devinit write_phy (struct fs_dev *dev, int regnum, int val) { submit_command (dev, &dev->hp_txq, QE_CMD_PRP_WR | QE_CMD_IMM_INQ, regnum, val, 0); } -static int __init init_phy (struct fs_dev *dev, struct reginit_item *reginit) +static int __devinit init_phy (struct fs_dev *dev, struct reginit_item *reginit) { int i; @@ -1382,7 +1382,7 @@ } } -static void __init *aligned_kmalloc (int size, int flags, int alignment) +static void __devinit *aligned_kmalloc (int size, int flags, int alignment) { void *t; @@ -1399,7 +1399,7 @@ return NULL; } -static int __init init_q (struct fs_dev *dev, +static int __devinit init_q (struct fs_dev *dev, struct queue *txq, int queue, int nentries, int is_rq) { int sz = nentries * sizeof (struct FS_QENTRY); @@ -1435,7 +1435,7 @@ } -static int __init init_fp (struct fs_dev *dev, +static int __devinit init_fp (struct fs_dev *dev, struct freepool *fp, int queue, int bufsize, int nr_buffers) { func_enter (); @@ -1655,7 +1655,7 @@ } #endif -static int __init fs_init (struct fs_dev *dev) +static int __devinit fs_init (struct fs_dev *dev) { struct pci_dev *pci_dev; int isr, to; @@ -1890,7 +1890,7 @@ return 0; } -static int __init firestream_init_one (struct pci_dev *pci_dev, +static int __devinit firestream_init_one (struct pci_dev *pci_dev, const struct pci_device_id *ent) { struct atm_dev *atm_dev; diff -Nru a/drivers/block/DAC960.c b/drivers/block/DAC960.c --- a/drivers/block/DAC960.c Thu Sep 11 23:03:13 2003 +++ b/drivers/block/DAC960.c Thu Sep 11 23:03:13 2003 @@ -71,7 +71,7 @@ { struct gendisk *disk = inode->i_bdev->bd_disk; DAC960_Controller_T *p = disk->queue->queuedata; - int drive_nr = (int)disk->private_data; + int drive_nr = (long)disk->private_data; if (p->FirmwareType == DAC960_V1_Controller) { if (p->V1.LogicalDriveInformation[drive_nr]. @@ -96,7 +96,7 @@ { struct gendisk *disk = inode->i_bdev->bd_disk; DAC960_Controller_T *p = disk->queue->queuedata; - int drive_nr = (int)disk->private_data; + int drive_nr = (long)disk->private_data; struct hd_geometry g, *loc = (struct hd_geometry *)arg; if (cmd != HDIO_GETGEO || !loc) @@ -136,7 +136,7 @@ static int DAC960_media_changed(struct gendisk *disk) { DAC960_Controller_T *p = disk->queue->queuedata; - int drive_nr = (int)disk->private_data; + int drive_nr = (long)disk->private_data; if (!p->LogicalDriveInitiallyAccessible[drive_nr]) return 1; @@ -146,7 +146,7 @@ static int DAC960_revalidate_disk(struct gendisk *disk) { DAC960_Controller_T *p = disk->queue->queuedata; - int unit = (int)disk->private_data; + int unit = (long)disk->private_data; set_capacity(disk, disk_size(p, unit)); return 0; @@ -1603,6 +1603,26 @@ DAC960PU/PD/PL 3.51 and above DAC960PU/PD/PL/P 2.73 and above */ +#if defined(CONFIG_ALPHA) + /* + DEC Alpha machines were often equipped with DAC960 cards that were + OEMed from Mylex, and had their own custom firmware. Version 2.70, + the last custom FW revision to be released by DEC for these older + controllers, appears to work quite well with this driver. + + Cards tested successfully were several versions each of the PD and + PU, called by DEC the KZPSC and KZPAC, respectively, and having + the Manufacturer Numbers (from Mylex), usually on a sticker on the + back of the board, of: + + KZPSC: D040347 (1-channel) or D040348 (2-channel) or D040349 (3-channel) + KZPAC: D040395 (1-channel) or D040396 (2-channel) or D040397 (3-channel) + */ +# define FIRMWARE_27X "2.70" +#else +# define FIRMWARE_27X "2.73" +#endif + if (Enquiry2->FirmwareID.MajorVersion == 0) { Enquiry2->FirmwareID.MajorVersion = @@ -1622,7 +1642,7 @@ (Controller->FirmwareVersion[0] == '3' && strcmp(Controller->FirmwareVersion, "3.51") >= 0) || (Controller->FirmwareVersion[0] == '2' && - strcmp(Controller->FirmwareVersion, "2.73") >= 0))) + strcmp(Controller->FirmwareVersion, FIRMWARE_27X) >= 0))) { DAC960_Failure(Controller, "FIRMWARE VERSION VERIFICATION"); DAC960_Error("Firmware Version = '%s'\n", Controller, @@ -2485,7 +2505,7 @@ disk->queue = RequestQueue; sprintf(disk->disk_name, "rd/c%dd%d", Controller->ControllerNumber, n); - sprintf(disk->devfs_name, "rd/c%dd%d", Controller->ControllerNumber, n); + sprintf(disk->devfs_name, "rd/host%d/target%d", Controller->ControllerNumber, n); disk->major = MajorNumber; disk->first_minor = n << DAC960_MaxPartitionsBits; disk->fops = &DAC960_BlockDeviceOperations; @@ -2708,12 +2728,12 @@ break; } - pci_set_drvdata(PCI_Device, (void *)((int)Controller->ControllerNumber)); + pci_set_drvdata(PCI_Device, (void *)((long)Controller->ControllerNumber)); for (i = 0; i < DAC960_MaxLogicalDrives; i++) { Controller->disks[i] = alloc_disk(1<disks[i]) goto Failure; - Controller->disks[i]->private_data = (void *)i; + Controller->disks[i]->private_data = (void *)((long)i); } init_waitqueue_head(&Controller->CommandWaitQueue); init_waitqueue_head(&Controller->HealthStatusWaitQueue); @@ -3097,7 +3117,7 @@ static void DAC960_Remove(struct pci_dev *PCI_Device) { - int Controller_Number = (int)pci_get_drvdata(PCI_Device); + int Controller_Number = (long)pci_get_drvdata(PCI_Device); DAC960_Controller_T *Controller = DAC960_Controllers[Controller_Number]; if (Controller != NULL) DAC960_FinalizeController(Controller); @@ -3272,7 +3292,7 @@ Command->CommandType = DAC960_WriteCommand; } Command->Completion = Request->waiting; - Command->LogicalDriveNumber = (int)Request->rq_disk->private_data; + Command->LogicalDriveNumber = (long)Request->rq_disk->private_data; Command->BlockNumber = Request->sector; Command->BlockCount = Request->nr_sectors; Command->Request = Request; diff -Nru a/drivers/block/Kconfig b/drivers/block/Kconfig --- a/drivers/block/Kconfig Thu Sep 11 23:03:11 2003 +++ b/drivers/block/Kconfig Thu Sep 11 23:03:11 2003 @@ -44,7 +44,7 @@ config BLK_DEV_PS2 tristate "PS/2 ESDI hard disk support" - depends on MCA + depends on MCA && MCA_LEGACY help Say Y here if you have a PS/2 machine with a MCA bus and an ESDI hard disk. diff -Nru a/drivers/block/acsi.c b/drivers/block/acsi.c --- a/drivers/block/acsi.c Thu Sep 11 23:03:14 2003 +++ b/drivers/block/acsi.c Thu Sep 11 23:03:14 2003 @@ -1729,10 +1729,14 @@ for( i = 0; i < NDevices; ++i ) { struct gendisk *disk = acsi_gendisk[i]; sprintf(disk->disk_name, "ad%c", 'a'+i); + aip = &acsi_info[NDevices]; + sprintf(disk->devfs_name, "ad/target%d/lun%d", aip->target, aip->lun); disk->major = ACSI_MAJOR; disk->first_minor = i << 4; - if (acsi_info[i].type != HARDDISK) + if (acsi_info[i].type != HARDDISK) { disk->minors = 1; + strcat(disk->devfs_name, "/disc"); + } disk->fops = &acsi_fops; disk->private_data = &acsi_info[i]; set_capacity(disk, acsi_info[i].size); diff -Nru a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c --- a/drivers/block/as-iosched.c Thu Sep 11 23:03:11 2003 +++ b/drivers/block/as-iosched.c Thu Sep 11 23:03:11 2003 @@ -162,7 +162,7 @@ unsigned long expires; unsigned int is_sync; - enum arq_state state; /* debug only */ + enum arq_state state; }; #define RQ_DATA(rq) ((struct as_rq *) (rq)->elevator_private) @@ -344,11 +344,19 @@ } } -static struct as_rq *__as_add_arq_rb(struct as_data *ad, struct as_rq *arq) +/* + * Add the request to the rb tree if it is unique. If there is an alias (an + * existing request against the same sector), which can happen when using + * direct IO, then return the alias. + */ +static struct as_rq *as_add_arq_rb(struct as_data *ad, struct as_rq *arq) { struct rb_node **p = &ARQ_RB_ROOT(ad, arq)->rb_node; struct rb_node *parent = NULL; struct as_rq *__arq; + struct request *rq = arq->request; + + arq->rb_key = rq_rb_key(rq); while (*p) { parent = *p; @@ -363,28 +371,9 @@ } rb_link_node(&arq->rb_node, parent, p); - return 0; -} - -static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq); -/* - * Add the request to the rb tree if it is unique. If there is an alias (an - * existing request against the same sector), which can happen when using - * direct IO, then move the alias to the dispatch list and then add the - * request. - */ -static void as_add_arq_rb(struct as_data *ad, struct as_rq *arq) -{ - struct as_rq *alias; - struct request *rq = arq->request; - - arq->rb_key = rq_rb_key(rq); - - /* This can be caused by direct IO */ - while ((alias = __as_add_arq_rb(ad, arq))) - as_move_to_dispatch(ad, alias); - rb_insert_color(&arq->rb_node, ARQ_RB_ROOT(ad, arq)); + + return NULL; } static inline void as_del_arq_rb(struct as_data *ad, struct as_rq *arq) @@ -1021,6 +1010,7 @@ } } } + /* * as_remove_request is called when a driver has finished with a request. * This should be only called for dispatched requests, but for some reason @@ -1095,6 +1085,7 @@ */ static void as_move_to_dispatch(struct as_data *ad, struct as_rq *arq) { + struct list_head *insert; const int data_dir = arq->is_sync; BUG_ON(!ON_RB(&arq->rb_node)); @@ -1109,8 +1100,6 @@ ad->last_sector[data_dir] = arq->request->sector + arq->request->nr_sectors; - ad->nr_dispatched++; - if (data_dir == REQ_SYNC) { /* In case we have to anticipate after this */ copy_io_context(&ad->io_context, &arq->io_context); @@ -1131,12 +1120,33 @@ * take it off the sort and fifo list, add to dispatch queue */ as_remove_queued_request(ad->q, arq->request); - list_add_tail(&arq->request->queuelist, ad->dispatch); + + insert = ad->dispatch->prev; + + while (!list_empty(&arq->request->queuelist)) { + struct request *rq = list_entry_rq(arq->request->queuelist.next); + struct as_rq *__arq = RQ_DATA(rq); + + list_move_tail(&rq->queuelist, ad->dispatch); + + if (__arq->io_context && __arq->io_context->aic) + atomic_inc(&__arq->io_context->aic->nr_dispatched); + + WARN_ON(__arq->state != AS_RQ_QUEUED); + __arq->state = AS_RQ_DISPATCHED; + + ad->nr_dispatched++; + } + + list_add(&arq->request->queuelist, insert); if (arq->io_context && arq->io_context->aic) atomic_inc(&arq->io_context->aic->nr_dispatched); WARN_ON(arq->state != AS_RQ_QUEUED); arq->state = AS_RQ_DISPATCHED; + + ad->nr_dispatched++; + } /* @@ -1290,10 +1300,26 @@ } /* + * Add arq to a list behind alias + */ +static inline void +as_add_aliased_request(struct as_rq *arq, struct as_rq *alias) +{ + /* + * Another request with the same start sector on the rbtree. + * Link this request to that sector. They are untangled in + * as_move_to_dispatch + */ + list_add_tail(&arq->request->queuelist, &alias->request->queuelist); + +} + +/* * add arq to rbtree and fifo */ static void as_add_request(struct as_data *ad, struct as_rq *arq) { + struct as_rq *alias; int data_dir; if (rq_data_dir(arq->request) == READ @@ -1310,15 +1336,40 @@ as_update_iohist(arq->io_context->aic, arq->request); } - as_add_arq_rb(ad, arq); + alias = as_add_arq_rb(ad, arq); + if (!alias) { + /* + * set expire time (only used for reads) and add to fifo list + */ + arq->expires = jiffies + ad->fifo_expire[data_dir]; + list_add_tail(&arq->fifo, &ad->fifo_list[data_dir]); + + if (rq_mergeable(arq->request)) { + as_add_arq_hash(ad, arq); + + if (!ad->q->last_merge) + ad->q->last_merge = arq->request; + } + as_update_arq(ad, arq); /* keep state machine up to date */ + + } else { + as_add_aliased_request(arq, alias); + /* + * have we been anticipating this request? + * or does it come from the same process as the one we are + * anticipating for? + */ + if (ad->antic_status == ANTIC_WAIT_REQ + || ad->antic_status == ANTIC_WAIT_NEXT) { + if (as_can_break_anticipation(ad, arq)) + as_antic_stop(ad); + } + } + + + - /* - * set expire time (only used for reads) and add to fifo list - */ - arq->expires = jiffies + ad->fifo_expire[data_dir]; - list_add_tail(&arq->fifo, &ad->fifo_list[data_dir]); arq->state = AS_RQ_QUEUED; - as_update_arq(ad, arq); /* keep state machine up to date */ } /* @@ -1359,7 +1410,9 @@ while (ad->next_arq[REQ_ASYNC]) as_move_to_dispatch(ad, ad->next_arq[REQ_ASYNC]); + list_add_tail(&rq->queuelist, ad->dispatch); + as_antic_stop(ad); break; case ELEVATOR_INSERT_FRONT: list_add(&rq->queuelist, ad->dispatch); @@ -1373,13 +1426,6 @@ printk("%s: bad insert point %d\n", __FUNCTION__,where); return; } - - if (rq_mergeable(rq)) { - as_add_arq_hash(ad, arq); - - if (!q->last_merge) - q->last_merge = rq; - } } /* @@ -1494,8 +1540,16 @@ * if the merge was a front merge, we need to reposition request */ if (rq_rb_key(req) != arq->rb_key) { + struct as_rq *alias; + + /* + * Note! We should really be moving any old aliased requests + * off this request and try to insert them into the rbtree. We + * currently don't bother. Ditto the next function. + */ as_del_arq_rb(ad, arq); - as_add_arq_rb(ad, arq); + if ((alias = as_add_arq_rb(ad, arq)) ) + as_add_aliased_request(arq, alias); /* * Note! At this stage of this and the next function, our next * request may not be optimal - eg the request may have "grown" @@ -1525,8 +1579,10 @@ as_add_arq_hash(ad, arq); if (rq_rb_key(req) != arq->rb_key) { + struct as_rq *alias; as_del_arq_rb(ad, arq); - as_add_arq_rb(ad, arq); + if ((alias = as_add_arq_rb(ad, arq)) ) + as_add_aliased_request(arq, alias); } /* diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c --- a/drivers/block/cciss.c Thu Sep 11 23:03:14 2003 +++ b/drivers/block/cciss.c Thu Sep 11 23:03:14 2003 @@ -243,7 +243,7 @@ * Get us a file in /proc/cciss that says something about each controller. * Create /proc/cciss if it doesn't exist yet. */ -static void __init cciss_procinit(int i) +static void __devinit cciss_procinit(int i) { struct proc_dir_entry *pde; @@ -2427,7 +2427,7 @@ * stealing all these major device numbers. * returns the number of block devices registered. */ -static int __init cciss_init_one(struct pci_dev *pdev, +static int __devinit cciss_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { request_queue_t *q; @@ -2531,6 +2531,7 @@ struct gendisk *disk = hba[i]->gendisk[j]; sprintf(disk->disk_name, "cciss/c%dd%d", i, j); + sprintf(disk->devfs_name, "cciss/host%d/target%d", i, j); disk->major = COMPAQ_CISS_MAJOR + i; disk->first_minor = j << NWD_SHIFT; disk->fops = &cciss_fops; diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c --- a/drivers/block/ll_rw_blk.c Thu Sep 11 23:03:11 2003 +++ b/drivers/block/ll_rw_blk.c Thu Sep 11 23:03:11 2003 @@ -1016,7 +1016,13 @@ void blk_plug_device(request_queue_t *q) { WARN_ON(!irqs_disabled()); - if (!blk_queue_plugged(q)) { + + /* + * don't plug a stopped queue, it must be paired with blk_start_queue() + * which will restart the queueing + */ + if (!blk_queue_plugged(q) + && !test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags)) { spin_lock(&blk_plug_lock); list_add_tail(&q->plug_list, &blk_plug_list); mod_timer(&q->unplug_timer, jiffies + q->unplug_delay); diff -Nru a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c --- a/drivers/block/ps2esdi.c Thu Sep 11 23:03:11 2003 +++ b/drivers/block/ps2esdi.c Thu Sep 11 23:03:11 2003 @@ -62,8 +62,6 @@ static void reset_ctrl(void); -int ps2esdi_init(void); - static int ps2esdi_geninit(void); static void do_ps2esdi_request(request_queue_t * q); @@ -141,7 +139,7 @@ static struct gendisk *ps2esdi_gendisk[2]; /* initialization routine called by ll_rw_blk.c */ -int __init ps2esdi_init(void) +static int __init ps2esdi_init(void) { int error = 0; @@ -169,9 +167,11 @@ return 0; } /* ps2esdi_init */ +#ifndef MODULE + module_init(ps2esdi_init); -#ifdef MODULE +#else static int cyl[MAX_HD] = {-1,-1}; static int head[MAX_HD] = {-1, -1}; @@ -187,7 +187,7 @@ int drive; for(drive = 0; drive < MAX_HD; drive++) { - struct ps2_esdi_i_struct *info = &ps2esdi_info[drive]; + struct ps2esdi_i_struct *info = &ps2esdi_info[drive]; if (cyl[drive] != -1) { info->cyl = info->lzone = cyl[drive]; @@ -204,6 +204,7 @@ void cleanup_module(void) { + int i; if(ps2esdi_slot) { mca_mark_as_unused(ps2esdi_slot); mca_set_adapter_procfn(ps2esdi_slot, NULL, NULL); @@ -421,6 +422,7 @@ disk->major = PS2ESDI_MAJOR; disk->first_minor = i<<6; sprintf(disk->disk_name, "ed%c", 'a'+i); + sprintf(disk->devfs_name, "ed/target%d", i); disk->fops = &ps2esdi_fops; ps2esdi_gendisk[i] = disk; } diff -Nru a/drivers/block/umem.c b/drivers/block/umem.c --- a/drivers/block/umem.c Thu Sep 11 23:03:14 2003 +++ b/drivers/block/umem.c Thu Sep 11 23:03:14 2003 @@ -52,7 +52,6 @@ #include /* O_ACCMODE */ #include /* HDIO_GETGEO */ -#include #include @@ -1204,11 +1203,10 @@ goto out; } - devfs_mk_dir("umem"); - for (i = 0; i < num_cards; i++) { struct gendisk *disk = mm_gendisk[i]; sprintf(disk->disk_name, "umem%c", 'a'+i); + sprintf(disk->devfs_name, "umem/card%d", i); spin_lock_init(&cards[i].lock); disk->major = major_nr; disk->first_minor = i << MM_SHIFT; @@ -1245,7 +1243,6 @@ del_gendisk(mm_gendisk[i]); put_disk(mm_gendisk[i]); } - devfs_remove("umem"); pci_unregister_driver(&mm_pci_driver); diff -Nru a/drivers/block/xd.c b/drivers/block/xd.c --- a/drivers/block/xd.c Thu Sep 11 23:03:13 2003 +++ b/drivers/block/xd.c Thu Sep 11 23:03:13 2003 @@ -45,7 +45,6 @@ #include #include #include -#include #include #include @@ -182,7 +181,6 @@ if (!xd_queue) goto out1a; - devfs_mk_dir("xd"); if (xd_detect(&controller,&address)) { printk("Detected a%s controller (type %d) at address %06x\n", @@ -213,6 +211,7 @@ disk->major = XT_DISK_MAJOR; disk->first_minor = i<<6; sprintf(disk->disk_name, "xd%c", i+'a'); + sprintf(disk->devfs_name, "xd/target%d", i); disk->fops = &xd_fops; disk->private_data = p; disk->queue = xd_queue; @@ -249,7 +248,6 @@ out3: release_region(xd_iobase,4); out2: - devfs_remove("xd"); blk_cleanup_queue(xd_queue); out1a: unregister_blkdev(XT_DISK_MAJOR, "xd"); @@ -1064,7 +1062,6 @@ } blk_cleanup_queue(xd_queue); release_region(xd_iobase,4); - devfs_remove("xd"); if (xd_drives) { free_irq(xd_irq, NULL); free_dma(xd_dma); diff -Nru a/drivers/block/z2ram.c b/drivers/block/z2ram.c --- a/drivers/block/z2ram.c Thu Sep 11 23:03:13 2003 +++ b/drivers/block/z2ram.c Thu Sep 11 23:03:13 2003 @@ -354,6 +354,7 @@ z2ram_gendisk->first_minor = 0; z2ram_gendisk->fops = &z2_fops; sprintf(z2ram_gendisk->disk_name, "z2ram"); + strcpy(z2ram_gendisk->devfs_name, z2ram_gendisk->disk_name); z2ram_gendisk->queue = z2_queue; add_disk(z2ram_gendisk); diff -Nru a/drivers/cdrom/Kconfig b/drivers/cdrom/Kconfig --- a/drivers/cdrom/Kconfig Thu Sep 11 23:03:13 2003 +++ b/drivers/cdrom/Kconfig Thu Sep 11 23:03:13 2003 @@ -267,7 +267,7 @@ config CDU535 tristate "Sony CDU535 CDROM support" - depends on CD_NO_IDESCSI && BROKEN_ON_SMP + depends on CD_NO_IDESCSI ---help--- This is the driver for the older Sony CDU-535 and CDU-531 CD-ROM drives. Please read the file . diff -Nru a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c --- a/drivers/cdrom/gscd.c Thu Sep 11 23:03:11 2003 +++ b/drivers/cdrom/gscd.c Thu Sep 11 23:03:11 2003 @@ -965,7 +965,7 @@ gscd_queue = blk_init_queue(do_gscd_request, &gscd_lock); if (!gscd_queue) { - ret -ENOMEM; + ret = -ENOMEM; goto err_out3; } diff -Nru a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c --- a/drivers/cdrom/sonycd535.c Thu Sep 11 23:03:12 2003 +++ b/drivers/cdrom/sonycd535.c Thu Sep 11 23:03:12 2003 @@ -36,6 +36,10 @@ * module_init & module_exit. * Torben Mathiasen * + * September 2003 - Fix SMP support by removing cli/sti calls. + * Using spinlocks with a wait_queue instead. + * Felipe Damasio + * * Things to do: * - handle errors and status better, put everything into a single word * - use interrupts (code mostly there, but a big hole still missing) @@ -340,10 +344,14 @@ if (sony535_irq_used <= 0) { /* poll */ yield(); } else { /* Interrupt driven */ - cli(); + DEFINE_WAIT(wait); + + spin_lock_irq(&sonycd535_lock); enable_interrupts(); - interruptible_sleep_on(&cdu535_irq_wait); - sti(); + prepare_to_wait(&cdu535_irq_wait, &wait, TASK_INTERRUPTIBLE); + spin_unlock_irq(&sonycd535_lock); + schedule(); + finish_wait(&cdu535_irq_wait, &wait); } } @@ -804,14 +812,14 @@ block = req->sector; nsect = req->nr_sectors; - if (!(req->flags & REQ_CMD)) - continue; /* FIXME */ + if (!blk_fs_request(req)) { + end_request(req, 0); + continue; + } if (rq_data_dir(req) == WRITE) { end_request(req, 0); continue; } - if (rq_data_dir(req) != READ) - panic("Unknown SONY CD cmd"); /* * If the block address is invalid or the request goes beyond * the end of the media, return an error. @@ -888,8 +896,10 @@ } if (readStatus == BAD_STATUS) { /* Sleep for a while, then retry */ - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_irq(&sonycd535_lock); schedule_timeout(RETRY_FOR_BAD_STATUS*HZ/10); + spin_lock_irq(&sonycd535_lock); } #if DEBUG > 0 printk(CDU535_MESSAGE_NAME @@ -1473,7 +1483,7 @@ /* look for the CD-ROM, follows the procedure in the DOS driver */ inb(select_unit_reg); /* wait for 40 18 Hz ticks (reverse-engineered from DOS driver) */ - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((HZ+17)*40/18); inb(result_reg); diff -Nru a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c --- a/drivers/char/agp/ati-agp.c Thu Sep 11 23:03:13 2003 +++ b/drivers/char/agp/ati-agp.c Thu Sep 11 23:03:13 2003 @@ -491,7 +491,7 @@ agp_put_bridge(bridge); } -static struct pci_device_id agp_ati_pci_table[] __initdata = { +static struct pci_device_id agp_ati_pci_table[] = { { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, diff -Nru a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c --- a/drivers/char/agp/sis-agp.c Thu Sep 11 23:03:11 2003 +++ b/drivers/char/agp/sis-agp.c Thu Sep 11 23:03:11 2003 @@ -215,7 +215,7 @@ agp_put_bridge(bridge); } -static struct pci_device_id agp_sis_pci_table[] __initdata = { +static struct pci_device_id agp_sis_pci_table[] = { { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, diff -Nru a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c --- a/drivers/char/agp/uninorth-agp.c Thu Sep 11 23:03:12 2003 +++ b/drivers/char/agp/uninorth-agp.c Thu Sep 11 23:03:12 2003 @@ -350,7 +350,7 @@ agp_put_bridge(bridge); } -static struct pci_device_id agp_uninorth_pci_table[] __initdata = { +static struct pci_device_id agp_uninorth_pci_table[] = { { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, diff -Nru a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c --- a/drivers/char/agp/via-agp.c Thu Sep 11 23:03:13 2003 +++ b/drivers/char/agp/via-agp.c Thu Sep 11 23:03:13 2003 @@ -432,7 +432,7 @@ agp_put_bridge(bridge); } -static struct pci_device_id agp_via_pci_table[] __initdata = { +static struct pci_device_id agp_via_pci_table[] = { { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, diff -Nru a/drivers/char/epca.c b/drivers/char/epca.c --- a/drivers/char/epca.c Thu Sep 11 23:03:12 2003 +++ b/drivers/char/epca.c Thu Sep 11 23:03:13 2003 @@ -3868,7 +3868,7 @@ }; -static int __init epca_init_one (struct pci_dev *pdev, +static int __devinit epca_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { static int board_num = -1; diff -Nru a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c --- a/drivers/char/hvc_console.c Thu Sep 11 23:03:13 2003 +++ b/drivers/char/hvc_console.c Thu Sep 11 23:03:13 2003 @@ -284,9 +284,6 @@ if (tty_register_driver(hvc_driver)) panic("Couldn't register hvc console driver\n"); - for (i = 0; i < num; i++) - tty_register_device(hvc_driver, i, NULL); - if (num > 0) kernel_thread(khvcd, NULL, CLONE_KERNEL); diff -Nru a/drivers/char/hw_random.c b/drivers/char/hw_random.c --- a/drivers/char/hw_random.c Thu Sep 11 23:03:12 2003 +++ b/drivers/char/hw_random.c Thu Sep 11 23:03:12 2003 @@ -149,7 +149,7 @@ * register a pci_driver, because someone else might one day * want to register another driver on the same PCI id. */ -static struct pci_device_id rng_pci_tbl[] __initdata = { +static struct pci_device_id rng_pci_tbl[] = { { 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_amd }, { 0x1022, 0x746b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_amd }, diff -Nru a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c --- a/drivers/char/mwave/mwavedd.c Thu Sep 11 23:03:12 2003 +++ b/drivers/char/mwave/mwavedd.c Thu Sep 11 23:03:12 2003 @@ -293,8 +293,6 @@ case IOCTL_MW_GET_IPC: { unsigned int ipcnum = (unsigned int) ioarg; - spinlock_t ipc_lock = SPIN_LOCK_UNLOCKED; - unsigned long flags; PRINTK_3(TRACE_MWAVE, "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC" @@ -310,32 +308,29 @@ } if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) { + DECLARE_WAITQUEUE(wait, current); + PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_ioctl, thread for" " ipc %x going to sleep\n", ipcnum); - - spin_lock_irqsave(&ipc_lock, flags); + add_wait_queue(&pDrvData->IPCs[ipcnum].ipc_wait_queue, &wait); + pDrvData->IPCs[ipcnum].bIsHere = TRUE; + set_current_state(TASK_INTERRUPTIBLE); /* check whether an event was signalled by */ /* the interrupt handler while we were gone */ if (pDrvData->IPCs[ipcnum].usIntCount == 1) { /* first int has occurred (race condition) */ pDrvData->IPCs[ipcnum].usIntCount = 2; /* first int has been handled */ - spin_unlock_irqrestore(&ipc_lock, flags); PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_ioctl" " IOCTL_MW_GET_IPC ipcnum %x" " handling first int\n", ipcnum); } else { /* either 1st int has not yet occurred, or we have already handled the first int */ - pDrvData->IPCs[ipcnum].bIsHere = TRUE; -#warning "Sleeping on spinlock" - interruptible_sleep_on(&pDrvData->IPCs[ipcnum].ipc_wait_queue); - pDrvData->IPCs[ipcnum].bIsHere = FALSE; + schedule(); if (pDrvData->IPCs[ipcnum].usIntCount == 1) { - pDrvData->IPCs[ipcnum]. - usIntCount = 2; + pDrvData->IPCs[ipcnum].usIntCount = 2; } - spin_unlock_irqrestore(&ipc_lock, flags); PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_ioctl" " IOCTL_MW_GET_IPC ipcnum %x" @@ -343,6 +338,9 @@ " application\n", ipcnum); } + pDrvData->IPCs[ipcnum].bIsHere = FALSE; + remove_wait_queue(&pDrvData->IPCs[ipcnum].ipc_wait_queue, &wait); + set_current_state(TASK_RUNNING); PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC," " returning thread for ipc %x" diff -Nru a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c --- a/drivers/char/n_r3964.c Thu Sep 11 23:03:14 2003 +++ b/drivers/char/n_r3964.c Thu Sep 11 23:03:14 2003 @@ -150,22 +150,18 @@ static int r3964_receive_room(struct tty_struct *tty); static struct tty_ldisc tty_ldisc_N_R3964 = { - TTY_LDISC_MAGIC, /* magic */ - "R3964", /* name */ - 0, /* num */ - 0, /* flags */ - r3964_open, /* open */ - r3964_close, /* close */ - 0, /* flush_buffer */ - 0, /* chars_in_buffer */ - r3964_read, /* read */ - r3964_write, /* write */ - r3964_ioctl, /* ioctl */ - r3964_set_termios, /* set_termios */ - r3964_poll, /* poll */ - r3964_receive_buf, /* receive_buf */ - r3964_receive_room, /* receive_room */ - 0 /* write_wakeup */ + .owner = THIS_MODULE, + .magic = TTY_LDISC_MAGIC, + .name = "R3964", + .open = r3964_open, + .close = r3964_close, + .read = r3964_read, + .write = r3964_write, + .ioctl = r3964_ioctl, + .set_termios = r3964_set_termios, + .poll = r3964_poll, + .receive_buf = r3964_receive_buf, + .receive_room = r3964_receive_room, }; @@ -1070,8 +1066,6 @@ { struct r3964_info *pInfo; - MOD_INC_USE_COUNT; - TRACE_L("open"); TRACE_L("tty=%x, PID=%d, disc_data=%x", (int)tty, current->pid, (int)tty->disc_data); @@ -1188,8 +1182,6 @@ TRACE_M("r3964_close - tx_buf kfree %x",(int)pInfo->tx_buf); kfree(pInfo); TRACE_M("r3964_close - info kfree %x",(int)pInfo); - - MOD_DEC_USE_COUNT; } static ssize_t r3964_read(struct tty_struct *tty, struct file *file, diff -Nru a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c --- a/drivers/char/pcmcia/synclink_cs.c Thu Sep 11 23:03:12 2003 +++ b/drivers/char/pcmcia/synclink_cs.c Thu Sep 11 23:03:12 2003 @@ -725,14 +725,6 @@ if (debug_level >= DEBUG_LEVEL_INFO) printk("mgslpc_release(0x%p)\n", link); - if (link->open) { - if (debug_level >= DEBUG_LEVEL_INFO) - printk("synclink_cs: release postponed, '%s' still open\n", - link->dev->dev_name); - link->state |= DEV_STALE_CONFIG; - return; - } - /* Unlink the device chain */ link->dev = NULL; link->state &= ~DEV_CONFIG; diff -Nru a/drivers/char/random.c b/drivers/char/random.c --- a/drivers/char/random.c Thu Sep 11 23:03:11 2003 +++ b/drivers/char/random.c Thu Sep 11 23:03:11 2003 @@ -253,6 +253,7 @@ #include #include #include +#include #include #include @@ -281,6 +282,15 @@ static int random_write_wakeup_thresh = 128; /* + * When the input pool goes over trickle_thresh, start dropping most + * samples to avoid wasting CPU time and reduce lock contention. + */ + +static int trickle_thresh = DEFAULT_POOL_SIZE * 7; + +static DEFINE_PER_CPU(int, trickle_count) = 0; + +/* * A pool of size .poolwords is stirred with a primitive polynomial * of degree .poolwords over GF(2). The taps for various sizes are * defined below. They are chosen to be evenly spaced (minimum RMS @@ -777,6 +787,11 @@ __u32 time; __s32 delta, delta2, delta3; int entropy = 0; + + /* if over the trickle threshold, use only 1 in 4096 samples */ + if ( random_state->entropy_count > trickle_thresh && + (__get_cpu_var(trickle_count)++ & 0xfff)) + return; #if defined (__i386__) || defined (__x86_64__) if (cpu_has_tsc) { diff -Nru a/drivers/char/watchdog/alim1535_wdt.c b/drivers/char/watchdog/alim1535_wdt.c --- a/drivers/char/watchdog/alim1535_wdt.c Thu Sep 11 23:03:11 2003 +++ b/drivers/char/watchdog/alim1535_wdt.c Thu Sep 11 23:03:11 2003 @@ -317,7 +317,7 @@ * want to register another driver on the same PCI id. */ -static struct pci_device_id ali_pci_tbl[] __initdata = { +static struct pci_device_id ali_pci_tbl[] = { { PCI_VENDOR_ID_AL, 1535, PCI_ANY_ID, PCI_ANY_ID,}, { 0, }, }; diff -Nru a/drivers/char/watchdog/amd7xx_tco.c b/drivers/char/watchdog/amd7xx_tco.c --- a/drivers/char/watchdog/amd7xx_tco.c Thu Sep 11 23:03:11 2003 +++ b/drivers/char/watchdog/amd7xx_tco.c Thu Sep 11 23:03:11 2003 @@ -294,7 +294,7 @@ .fops = &amdtco_fops }; -static struct pci_device_id amdtco_pci_tbl[] __initdata = { +static struct pci_device_id amdtco_pci_tbl[] = { /* AMD 766 PCI_IDs here */ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7443, PCI_ANY_ID, PCI_ANY_ID, }, { 0, } diff -Nru a/drivers/char/watchdog/i810-tco.c b/drivers/char/watchdog/i810-tco.c --- a/drivers/char/watchdog/i810-tco.c Thu Sep 11 23:03:11 2003 +++ b/drivers/char/watchdog/i810-tco.c Thu Sep 11 23:03:11 2003 @@ -301,7 +301,7 @@ * register a pci_driver, because someone else might one day * want to register another driver on the same PCI id. */ -static struct pci_device_id i810tco_pci_tbl[] __initdata = { +static struct pci_device_id i810tco_pci_tbl[] = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, PCI_ANY_ID, PCI_ANY_ID, }, diff -Nru a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c --- a/drivers/char/watchdog/wdt_pci.c Thu Sep 11 23:03:13 2003 +++ b/drivers/char/watchdog/wdt_pci.c Thu Sep 11 23:03:13 2003 @@ -505,7 +505,7 @@ }; -static int __init wdtpci_init_one (struct pci_dev *dev, +static int __devinit wdtpci_init_one (struct pci_dev *dev, const struct pci_device_id *ent) { static int dev_count = 0; diff -Nru a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c --- a/drivers/cpufreq/cpufreq.c Thu Sep 11 23:03:11 2003 +++ b/drivers/cpufreq/cpufreq.c Thu Sep 11 23:03:11 2003 @@ -1,11 +1,9 @@ /* - * linux/kernel/cpufreq.c + * linux/drivers/cpufreq/cpufreq.c * * Copyright (C) 2001 Russell King * (C) 2002 - 2003 Dominik Brodowski * - * $Id: cpufreq.c,v 1.59 2003/01/20 17:31:48 db Exp $ - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. @@ -743,26 +741,9 @@ EXPORT_SYMBOL(cpufreq_get_policy); -/** - * cpufreq_set_policy - set a new CPUFreq policy - * @policy: policy to be set. - * - * Sets a new CPU frequency and voltage scaling policy. - */ -int cpufreq_set_policy(struct cpufreq_policy *policy) +static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_policy *policy) { int ret = 0; - struct cpufreq_policy *data; - - if (!policy) - return -EINVAL; - - data = cpufreq_cpu_get(policy->cpu); - if (!data) - return -EINVAL; - - /* lock this CPU */ - down(&data->lock); memcpy(&policy->cpuinfo, &data->cpuinfo, @@ -829,6 +810,36 @@ } error_out: + return ret; +} + +/** + * cpufreq_set_policy - set a new CPUFreq policy + * @policy: policy to be set. + * + * Sets a new CPU frequency and voltage scaling policy. + */ +int cpufreq_set_policy(struct cpufreq_policy *policy) +{ + int ret = 0; + struct cpufreq_policy *data; + + if (!policy) + return -EINVAL; + + data = cpufreq_cpu_get(policy->cpu); + if (!data) + return -EINVAL; + + /* lock this CPU */ + down(&data->lock); + + ret = __cpufreq_set_policy(data, policy); + data->user_policy.min = data->min; + data->user_policy.max = data->max; + data->user_policy.policy = data->policy; + data->user_policy.governor = data->governor; + up(&data->lock); cpufreq_cpu_put(data); @@ -836,6 +847,41 @@ } EXPORT_SYMBOL(cpufreq_set_policy); + +/** + * cpufreq_update_policy - re-evaluate an existing cpufreq policy + * @cpu: CPU which shall be re-evaluated + * + * Usefull for policy notifiers which have different necessities + * at different times. + */ +int cpufreq_update_policy(unsigned int cpu) +{ + struct cpufreq_policy *data = cpufreq_cpu_get(cpu); + struct cpufreq_policy policy; + int ret = 0; + + if (!data) + return -ENODEV; + + down(&data->lock); + + memcpy(&policy, + &data, + sizeof(struct cpufreq_policy)); + policy.min = data->user_policy.min; + policy.max = data->user_policy.max; + policy.policy = data->user_policy.policy; + policy.governor = data->user_policy.governor; + + ret = __cpufreq_set_policy(data, &policy); + + up(&data->lock); + + cpufreq_cpu_put(data); + return ret; +} +EXPORT_SYMBOL(cpufreq_update_policy); /********************************************************************* diff -Nru a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c --- a/drivers/cpufreq/cpufreq_userspace.c Thu Sep 11 23:03:11 2003 +++ b/drivers/cpufreq/cpufreq_userspace.c Thu Sep 11 23:03:11 2003 @@ -1,10 +1,8 @@ /* - * drivers/cpufreq/userspace.c + * linux/drivers/cpufreq/cpufreq_userspace.c * * Copyright (C) 2001 Russell King * (C) 2002 - 2003 Dominik Brodowski - * - * $Id:$ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff -Nru a/drivers/ide/ide-default.c b/drivers/ide/ide-default.c --- a/drivers/ide/ide-default.c Thu Sep 11 23:03:14 2003 +++ b/drivers/ide/ide-default.c Thu Sep 11 23:03:14 2003 @@ -57,6 +57,14 @@ "driver with ide.c\n", drive->name); return 1; } + + /* For the sake of the request layer, we must make sure we have a + * correct ready_stat value, that is 0 for ATAPI devices or we will + * fail any request like Power Management + */ + if (drive->media != ide_disk) + drive->ready_stat = 0; + return 0; } diff -Nru a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c --- a/drivers/ide/ide-io.c Thu Sep 11 23:03:13 2003 +++ b/drivers/ide/ide-io.c Thu Sep 11 23:03:13 2003 @@ -928,13 +928,10 @@ * * We let requests forced at head of queue with ide-preempt * though. I hope that doesn't happen too much, hopefully not - * unless the subdriver triggers such a thing in it's own PM + * unless the subdriver triggers such a thing in its own PM * state machine. */ if (drive->blocked && !blk_pm_request(rq) && !(rq->flags & REQ_PREEMPT)) { -#ifdef DEBUG_PM - printk("%s: a request made it's way while we are power managing...\n", drive->name); -#endif /* We clear busy, there should be no pending ATA command at this point. */ hwgroup->busy = 0; break; @@ -1417,8 +1414,9 @@ } spin_lock_irqsave(&ide_lock, flags); - if (action == ide_preempt || action == ide_head_wait) { + if (action == ide_preempt) hwgroup->rq = NULL; + if (action == ide_preempt || action == ide_head_wait) { where = ELEVATOR_INSERT_FRONT; rq->flags |= REQ_PREEMPT; } diff -Nru a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c --- a/drivers/input/keyboard/atkbd.c Thu Sep 11 23:03:13 2003 +++ b/drivers/input/keyboard/atkbd.c Thu Sep 11 23:03:13 2003 @@ -322,6 +322,16 @@ } /* + * Enable keyboard. + */ +static void atkbd_enable(struct atkbd *atkbd) +{ + if (atkbd_command(atkbd, NULL, ATKBD_CMD_ENABLE)) + printk(KERN_ERR "atkbd.c: Failed to enable keyboard on %s\n", + atkbd->serio->phys); +} + +/* * atkbd_set_3 checks if a keyboard has a working Set 3 support, and * sets it into that. Unfortunately there are keyboards that can be switched * to Set 3, but don't work well in that (BTC Multimedia ...) @@ -399,7 +409,9 @@ if (atkbd_reset) if (atkbd_command(atkbd, NULL, ATKBD_CMD_RESET_BAT)) - printk(KERN_WARNING "atkbd.c: keyboard reset failed on %s\n", atkbd->serio->phys); + printk(KERN_WARNING + "atkbd.c: keyboard reset failed on %s\n", + atkbd->serio->phys); /* * Then we check the keyboard ID. We should get 0xab83 under normal conditions. @@ -433,24 +445,20 @@ if (atkbd_command(atkbd, param, ATKBD_CMD_SETLEDS)) return -1; + return 0; +} + /* * Disable autorepeat. We don't need it, as we do it in software anyway, * because that way can get faster repeat, and have less system load (less * accesses to the slow ISA hardware). If this fails, we don't care, and will * just ignore the repeated keys. + * + * This command is for scancode set 3 only. */ - +static void atkbd_disable_autorepeat(struct atkbd *atkbd) +{ atkbd_command(atkbd, NULL, ATKBD_CMD_SETALL_MB); - -/* - * Last, we enable the keyboard to make sure that we get keypresses from it. - */ - - if (atkbd_command(atkbd, NULL, ATKBD_CMD_ENABLE)) - printk(KERN_ERR "atkbd.c: Failed to enable keyboard on %s\n", - atkbd->serio->phys); - - return 0; } /* @@ -477,7 +485,7 @@ } /* - * atkbd_connect() is called when the serio module finds and interface + * atkbd_connect() is called when the serio module finds an interface * that isn't handled yet by an appropriate device driver. We check if * there is an AT keyboard out there and if yes, we register ourselves * to the input module. @@ -531,7 +539,9 @@ } atkbd->set = atkbd_set_3(atkbd); - + if (atkbd->set == 3) + atkbd_disable_autorepeat(atkbd); + atkbd_enable(atkbd); } else { atkbd->set = 2; atkbd->id = 0xab00; diff -Nru a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c --- a/drivers/isdn/hardware/avm/avm_cs.c Thu Sep 11 23:03:11 2003 +++ b/drivers/isdn/hardware/avm/avm_cs.c Thu Sep 11 23:03:11 2003 @@ -431,15 +431,6 @@ static void avmcs_release(dev_link_t *link) { - /* - If the device is currently in use, we won't release until it - is actually closed. - */ - if (link->open) { - link->state |= DEV_STALE_CONFIG; - return; - } - b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ); /* Unlink the device chain */ diff -Nru a/drivers/isdn/hardware/eicon/Kconfig b/drivers/isdn/hardware/eicon/Kconfig --- a/drivers/isdn/hardware/eicon/Kconfig Thu Sep 11 23:03:12 2003 +++ b/drivers/isdn/hardware/eicon/Kconfig Thu Sep 11 23:03:12 2003 @@ -12,7 +12,7 @@ config ISDN_DIVAS tristate "Support Eicon DIVA Server cards" - depends on CAPI_EICON && PROC_FS && PCI && m + depends on CAPI_EICON && PROC_FS && PCI help Say Y here if you have an Eicon Networks DIVA Server PCI ISDN card. In order to use this card, additional firmware is necessary, which @@ -24,12 +24,6 @@ help Enable support for DIVA Server BRI-PCI. -config ISDN_DIVAS_4BRIPCI - bool "DIVA Server 4BRI/PCI support" - depends on ISDN_DIVAS - help - Enable support for DIVA Server 4BRI-PCI. - config ISDN_DIVAS_PRIPCI bool "DIVA Server PRI/PCI support" depends on ISDN_DIVAS @@ -43,17 +37,17 @@ You need this to provide the CAPI interface for DIVA Server cards. -config ISDN_DIVAS_MAINT - tristate "DIVA Maint driver support" - depends on ISDN_DIVAS - help - Enable Divas Maintainance driver. - config ISDN_DIVAS_USERIDI tristate "DIVA User-IDI interface support" depends on ISDN_DIVAS help Enable support for user-mode IDI interface. + +config ISDN_DIVAS_MAINT + tristate "DIVA Maint driver support" + depends on ISDN_DIVAS && m + help + Enable Divas Maintainance driver. endmenu diff -Nru a/drivers/isdn/hardware/eicon/Makefile b/drivers/isdn/hardware/eicon/Makefile --- a/drivers/isdn/hardware/eicon/Makefile Thu Sep 11 23:03:13 2003 +++ b/drivers/isdn/hardware/eicon/Makefile Thu Sep 11 23:03:13 2003 @@ -10,9 +10,8 @@ # Multipart objects. divas-y := divasmain.o divasfunc.o di.o io.o istream.o \ - diva.o dlist.o divasproc.o diva_dma.o -divas-$(CONFIG_ISDN_DIVAS_BRIPCI) += os_bri.o s_bri.o -divas-$(CONFIG_ISDN_DIVAS_4BRIPCI) += os_4bri.o s_4bri.o + diva.o divasproc.o diva_dma.o +divas-$(CONFIG_ISDN_DIVAS_BRIPCI) += os_bri.o s_bri.o os_4bri.o s_4bri.o divas-$(CONFIG_ISDN_DIVAS_PRIPCI) += os_pri.o s_pri.o divacapi-y := capimain.o capifunc.o message.o capidtmf.o @@ -21,4 +20,4 @@ diva_mnt-y := divamnt.o mntfunc.o debug.o maintidi.o -diva_idi-y := divasi.o idifunc.o um_idi.o dqueue.o dlist.o +diva_idi-y := divasi.o idifunc.o um_idi.o dqueue.o diff -Nru a/drivers/isdn/hardware/eicon/capifunc.c b/drivers/isdn/hardware/eicon/capifunc.c --- a/drivers/isdn/hardware/eicon/capifunc.c Thu Sep 11 23:03:13 2003 +++ b/drivers/isdn/hardware/eicon/capifunc.c Thu Sep 11 23:03:13 2003 @@ -1,10 +1,10 @@ -/* $Id: capifunc.c,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $ +/* $Id: capifunc.c,v 1.47 2003/09/09 06:52:29 schindler Exp $ * * ISDN interface module for Eicon active cards DIVA. * CAPI Interface common functions * - * Copyright 2000-2002 by Armin Schindler (mac@melware.de) - * Copyright 2000-2002 Cytronics & Melware (info@melware.de) + * Copyright 2000-2003 by Armin Schindler (mac@melware.de) + * Copyright 2000-2003 Cytronics & Melware (info@melware.de) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. @@ -25,10 +25,11 @@ DIVA_CAPI_ADAPTER *adapter = (DIVA_CAPI_ADAPTER *) NULL; APPL *application = (APPL *) NULL; byte max_appl = MAX_APPL; +byte max_adapter = 0; static CAPI_MSG *mapped_msg = (CAPI_MSG *) NULL; byte UnMapController(byte); -char DRIVERRELEASE[32]; +char DRIVERRELEASE_CAPI[32]; extern void AutomaticLaw(DIVA_CAPI_ADAPTER *); extern void callback(ENTITY *); @@ -45,7 +46,6 @@ static void DIRequest(ENTITY * e); static DESCRIPTOR MAdapter; static DESCRIPTOR DAdapter; -byte max_adapter = 0; static byte ControllerMap[MAX_DESCRIPTORS + 1]; @@ -59,16 +59,14 @@ extern void DIVA_DIDD_Read(DESCRIPTOR *, int); -static void no_printf(unsigned char *, ...); - -DIVA_DI_PRINTF dprintf = no_printf; - /* * debug */ +static void no_printf(unsigned char *, ...); #include "debuglib.c" void xlog(char *x, ...) { +#ifndef DIVA_NO_DEBUGLIB va_list ap; if (myDriverDebugHandle.dbgMask & DL_XLOG) { va_start(ap, x); @@ -81,6 +79,7 @@ } va_end(ap); } +#endif } /* @@ -162,13 +161,14 @@ p = cards; while (p) { if (p->Id == num) - goto next_id; + break; p = p->next; } + if(!p) { diva_os_leave_spin_lock(&ll_lock, &old_irql, "find free id"); return (num); - next_id: + } } diva_os_leave_spin_lock(&ll_lock, &old_irql, "find free id"); return (999); @@ -315,10 +315,11 @@ /* if DATA_B3_IND, copy data too */ if (command == _DATA_B3_I) { - dword data = READ_DWORD(((byte *) & msg.info.data_b3_ind.Data)); + dword data = READ_DWORD(&msg.info.data_b3_ind.Data); memcpy(write + length, (void *) data, dlength); } +#ifndef DIVA_NO_DEBUGLIB if (myDriverDebugHandle.dbgMask & DL_XLOG) { switch (command) { default: @@ -332,8 +333,8 @@ if (myDriverDebugHandle.dbgMask & DL_BLK) { xlog("\x00\x02", &msg, 0x81, length); for (i = 0; i < dlength; i += 256) { - DBG_BLK((((char *) msg.info.data_b3_ind. - Data) + i, ((dlength - i) < 256) ? (dlength - i) : 256)) + DBG_BLK((((char *) READ_DWORD(&msg.info.data_b3_ind.Data)) + i, + ((dlength - i) < 256) ? (dlength - i) : 256)) if (!(myDriverDebugHandle.dbgMask & DL_PRV0)) break; /* not more if not explicitely requested */ } @@ -341,6 +342,7 @@ break; } } +#endif /* find the card structure for this controller */ if (!(card = find_card_by_ctrl(write[8] & 0x7f))) { @@ -719,7 +721,7 @@ } /* profile information */ - ctrl->profile.nbchannel = card->d.channels; + WRITE_WORD(&ctrl->profile.nbchannel, card->d.channels); ctrl->profile.goptions = a->profile.Global_Options; ctrl->profile.support1 = a->profile.B1_Protocols; ctrl->profile.support2 = a->profile.B2_Protocols; @@ -745,17 +747,20 @@ { APPL *this; word bnum, xnum; - int i = 0, j = 0; + int i = 0; + unsigned char *p; void *DataNCCI, *DataFlags, *ReceiveBuffer, *xbuffer_used; void **xbuffer_ptr, **xbuffer_internal; diva_os_spin_lock_magic_t old_irql; + unsigned int mem_len; + if (diva_os_in_irq()) { DBG_ERR(("CAPI_REGISTER - in irq context !")) return; } - DBG_TRC(("application register")) + DBG_TRC(("application register Id=%d", appl)) if (appl > MAX_APPL) { DBG_ERR(("CAPI_REGISTER - appl.Id exceeds MAX_APPL")) @@ -775,97 +780,47 @@ return; /* appl already registered */ } - if (!try_module_get(ctrl->owner)) { - printk(KERN_WARNING "%s: cannot reserve module\n", __FUNCTION__); - return; - } - /* alloc memory */ bnum = rp->level3cnt * rp->datablkcnt; xnum = rp->level3cnt * MAX_DATA_B3; - if (!(DataNCCI = diva_os_malloc(0, bnum * sizeof(word)))) { - DBG_ERR(("CAPI_REGISTER - memory allocation failed")) - module_put(ctrl->owner); - return; - } - memset(DataNCCI, 0, bnum * sizeof(word)); - - if (!(DataFlags = diva_os_malloc(0, bnum * sizeof(word)))) { - DBG_ERR(("CAPI_REGISTER - memory allocation failed")) - diva_os_free(0, DataNCCI); - module_put(ctrl->owner); - return; - } - memset(DataFlags, 0, bnum * sizeof(word)); - - if (!(ReceiveBuffer = diva_os_malloc(0, bnum * rp->datablklen))) { - DBG_ERR(("CAPI_REGISTER - memory allocation failed")) - diva_os_free(0, DataNCCI); - diva_os_free(0, DataFlags); - module_put(ctrl->owner); - return; - } - memset(ReceiveBuffer, 0, bnum * rp->datablklen); - - if (!(xbuffer_used = (byte *) diva_os_malloc(0, xnum))) { - DBG_ERR(("CAPI_REGISTER - memory allocation failed")) - diva_os_free(0, DataNCCI); - diva_os_free(0, DataFlags); - diva_os_free(0, ReceiveBuffer); - module_put(ctrl->owner); - return; - } - memset(xbuffer_used, 0, xnum); + mem_len = bnum * sizeof(word); /* DataNCCI */ + mem_len += bnum * sizeof(word); /* DataFlags */ + mem_len += bnum * rp->datablklen; /* ReceiveBuffer */ + mem_len += xnum; /* xbuffer_used */ + mem_len += xnum * sizeof(void *); /* xbuffer_ptr */ + mem_len += xnum * sizeof(void *); /* xbuffer_internal */ + mem_len += xnum * rp->datablklen; /* xbuffer_ptr[xnum] */ - if (!(xbuffer_ptr = (void **) diva_os_malloc(0, xnum * sizeof(void *)))) { + if (!(p = diva_os_malloc(0, mem_len))) { DBG_ERR(("CAPI_REGISTER - memory allocation failed")) - diva_os_free(0, DataNCCI); - diva_os_free(0, DataFlags); - diva_os_free(0, ReceiveBuffer); - diva_os_free(0, xbuffer_used); - module_put(ctrl->owner); return; } - memset(xbuffer_ptr, 0, xnum * sizeof(void *)); - - if (!(xbuffer_internal = (void **) diva_os_malloc(0, xnum * sizeof(void *)))) { - DBG_ERR(("CAPI_REGISTER - memory allocation failed")) - diva_os_free(0, DataNCCI); - diva_os_free(0, DataFlags); - diva_os_free(0, ReceiveBuffer); - diva_os_free(0, xbuffer_used); - diva_os_free(0, xbuffer_ptr); - module_put(ctrl->owner); - return; - } - memset(xbuffer_internal, 0, xnum * sizeof(void *)); + memset(p, 0, mem_len); + DataNCCI = (void *)p; + p += bnum * sizeof(word); + DataFlags = (void *)p; + p += bnum * sizeof(word); + ReceiveBuffer = (void *)p; + p += bnum * rp->datablklen; + xbuffer_used = (void *)p; + p += xnum; + xbuffer_ptr = (void **)p; + p += xnum * sizeof(void *); + xbuffer_internal = (void **)p; + p += xnum * sizeof(void *); for (i = 0; i < xnum; i++) { - xbuffer_ptr[i] = diva_os_malloc(0, rp->datablklen); - if (!xbuffer_ptr[i]) { - DBG_ERR(("CAPI_REGISTER - memory allocation failed")) - if (i) { - for (j = 0; j < i; j++) - if (xbuffer_ptr[j]) - diva_os_free(0, xbuffer_ptr [j]); - } - diva_os_free(0, DataNCCI); - diva_os_free(0, DataFlags); - diva_os_free(0, ReceiveBuffer); - diva_os_free(0, xbuffer_used); - diva_os_free(0, xbuffer_ptr); - diva_os_free(0, xbuffer_internal); - module_put(ctrl->owner); - return; - } + xbuffer_ptr[i] = (void *)p; + p += rp->datablklen; } DBG_LOG(("CAPI_REGISTER - Id = %d", appl)) DBG_LOG((" MaxLogicalConnections = %d", rp->level3cnt)) DBG_LOG((" MaxBDataBuffers = %d", rp->datablkcnt)) DBG_LOG((" MaxBDataLength = %d", rp->datablklen)) + DBG_LOG((" Allocated Memory = %d", mem_len)) /* initialize application data */ diva_os_enter_spin_lock(&api_lock, &old_irql, "register_appl"); @@ -875,9 +830,6 @@ this->Id = appl; - /* We do not need a list */ - /* InitializeListHead(&this->s_function); */ - for (i = 0; i < max_adapter; i++) { adapter[i].CIP_Mask[appl - 1] = 0; } @@ -911,41 +863,24 @@ { diva_os_spin_lock_magic_t old_irql; APPL *this = &application[appl - 1]; - int i = 0; + + DBG_TRC(("application %d(%d) cleanup", this->Id, appl)) if (diva_os_in_irq()) { DBG_ERR(("CAPI_RELEASE - in irq context !")) return; } - if (this->Id) { - DBG_TRC(("application %d cleanup", this->Id)) - } diva_os_enter_spin_lock(&api_lock, &old_irql, "release_appl"); if (this->Id) { CapiRelease(this->Id); if (this->DataNCCI) diva_os_free(0, this->DataNCCI); - if (this->DataFlags) - diva_os_free(0, this->DataFlags); - if (this->ReceiveBuffer) - diva_os_free(0, this->ReceiveBuffer); - if (this->xbuffer_ptr) { - for (i = 0; i < (MAX_DATA_B3 * this->MaxNCCI); i++) { - if (this->xbuffer_ptr[i]) - diva_os_free(0, this->xbuffer_ptr[i]); - } - diva_os_free(0, this->xbuffer_ptr); - } - if (this->xbuffer_internal) - diva_os_free(0, this->xbuffer_internal); - if (this->xbuffer_used) - diva_os_free(0, this->xbuffer_used); + this->DataNCCI = NULL; this->Id = 0; } diva_os_leave_spin_lock(&api_lock, &old_irql, "release_appl"); - module_put(ctrl->owner); } /* @@ -954,7 +889,7 @@ static u16 diva_send_message(struct capi_ctr *ctrl, diva_os_message_buffer_s * dmb) { - int i = 0, j = 0; + int i = 0; word ret = 0; diva_os_spin_lock_magic_t old_irql; CAPI_MSG *msg = (CAPI_MSG *) DIVA_MESSAGE_BUFFER_DATA(dmb); @@ -971,6 +906,10 @@ } DBG_PRV1(("Write - appl = %d, cmd = 0x%x", this->Id, command)) + if (!this->Id) { + return CAPI_ILLAPPNR; + } + /* patch controller number */ msg->header.controller = ControllerMap[card->Id] | (msg->header.controller & 0x80); /* preserve external controller bit */ @@ -983,13 +922,17 @@ break; case _DATA_B3_I | RESPONSE: +#ifndef DIVA_NO_DEBUGLIB if (myDriverDebugHandle.dbgMask & DL_BLK) xlog("\x00\x02", msg, 0x80, clength); +#endif break; case _DATA_B3_R: +#ifndef DIVA_NO_DEBUGLIB if (myDriverDebugHandle.dbgMask & DL_BLK) xlog("\x00\x02", msg, 0x80, clength); +#endif if (clength == 24) clength = 22; /* workaround for PPcom bug */ @@ -1016,8 +959,10 @@ memcpy(this->xbuffer_ptr[i], &((__u8 *) msg)[clength], READ_WORD(&msg->info.data_b3_req.Data_Length)); +#ifndef DIVA_NO_DEBUGLIB if ((myDriverDebugHandle.dbgMask & DL_BLK) && (myDriverDebugHandle.dbgMask & DL_XLOG)) { + int j; for (j = 0; j < READ_WORD(&msg->info.data_b3_req.Data_Length); j += 256) { @@ -1028,6 +973,7 @@ break; /* not more if not explicitely requested */ } } +#endif break; } @@ -1091,7 +1037,7 @@ } else { memcpy(&MAdapter, adapter, sizeof(MAdapter)); dprintf = (DIVA_DI_PRINTF) MAdapter.request; - DbgRegister("CAPI20", DRIVERRELEASE, DBG_DEFAULT); + DbgRegister("CAPI20", DRIVERRELEASE_CAPI, DBG_DEFAULT); } } else if ((adapter->type > 0) && (adapter->type < 16)) { /* IDI Adapter */ if (removal) { @@ -1119,7 +1065,7 @@ if (DIDD_Table[x].type == IDI_DIMAINT) { /* MAINT found */ memcpy(&MAdapter, &DIDD_Table[x], sizeof(DAdapter)); dprintf = (DIVA_DI_PRINTF) MAdapter.request; - DbgRegister("CAPI20", DRIVERRELEASE, DBG_DEFAULT); + DbgRegister("CAPI20", DRIVERRELEASE_CAPI, DBG_DEFAULT); break; } } @@ -1130,7 +1076,7 @@ req.didd_notify.e.Req = 0; req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY; - req.didd_notify.info.callback = didd_callback; + req.didd_notify.info.callback = (void *)didd_callback; req.didd_notify.info.context = 0; DAdapter.request((ENTITY *) & req); if (req.didd_notify.e.Rc != 0xff) { @@ -1260,4 +1206,7 @@ divacapi_remove_cards(); remove_main_structs(); + + diva_os_destroy_spin_lock(&api_lock, "capifunc"); + diva_os_destroy_spin_lock(&ll_lock, "capifunc"); } diff -Nru a/drivers/isdn/hardware/eicon/capifunc.h b/drivers/isdn/hardware/eicon/capifunc.h --- a/drivers/isdn/hardware/eicon/capifunc.h Thu Sep 11 23:03:13 2003 +++ b/drivers/isdn/hardware/eicon/capifunc.h Thu Sep 11 23:03:13 2003 @@ -1,10 +1,10 @@ -/* $Id: capifunc.h,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $ +/* $Id: capifunc.h,v 1.10 2003/08/25 10:06:37 schindler Exp $ * * ISDN interface module for Eicon active cards DIVA. * CAPI Interface common functions * - * Copyright 2000-2002 by Armin Schindler (mac@melware.de) - * Copyright 2000-2002 Cytronics & Melware (info@melware.de) + * Copyright 2000-2003 by Armin Schindler (mac@melware.de) + * Copyright 2000-2003 Cytronics & Melware (info@melware.de) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. @@ -21,7 +21,7 @@ #define M_COMPANY "Eicon Networks" -extern char DRIVERRELEASE[]; +extern char DRIVERRELEASE_CAPI[]; typedef struct _diva_card { int Id; diff -Nru a/drivers/isdn/hardware/eicon/capimain.c b/drivers/isdn/hardware/eicon/capimain.c --- a/drivers/isdn/hardware/eicon/capimain.c Thu Sep 11 23:03:11 2003 +++ b/drivers/isdn/hardware/eicon/capimain.c Thu Sep 11 23:03:11 2003 @@ -1,10 +1,10 @@ -/* $Id: capimain.c,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $ +/* $Id: capimain.c,v 1.24 2003/09/09 06:51:05 schindler Exp $ * * ISDN interface module for Eicon active cards DIVA. * CAPI Interface * - * Copyright 2000-2002 by Armin Schindler (mac@melware.de) - * Copyright 2000-2002 Cytronics & Melware (info@melware.de) + * Copyright 2000-2003 by Armin Schindler (mac@melware.de) + * Copyright 2000-2003 Cytronics & Melware (info@melware.de) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. @@ -15,10 +15,7 @@ #include #include #include -#include -#include #include -#include #include "os_capi.h" @@ -29,7 +26,7 @@ #include "cp_vers.h" #include "capifunc.h" -static char *main_revision = "$Revision: 1.1.2.11 $"; +static char *main_revision = "$Revision: 1.24 $"; static char *DRIVERNAME = "Eicon DIVA - CAPI Interface driver (http://www.melware.net)"; static char *DRIVERLNAME = "divacapi"; @@ -57,47 +54,6 @@ } /* - * sleep for some milliseconds - */ -void diva_os_sleep(dword mSec) -{ - unsigned long timeout = HZ * mSec / 1000 + 1; - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(timeout); -} - -/* - * wait for some milliseconds - */ -void diva_os_wait(dword mSec) -{ - mdelay(mSec); -} - -/* - * alloc memory - */ -void *diva_os_malloc(unsigned long flags, unsigned long size) -{ - void *ret = NULL; - if (size) { - ret = (void *) vmalloc((unsigned int) size); - } - return (ret); -} - -/* - * free memory - */ -void diva_os_free(unsigned long unused, void *ptr) -{ - if (ptr) { - vfree(ptr); - } -} - -/* * alloc a message buffer */ diva_os_message_buffer_s *diva_os_alloc_message_buffer(unsigned long size, @@ -160,11 +116,11 @@ char tmprev[32]; int ret = 0; - sprintf(DRIVERRELEASE, "%d.%d%s", DRRELMAJOR, DRRELMINOR, + sprintf(DRIVERRELEASE_CAPI, "%d.%d%s", DRRELMAJOR, DRRELMINOR, DRRELEXTRA); printk(KERN_INFO "%s\n", DRIVERNAME); - printk(KERN_INFO "%s: Rel:%s Rev:", DRIVERLNAME, DRIVERRELEASE); + printk(KERN_INFO "%s: Rel:%s Rev:", DRIVERLNAME, DRIVERRELEASE_CAPI); strcpy(tmprev, main_revision); printk("%s Build: %s(%s)\n", getrev(tmprev), diva_capi_common_code_build, DIVA_BUILD); diff -Nru a/drivers/isdn/hardware/eicon/dadapter.c b/drivers/isdn/hardware/eicon/dadapter.c --- a/drivers/isdn/hardware/eicon/dadapter.c Thu Sep 11 23:03:12 2003 +++ b/drivers/isdn/hardware/eicon/dadapter.c Thu Sep 11 23:03:12 2003 @@ -49,8 +49,21 @@ Shadow IDI_DIMAINT and 'shadow' debug stuff -------------------------------------------------------------------------- */ -static void no_printf (unsigned char * format, ...) { } -DIVA_DI_PRINTF dprintf = no_printf; +static void no_printf (unsigned char * format, ...) +{ +#ifdef EBUG + va_list ap; + va_start (ap, format); + debug((format, ap)); + va_end (ap); +#endif +} + +/* ------------------------------------------------------------------------- + Portable debug Library + ------------------------------------------------------------------------- */ +#include "debuglib.c" + static DESCRIPTOR MAdapter = {IDI_DIMAINT, /* Adapter Type */ 0x00, /* Channels */ 0x0000, /* Features */ @@ -86,6 +99,7 @@ Should be called as last step, if driver does unload -------------------------------------------------------------------------- */ void diva_didd_load_time_finit (void) { + diva_os_destroy_spin_lock (&didd_spin, "didd"); } /* -------------------------------------------------------------------------- Called in order to register new adapter in adapter array @@ -349,7 +363,4 @@ int length) { diva_didd_read_adapter_array (buffer, length); } -/* ------------------------------------------------------------------------- - Portable debug Library - ------------------------------------------------------------------------- */ -#include "debuglib.c" + diff -Nru a/drivers/isdn/hardware/eicon/debug.c b/drivers/isdn/hardware/eicon/debug.c --- a/drivers/isdn/hardware/eicon/debug.c Thu Sep 11 23:03:12 2003 +++ b/drivers/isdn/hardware/eicon/debug.c Thu Sep 11 23:03:12 2003 @@ -2,7 +2,6 @@ #include "pc.h" #include "di_defs.h" #include "debug_if.h" -#include "linux/kernel.h" #include "divasync.h" #include "kst_ifc.h" #include "maintidi.h" @@ -96,9 +95,9 @@ static byte *queueAllocMsg (MSG_QUEUE *Q, word size) { /* Allocate 'size' bytes at tail of queue which will be filled later - * directly whith callers own message header info and/or message. + * directly with callers own message header info and/or message. * An 'alloced' message is marked incomplete by oring the 'Size' field - * whith MSG_INCOMPLETE. + * with MSG_INCOMPLETE. * This must be reset via queueCompleteMsg() after the message is filled. * As long as a message is marked incomplete queuePeekMsg() will return * a 'queue empty' condition when it reaches such a message. */ @@ -160,7 +159,7 @@ } static byte *queuePeekMsg (MSG_QUEUE *Q, word *size) { - /* Show the first valid message in queue BUT DONT free the message. + /* Show the first valid message in queue BUT DON'T free the message. * After looking on the message contents it can be freed queueFreeMsg() * or simply remain in message queue. */ @@ -195,7 +194,7 @@ length: length of the message queue do_init: perfor queue reset - return: zero on sucess, -1 on error + return: zero on success, -1 on error */ int diva_maint_init (byte* base, unsigned long length, int do_init) { if (dbg_queue || (!base) || (length < (4096*4))) { @@ -296,7 +295,7 @@ /* INTERFACE: - Lock messafe queue and return the pointer to the first + Lock message queue and return the pointer to the first entry. */ diva_dbg_entry_head_t* diva_maint_get_message (word* size, @@ -725,12 +724,12 @@ if (clients[id].hDbg) { *p++ = 1; - *p++ = (byte)clients[id].sec; /* save secounds */ + *p++ = (byte)clients[id].sec; /* save seconds */ *p++ = (byte)(clients[id].sec >> 8); *p++ = (byte)(clients[id].sec >> 16); *p++ = (byte)(clients[id].sec >> 24); - *p++ = (byte)(clients[id].usec/1000); /* save msecounds */ + *p++ = (byte)(clients[id].usec/1000); /* save mseconds */ *p++ = (byte)((clients[id].usec/1000) >> 8); *p++ = (byte)((clients[id].usec/1000) >> 16); *p++ = (byte)((clients[id].usec/1000) >> 24); @@ -1079,7 +1078,7 @@ } /* ---------------------------------------------------------------- - Low level interface for management interace client + Low level interface for management interface client ---------------------------------------------------------------- */ /* Return handle to client structure @@ -1462,7 +1461,7 @@ case DIVA_SUPER_TRACE_NOTIFY_STAT_CHANGE: if (pC->hDbg->dbgMask & DIVA_MGT_DBG_IFC_STATISTICS) { /* - Incoming Statistices + Incoming Statistics */ if (channel->pInterfaceStat->inc.Calls) { diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, @@ -1498,7 +1497,7 @@ } /* - Outgoing Statistices + Outgoing Statistics */ if (channel->pInterfaceStat->outg.Calls) { diva_mnt_internal_dprintf (pC->hDbg->id, DLI_LOG, diff -Nru a/drivers/isdn/hardware/eicon/debuglib.c b/drivers/isdn/hardware/eicon/debuglib.c --- a/drivers/isdn/hardware/eicon/debuglib.c Thu Sep 11 23:03:12 2003 +++ b/drivers/isdn/hardware/eicon/debuglib.c Thu Sep 11 23:03:12 2003 @@ -23,8 +23,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ + #include "debuglib.h" + +#ifdef DIVA_NO_DEBUGLIB +static DIVA_DI_PRINTF dprintf; +#else /* DIVA_NO_DEBUGLIB */ + _DbgHandle_ myDriverDebugHandle = { 0 /*!Registered*/, DBG_HANDLE_VERSION }; +DIVA_DI_PRINTF dprintf = no_printf; /*****************************************************************************/ #define DBG_FUNC(name) \ void \ @@ -146,3 +153,4 @@ va_end(ap); } /*****************************************************************************/ +#endif /* DIVA_NO_DEBUGLIB */ diff -Nru a/drivers/isdn/hardware/eicon/debuglib.h b/drivers/isdn/hardware/eicon/debuglib.h --- a/drivers/isdn/hardware/eicon/debuglib.h Thu Sep 11 23:03:14 2003 +++ b/drivers/isdn/hardware/eicon/debuglib.h Thu Sep 11 23:03:14 2003 @@ -101,6 +101,34 @@ * with _KERNEL_DBG_PRINT_ */ #define DL_TO_KERNEL 0x40000000 + +#ifdef DIVA_NO_DEBUGLIB +#define myDbgPrint_LOG(x,...) do { } while(0); +#define myDbgPrint_FTL(x,...) do { } while(0); +#define myDbgPrint_ERR(x,...) do { } while(0); +#define myDbgPrint_TRC(x,...) do { } while(0); +#define myDbgPrint_MXLOG(x,...) do { } while(0); +#define myDbgPrint_EVL(x,...) do { } while(0); +#define myDbgPrint_REG(x,...) do { } while(0); +#define myDbgPrint_MEM(x,...) do { } while(0); +#define myDbgPrint_SPL(x,...) do { } while(0); +#define myDbgPrint_IRP(x,...) do { } while(0); +#define myDbgPrint_TIM(x,...) do { } while(0); +#define myDbgPrint_BLK(x,...) do { } while(0); +#define myDbgPrint_TAPI(x,...) do { } while(0); +#define myDbgPrint_NDIS(x,...) do { } while(0); +#define myDbgPrint_CONN(x,...) do { } while(0); +#define myDbgPrint_STAT(x,...) do { } while(0); +#define myDbgPrint_SEND(x,...) do { } while(0); +#define myDbgPrint_RECV(x,...) do { } while(0); +#define myDbgPrint_PRV0(x,...) do { } while(0); +#define myDbgPrint_PRV1(x,...) do { } while(0); +#define myDbgPrint_PRV2(x,...) do { } while(0); +#define myDbgPrint_PRV3(x,...) do { } while(0); +#define DBG_TEST(func,args) do { } while(0); +#define DBG_EVL_ID(args) do { } while(0); + +#else /* DIVA_NO_DEBUGLIB */ /* * define low level macros for formatted & raw debugging */ @@ -156,6 +184,9 @@ { if ( (myDriverDebugHandle.dbgMask) & (unsigned long)DL_EVL ) \ { myDbgPrint_EVL args ; \ } } + +#endif /* DIVA_NO_DEBUGLIB */ + #define DBG_LOG(args) DBG_TEST(LOG, args) #define DBG_FTL(args) DBG_TEST(FTL, args) #define DBG_ERR(args) DBG_TEST(ERR, args) @@ -182,9 +213,16 @@ /* * prototypes for debug register/deregister functions in "debuglib.c" */ +#ifdef DIVA_NO_DEBUGLIB +#define DbgRegister(name,tag, mask) do { } while(0) +#define DbgDeregister() do { } while(0) +#define DbgSetLevel(mask) do { } while(0) +#else +extern DIVA_DI_PRINTF dprintf; extern int DbgRegister (char *drvName, char *drvTag, unsigned long dbgMask) ; extern void DbgDeregister (void) ; extern void DbgSetLevel (unsigned long dbgMask) ; +#endif /* * driver internal structure for debug handling; * in client drivers this structure is maintained in "debuglib.c", @@ -274,9 +312,11 @@ } CardTrace; } u1; } _DbgExtendedInfo_; +#ifndef DIVA_NO_DEBUGLIB /* ------------------------------------------------------------- Function used for xlog-style debug ------------------------------------------------------------- */ #define XDI_USE_XLOG 1 void xdi_dbg_xlog (char* x, ...); +#endif /* DIVA_NO_DEBUGLIB */ #endif /* __DEBUGLIB_H__ */ diff -Nru a/drivers/isdn/hardware/eicon/di.c b/drivers/isdn/hardware/eicon/di.c --- a/drivers/isdn/hardware/eicon/di.c Thu Sep 11 23:03:12 2003 +++ b/drivers/isdn/hardware/eicon/di.c Thu Sep 11 23:03:12 2003 @@ -112,16 +112,14 @@ #ifdef USE_EXTENDED_DEBUGS if ( !this ) { - ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ; DBG_FTL(("XDI: [%02x] !A%d ==> NULL entity ptr - try to ignore", - xdi_xlog_sec++, (int)io->ANum)) + xdi_xlog_sec++, (int)((ISDN_ADAPTER *)a->io)->ANum)) e_no = look_req(a) ; ReadyCount-- ; continue ; } { - ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ; - DBG_TRC((">A%d Id=0x%x Req=0x%x", io->ANum, this->Id, this->Req)) + DBG_TRC((">A%d Id=0x%x Req=0x%x", ((ISDN_ADAPTER *)a->io)->ANum, this->Id, this->Req)) } #else dbug(dprintf("out:Req=%x,Id=%x,Ch=%x",this->Req,this->Id,this->ReqCh)); @@ -563,8 +561,7 @@ int cancel_rc; #ifdef USE_EXTENDED_DEBUGS { - ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ; - DBG_TRC(("ANum, Id, Rc)) + DBG_TRC(("io)->ANum, Id, Rc)) } #else dbug(dprintf("isdn_rc(Rc=%x,Id=%x,Ch=%x)",Rc,Id,Ch)); @@ -767,8 +764,7 @@ byte* cma = 0; #ifdef USE_EXTENDED_DEBUGS { - ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ; - DBG_TRC(("ANum, Id, Ind)) + DBG_TRC(("io)->ANum, Id, Ind)) } #else dbug(dprintf("isdn_ind(Ind=%x,Id=%x,Ch=%x)",Ind,Id,Ch)); @@ -956,10 +952,10 @@ byte Id, byte Ch, byte Rc, byte cb, byte type) { #if defined(XDI_USE_XLOG) word LogInfo[4]; - LogInfo[0] = (word)Adapter | (word)(xdi_xlog_sec++ << 8); - LogInfo[1] = (word)Id | (word)(Ch << 8); - LogInfo[2] = (word)Rc | (word)(type << 8); - LogInfo[3] = cb; + WRITE_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8))); + WRITE_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8))); + WRITE_WORD(&LogInfo[2], ((word)Rc | (word)(type << 8))); + WRITE_WORD(&LogInfo[3], cb); xdi_xlog ((byte*)&LogInfo[0], 221, sizeof(LogInfo)); #endif } @@ -980,9 +976,9 @@ byte Ch, byte Req, byte type) { #if defined(XDI_USE_XLOG) word LogInfo[3]; - LogInfo[0] = (word)Adapter | (word)(xdi_xlog_sec++ << 8); - LogInfo[1] = (word)Id | (word)(Ch << 8); - LogInfo[2] = (word)Req | (word)(type << 8); + WRITE_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8))); + WRITE_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8))); + WRITE_WORD(&LogInfo[2], ((word)Req | (word)(type << 8))); xdi_xlog ((byte*)&LogInfo[0], 220, sizeof(LogInfo)); #endif } @@ -1024,10 +1020,10 @@ byte type) { #if defined(XDI_USE_XLOG) word LogInfo[4]; - LogInfo[0] = (word)Adapter | (word)(xdi_xlog_sec++ << 8); - LogInfo[1] = (word)Id | (word)(Ch << 8); - LogInfo[2] = (word)Ind | (word)(type << 8); - LogInfo[3] = (word)rnr | (word)(rnr_valid << 8); + WRITE_WORD(&LogInfo[0], ((word)Adapter | (word)(xdi_xlog_sec++ << 8))); + WRITE_WORD(&LogInfo[1], ((word)Id | (word)(Ch << 8))); + WRITE_WORD(&LogInfo[2], ((word)Ind | (word)(type << 8))); + WRITE_WORD(&LogInfo[3], ((word)rnr | (word)(rnr_valid << 8))); xdi_xlog ((byte*)&LogInfo[0], 222, sizeof(LogInfo)); #endif } diff -Nru a/drivers/isdn/hardware/eicon/diddfunc.c b/drivers/isdn/hardware/eicon/diddfunc.c --- a/drivers/isdn/hardware/eicon/diddfunc.c Thu Sep 11 23:03:14 2003 +++ b/drivers/isdn/hardware/eicon/diddfunc.c Thu Sep 11 23:03:14 2003 @@ -1,11 +1,11 @@ -/* $Id: diddfunc.c,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $ +/* $Id: diddfunc.c,v 1.14 2003/08/25 10:06:37 schindler Exp $ * * DIDD Interface module for Eicon active cards. * * Functions are in dadapter.c * - * Copyright 2002 by Armin Schindler (mac@melware.de) - * Copyright 2002 Cytronics & Melware (info@melware.de) + * Copyright 2002-2003 by Armin Schindler (mac@melware.de) + * Copyright 2002-2003 Cytronics & Melware (info@melware.de) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. @@ -23,7 +23,7 @@ extern void DIVA_DIDD_Read(void *, int); -extern char *DRIVERRELEASE; +extern char *DRIVERRELEASE_DIDD; static dword notify_handle; static DESCRIPTOR _DAdapter; @@ -40,7 +40,7 @@ if (removal) { DbgDeregister(); } else { - DbgRegister("DIDD", DRIVERRELEASE, DBG_DEFAULT); + DbgRegister("DIDD", DRIVERRELEASE_DIDD, DBG_DEFAULT); } } return (NULL); @@ -65,14 +65,14 @@ req.didd_notify.e.Req = 0; req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY; - req.didd_notify.info.callback = didd_callback; + req.didd_notify.info.callback = (void *)didd_callback; req.didd_notify.info.context = 0; _DAdapter.request((ENTITY *) & req); if (req.didd_notify.e.Rc != 0xff) return (0); notify_handle = req.didd_notify.info.handle; } else if (DIDD_Table[x].type == IDI_DIMAINT) { /* MAINT found */ - DbgRegister("DIDD", DRIVERRELEASE, DBG_DEFAULT); + DbgRegister("DIDD", DRIVERRELEASE_DIDD, DBG_DEFAULT); } } return (dadapter); diff -Nru a/drivers/isdn/hardware/eicon/diva.c b/drivers/isdn/hardware/eicon/diva.c --- a/drivers/isdn/hardware/eicon/diva.c Thu Sep 11 23:03:13 2003 +++ b/drivers/isdn/hardware/eicon/diva.c Thu Sep 11 23:03:13 2003 @@ -1,4 +1,4 @@ -/* $Id: diva.c,v 1.1.2.5 2001/02/14 21:10:19 armin Exp $ */ +/* $Id: diva.c,v 1.17 2003/09/09 06:52:01 schindler Exp $ */ #define CARDTYPE_H_WANT_DATA 1 #define CARDTYPE_H_WANT_IDI_DATA 0 @@ -7,7 +7,6 @@ #include "platform.h" #include "debuglib.h" -#include "diva_pci.h" #include "cardtype.h" #include "dlist.h" #include "pc.h" @@ -15,19 +14,17 @@ #include "di.h" #include "io.h" #include "pc_maint.h" - #include "xdi_msg.h" #include "xdi_adapter.h" +#include "diva_pci.h" #include "diva.h" #ifdef CONFIG_ISDN_DIVAS_PRIPCI #include "os_pri.h" #endif -#ifdef CONFIG_ISDN_DIVAS_4BRIPCI -#include "os_4bri.h" -#endif #ifdef CONFIG_ISDN_DIVAS_BRIPCI #include "os_bri.h" +#include "os_4bri.h" #endif PISDN_ADAPTER IoAdapters[MAX_ADAPTER]; @@ -78,6 +75,11 @@ struct pt_regs; /* + * include queue functions + */ +#include "dlist.c" + +/* ** LOCALS */ diva_entity_queue_t adapter_queue; @@ -109,7 +111,7 @@ */ {CARDTYPE_DIVASRV_VOICE_P_30M_V2_PCI, diva_pri_init_card}, #endif -#ifdef CONFIG_ISDN_DIVAS_4BRIPCI +#ifdef CONFIG_ISDN_DIVAS_BRIPCI /* 4BRI Rev 1 Cards */ @@ -126,8 +128,6 @@ {CARDTYPE_DIVASRV_B_2M_V2_PCI, diva_4bri_init_card}, {CARDTYPE_DIVASRV_B_2F_PCI, diva_4bri_init_card}, {CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI, diva_4bri_init_card}, -#endif -#ifdef CONFIG_ISDN_DIVAS_BRIPCI /* BRI */ @@ -193,6 +193,7 @@ pdiva->controller = i + 1; pdiva->xdi_adapter.ANum = pdiva->controller; IoAdapters[i] = &pdiva->xdi_adapter; + diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card"); create_adapter_proc(pdiva); /* add adapter to proc file system */ DBG_LOG(("add %s:%d", @@ -200,6 +201,7 @@ [CardOrdinal].Name, pdiva->controller)) + diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add card"); pa = pdiva; for (j = 1; j < nr; j++) { /* slave adapters, if any */ pa = (diva_os_xdi_adapter_t *) diva_q_get_next(&pa->link); @@ -207,8 +209,11 @@ pa->controller = i + 1 + j; pa->xdi_adapter.ANum = pa->controller; IoAdapters[i + j] = &pa->xdi_adapter; + diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card"); DBG_LOG(("add slave adapter (%d)", - pa->controller)) create_adapter_proc(pa); /* add adapter to proc file system */ + pa->controller)) + create_adapter_proc(pa); /* add adapter to proc file system */ + diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add card"); } else { DBG_ERR(("slave adapter problem")) break; @@ -463,7 +468,8 @@ } } else { DBG_ERR(("A: A(%d) write error (%d)", a->controller, - length))} + length)) + } diva_os_free(0, data); @@ -564,7 +570,6 @@ Requests[31] = DivaIdiRequest31; } -/* card: 1-based card number */ void diva_xdi_display_adapter_features(int card) { dword features; diff -Nru a/drivers/isdn/hardware/eicon/diva_didd.c b/drivers/isdn/hardware/eicon/diva_didd.c --- a/drivers/isdn/hardware/eicon/diva_didd.c Thu Sep 11 23:03:13 2003 +++ b/drivers/isdn/hardware/eicon/diva_didd.c Thu Sep 11 23:03:13 2003 @@ -1,11 +1,11 @@ -/* $Id: diva_didd.c,v 1.1.2.6 2001/05/01 15:48:05 armin Exp $ +/* $Id: diva_didd.c,v 1.13 2003/08/27 10:11:21 schindler Exp $ * * DIDD Interface module for Eicon active cards. * * Functions are in dadapter.c * - * Copyright 2002 by Armin Schindler (mac@melware.de) - * Copyright 2002 Cytronics & Melware (info@melware.de) + * Copyright 2002-2003 by Armin Schindler (mac@melware.de) + * Copyright 2002-2003 Cytronics & Melware (info@melware.de) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. @@ -23,14 +23,13 @@ #include "divasync.h" #include "did_vers.h" -static char *main_revision = "$Revision: 1.1.2.6 $"; +static char *main_revision = "$Revision: 1.13 $"; static char *DRIVERNAME = "Eicon DIVA - DIDD table (http://www.melware.net)"; static char *DRIVERLNAME = "divadidd"; -char *DRIVERRELEASE = "2.0"; +char *DRIVERRELEASE_DIDD = "2.0"; -static char *dir_in_proc_net = "isdn"; static char *main_proc_dir = "eicon"; MODULE_DESCRIPTION("DIDD table driver for diva drivers"); @@ -48,12 +47,11 @@ extern void DIVA_DIDD_Read(void *, int); -static struct proc_dir_entry *proc_net_isdn; static struct proc_dir_entry *proc_didd; -struct proc_dir_entry *proc_net_isdn_eicon = NULL; +struct proc_dir_entry *proc_net_eicon = NULL; EXPORT_SYMBOL_NOVERS(DIVA_DIDD_Read); -EXPORT_SYMBOL_NOVERS(proc_net_isdn_eicon); +EXPORT_SYMBOL_NOVERS(proc_net_eicon); static char *getrev(const char *revision) { @@ -78,7 +76,7 @@ strcpy(tmprev, main_revision); len += sprintf(page + len, "%s\n", DRIVERNAME); len += sprintf(page + len, "name : %s\n", DRIVERLNAME); - len += sprintf(page + len, "release : %s\n", DRIVERRELEASE); + len += sprintf(page + len, "release : %s\n", DRIVERRELEASE_DIDD); len += sprintf(page + len, "build : %s(%s)\n", diva_didd_common_code_build, DIVA_BUILD); len += sprintf(page + len, "revision : %s\n", getrev(tmprev)); @@ -93,26 +91,12 @@ static int DIVA_INIT_FUNCTION create_proc(void) { - struct proc_dir_entry *pe; + proc_net_eicon = create_proc_entry(main_proc_dir, S_IFDIR, proc_net); - for (pe = proc_net->subdir; pe; pe = pe->next) { - if (!memcmp(dir_in_proc_net, pe->name, pe->namelen)) { - proc_net_isdn = pe; - break; - } - } - if (!proc_net_isdn) { - proc_net_isdn = - create_proc_entry(dir_in_proc_net, S_IFDIR, proc_net); - } - proc_net_isdn_eicon = - create_proc_entry(main_proc_dir, S_IFDIR, proc_net_isdn); - - if (proc_net_isdn_eicon) { - if ( - (proc_didd = + if (proc_net_eicon) { + if ((proc_didd = create_proc_entry(DRIVERLNAME, S_IFREG | S_IRUGO, - proc_net_isdn_eicon))) { + proc_net_eicon))) { proc_didd->read_proc = proc_read; } return (1); @@ -120,14 +104,10 @@ return (0); } -static void remove_proc(void) +static void DIVA_EXIT_FUNCTION remove_proc(void) { - remove_proc_entry(DRIVERLNAME, proc_net_isdn_eicon); - remove_proc_entry(main_proc_dir, proc_net_isdn); - - if ((proc_net_isdn) && (!proc_net_isdn->subdir)) { - remove_proc_entry(dir_in_proc_net, proc_net); - } + remove_proc_entry(DRIVERLNAME, proc_net_eicon); + remove_proc_entry(main_proc_dir, proc_net); } static int DIVA_INIT_FUNCTION divadidd_init(void) @@ -136,7 +116,7 @@ int ret = 0; printk(KERN_INFO "%s\n", DRIVERNAME); - printk(KERN_INFO "%s: Rel:%s Rev:", DRIVERLNAME, DRIVERRELEASE); + printk(KERN_INFO "%s: Rel:%s Rev:", DRIVERLNAME, DRIVERRELEASE_DIDD); strcpy(tmprev, main_revision); printk("%s Build:%s(%s)\n", getrev(tmprev), diva_didd_common_code_build, DIVA_BUILD); @@ -151,7 +131,9 @@ if (!diddfunc_init()) { printk(KERN_ERR "%s: failed to connect to DIDD.\n", DRIVERLNAME); +#ifdef MODULE remove_proc(); +#endif ret = -EIO; goto out; } diff -Nru a/drivers/isdn/hardware/eicon/diva_pci.h b/drivers/isdn/hardware/eicon/diva_pci.h --- a/drivers/isdn/hardware/eicon/diva_pci.h Thu Sep 11 23:03:12 2003 +++ b/drivers/isdn/hardware/eicon/diva_pci.h Thu Sep 11 23:03:12 2003 @@ -1,9 +1,12 @@ -/* $Id: diva_pci.h,v 1.1.2.2 2001/02/12 20:23:46 armin Exp $ */ +/* $Id: diva_pci.h,v 1.6 2003/01/04 15:29:45 schindler Exp $ */ #ifndef __DIVA_PCI_INTERFACE_H__ #define __DIVA_PCI_INTERFACE_H__ -void *divasa_remap_pci_bar(unsigned long bar, unsigned long area_length); +void *divasa_remap_pci_bar(diva_os_xdi_adapter_t *a, + int id, + unsigned long bar, + unsigned long area_length); void divasa_unmap_pci_bar(void *bar); unsigned long divasa_get_pci_irq(unsigned char bus, unsigned char func, void *pci_dev_handle); diff -Nru a/drivers/isdn/hardware/eicon/divacapi.h b/drivers/isdn/hardware/eicon/divacapi.h --- a/drivers/isdn/hardware/eicon/divacapi.h Thu Sep 11 23:03:12 2003 +++ b/drivers/isdn/hardware/eicon/divacapi.h Thu Sep 11 23:03:12 2003 @@ -643,7 +643,7 @@ unsigned parity:2; unsigned spare: 2; unsigned stp: 1; - unsigned ch_len:2; // 3th octett in CAI + unsigned ch_len:2; /* 3th octett in CAI */ }; diff -Nru a/drivers/isdn/hardware/eicon/divamnt.c b/drivers/isdn/hardware/eicon/divamnt.c --- a/drivers/isdn/hardware/eicon/divamnt.c Thu Sep 11 23:03:12 2003 +++ b/drivers/isdn/hardware/eicon/divamnt.c Thu Sep 11 23:03:12 2003 @@ -1,10 +1,10 @@ -/* $Id: divamnt.c,v 1.1.2.4 2001/05/01 15:48:05 armin Exp $ +/* $Id: divamnt.c,v 1.27 2003/09/09 06:46:29 schindler Exp $ * * Driver for Eicon DIVA Server ISDN cards. * Maint module * - * Copyright 2000-2002 by Armin Schindler (mac@melware.de) - * Copyright 2000-2002 Cytronics & Melware (info@melware.de) + * Copyright 2000-2003 by Armin Schindler (mac@melware.de) + * Copyright 2000-2003 Cytronics & Melware (info@melware.de) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. @@ -19,7 +19,6 @@ #include #include #include -#include #include #include "platform.h" @@ -28,16 +27,14 @@ #include "di_defs.h" #include "debug_if.h" -static char *main_revision = "$Revision: 1.1.2.4 $"; +static char *main_revision = "$Revision: 1.27 $"; -static int major = 241; +static int major; MODULE_DESCRIPTION("Maint driver for Eicon DIVA Server cards"); MODULE_AUTHOR("Cytronics & Melware, Eicon Networks"); MODULE_SUPPORTED_DEVICE("DIVA card driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(major, "i"); -MODULE_PARM_DESC(major, "Major number for /dev/DivasMAINT"); int buffer_length = 128; MODULE_PARM(buffer_length, "i"); @@ -47,7 +44,8 @@ static char *DRIVERNAME = "Eicon DIVA - MAINT module (http://www.melware.net)"; static char *DRIVERLNAME = "diva_mnt"; -char *DRIVERRELEASE = "2.0"; +static char *DEVNAME = "DivasMAINT"; +char *DRIVERRELEASE_MNT = "2.0"; static wait_queue_head_t msgwaitq; static DECLARE_MUTEX(opened_sem); @@ -77,18 +75,8 @@ } /* - * memory alloc + * buffer alloc */ -void *diva_os_malloc(unsigned long flags, unsigned long size) -{ - return (vmalloc(size)); -} -void diva_os_free(unsigned long flags, void *ptr) -{ - if (ptr) { - vfree(ptr); - } -} void *diva_os_malloc_tbuffer(unsigned long flags, unsigned long size) { return (kmalloc(size, GFP_KERNEL)); @@ -101,17 +89,6 @@ } /* - * sleep msec - */ -void diva_os_sleep(dword mSec) -{ - unsigned long timeout = HZ * mSec / 1000 + 1; - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(timeout); -} - -/* * kernel/user space copy functions */ int diva_os_copy_to_user(void *os_handle, void *dst, const void *src, @@ -158,7 +135,7 @@ * /proc entries */ -extern struct proc_dir_entry *proc_net_isdn_eicon; +extern struct proc_dir_entry *proc_net_eicon; static struct proc_dir_entry *maint_proc_entry = NULL; /* @@ -363,7 +340,7 @@ { maint_proc_entry = create_proc_entry("maint", S_IFREG | S_IRUGO | S_IWUSR, - proc_net_isdn_eicon); + proc_net_eicon); if (!maint_proc_entry) return (0); @@ -376,7 +353,7 @@ static void remove_maint_proc(void) { if (maint_proc_entry) { - remove_proc_entry("maint", proc_net_isdn_eicon); + remove_proc_entry("maint", proc_net_eicon); maint_proc_entry = NULL; } } @@ -408,20 +385,20 @@ static void divas_maint_unregister_chrdev(void) { - devfs_remove("DivasMAINT"); - unregister_chrdev(major, "DivasMAINT"); + devfs_remove(DEVNAME); + unregister_chrdev(major, DEVNAME); } static int DIVA_INIT_FUNCTION divas_maint_register_chrdev(void) { - if (register_chrdev(major, "DivasMAINT", &divas_maint_fops)) + if ((major = register_chrdev(0, DEVNAME, &divas_maint_fops)) < 0) { printk(KERN_ERR "%s: failed to create /dev entry.\n", DRIVERLNAME); return (0); } + devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, DEVNAME); - devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, "DivasMAINT"); return (1); } @@ -446,10 +423,9 @@ init_waitqueue_head(&msgwaitq); printk(KERN_INFO "%s\n", DRIVERNAME); - printk(KERN_INFO "%s: Rel:%s Rev:", DRIVERLNAME, DRIVERRELEASE); + printk(KERN_INFO "%s: Rel:%s Rev:", DRIVERLNAME, DRIVERRELEASE_MNT); strcpy(tmprev, main_revision); - printk("%s Build: %s Major: %d\n", getrev(tmprev), DIVA_BUILD, - major); + printk("%s Build: %s \n", getrev(tmprev), DIVA_BUILD); if (!divas_maint_register_chrdev()) { ret = -EIO; @@ -472,9 +448,9 @@ goto out; } - printk(KERN_INFO "%s: trace buffer = %p - %d kBytes, %s \n", - DRIVERLNAME, buffer, buffer_length, - (diva_dbg_mem == 0) ? "internal" : "external"); + printk(KERN_INFO "%s: trace buffer = %p - %d kBytes, %s (Major: %d)\n", + DRIVERLNAME, buffer, (buffer_length / 1024), + (diva_dbg_mem == 0) ? "internal" : "external", major); out: return (ret); diff -Nru a/drivers/isdn/hardware/eicon/divasfunc.c b/drivers/isdn/hardware/eicon/divasfunc.c --- a/drivers/isdn/hardware/eicon/divasfunc.c Thu Sep 11 23:03:12 2003 +++ b/drivers/isdn/hardware/eicon/divasfunc.c Thu Sep 11 23:03:12 2003 @@ -1,9 +1,9 @@ -/* $Id: divasfunc.c,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $ +/* $Id: divasfunc.c,v 1.22 2003/09/09 06:46:29 schindler Exp $ * * Low level driver for Eicon DIVA Server ISDN cards. * - * Copyright 2000-2002 by Armin Schindler (mac@melware.de) - * Copyright 2000-2002 Cytronics & Melware (info@melware.de) + * Copyright 2000-2003 by Armin Schindler (mac@melware.de) + * Copyright 2000-2003 Cytronics & Melware (info@melware.de) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. @@ -21,6 +21,8 @@ #define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR) #define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG) +static int debugmask; + extern void DIVA_DIDD_Read(void *, int); extern PISDN_ADAPTER IoAdapters[MAX_ADAPTER]; @@ -28,7 +30,7 @@ #define MAX_DESCRIPTORS 32 extern void diva_run_trap_script(PISDN_ADAPTER IoAdapter, dword ANum); -extern char *DRIVERRELEASE; +extern char *DRIVERRELEASE_DIVAS; static dword notify_handle; static DESCRIPTOR DAdapter; @@ -42,8 +44,6 @@ /* dummy debug function */ } -DIVA_DI_PRINTF dprintf = no_printf; - #include "debuglib.c" /* @@ -117,10 +117,11 @@ */ static void start_dbg(void) { - DbgRegister("DIVAS", DRIVERRELEASE, DBG_DEFAULT); + DbgRegister("DIVAS", DRIVERRELEASE_DIVAS, (debugmask) ? debugmask : DBG_DEFAULT); DBG_LOG(("DIVA ISDNXDI BUILD (%s[%s]-%s-%s)", DIVA_BUILD, diva_xdi_common_code_build, __DATE__, - __TIME__))} + __TIME__)) +} /* * stop debug @@ -174,7 +175,7 @@ req.didd_notify.e.Req = 0; req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY; - req.didd_notify.info.callback = didd_callback; + req.didd_notify.info.callback = (void *)didd_callback; req.didd_notify.info.context = 0; DAdapter.request((ENTITY *) & req); if (req.didd_notify.e.Rc != 0xff) { @@ -214,12 +215,18 @@ /* * init */ -int DIVA_INIT_FUNCTION divasfunc_init(void) +int DIVA_INIT_FUNCTION divasfunc_init(int dbgmask) { + char *version; + + debugmask = dbgmask; + if (!connect_didd()) { DBG_ERR(("divasfunc: failed to connect to DIDD.")) return (0); } + + version = diva_xdi_common_code_build; divasa_xdi_driver_entry(); diff -Nru a/drivers/isdn/hardware/eicon/divasi.c b/drivers/isdn/hardware/eicon/divasi.c --- a/drivers/isdn/hardware/eicon/divasi.c Thu Sep 11 23:03:12 2003 +++ b/drivers/isdn/hardware/eicon/divasi.c Thu Sep 11 23:03:12 2003 @@ -1,10 +1,10 @@ -/* $Id: divasi.c,v 1.1.2.7 2001/05/01 15:48:05 armin Exp $ +/* $Id: divasi.c,v 1.25 2003/09/09 06:46:29 schindler Exp $ * * Driver for Eicon DIVA Server ISDN cards. * User Mode IDI Interface * - * Copyright 2000-2002 by Armin Schindler (mac@melware.de) - * Copyright 2000-2002 Cytronics & Melware (info@melware.de) + * Copyright 2000-2003 by Armin Schindler (mac@melware.de) + * Copyright 2000-2003 Cytronics & Melware (info@melware.de) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. @@ -19,7 +19,6 @@ #include #include #include -#include #include #include "platform.h" @@ -28,27 +27,27 @@ #include "um_xdi.h" #include "um_idi.h" -static char *main_revision = "$Revision: 1.1.2.7 $"; +static char *main_revision = "$Revision: 1.25 $"; -static int major = 242; +static int major; MODULE_DESCRIPTION("User IDI Interface for Eicon ISDN cards"); MODULE_AUTHOR("Cytronics & Melware, Eicon Networks"); MODULE_SUPPORTED_DEVICE("DIVA card driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(major, "i"); -MODULE_PARM_DESC(major, "Major number for /dev/DivasIDI"); typedef struct _diva_um_idi_os_context { wait_queue_head_t read_wait; wait_queue_head_t close_wait; struct timer_list diva_timer_id; int aborted; + int adapter_nr; } diva_um_idi_os_context_t; static char *DRIVERNAME = "Eicon DIVA - User IDI (http://www.melware.net)"; static char *DRIVERLNAME = "diva_idi"; -char *DRIVERRELEASE = "2.0"; +static char *DEVNAME = "DivasIDI"; +char *DRIVERRELEASE_IDI = "2.0"; extern int idifunc_init(void); extern void idifunc_finit(void); @@ -83,32 +82,9 @@ static void diva_um_timer_function(unsigned long data); /* - * malloc - */ -void *diva_os_malloc(unsigned long flags, unsigned long size) -{ - void *ret = NULL; - - if (size) { - ret = (void *) vmalloc((unsigned int) size); - } - return (ret); -} - -/* - * free - */ -void diva_os_free(unsigned long unused, void *ptr) -{ - if (ptr) { - vfree(ptr); - } -} - -/* * proc entry */ -extern struct proc_dir_entry *proc_net_isdn_eicon; +extern struct proc_dir_entry *proc_net_eicon; static struct proc_dir_entry *um_idi_proc_entry = NULL; static int @@ -120,10 +96,11 @@ len += sprintf(page + len, "%s\n", DRIVERNAME); len += sprintf(page + len, "name : %s\n", DRIVERLNAME); - len += sprintf(page + len, "release : %s\n", DRIVERRELEASE); + len += sprintf(page + len, "release : %s\n", DRIVERRELEASE_IDI); strcpy(tmprev, main_revision); len += sprintf(page + len, "revision : %s\n", getrev(tmprev)); len += sprintf(page + len, "build : %s\n", DIVA_BUILD); + len += sprintf(page + len, "major : %d\n", major); if (off + count >= len) *eof = 1; @@ -137,7 +114,7 @@ { um_idi_proc_entry = create_proc_entry(DRIVERLNAME, S_IFREG | S_IRUGO | S_IWUSR, - proc_net_isdn_eicon); + proc_net_eicon); if (!um_idi_proc_entry) return (0); @@ -150,7 +127,7 @@ static void remove_um_idi_proc(void) { if (um_idi_proc_entry) { - remove_proc_entry(DRIVERLNAME, proc_net_isdn_eicon); + remove_proc_entry(DRIVERLNAME, proc_net_eicon); um_idi_proc_entry = NULL; } } @@ -167,20 +144,20 @@ static void divas_idi_unregister_chrdev(void) { - devfs_remove("DivasIDI"); - unregister_chrdev(major, "DivasIDI"); + devfs_remove(DEVNAME); + unregister_chrdev(major, DEVNAME); } static int DIVA_INIT_FUNCTION divas_idi_register_chrdev(void) { - if (register_chrdev(major, "DivasIDI", &divas_idi_fops)) + if ((major = register_chrdev(0, DEVNAME, &divas_idi_fops)) < 0) { printk(KERN_ERR "%s: failed to create /dev entry.\n", DRIVERLNAME); return (0); } + devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, DEVNAME); - devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, "DivasIDI"); return (1); } @@ -193,10 +170,9 @@ int ret = 0; printk(KERN_INFO "%s\n", DRIVERNAME); - printk(KERN_INFO "%s: Rel:%s Rev:", DRIVERLNAME, DRIVERRELEASE); + printk(KERN_INFO "%s: Rel:%s Rev:", DRIVERLNAME, DRIVERRELEASE_IDI); strcpy(tmprev, main_revision); - printk("%s Build: %s Major: %d\n", getrev(tmprev), DIVA_BUILD, - major); + printk("%s Build: %s\n", getrev(tmprev), DIVA_BUILD); if (!divas_idi_register_chrdev()) { ret = -EIO; @@ -219,6 +195,7 @@ ret = -EIO; goto out; } + printk(KERN_INFO "%s: started with major %d\n", DRIVERLNAME, major); out: return (ret); @@ -330,6 +307,7 @@ p_os->diva_timer_id.function = (void *) diva_um_timer_function; p_os->diva_timer_id.data = (unsigned long) p_os; p_os->aborted = 0; + p_os->adapter_nr = adapter_nr; return (1); } @@ -432,13 +410,22 @@ static int um_idi_release(struct inode *inode, struct file *file) { - unsigned int adapter_nr = iminor(inode); + diva_um_idi_os_context_t *p_os; + unsigned int adapter_nr; int ret = 0; if (!(file->private_data)) { ret = -ENODEV; goto out; } + + if (!(p_os = + (diva_um_idi_os_context_t *) diva_um_id_get_os_context(file->private_data))) { + ret = -ENODEV; + goto out; + } + + adapter_nr = p_os->adapter_nr; if ((ret = remove_entity(file->private_data))) { goto out; diff -Nru a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c --- a/drivers/isdn/hardware/eicon/divasmain.c Thu Sep 11 23:03:11 2003 +++ b/drivers/isdn/hardware/eicon/divasmain.c Thu Sep 11 23:03:11 2003 @@ -1,9 +1,9 @@ -/* $Id: divasmain.c,v 1.1.2.8 2001/05/01 15:48:05 armin Exp $ +/* $Id: divasmain.c,v 1.40 2003/09/10 08:02:33 schindler Exp $ * * Low level driver for Eicon DIVA Server ISDN cards. * - * Copyright 2000-2002 by Armin Schindler (mac@melware.de) - * Copyright 2000-2002 Cytronics & Melware (info@melware.de) + * Copyright 2000-2003 by Armin Schindler (mac@melware.de) + * Copyright 2000-2003 Cytronics & Melware (info@melware.de) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. @@ -16,14 +16,12 @@ #include #include #include -#include #include #include #include #include #include #include -#include #include #include #include @@ -37,36 +35,40 @@ #include "di_defs.h" #include "divasync.h" #include "diva.h" -#include "diva_pci.h" #include "di.h" #include "io.h" #include "xdi_msg.h" #include "xdi_adapter.h" #include "xdi_vers.h" #include "diva_dma.h" +#include "diva_pci.h" -static char *main_revision = "$Revision: 1.1.2.8 $"; +static char *main_revision = "$Revision: 1.40 $"; int errno = 0; -static int major = 240; +static int major; + +static int dbgmask; MODULE_DESCRIPTION("Kernel driver for Eicon DIVA Server cards"); MODULE_AUTHOR("Cytronics & Melware, Eicon Networks"); MODULE_LICENSE("GPL"); -MODULE_PARM(major, "i"); -MODULE_PARM_DESC(major, "Major number for /dev/Divas"); + +MODULE_PARM(dbgmask, "i"); +MODULE_PARM_DESC(dbgmask, "initial debug mask"); static char *DRIVERNAME = "Eicon DIVA Server driver (http://www.melware.net)"; static char *DRIVERLNAME = "divas"; -char *DRIVERRELEASE = "2.0"; +static char *DEVNAME = "Divas"; +char *DRIVERRELEASE_DIVAS = "2.0"; extern irqreturn_t diva_os_irq_wrapper(int irq, void *context, struct pt_regs *regs); extern int create_divas_proc(void); extern void remove_divas_proc(void); extern void diva_get_vserial_number(PISDN_ADAPTER IoAdapter, char *buf); -extern int divasfunc_init(void); +extern int divasfunc_init(int dbgmask); extern void divasfunc_exit(void); typedef struct _diva_os_thread_dpc { @@ -185,19 +187,6 @@ return rev; } -void diva_os_sleep(dword mSec) -{ - unsigned long timeout = HZ * mSec / 1000 + 1; - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(timeout); -} - -void diva_os_wait(dword mSec) -{ - mdelay(mSec); -} - void diva_log_info(unsigned char *format, ...) { va_list args; @@ -215,29 +204,8 @@ char tmprev[32]; strcpy(tmprev, main_revision); - sprintf(p, "%s: %s(%s) %s(%s)\n", DRIVERLNAME, DRIVERRELEASE, - getrev(tmprev), diva_xdi_common_code_build, DIVA_BUILD); -} - -/********************************************************* - ** malloc / free - *********************************************************/ - -void *diva_os_malloc(unsigned long flags, unsigned long size) -{ - void *ret = NULL; - - if (size) { - ret = (void *) vmalloc((unsigned int) size); - } - return (ret); -} - -void diva_os_free(unsigned long unused, void *ptr) -{ - if (ptr) { - vfree(ptr); - } + sprintf(p, "%s: %s(%s) %s(%s) major=%d\n", DRIVERLNAME, DRIVERRELEASE_DIVAS, + getrev(tmprev), diva_xdi_common_code_build, DIVA_BUILD, major); } /* -------------------------------------------------------------------------- @@ -282,6 +250,7 @@ (diva_os_thread_dpc_t *) psoft_isr->object; if (context && !context->card_failed) { + printk(KERN_ERR "%s: adapter %d trapped !\n", DRIVERLNAME, ANum + 1); context->card_failed = ANum + 1; schedule_work(&context->trap_script_task); } @@ -505,8 +474,8 @@ *********************************************************/ int -diva_os_register_io_port(int on, unsigned long port, unsigned long length, - const char *name) +diva_os_register_io_port(void *adapter, int on, unsigned long port, + unsigned long length, const char *name, int id) { if (on) { if (!request_region(port, length, name)) { @@ -519,7 +488,7 @@ return (0); } -void *divasa_remap_pci_bar(unsigned long bar, unsigned long area_length) +void *divasa_remap_pci_bar(diva_os_xdi_adapter_t *a, int id, unsigned long bar, unsigned long area_length) { void *ret; @@ -772,20 +741,20 @@ static void divas_unregister_chrdev(void) { - devfs_remove("Divas"); - unregister_chrdev(major, "Divas"); + devfs_remove(DEVNAME); + unregister_chrdev(major, DEVNAME); } static int DIVA_INIT_FUNCTION divas_register_chrdev(void) { - if (register_chrdev(major, "Divas", &divas_fops)) + if ((major = register_chrdev(0, DEVNAME, &divas_fops)) < 0) { printk(KERN_ERR "%s: failed to create /dev entry.\n", DRIVERLNAME); return (0); } + devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, DEVNAME); - devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, "Divas"); return (1); } @@ -877,23 +846,20 @@ int ret = 0; printk(KERN_INFO "%s\n", DRIVERNAME); - printk(KERN_INFO "%s: Rel:%s Rev:", DRIVERLNAME, DRIVERRELEASE); + printk(KERN_INFO "%s: Rel:%s Rev:", DRIVERLNAME, DRIVERRELEASE_DIVAS); strcpy(tmprev, main_revision); - printk("%s Build: %s(%s) Major: %d\n", getrev(tmprev), - diva_xdi_common_code_build, DIVA_BUILD, major); + printk("%s Build: %s(%s)\n", getrev(tmprev), + diva_xdi_common_code_build, DIVA_BUILD); printk(KERN_INFO "%s: support for: ", DRIVERLNAME); #ifdef CONFIG_ISDN_DIVAS_BRIPCI printk("BRI/PCI "); #endif -#ifdef CONFIG_ISDN_DIVAS_4BRIPCI - printk("4BRI/PCI "); -#endif #ifdef CONFIG_ISDN_DIVAS_PRIPCI printk("PRI/PCI "); #endif - printk("\n"); + printk("adapters\n"); - if (!divasfunc_init()) { + if (!divasfunc_init(dbgmask)) { printk(KERN_ERR "%s: failed to connect to DIDD.\n", DRIVERLNAME); ret = -EIO; @@ -901,15 +867,19 @@ } if (!divas_register_chrdev()) { +#ifdef MODULE divasfunc_exit(); +#endif ret = -EIO; goto out; } if (!create_divas_proc()) { +#ifdef MODULE remove_divas_proc(); divas_unregister_chrdev(); divasfunc_exit(); +#endif printk(KERN_ERR "%s: failed to create proc entry.\n", DRIVERLNAME); ret = -EIO; @@ -917,13 +887,16 @@ } if ((ret = pci_module_init(&diva_pci_driver))) { +#ifdef MODULE remove_divas_proc(); divas_unregister_chrdev(); divasfunc_exit(); +#endif printk(KERN_ERR "%s: failed to init pci driver.\n", DRIVERLNAME); goto out; } + printk(KERN_INFO "%s: started with major %d\n", DRIVERLNAME, major); out: return (ret); diff -Nru a/drivers/isdn/hardware/eicon/divasproc.c b/drivers/isdn/hardware/eicon/divasproc.c --- a/drivers/isdn/hardware/eicon/divasproc.c Thu Sep 11 23:03:13 2003 +++ b/drivers/isdn/hardware/eicon/divasproc.c Thu Sep 11 23:03:13 2003 @@ -1,10 +1,10 @@ -/* $Id: divasproc.c,v 1.1.2.4 2001/02/16 08:40:36 armin Exp $ +/* $Id: divasproc.c,v 1.18 2003/09/09 06:46:29 schindler Exp $ * * Low level driver for Eicon DIVA Server ISDN cards. * /proc functions * - * Copyright 2000-2002 by Armin Schindler (mac@melware.de) - * Copyright 2000-2002 Cytronics & Melware (info@melware.de) + * Copyright 2000-2003 by Armin Schindler (mac@melware.de) + * Copyright 2000-2003 Cytronics & Melware (info@melware.de) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. @@ -15,7 +15,6 @@ #include #include #include -#include #include "platform.h" #include "debuglib.h" @@ -23,7 +22,6 @@ #undef ID_MASK #undef N_DATA #include "pc.h" -#include "diva_pci.h" #include "di_defs.h" #include "divasync.h" #include "di.h" @@ -31,6 +29,7 @@ #include "xdi_msg.h" #include "xdi_adapter.h" #include "diva.h" +#include "diva_pci.h" extern PISDN_ADAPTER IoAdapters[MAX_ADAPTER]; @@ -52,7 +51,7 @@ ** "divas" entry */ -extern struct proc_dir_entry *proc_net_isdn_eicon; +extern struct proc_dir_entry *proc_net_eicon; static struct proc_dir_entry *divas_proc_entry = NULL; static ssize_t @@ -131,7 +130,7 @@ { divas_proc_entry = create_proc_entry(divas_proc_name, S_IFREG | S_IRUGO, - proc_net_isdn_eicon); + proc_net_eicon); if (!divas_proc_entry) return (0); @@ -144,7 +143,7 @@ void remove_divas_proc(void) { if (divas_proc_entry) { - remove_proc_entry(divas_proc_name, proc_net_isdn_eicon); + remove_proc_entry(divas_proc_name, proc_net_eicon); divas_proc_entry = NULL; } } @@ -333,7 +332,8 @@ } } if ((!a->xdi_adapter.port) && - ((!a->xdi_adapter.ram) || (!a->xdi_adapter.reset) + ((!a->xdi_adapter.ram) || + (!a->xdi_adapter.reset) || (!a->xdi_adapter.cfg))) { if (!IoAdapter->irq_info.irq_nr) { p = "slave"; @@ -369,20 +369,14 @@ struct proc_dir_entry *de, *pe; char tmp[16]; - if (in_interrupt()) { - printk(KERN_ERR - "divasproc: create_proc in_interrupt, not creating\n"); - return (1); - } - sprintf(tmp, "%s%d", adapter_dir_name, a->controller); - if (!(de = create_proc_entry(tmp, S_IFDIR, proc_net_isdn_eicon))) + if (!(de = create_proc_entry(tmp, S_IFDIR, proc_net_eicon))) return (0); a->proc_adapter_dir = (void *) de; if (!(pe = - create_proc_entry(info_proc_name, S_IFREG | S_IRUGO | S_IWUSR, - de))) return (0); + create_proc_entry(info_proc_name, S_IFREG | S_IRUGO | S_IWUSR, de))) + return (0); a->proc_info = (void *) pe; pe->write_proc = info_write; pe->read_proc = info_read; @@ -429,7 +423,7 @@ (struct proc_dir_entry *) a->proc_adapter_dir); } sprintf(tmp, "%s%d", adapter_dir_name, a->controller); - remove_proc_entry(tmp, proc_net_isdn_eicon); + remove_proc_entry(tmp, proc_net_eicon); DBG_TRC(("proc entry %s%d removed", adapter_dir_name, a->controller)); } diff -Nru a/drivers/isdn/hardware/eicon/dlist.c b/drivers/isdn/hardware/eicon/dlist.c --- a/drivers/isdn/hardware/eicon/dlist.c Thu Sep 11 23:03:11 2003 +++ b/drivers/isdn/hardware/eicon/dlist.c Thu Sep 11 23:03:11 2003 @@ -1,4 +1,4 @@ -/* $Id: dlist.c,v 1.1.2.2 2001/02/11 14:40:41 armin Exp $ */ +/* $Id: dlist.c,v 1.6 2003/08/25 16:03:35 schindler Exp $ */ #include "platform.h" #include "dlist.h" @@ -7,7 +7,7 @@ ** Initialize linked list */ -void diva_q_init(diva_entity_queue_t * q) +static void diva_q_init(diva_entity_queue_t * q) { memset(q, 0x00, sizeof(*q)); } @@ -15,7 +15,7 @@ /* ** Remove element from linked list */ -void diva_q_remove(diva_entity_queue_t * q, diva_entity_link_t * what) +static void diva_q_remove(diva_entity_queue_t * q, diva_entity_link_t * what) { if (!what->prev) { if ((q->head = what->next)) { @@ -36,7 +36,7 @@ /* ** Add element to the tail of linked list */ -void diva_q_add_tail(diva_entity_queue_t * q, diva_entity_link_t * what) +static void diva_q_add_tail(diva_entity_queue_t * q, diva_entity_link_t * what) { what->next = 0; if (!q->head) { @@ -49,7 +49,7 @@ } } -diva_entity_link_t *diva_q_find(const diva_entity_queue_t * q, +static diva_entity_link_t *diva_q_find(const diva_entity_queue_t * q, const void *what, diva_q_cmp_fn_t cmp_fn) { diva_entity_link_t *diva_current = q->head; @@ -64,35 +64,13 @@ return (diva_current); } -diva_entity_link_t *diva_q_get_head(diva_entity_queue_t * q) +static diva_entity_link_t *diva_q_get_head(diva_entity_queue_t * q) { return (q->head); } -diva_entity_link_t *diva_q_get_tail(diva_entity_queue_t * q) -{ - return (q->tail); -} - -diva_entity_link_t *diva_q_get_next(diva_entity_link_t * what) +static diva_entity_link_t *diva_q_get_next(diva_entity_link_t * what) { return ((what) ? what->next : 0); } -diva_entity_link_t *diva_q_get_prev(diva_entity_link_t * what) -{ - return ((what) ? what->prev : 0); -} - -int diva_q_get_nr_of_entries(const diva_entity_queue_t * q) -{ - int i = 0; - const diva_entity_link_t *diva_current = q->head; - - while (diva_current) { - i++; - diva_current = diva_current->next; - } - - return (i); -} diff -Nru a/drivers/isdn/hardware/eicon/dlist.h b/drivers/isdn/hardware/eicon/dlist.h --- a/drivers/isdn/hardware/eicon/dlist.h Thu Sep 11 23:03:14 2003 +++ b/drivers/isdn/hardware/eicon/dlist.h Thu Sep 11 23:03:14 2003 @@ -1,4 +1,4 @@ -/* $Id: dlist.h,v 1.1.2.2 2001/02/08 12:25:43 armin Exp $ */ +/* $Id: dlist.h,v 1.5 2003/08/25 16:03:35 schindler Exp $ */ #ifndef __DIVA_LINK_H__ #define __DIVA_LINK_H__ @@ -16,17 +16,5 @@ typedef int (*diva_q_cmp_fn_t) (const void *what, const diva_entity_link_t *); - -void diva_q_remove(diva_entity_queue_t * q, diva_entity_link_t * what); -void diva_q_add_tail(diva_entity_queue_t * q, diva_entity_link_t * what); -diva_entity_link_t *diva_q_find(const diva_entity_queue_t * q, - const void *what, diva_q_cmp_fn_t cmp_fn); - -diva_entity_link_t *diva_q_get_head(diva_entity_queue_t * q); -diva_entity_link_t *diva_q_get_tail(diva_entity_queue_t * q); -diva_entity_link_t *diva_q_get_next(diva_entity_link_t * what); -diva_entity_link_t *diva_q_get_prev(diva_entity_link_t * what); -int diva_q_get_nr_of_entries(const diva_entity_queue_t * q); -void diva_q_init(diva_entity_queue_t * q); #endif diff -Nru a/drivers/isdn/hardware/eicon/idifunc.c b/drivers/isdn/hardware/eicon/idifunc.c --- a/drivers/isdn/hardware/eicon/idifunc.c Thu Sep 11 23:03:14 2003 +++ b/drivers/isdn/hardware/eicon/idifunc.c Thu Sep 11 23:03:14 2003 @@ -1,10 +1,10 @@ -/* $Id: idifunc.c,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $ +/* $Id: idifunc.c,v 1.13 2003/08/25 14:49:53 schindler Exp $ * * Driver for Eicon DIVA Server ISDN cards. * User Mode IDI Interface * - * Copyright 2000-2002 by Armin Schindler (mac@melware.de) - * Copyright 2000-2002 Cytronics & Melware (info@melware.de) + * Copyright 2000-2003 by Armin Schindler (mac@melware.de) + * Copyright 2000-2003 Cytronics & Melware (info@melware.de) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. @@ -19,7 +19,7 @@ #define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR) #define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG) -extern char *DRIVERRELEASE; +extern char *DRIVERRELEASE_IDI; extern void DIVA_DIDD_Read(void *, int); extern int diva_user_mode_idi_create_adapter(const DESCRIPTOR *, int); @@ -36,8 +36,6 @@ /* dummy debug function */ } -DIVA_DI_PRINTF dprintf = no_printf; - #include "debuglib.c" /* @@ -202,7 +200,7 @@ } else { memcpy(&MAdapter, adapter, sizeof(MAdapter)); dprintf = (DIVA_DI_PRINTF) MAdapter.request; - DbgRegister("User IDI", DRIVERRELEASE, DBG_DEFAULT); + DbgRegister("User IDI", DRIVERRELEASE_IDI, DBG_DEFAULT); } } else if ((adapter->type > 0) && (adapter->type < 16)) { /* IDI Adapter */ if (removal) { @@ -233,7 +231,7 @@ req.didd_notify.e.Req = 0; req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY; - req.didd_notify.info.callback = didd_callback; + req.didd_notify.info.callback = (void *)didd_callback; req.didd_notify.info.context = 0; DAdapter.request((ENTITY *) & req); if (req.didd_notify.e.Rc != 0xff) { @@ -244,7 +242,7 @@ } else if (DIDD_Table[x].type == IDI_DIMAINT) { /* MAINT found */ memcpy(&MAdapter, &DIDD_Table[x], sizeof(DAdapter)); dprintf = (DIVA_DI_PRINTF) MAdapter.request; - DbgRegister("User IDI", DRIVERRELEASE, DBG_DEFAULT); + DbgRegister("User IDI", DRIVERRELEASE_IDI, DBG_DEFAULT); } else if ((DIDD_Table[x].type > 0) && (DIDD_Table[x].type < 16)) { /* IDI Adapter found */ um_new_card(&DIDD_Table[x]); diff -Nru a/drivers/isdn/hardware/eicon/io.c b/drivers/isdn/hardware/eicon/io.c --- a/drivers/isdn/hardware/eicon/io.c Thu Sep 11 23:03:11 2003 +++ b/drivers/isdn/hardware/eicon/io.c Thu Sep 11 23:03:11 2003 @@ -72,10 +72,10 @@ */ static byte extended_xdi_features[DIVA_XDI_EXTENDED_FEATURES_MAX_SZ+1] = { (DIVA_XDI_EXTENDED_FEATURES_VALID | - DIVA_XDI_EXTENDED_FEATURE_CMA | DIVA_XDI_EXTENDED_FEATURE_SDRAM_BAR | DIVA_XDI_EXTENDED_FEATURE_CAPI_PRMS | #if defined(DIVA_IDI_RX_DMA) + DIVA_XDI_EXTENDED_FEATURE_CMA | DIVA_XDI_EXTENDED_FEATURE_RX_DMA | #endif DIVA_XDI_EXTENDED_FEATURE_NO_CANCEL_RC), @@ -156,7 +156,8 @@ dump_trap_frame (PISDN_ADAPTER IoAdapter, byte *exceptionFrame) { MP_XCPTC *xcept = (MP_XCPTC *)exceptionFrame ; - dword *regs = &xcept->regs[0] ; + dword *regs; + regs = &xcept->regs[0] ; DBG_FTL(("%s: ***************** CPU TRAPPED *****************", &IoAdapter->Name[0])) DBG_FTL(("Microcode: %s", &IoAdapter->ProtocolIdString[0])) @@ -567,26 +568,38 @@ /*------------------------------------------------------------------*/ byte mem_in (ADAPTER *a, void *addr) { - byte* Base = (byte*)&((PISDN_ADAPTER)a->io)->ram[(unsigned long)addr] ; - return (*Base) ; + byte val; + volatile byte* Base; + + Base = (volatile byte *)DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); + val = *(Base + (unsigned long)addr); + DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base); + return (val); } word mem_inw (ADAPTER *a, void *addr) { - word* Base = (word*)&((PISDN_ADAPTER)a->io)->ram[(unsigned long)addr] ; - return (READ_WORD(Base)) ; + word val; + volatile byte* Base; + + Base = (volatile byte*)DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); + val = READ_WORD((Base + (unsigned long)addr)); + DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base); + return (val); } void mem_in_dw (ADAPTER *a, void *addr, dword* data, int dwords) { - volatile dword* Base = (dword*)&((PISDN_ADAPTER)a->io)->ram[(unsigned long)addr] ; + volatile byte* Base = (volatile byte*)DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); while (dwords--) { - *data++ = READ_DWORD(Base); - Base++; + *data++ = READ_DWORD((Base + (unsigned long)addr)); + addr+=4; } + DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base); } void mem_in_buffer (ADAPTER *a, void *addr, void *buffer, word length) { - byte* Base = (byte*)&((PISDN_ADAPTER)a->io)->ram[(unsigned long)addr] ; - memcpy (buffer, Base, length) ; + volatile byte* Base = (volatile byte*)DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); + memcpy (buffer, (void *)(Base + (unsigned long)addr), length); + DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base); } void mem_look_ahead (ADAPTER *a, PBUFFER *RBuffer, ENTITY *e) { @@ -598,99 +611,130 @@ } void mem_out (ADAPTER *a, void *addr, byte data) { - byte* Base = (byte*)&((PISDN_ADAPTER)a->io)->ram[(unsigned long)addr] ; - *Base = data ; + volatile byte* Base = (volatile byte*)DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); + *(Base + (unsigned long)addr) = data ; + DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base); } void mem_outw (ADAPTER *a, void *addr, word data) { - word* Base = (word*)&((PISDN_ADAPTER)a->io)->ram[(unsigned long)addr] ; - WRITE_WORD(Base, data); + volatile byte* Base = (volatile byte*)DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); + WRITE_WORD((Base + (unsigned long)addr), data); + DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base); } void mem_out_dw (ADAPTER *a, void *addr, const dword* data, int dwords) { - volatile dword* Base = (dword*)&((PISDN_ADAPTER)a->io)->ram[(unsigned long)addr] ; + volatile byte* Base = (volatile byte*)DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); while (dwords--) { - WRITE_DWORD(Base, *data); - Base++; + WRITE_DWORD((Base + (unsigned long)addr), *data); + addr+=4; data++; } + DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base); } void mem_out_buffer (ADAPTER *a, void *addr, void *buffer, word length) { - byte* Base = (byte*)&((PISDN_ADAPTER)a->io)->ram[(unsigned long)addr] ; - memcpy (Base, buffer, length) ; + volatile byte* Base = (volatile byte*)DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); + memcpy ((void *)(Base + (unsigned long)addr), buffer, length) ; + DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base); } void mem_inc (ADAPTER *a, void *addr) { - byte* Base = (byte*)&((PISDN_ADAPTER)a->io)->ram[(unsigned long)addr] ; - byte x = *Base ; - *Base = x + 1 ; + volatile byte* Base = (volatile byte*)DIVA_OS_MEM_ATTACH_RAM((PISDN_ADAPTER)a->io); + byte x = *(Base + (unsigned long)addr); + *(Base + (unsigned long)addr) = x + 1 ; + DIVA_OS_MEM_DETACH_RAM((PISDN_ADAPTER)a->io, Base); } /*------------------------------------------------------------------*/ /* ram access functions for io-mapped cards */ /*------------------------------------------------------------------*/ byte io_in(ADAPTER * a, void * adr) { - outppw(((PISDN_ADAPTER)a->io)->port+4, (word)(unsigned long)adr); - return inpp(((PISDN_ADAPTER)a->io)->port); + byte val; + byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); + outppw(Port + 4, (word)(unsigned long)adr); + val = inpp(Port); + DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port); + return(val); } word io_inw(ADAPTER * a, void * adr) { - outppw(((PISDN_ADAPTER)a->io)->port+4, (word)(unsigned long)adr); - return inppw(((PISDN_ADAPTER)a->io)->port); + word val; + byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); + outppw(Port + 4, (word)(unsigned long)adr); + val = inppw(Port); + DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port); + return(val); } void io_in_buffer(ADAPTER * a, void * adr, void * buffer, word len) { + byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); byte* P = (byte*)buffer; if ((long)adr & 1) { - outppw(((PISDN_ADAPTER)a->io)->port+4, (word)(unsigned long)adr); - *P = inpp(((PISDN_ADAPTER)a->io)->port); + outppw(Port+4, (word)(unsigned long)adr); + *P = inpp(Port); P++; adr = ((byte *) adr) + 1; len--; - if (!len) return; + if (!len) { + DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port); + return; } - outppw(((PISDN_ADAPTER)a->io)->port+4, (word)(unsigned long)adr); - inppw_buffer (((PISDN_ADAPTER)a->io)->port, P, len+1); + } + outppw(Port+4, (word)(unsigned long)adr); + inppw_buffer (Port, P, len+1); + DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port); } void io_look_ahead(ADAPTER * a, PBUFFER * RBuffer, ENTITY * e) { - outppw(((PISDN_ADAPTER)a->io)->port+4, (word)(unsigned long)RBuffer); - ((PISDN_ADAPTER)a->io)->RBuffer.length = inppw(((PISDN_ADAPTER)a->io)->port); - inppw_buffer (((PISDN_ADAPTER)a->io)->port, ((PISDN_ADAPTER)a->io)->RBuffer.P, ((PISDN_ADAPTER)a->io)->RBuffer.length + 1); + byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); + outppw(Port+4, (word)(unsigned long)RBuffer); + ((PISDN_ADAPTER)a->io)->RBuffer.length = inppw(Port); + inppw_buffer (Port, ((PISDN_ADAPTER)a->io)->RBuffer.P, ((PISDN_ADAPTER)a->io)->RBuffer.length + 1); e->RBuffer = (DBUFFER *) &(((PISDN_ADAPTER)a->io)->RBuffer); + DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port); } void io_out(ADAPTER * a, void * adr, byte data) { - outppw(((PISDN_ADAPTER)a->io)->port+4, (word)(unsigned long)adr); - outpp(((PISDN_ADAPTER)a->io)->port, data); + byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); + outppw(Port+4, (word)(unsigned long)adr); + outpp(Port, data); + DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port); } void io_outw(ADAPTER * a, void * adr, word data) { - outppw(((PISDN_ADAPTER)a->io)->port+4, (word)(unsigned long)adr); - outppw(((PISDN_ADAPTER)a->io)->port, data); + byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); + outppw(Port+4, (word)(unsigned long)adr); + outppw(Port, data); + DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port); } void io_out_buffer(ADAPTER * a, void * adr, void * buffer, word len) { + byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); byte* P = (byte*)buffer; if ((long)adr & 1) { - outppw(((PISDN_ADAPTER)a->io)->port+4, (word)(unsigned long)adr); - outpp(((PISDN_ADAPTER)a->io)->port, *P); + outppw(Port+4, (word)(unsigned long)adr); + outpp(Port, *P); P++; adr = ((byte *) adr) + 1; len--; - if (!len) return; + if (!len) { + DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port); + return; + } } - outppw(((PISDN_ADAPTER)a->io)->port+4, (word)(unsigned long)adr); - outppw_buffer (((PISDN_ADAPTER)a->io)->port, P, len+1); + outppw(Port+4, (word)(unsigned long)adr); + outppw_buffer (Port, P, len+1); + DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port); } void io_inc(ADAPTER * a, void * adr) { byte x; - outppw(((PISDN_ADAPTER)a->io)->port+4, (word)(unsigned long)adr); - x = inpp(((PISDN_ADAPTER)a->io)->port); - outppw(((PISDN_ADAPTER)a->io)->port+4, (word)(unsigned long)adr); - outpp(((PISDN_ADAPTER)a->io)->port, x+1); + byte *Port = (byte*)DIVA_OS_MEM_ATTACH_PORT((PISDN_ADAPTER)a->io); + outppw(Port+4, (word)(unsigned long)adr); + x = inpp(Port); + outppw(Port+4, (word)(unsigned long)adr); + outpp(Port, x+1); + DIVA_OS_MEM_DETACH_PORT((PISDN_ADAPTER)a->io, Port); } /*------------------------------------------------------------------*/ /* OS specific functions related to queuing of entities */ diff -Nru a/drivers/isdn/hardware/eicon/io.h b/drivers/isdn/hardware/eicon/io.h --- a/drivers/isdn/hardware/eicon/io.h Thu Sep 11 23:03:14 2003 +++ b/drivers/isdn/hardware/eicon/io.h Thu Sep 11 23:03:14 2003 @@ -40,14 +40,6 @@ PISDN_ADAPTER QuadroAdapter[4] ; } ADAPTER_LIST_ENTRY, *PADAPTER_LIST_ENTRY ; /* -------------------------------------------------------------------------- - Special OS memory support structures - -------------------------------------------------------------------------- */ -#define MAX_MAPPED_ENTRIES 8 -typedef struct { - void * Address; - dword Length; -} ADAPTER_MEMORY ; -/* -------------------------------------------------------------------------- Configuration of XDI clients carried by XDI -------------------------------------------------------------------------- */ #define DIVA_XDI_CAPI_CFG_1_DYNAMIC_L1_ON 0x01 @@ -71,7 +63,6 @@ /* remember mapped memory areas */ - ADAPTER_MEMORY MappedMemory[MAX_MAPPED_ENTRIES] ; CARD_PROPERTIES Properties ; dword cardType ; dword protocol_id ; /* configured protocol identifier */ @@ -97,6 +88,8 @@ dword MemoryBase ; dword MemorySize ; byte *Address ; + byte *Config ; + byte *Control ; byte *reset ; byte *port ; byte *ram ; diff -Nru a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c --- a/drivers/isdn/hardware/eicon/message.c Thu Sep 11 23:03:13 2003 +++ b/drivers/isdn/hardware/eicon/message.c Thu Sep 11 23:03:13 2003 @@ -3590,7 +3590,7 @@ { if (plci->channels) { - for (ncci = 1; ncci < MAX_NCCI+1; i++) + for (ncci = 1; ncci < MAX_NCCI+1; ncci++) { if ((a->ncci_plci[ncci] == plci->Id) && (a->ncci_state[ncci] == CONNECTED)) { @@ -6612,7 +6612,7 @@ ||(*data == DSP_UDATA_INDICATION_CTS_ON)) ) { word conn_opt, ncpi_opt = 0x00; -// HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); +/* HexDump ("MDM N_UDATA:", plci->NL.RBuffer->length, data); */ if (*data == DSP_UDATA_INDICATION_DCD_ON) plci->ncpi_state |= NCPI_MDM_DCD_ON_RECEIVED; @@ -7813,15 +7813,15 @@ } } - if(READ_WORD(bp_parms[0].info)==2 || // V.110 async - READ_WORD(bp_parms[0].info)==3 ) // V.110 sync + if(READ_WORD(bp_parms[0].info)==2 || /* V.110 async */ + READ_WORD(bp_parms[0].info)==3 ) /* V.110 sync */ { if(bp_parms[3].length){ dbug(1,dprintf("V.110,%d",READ_WORD(&bp_parms[3].info[1]))); - switch(READ_WORD(&bp_parms[3].info[1])){ // Rate + switch(READ_WORD(&bp_parms[3].info[1])){ /* Rate */ case 0: case 56000: - if(READ_WORD(bp_parms[0].info)==3){ //V.110 sync 56k + if(READ_WORD(bp_parms[0].info)==3){ /* V.110 sync 56k */ dbug(1,dprintf("56k sync HSCX")); cai[1] = 8; cai[2] = 0; @@ -7859,7 +7859,7 @@ return _B1_PARM_NOT_SUPPORTED; } cai[3] = 0; - if (cai[1] == 13) // v.110 async + if (cai[1] == 13) /* v.110 async */ { if (bp_parms[3].length >= 8) { @@ -7906,7 +7906,7 @@ } WRITE_WORD(&cai[5],plci->appl->MaxDataLength); dbug(1,dprintf("CAI[%d]=%x,%x,%x,%x,%x,%x", cai[0], cai[1], cai[2], cai[3], cai[4], cai[5], cai[6])); -//HexDump ("CAI", sizeof(cai), &cai[0]); +/* HexDump ("CAI", sizeof(cai), &cai[0]); */ add_p(plci, CAI, cai); return 0; @@ -8681,7 +8681,7 @@ DLC_MODEMPROT_DISABLE_COMPRESSION; } dlc[0] = (byte)(i - 1); -//HexDump ("DLC", sizeof(dlc), &dlc[0]); +/* HexDump ("DLC", sizeof(dlc), &dlc[0]); */ add_p(plci, DLC, dlc); return (0); } @@ -8739,7 +8739,7 @@ { ENTITY * e; word l; -// word i; +/* word i; */ if(!plci) return; if(plci->adapter->adapter_disabled) return; @@ -8856,7 +8856,7 @@ } else if (plci->send_disc == ncci) { - //dprintf("N_DISC"); + /* dprintf("N_DISC"); */ plci->NData[0].PLength = 0; plci->NL.ReqCh = a->ncci_ch[ncci]; plci->NL.Req = plci->nl_req = N_DISC; @@ -9059,15 +9059,15 @@ for(k=0;k<=flen;k++,j++) { facility[j]=fty_i[i][k]; -// dbug(1,dprintf("%x ",facility[j])); +/* dbug(1,dprintf("%x ",facility[j])); */ } } facility[0] = len; add_i[3] = facility; } -// dbug(1,dprintf("FacArrLen=%d ",len)); +/* dbug(1,dprintf("FacArrLen=%d ",len)); */ len = add_i[0][0]+add_i[1][0]+add_i[2][0]+add_i[3][0]; - len += 4; // calculate length of all + len += 4; /* calculate length of all */ return(len); } @@ -9083,8 +9083,8 @@ channel = chi[chi[0]]&0x3; dbug(1,dprintf("ExtDevON(Ch=0x%x)",channel)); voice_chi[2] = (channel) ? channel : 1; - add_p(plci,FTY,"\x02\x01\x07"); // B On, default on 1 - add_p(plci,ESC,voice_chi); // Channel + add_p(plci,FTY,"\x02\x01\x07"); /* B On, default on 1 */ + add_p(plci,ESC,voice_chi); /* Channel */ sig_req(plci,TEL_CTRL,0); send_req(plci); if(a->AdvSignalPLCI) @@ -9096,7 +9096,7 @@ void VoiceChannelOff(PLCI *plci) { dbug(1,dprintf("ExtDevOFF")); - add_p(plci,FTY,"\x02\x01\x08"); // B Off + add_p(plci,FTY,"\x02\x01\x08"); /* B Off */ sig_req(plci,TEL_CTRL,0); send_req(plci); if(plci->adapter->AdvSignalPLCI) diff -Nru a/drivers/isdn/hardware/eicon/mntfunc.c b/drivers/isdn/hardware/eicon/mntfunc.c --- a/drivers/isdn/hardware/eicon/mntfunc.c Thu Sep 11 23:03:11 2003 +++ b/drivers/isdn/hardware/eicon/mntfunc.c Thu Sep 11 23:03:11 2003 @@ -1,10 +1,10 @@ -/* $Id: mntfunc.c,v 1.1.2.2 2002/10/02 14:38:37 armin Exp $ +/* $Id: mntfunc.c,v 1.15 2003/08/25 14:49:53 schindler Exp $ * * Driver for Eicon DIVA Server ISDN cards. * Maint module * - * Copyright 2000,2001 by Armin Schindler (mac@melware.de) - * Copyright 2000,2001 Cytronics & Melware (info@melware.de) + * Copyright 2000-2003 by Armin Schindler (mac@melware.de) + * Copyright 2000-2003 Cytronics & Melware (info@melware.de) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. @@ -17,7 +17,7 @@ #include "di_defs.h" #include "debug_if.h" -extern char *DRIVERRELEASE; +extern char *DRIVERRELEASE_MNT; #define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR) #define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG) @@ -45,8 +45,6 @@ /* dummy debug function */ } -DIVA_DI_PRINTF dprintf = no_printf; - #include "debuglib.c" /* @@ -73,7 +71,7 @@ } else { memcpy(&MAdapter, adapter, sizeof(MAdapter)); dprintf = (DIVA_DI_PRINTF) MAdapter.request; - DbgRegister("MAINT", DRIVERRELEASE, DBG_DEFAULT); + DbgRegister("MAINT", DRIVERRELEASE_MNT, DBG_DEFAULT); } } else if ((adapter->type > 0) && (adapter->type < 16)) { if (removal) { @@ -104,7 +102,7 @@ req.didd_notify.e.Req = 0; req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY; - req.didd_notify.info.callback = didd_callback; + req.didd_notify.info.callback = (void *)didd_callback; req.didd_notify.info.context = 0; DAdapter.request((ENTITY *) & req); if (req.didd_notify.e.Rc != 0xff) diff -Nru a/drivers/isdn/hardware/eicon/os_4bri.c b/drivers/isdn/hardware/eicon/os_4bri.c --- a/drivers/isdn/hardware/eicon/os_4bri.c Thu Sep 11 23:03:12 2003 +++ b/drivers/isdn/hardware/eicon/os_4bri.c Thu Sep 11 23:03:12 2003 @@ -1,4 +1,4 @@ -/* $Id: os_4bri.c,v 1.1.2.3 2001/02/14 21:10:19 armin Exp $ */ +/* $Id: os_4bri.c,v 1.25 2003/06/21 17:08:44 schindler Exp $ */ #include "platform.h" #include "debuglib.h" @@ -99,6 +99,40 @@ return (0); } +static void diva_4bri_set_addresses(diva_os_xdi_adapter_t *a) +{ + dword offset = a->resources.pci.qoffset; + dword c_offset = offset * a->xdi_adapter.ControllerNumber; + + a->resources.pci.mem_type_id[MEM_TYPE_RAM] = 2; + a->resources.pci.mem_type_id[MEM_TYPE_ADDRESS] = 2; + a->resources.pci.mem_type_id[MEM_TYPE_CONTROL] = 2; + a->resources.pci.mem_type_id[MEM_TYPE_RESET] = 0; + a->resources.pci.mem_type_id[MEM_TYPE_CTLREG] = 3; + a->resources.pci.mem_type_id[MEM_TYPE_PROM] = 0; + + /* + Set up hardware related pointers + */ + a->xdi_adapter.Address = a->resources.pci.addr[2]; /* BAR2 SDRAM */ + a->xdi_adapter.Address += c_offset; + + a->xdi_adapter.Control = a->resources.pci.addr[2]; /* BAR2 SDRAM */ + + a->xdi_adapter.ram = a->resources.pci.addr[2]; /* BAR2 SDRAM */ + a->xdi_adapter.ram += c_offset + (offset - MQ_SHARED_RAM_SIZE); + + a->xdi_adapter.reset = a->resources.pci.addr[0]; /* BAR0 CONFIG */ + /* + ctlReg contains the register address for the MIPS CPU reset control + */ + a->xdi_adapter.ctlReg = a->resources.pci.addr[3]; /* BAR3 CNTRL */ + /* + prom contains the register address for FPGA and EEPROM programming + */ + a->xdi_adapter.prom = &a->xdi_adapter.reset[0x6E]; +} + /* ** BAR0 - MEM - 0x100 - CONFIG MEM ** BAR1 - I/O - 0x100 - UNUSED @@ -110,11 +144,11 @@ int diva_4bri_init_card(diva_os_xdi_adapter_t * a) { int bar, i; + byte *p; PADAPTER_LIST_ENTRY quadro_list; diva_os_xdi_adapter_t *diva_current; diva_os_xdi_adapter_t *adapter_list[4]; PISDN_ADAPTER Slave; - dword offset; unsigned long bar_length[sizeof(_4bri_bar_length) / sizeof(_4bri_bar_length[0])]; int v2 = _4bri_is_rev_2_card(a->CardOrdinal); @@ -142,7 +176,7 @@ have to map any BAR before we can access it */ if (!_4bri_get_serial_number(a)) { - DBG_ERR(("A: 4BRI can't ger Serial Number")) + DBG_ERR(("A: 4BRI can't get Serial Number")) diva_4bri_cleanup_adapter(a); return (-1); } @@ -190,7 +224,7 @@ for (bar = 0; bar < 4; bar++) { if (bar != 1) { /* ignore I/O */ a->resources.pci.addr[bar] = - divasa_remap_pci_bar(a->resources.pci.bar[bar], + divasa_remap_pci_bar(a, bar, a->resources.pci.bar[bar], bar_length[bar]); if (!a->resources.pci.addr[bar]) { DBG_ERR(("A: 4BRI: can't map bar[%d]", bar)) @@ -205,14 +239,15 @@ */ sprintf(&a->port_name[0], "DIVA 4BRI %ld", (long) a->xdi_adapter.serialNo); - if (diva_os_register_io_port(1, a->resources.pci.bar[1], - bar_length[1], &a->port_name[0])) { + if (diva_os_register_io_port(a, 1, a->resources.pci.bar[1], + bar_length[1], &a->port_name[0], 1)) { DBG_ERR(("A: 4BRI: can't register bar[1]")) diva_4bri_cleanup_adapter(a); return (-1); } - a->resources.pci.addr[1] = (void *) (unsigned long) a->resources.pci.bar[1]; + a->resources.pci.addr[1] = + (void *) (unsigned long) a->resources.pci.bar[1]; /* Set cleanup pointer for base adapter only, so slave adapter @@ -265,8 +300,8 @@ (PADAPTER_LIST_ENTRY) diva_os_malloc(0, sizeof(*quadro_list)); if (!(a->slave_list = quadro_list)) { for (i = 0; i < (tasks - 1); i++) { - diva_os_free(0, a->slave_adapters[bar]); - a->slave_adapters[bar] = 0; + diva_os_free(0, a->slave_adapters[i]); + a->slave_adapters[i] = 0; } diva_4bri_cleanup_adapter(a); return (-1); @@ -359,60 +394,39 @@ prepare_qBri_functions(&a->xdi_adapter); } + for (i = 0; i < tasks; i++) { + diva_current = adapter_list[i]; + if (i) + memcpy(&diva_current->resources, &a->resources, sizeof(divas_card_resources_t)); + diva_current->resources.pci.qoffset = (a->xdi_adapter.MemorySize >> factor); + } + /* Set up hardware related pointers */ a->xdi_adapter.cfg = (void *) (unsigned long) a->resources.pci.bar[0]; /* BAR0 CONFIG */ a->xdi_adapter.port = (void *) (unsigned long) a->resources.pci.bar[1]; /* BAR1 */ - a->xdi_adapter.Address = a->resources.pci.addr[2]; /* BAR2 SDRAM */ - a->xdi_adapter.ctlReg = - (void *) (unsigned long) a->resources.pci.bar[3]; /* BAR3 CNTRL */ - - a->xdi_adapter.reset = a->resources.pci.addr[0]; /* BAR0 CONFIG */ - a->xdi_adapter.ram = a->resources.pci.addr[2]; /* BAR2 SDRAM */ - /* - ctlReg contains the register address for the MIPS CPU reset control - */ - a->xdi_adapter.ctlReg = a->resources.pci.addr[3]; /* BAR3 CNTRL */ - /* - prom contains the register address for FPGA and EEPROM programming - */ - a->xdi_adapter.prom = &a->xdi_adapter.reset[0x6E]; - /* - reset contains the base address for the PLX 9054 register set - */ - a->xdi_adapter.reset[PLX9054_INTCSR] = 0x00; /* disable PCI interrupts */ + a->xdi_adapter.ctlReg = (void *) (unsigned long) a->resources.pci.bar[3]; /* BAR3 CNTRL */ - /* - Replicate addresses to all instances, set shared memory - address for all instances - */ for (i = 0; i < tasks; i++) { + diva_current = adapter_list[i]; + diva_4bri_set_addresses(diva_current); Slave = a->xdi_adapter.QuadroList->QuadroAdapter[i]; - offset = - Slave->ControllerNumber * - (a->xdi_adapter.MemorySize >> factor); - Slave->Address = &a->xdi_adapter.Address[offset]; - Slave->ram = &a->xdi_adapter.ram[offset]; - Slave->reset = a->xdi_adapter.reset; - Slave->ctlReg = a->xdi_adapter.ctlReg; - Slave->prom = a->xdi_adapter.prom; - Slave->reset = a->xdi_adapter.reset; + Slave->MultiMaster = &a->xdi_adapter; Slave->sdram_bar = a->xdi_adapter.sdram_bar; - } - for (i = 0; i < tasks; i++) { - Slave = a->xdi_adapter.QuadroList->QuadroAdapter[i]; - Slave->ram += - ((a->xdi_adapter.MemorySize >> factor) - - MQ_SHARED_RAM_SIZE); - } - for (i = 1; i < tasks; i++) { - Slave = a->xdi_adapter.QuadroList->QuadroAdapter[i]; - Slave->serialNo = - ((dword) (Slave->ControllerNumber << 24)) | a-> - xdi_adapter.serialNo; + if (i) { + Slave->serialNo = ((dword) (Slave->ControllerNumber << 24)) | + a->xdi_adapter.serialNo; Slave->cardType = a->xdi_adapter.cardType; } + } + + /* + reset contains the base address for the PLX 9054 register set + */ + p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter); + p[PLX9054_INTCSR] = 0x00; /* disable PCI interrupts */ + DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p); /* Set IRQ handler @@ -484,8 +498,7 @@ if (bar != 1) { if (a->resources.pci.bar[bar] && a->resources.pci.addr[bar]) { - divasa_unmap_pci_bar(a->resources.pci. - addr[bar]); + divasa_unmap_pci_bar(a->resources.pci.addr[bar]); a->resources.pci.bar[bar] = 0; a->resources.pci.addr[bar] = 0; } @@ -496,12 +509,12 @@ Unregister I/O */ if (a->resources.pci.bar[1] && a->resources.pci.addr[1]) { - diva_os_register_io_port(0, a->resources.pci.bar[1], + diva_os_register_io_port(a, 0, a->resources.pci.bar[1], _4bri_is_rev_2_card(a-> CardOrdinal) ? _4bri_v2_bar_length[1] : _4bri_bar_length[1], - &a->port_name[0]); + &a->port_name[0], 1); a->resources.pci.bar[1] = 0; a->resources.pci.addr[1] = 0; } @@ -776,23 +789,18 @@ a->xdi_mbox. data_length); if (a->xdi_mbox.data) { - byte *src = - a->xdi_adapter.Address; - byte *dst = - a->xdi_mbox.data; - dword len = - a->xdi_mbox. - data_length; - - src += - cmd->command_data. - read_sdram.offset; + byte *p = DIVA_OS_MEM_ATTACH_ADDRESS(&a->xdi_adapter); + byte *src = p; + byte *dst = a->xdi_mbox.data; + dword len = a->xdi_mbox.data_length; + + src += cmd->command_data.read_sdram.offset; while (len--) { *dst++ = *src++; } - a->xdi_mbox.status = - DIVA_XDI_MBOX_BUSY; + DIVA_OS_MEM_DETACH_ADDRESS(&a->xdi_adapter, p); + a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; ret = 0; } } @@ -903,10 +911,12 @@ dword address, const byte * data, dword length, dword limit) { - byte *mem = IoAdapter->Address; + byte *p = DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter); + byte *mem = p; if (((address + length) >= limit) || !mem) { - DBG_ERR(("A: A(%d) write PRI address=0x%08lx", + DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p); + DBG_ERR(("A: A(%d) write 4BRI address=0x%08lx", IoAdapter->ANum, address + length)) return (-1); } @@ -916,6 +926,7 @@ *mem++ = *data++; } + DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p); return (0); } @@ -926,16 +937,18 @@ volatile word *signature; int started = 0; int i; + byte *p; /* start adapter */ start_qBri_hardware(IoAdapter); + p = DIVA_OS_MEM_ATTACH_RAM(IoAdapter); /* wait for signature in shared memory (max. 3 seconds) */ - signature = (volatile word *) (&IoAdapter->ram[0x1E]); + signature = (volatile word *) (&p[0x1E]); for (i = 0; i < 300; ++i) { diva_os_wait(10); @@ -958,10 +971,12 @@ DBG_FTL(("%s: Adapter selftest failed, signature=%04x", IoAdapter->Properties.Name, READ_WORD(&signature[0]))) + DIVA_OS_MEM_DETACH_RAM(IoAdapter, p); (*(IoAdapter->trapFnc)) (IoAdapter); IoAdapter->stop(IoAdapter); return (-1); } + DIVA_OS_MEM_DETACH_RAM(IoAdapter, p); for (i = 0; i < IoAdapter->tasks; i++) { IoAdapter->QuadroList->QuadroAdapter[i]->Initialized = 1; @@ -997,13 +1012,16 @@ #ifdef SUPPORT_INTERRUPT_TEST_ON_4BRI int i; ADAPTER *a = &IoAdapter->a; + byte *p; IoAdapter->IrqCount = 0; if (IoAdapter->ControllerNumber > 0) return (-1); - IoAdapter->reset[PLX9054_INTCSR] = PLX9054_INT_ENABLE; + p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); + p[PLX9054_INTCSR] = PLX9054_INT_ENABLE; + DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); /* interrupt test */ @@ -1015,20 +1033,23 @@ return ((IoAdapter->IrqCount > 0) ? 0 : -1); #else dword volatile *qBriIrq; + byte *p; /* Reset on-board interrupt register */ IoAdapter->IrqCount = 0; - qBriIrq = - (dword volatile *) (&IoAdapter-> - ctlReg[_4bri_is_rev_2_card + p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); + qBriIrq = (dword volatile *) (&p[_4bri_is_rev_2_card (IoAdapter-> cardType) ? (MQ2_BREG_IRQ_TEST) : (MQ_BREG_IRQ_TEST)]); WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF); + DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p); - IoAdapter->reset[PLX9054_INTCSR] = PLX9054_INT_ENABLE; + p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); + p[PLX9054_INTCSR] = PLX9054_INT_ENABLE; + DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); diva_os_wait(100); diff -Nru a/drivers/isdn/hardware/eicon/os_bri.c b/drivers/isdn/hardware/eicon/os_bri.c --- a/drivers/isdn/hardware/eicon/os_bri.c Thu Sep 11 23:03:11 2003 +++ b/drivers/isdn/hardware/eicon/os_bri.c Thu Sep 11 23:03:11 2003 @@ -1,4 +1,4 @@ -/* $Id: os_bri.c,v 1.1.2.2 2001/02/12 20:23:46 armin Exp $ */ +/* $Id: os_bri.c,v 1.18 2003/06/21 17:10:29 schindler Exp $ */ #include "platform.h" #include "debuglib.h" @@ -46,6 +46,27 @@ dword start_address, dword features); static int diva_bri_stop_adapter(diva_os_xdi_adapter_t * a); +static void diva_bri_set_addresses(diva_os_xdi_adapter_t * a) +{ + a->resources.pci.mem_type_id[MEM_TYPE_RAM] = 0; + a->resources.pci.mem_type_id[MEM_TYPE_CFG] = 1; + a->resources.pci.mem_type_id[MEM_TYPE_ADDRESS] = 2; + a->resources.pci.mem_type_id[MEM_TYPE_RESET] = 1; + a->resources.pci.mem_type_id[MEM_TYPE_PORT] = 2; + a->resources.pci.mem_type_id[MEM_TYPE_CTLREG] = 2; + + a->xdi_adapter.ram = a->resources.pci.addr[0]; + a->xdi_adapter.cfg = a->resources.pci.addr[1]; + a->xdi_adapter.Address = a->resources.pci.addr[2]; + + a->xdi_adapter.reset = a->xdi_adapter.cfg; + a->xdi_adapter.port = a->xdi_adapter.Address; + + a->xdi_adapter.ctlReg = a->xdi_adapter.port + M_PCI_RESET; + + a->xdi_adapter.reset += 0x4C; /* PLX 9050 !! */ +} + /* ** BAR0 - MEM Addr - 0x80 - NOT USED ** BAR1 - I/O Addr - 0x80 @@ -58,6 +79,7 @@ word cmd = 0, cmd_org; byte Bus, Slot; void *hdev; + byte *p; /* Set properties @@ -123,7 +145,7 @@ Map and register resources */ if (!(a->resources.pci.addr[0] = - divasa_remap_pci_bar(a->resources.pci.bar[0], + divasa_remap_pci_bar(a, 0, a->resources.pci.bar[0], bri_bar_length[0]))) { DBG_ERR(("A: BRI, can't map BAR[0]")) diva_bri_cleanup_adapter(a); @@ -133,8 +155,8 @@ sprintf(&a->port_name[0], "BRI %02x:%02x", a->resources.pci.bus, a->resources.pci.func); - if (diva_os_register_io_port(1, a->resources.pci.bar[1], - bri_bar_length[1], &a->port_name[0])) { + if (diva_os_register_io_port(a, 1, a->resources.pci.bar[1], + bri_bar_length[1], &a->port_name[0], 1)) { DBG_ERR(("A: BRI, can't register BAR[1]")) diva_bri_cleanup_adapter(a); return (-1); @@ -142,8 +164,8 @@ a->resources.pci.addr[1] = (void *) (unsigned long) a->resources.pci.bar[1]; a->resources.pci.length[1] = bri_bar_length[1]; - if (diva_os_register_io_port(1, a->resources.pci.bar[2], - bar2_length, &a->port_name[0])) { + if (diva_os_register_io_port(a, 1, a->resources.pci.bar[2], + bar2_length, &a->port_name[0], 2)) { DBG_ERR(("A: BRI, can't register BAR[2]")) diva_bri_cleanup_adapter(a); return (-1); @@ -152,6 +174,11 @@ a->resources.pci.length[2] = bar2_length; /* + Set all memory areas + */ + diva_bri_set_addresses(a); + + /* Get Serial Number */ a->xdi_adapter.serialNo = diva_bri_get_serial_number(a); @@ -210,15 +237,9 @@ a->interface.cleanup_adapter_proc = diva_bri_cleanup_adapter; a->interface.cmd_proc = diva_bri_cmd_card_proc; - a->xdi_adapter.cfg = a->resources.pci.addr[1]; - a->xdi_adapter.Address = a->resources.pci.addr[2]; - - a->xdi_adapter.reset = a->xdi_adapter.cfg; - a->xdi_adapter.port = a->xdi_adapter.Address; - - a->xdi_adapter.ctlReg = a->xdi_adapter.port + M_PCI_RESET; - a->xdi_adapter.reset += 0x4C; /* PLX 9050 !! */ - outpp(a->xdi_adapter.reset, 0x41); + p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter); + outpp(p, 0x41); + DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p); prepare_maestra_functions(&a->xdi_adapter); @@ -268,11 +289,11 @@ for (i = 1; i < 3; i++) { if (a->resources.pci.addr[i] && a->resources.pci.bar[i]) { - diva_os_register_io_port(0, + diva_os_register_io_port(a, 0, a->resources.pci.bar[i], a->resources.pci. length[i], - &a->port_name[0]); + &a->port_name[0], i); a->resources.pci.addr[i] = 0; a->resources.pci.bar[i] = 0; } @@ -314,18 +335,20 @@ byte *confIO; word serHi, serLo, *confMem; - confIO = (byte *) a->resources.pci.addr[1]; + confIO = (byte *) DIVA_OS_MEM_ATTACH_CFG(&a->xdi_adapter); serHi = (word) (inppw(&confIO[0x22]) & 0x0FFF); serLo = (word) (inppw(&confIO[0x26]) & 0x0FFF); serNo = ((dword) serHi << 16) | (dword) serLo; + DIVA_OS_MEM_DETACH_CFG(&a->xdi_adapter, confIO); if ((serNo == 0) || (serNo == 0xFFFFFFFF)) { DBG_FTL(("W: BRI use BAR[0] to get card serial number")) - confMem = (word *) a->resources.pci.addr[0]; + confMem = (word *) DIVA_OS_MEM_ATTACH_RAM(&a->xdi_adapter); serHi = (word) (READ_WORD(&confMem[0x11]) & 0x0FFF); serLo = (word) (READ_WORD(&confMem[0x13]) & 0x0FFF); serNo = (((dword) serHi) << 16) | ((dword) serLo); + DIVA_OS_MEM_DETACH_RAM(&a->xdi_adapter, confMem); } DBG_LOG(("Serial Number=%ld", serNo)) @@ -342,9 +365,9 @@ int i; for (i = 1; i < 3; i++) { - diva_os_register_io_port(0, a->resources.pci.bar[i], + diva_os_register_io_port(a, 0, a->resources.pci.bar[i], a->resources.pci.length[i], - &a->port_name[0]); + &a->port_name[0], i); a->resources.pci.addr[i] = 0; } @@ -352,9 +375,9 @@ (long) a->xdi_adapter.serialNo); for (i = 1; i < 3; i++) { - if (diva_os_register_io_port(1, a->resources.pci.bar[i], + if (diva_os_register_io_port(a, 1, a->resources.pci.bar[i], a->resources.pci.length[i], - &a->port_name[0])) { + &a->port_name[0], i)) { DBG_ERR(("A: failed to reregister BAR[%d]", i)) return (-1); } @@ -493,6 +516,7 @@ { byte *addrHi, *addrLo, *ioaddr; dword i; + byte *Port; if (!IoAdapter->port) { return (-1); @@ -501,13 +525,13 @@ DBG_ERR(("A: A(%d) can't reset BRI adapter - please stop first", IoAdapter->ANum)) return (-1); } - addrHi = - IoAdapter->port + - ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH); - addrLo = IoAdapter->port + ADDR; - ioaddr = IoAdapter->port + DATA; (*(IoAdapter->rstFnc)) (IoAdapter); diva_os_wait(100); + Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter); + addrHi = Port + + ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH); + addrLo = Port + ADDR; + ioaddr = Port + DATA; /* recover */ @@ -540,6 +564,8 @@ outppw(addrLo, (word) 0); outppw(ioaddr, (word) 0); + DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port); + /* Forget all outstanding entities */ @@ -578,16 +604,17 @@ dword address, const byte * data, dword length) { byte *addrHi, *addrLo, *ioaddr; + byte *Port; if (!IoAdapter->port) { return (-1); } - addrHi = - IoAdapter->port + + Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter); + addrHi = Port + ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH); - addrLo = IoAdapter->port + ADDR; - ioaddr = IoAdapter->port + DATA; + addrLo = Port + ADDR; + ioaddr = Port + DATA; while (length--) { outpp(addrHi, (word) (address >> 16)); @@ -596,6 +623,7 @@ address++; } + DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port); return (0); } @@ -603,6 +631,7 @@ diva_bri_start_adapter(PISDN_ADAPTER IoAdapter, dword start_address, dword features) { + byte *Port; dword i, test; byte *addrHi, *addrLo, *ioaddr; int started = 0; @@ -621,11 +650,11 @@ sprintf(IoAdapter->Name, "A(%d)", (int) IoAdapter->ANum); DBG_LOG(("A(%d) start BRI", IoAdapter->ANum)) - addrHi = - IoAdapter->port + + Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter); + addrHi = Port + ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH); - addrLo = IoAdapter->port + ADDR; - ioaddr = IoAdapter->port + DATA; + addrLo = Port + ADDR; + ioaddr = Port + DATA; outpp(addrHi, (byte) ( @@ -633,12 +662,20 @@ BRI_SHARED_RAM_SIZE) >> 16)); outppw(addrLo, 0x1e); outppw(ioaddr, 0x00); + DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port); /* start the protocol code */ - outpp(IoAdapter->ctlReg, 0x08); + Port = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); + outpp(Port, 0x08); + DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, Port); + Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter); + addrHi = Port + + ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH); + addrLo = Port + ADDR; + ioaddr = Port + DATA; /* wait for signature (max. 3 seconds) */ @@ -659,6 +696,7 @@ break; } } + DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port); if (!started) { DBG_FTL(("A: A(%d) %s: Adapter selftest failed 0x%04X", @@ -677,7 +715,9 @@ a->ReadyInt = 1; if (IoAdapter->reset) { - outpp(IoAdapter->reset, 0x41); + Port = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); + outpp(Port, 0x41); + DIVA_OS_MEM_DETACH_RESET(IoAdapter, Port); } a->ram_out(a, &PR_RAM->ReadyInt, 1); diff -Nru a/drivers/isdn/hardware/eicon/os_pri.c b/drivers/isdn/hardware/eicon/os_pri.c --- a/drivers/isdn/hardware/eicon/os_pri.c Thu Sep 11 23:03:12 2003 +++ b/drivers/isdn/hardware/eicon/os_pri.c Thu Sep 11 23:03:12 2003 @@ -1,4 +1,4 @@ -/* $Id: os_pri.c,v 1.1.2.3 2001/02/14 21:10:19 armin Exp $ */ +/* $Id: os_pri.c,v 1.29 2003/08/25 13:41:27 schindler Exp $ */ #include "platform.h" #include "debuglib.h" @@ -57,6 +57,34 @@ return (0); } +static void diva_pri_set_addresses(diva_os_xdi_adapter_t * a) +{ + a->resources.pci.mem_type_id[MEM_TYPE_ADDRESS] = 0; + a->resources.pci.mem_type_id[MEM_TYPE_CONTROL] = 2; + a->resources.pci.mem_type_id[MEM_TYPE_CONFIG] = 4; + a->resources.pci.mem_type_id[MEM_TYPE_RAM] = 0; + a->resources.pci.mem_type_id[MEM_TYPE_RESET] = 2; + a->resources.pci.mem_type_id[MEM_TYPE_CFG] = 4; + a->resources.pci.mem_type_id[MEM_TYPE_PROM] = 3; + + a->xdi_adapter.Address = a->resources.pci.addr[0]; + a->xdi_adapter.Control = a->resources.pci.addr[2]; + a->xdi_adapter.Config = a->resources.pci.addr[4]; + + a->xdi_adapter.ram = a->resources.pci.addr[0]; + a->xdi_adapter.ram += MP_SHARED_RAM_OFFSET; + + a->xdi_adapter.reset = a->resources.pci.addr[2]; + a->xdi_adapter.reset += MP_RESET; + + a->xdi_adapter.cfg = a->resources.pci.addr[4]; + a->xdi_adapter.cfg += MP_IRQ_RESET; + + a->xdi_adapter.sdram_bar = a->resources.pci.bar[0]; + + a->xdi_adapter.prom = a->resources.pci.addr[3]; +} + /* ** BAR0 - SDRAM, MP_MEMORY_SIZE, MP2_MEMORY_SIZE by Rev.2 ** BAR1 - DEVICES, 0x1000 @@ -117,7 +145,7 @@ */ for (bar = 0; bar < 5; bar++) { a->resources.pci.addr[bar] = - divasa_remap_pci_bar(a->resources.pci.bar[bar], + divasa_remap_pci_bar(a, bar, a->resources.pci.bar[bar], bar_length[bar]); if (!a->resources.pci.addr[bar]) { DBG_ERR(("A: A(%d), can't map bar[%d]", @@ -128,6 +156,11 @@ } /* + Set all memory areas + */ + diva_pri_set_addresses(a); + + /* Get Serial Number of this adapter */ if (pri_get_serial_number(a)) { @@ -194,23 +227,6 @@ prepare_pri_functions(&a->xdi_adapter); } - /* - Set all memory areas - */ - a->xdi_adapter.Address = a->resources.pci.addr[0]; - a->xdi_adapter.sdram_bar = a->resources.pci.bar[0]; - a->xdi_adapter.ram = a->resources.pci.addr[0]; - a->xdi_adapter.ram += MP_SHARED_RAM_OFFSET; - - a->xdi_adapter.reset = a->resources.pci.addr[2]; - a->xdi_adapter.reset += MP_RESET; - - a->xdi_adapter.prom = - (byte *) (unsigned long) a->resources.pci.bar[3]; - - a->xdi_adapter.cfg = a->resources.pci.addr[4]; - a->xdi_adapter.cfg += MP_IRQ_RESET; - a->dsp_mask = diva_pri_detect_dsps(a); /* @@ -317,7 +333,7 @@ static int diva_pri_reset_adapter(PISDN_ADAPTER IoAdapter) { dword i; - struct mp_load *boot = (struct mp_load *) IoAdapter->Address; + struct mp_load *boot; if (!IoAdapter->Address || !IoAdapter->reset) { return (-1); @@ -328,12 +344,20 @@ return (-1); } + boot = (struct mp_load *) DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter); WRITE_DWORD(&boot->err, 0); + DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot); + IoAdapter->rstFnc(IoAdapter); + diva_os_wait(10); + + boot = (struct mp_load *) DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter); i = READ_DWORD(&boot->live); + diva_os_wait(10); if (i == READ_DWORD(&boot->live)) { + DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot); DBG_ERR(("A: A(%d) CPU on PRI %ld is not alive!", IoAdapter->ANum, IoAdapter->serialNo)) return (-1); @@ -342,8 +366,10 @@ DBG_ERR(("A: A(%d) PRI %ld Board Selftest failed, error=%08lx", IoAdapter->ANum, IoAdapter->serialNo, READ_DWORD(&boot->err))) + DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot); return (-1); } + DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot); /* Forget all outstanding entities @@ -383,9 +409,11 @@ dword address, const byte * data, dword length, dword limit) { - byte *mem = IoAdapter->Address; + byte *p = DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter); + byte *mem = p; if (((address + length) >= limit) || !mem) { + DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p); DBG_ERR(("A: A(%d) write PRI address=0x%08lx", IoAdapter->ANum, address + length)) return (-1); @@ -396,6 +424,7 @@ *mem++ = *data++; } + DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, p); return (0); } @@ -405,15 +434,18 @@ { dword i; int started = 0; - struct mp_load *boot = (struct mp_load *) IoAdapter->Address; + byte *p; + struct mp_load *boot = (struct mp_load *) DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter); ADAPTER *a = &IoAdapter->a; if (IoAdapter->Initialized) { + DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot); DBG_ERR(("A: A(%d) pri_start_adapter, adapter already running", IoAdapter->ANum)) return (-1); } if (!boot) { + DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot); DBG_ERR(("A: PRI %ld can't start, adapter not mapped", IoAdapter->serialNo)) return (-1); @@ -437,17 +469,22 @@ } if (!started) { - dword TrapId = READ_DWORD(&IoAdapter->Address[0x80]); - dword debug = READ_DWORD(&IoAdapter->Address[0x1c]); + byte *p = (byte *)boot; + dword TrapId; + dword debug; + TrapId = READ_DWORD(&p[0x80]); + debug = READ_DWORD(&p[0x1c]); DBG_ERR(("A(%d) Adapter start failed 0x%08lx, TrapId=%08lx, debug=%08lx", IoAdapter->ANum, READ_DWORD(&boot->signature), TrapId, debug)) + DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot); if (IoAdapter->trapFnc) { (*(IoAdapter->trapFnc)) (IoAdapter); } IoAdapter->stop(IoAdapter); return (-1); } + DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, boot); IoAdapter->Initialized = TRUE; @@ -455,8 +492,9 @@ Check Interrupt */ IoAdapter->IrqCount = 0; - WRITE_DWORD(((dword volatile *) IoAdapter->cfg), - (dword) ~ 0x03E00000); + p = DIVA_OS_MEM_ATTACH_CFG(IoAdapter); + WRITE_DWORD(((dword volatile *) p), (dword) ~ 0x03E00000); + DIVA_OS_MEM_DETACH_CFG(IoAdapter, p); a->ReadyInt = 1; a->ram_out(a, &PR_RAM->ReadyInt, 1); @@ -658,7 +696,8 @@ diva_os_malloc(0, a->xdi_mbox.data_length); if (a->xdi_mbox.data) { dword *data = (dword *) a->xdi_mbox.data; - if (!a->xdi_adapter.ram || !a->xdi_adapter.reset || + if (!a->xdi_adapter.ram || + !a->xdi_adapter.reset || !a->xdi_adapter.cfg) { *data = 3; } else if (a->xdi_adapter.trapped) { @@ -691,23 +730,18 @@ a->xdi_mbox. data_length); if (a->xdi_mbox.data) { - byte *src = - a->xdi_adapter.Address; - byte *dst = - a->xdi_mbox.data; - dword len = - a->xdi_mbox. - data_length; - - src += - cmd->command_data. - read_sdram.offset; + byte *p = DIVA_OS_MEM_ATTACH_ADDRESS(&a->xdi_adapter); + byte *src = p; + byte *dst = a->xdi_mbox.data; + dword len = a->xdi_mbox.data_length; + + src += cmd->command_data.read_sdram.offset; while (len--) { *dst++ = *src++; } - a->xdi_mbox.status = - DIVA_XDI_MBOX_BUSY; + a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY; + DIVA_OS_MEM_DETACH_ADDRESS(&a->xdi_adapter, p); ret = 0; } } @@ -731,27 +765,33 @@ byte data[64]; int i; dword len = sizeof(data); - volatile byte *config = (byte *) a->resources.pci.addr[4]; - volatile byte *flash = (byte *) a->resources.pci.addr[3]; + volatile byte *config; + volatile byte *flash; /* * First set some GT6401x config registers before accessing the BOOT-ROM */ + config = DIVA_OS_MEM_ATTACH_CONFIG(&a->xdi_adapter); if (!(config[0xc3c] & 0x08)) { config[0xc3c] |= 0x08; /* Base Address enable register */ } config[LOW_BOOTCS_DREG] = 0x00; config[HI_BOOTCS_DREG] = 0xFF; + DIVA_OS_MEM_DETACH_CONFIG(&a->xdi_adapter, config); /* * Read only the last 64 bytes of manufacturing data */ memset(data, '\0', len); + flash = DIVA_OS_MEM_ATTACH_PROM(&a->xdi_adapter); for (i = 0; i < len; i++) { data[i] = flash[0x8000 - len + i]; } + DIVA_OS_MEM_DETACH_PROM(&a->xdi_adapter, flash); + config = DIVA_OS_MEM_ATTACH_CONFIG(&a->xdi_adapter); config[LOW_BOOTCS_DREG] = 0xFC; /* Disable FLASH EPROM access */ config[HI_BOOTCS_DREG] = 0xFF; + DIVA_OS_MEM_DETACH_CONFIG(&a->xdi_adapter, config); if (memcmp(&data[48], "DIVAserverPR", 12)) { #if !defined(DIVA_PRI_NO_PCI_BIOS_WORKAROUND) /* { */ @@ -791,22 +831,26 @@ /* Try to read Flash again */ - config = (byte *) a->resources.pci.addr[4]; - flash = (byte *) a->resources.pci.addr[3]; len = sizeof(data); + config = DIVA_OS_MEM_ATTACH_CONFIG(&a->xdi_adapter); if (!(config[0xc3c] & 0x08)) { config[0xc3c] |= 0x08; /* Base Address enable register */ } config[LOW_BOOTCS_DREG] = 0x00; config[HI_BOOTCS_DREG] = 0xFF; + DIVA_OS_MEM_DETACH_CONFIG(&a->xdi_adapter, config); memset(data, '\0', len); + flash = DIVA_OS_MEM_ATTACH_PROM(&a->xdi_adapter); for (i = 0; i < len; i++) { data[i] = flash[0x8000 - len + i]; } + DIVA_OS_MEM_ATTACH_PROM(&a->xdi_adapter, flash); + config = DIVA_OS_MEM_ATTACH_CONFIG(&a->xdi_adapter); config[LOW_BOOTCS_DREG] = 0xFC; config[HI_BOOTCS_DREG] = 0xFF; + DIVA_OS_MEM_DETACH_CONFIG(&a->xdi_adapter, config); if (memcmp(&data[48], "DIVAserverPR", 12)) { DBG_ERR(("A: failed to read serial number")) @@ -907,7 +951,8 @@ */ static dword diva_pri_detect_dsps(diva_os_xdi_adapter_t * a) { - byte *base = a->resources.pci.addr[2]; + byte *base; + byte *p; dword ret = 0; dword row_offset[7] = { 0x00000000, @@ -921,14 +966,17 @@ byte *dsp_addr_port, *dsp_data_port, row_state; int dsp_row = 0, dsp_index, dsp_num; - if (!base || !a->xdi_adapter.reset) { + if (!a->xdi_adapter.Control || !a->xdi_adapter.reset) { return (0); } - *(volatile byte *) (a->xdi_adapter.reset) = - _MP_RISC_RESET | _MP_DSP_RESET; + p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter); + *(volatile byte *) p = _MP_RISC_RESET | _MP_DSP_RESET; + DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p); diva_os_wait(5); + base = DIVA_OS_MEM_ATTACH_CONTROL(&a->xdi_adapter); + for (dsp_num = 0; dsp_num < 30; dsp_num++) { dsp_row = dsp_num / 7 + 1; dsp_index = dsp_num % 7; @@ -947,9 +995,11 @@ ret |= (1 << dsp_num); } } + DIVA_OS_MEM_DETACH_CONTROL(&a->xdi_adapter, base); - *(volatile byte *) (a->xdi_adapter.reset) = - _MP_RISC_RESET | _MP_LED1 | _MP_LED2; + p = DIVA_OS_MEM_ATTACH_RESET(&a->xdi_adapter); + *(volatile byte *) p = _MP_RISC_RESET | _MP_LED1 | _MP_LED2; + DIVA_OS_MEM_DETACH_RESET(&a->xdi_adapter, p); diva_os_wait(5); /* diff -Nru a/drivers/isdn/hardware/eicon/platform.h b/drivers/isdn/hardware/eicon/platform.h --- a/drivers/isdn/hardware/eicon/platform.h Thu Sep 11 23:03:13 2003 +++ b/drivers/isdn/hardware/eicon/platform.h Thu Sep 11 23:03:13 2003 @@ -1,9 +1,9 @@ -/* $Id: platform.h,v 1.1.2.6 2001/05/01 15:48:05 armin Exp $ +/* $Id: platform.h,v 1.31 2003/09/08 15:15:22 schindler Exp $ * * platform.h * * - * Copyright 2000-2002 by Armin Schindler (mac@melware.de) + * Copyright 2000-2003 by Armin Schindler (mac@melware.de) * Copyright 2000 Eicon Networks * * This software may be used and distributed according to the terms @@ -23,20 +23,27 @@ #include #include #include +#include #include +#include #include #include #include +#include #include #include #include "cardtype.h" +/* activate debuglib for modules only */ +#ifndef MODULE +#define DIVA_NO_DEBUGLIB +#endif + #define DIVA_INIT_FUNCTION __init #define DIVA_EXIT_FUNCTION __exit #define DIVA_USER_MODE_CARD_CONFIG 1 -#define XDI_USE_XLOG 1 #define USE_EXTENDED_DEBUGS 1 #define MAX_ADAPTER 32 @@ -46,11 +53,6 @@ #define MEMORY_SPACE_TYPE 0 #define PORT_SPACE_TYPE 1 -#include "debuglib.h" - -#define dtrc(p) DBG_PRV0(p) -#define dbug(a,p) DBG_PRV1(p) - #include @@ -106,6 +108,36 @@ #define _cdecl #endif +#define MEM_TYPE_RAM 0 +#define MEM_TYPE_PORT 1 +#define MEM_TYPE_PROM 2 +#define MEM_TYPE_CTLREG 3 +#define MEM_TYPE_RESET 4 +#define MEM_TYPE_CFG 5 +#define MEM_TYPE_ADDRESS 6 +#define MEM_TYPE_CONFIG 7 +#define MEM_TYPE_CONTROL 8 + +#define DIVA_OS_MEM_ATTACH_RAM(a) ((a)->ram) +#define DIVA_OS_MEM_ATTACH_PORT(a) ((a)->port) +#define DIVA_OS_MEM_ATTACH_PROM(a) ((a)->prom) +#define DIVA_OS_MEM_ATTACH_CTLREG(a) ((a)->ctlReg) +#define DIVA_OS_MEM_ATTACH_RESET(a) ((a)->reset) +#define DIVA_OS_MEM_ATTACH_CFG(a) ((a)->cfg) +#define DIVA_OS_MEM_ATTACH_ADDRESS(a) ((a)->Address) +#define DIVA_OS_MEM_ATTACH_CONFIG(a) ((a)->Config) +#define DIVA_OS_MEM_ATTACH_CONTROL(a) ((a)->Control) + +#define DIVA_OS_MEM_DETACH_RAM(a, x) do { } while(0) +#define DIVA_OS_MEM_DETACH_PORT(a, x) do { } while(0) +#define DIVA_OS_MEM_DETACH_PROM(a, x) do { } while(0) +#define DIVA_OS_MEM_DETACH_CTLREG(a, x) do { } while(0) +#define DIVA_OS_MEM_DETACH_RESET(a, x) do { } while(0) +#define DIVA_OS_MEM_DETACH_CFG(a, x) do { } while(0) +#define DIVA_OS_MEM_DETACH_ADDRESS(a, x) do { } while(0) +#define DIVA_OS_MEM_DETACH_CONFIG(a, x) do { } while(0) +#define DIVA_OS_MEM_DETACH_CONTROL(a, x) do { } while(0) + #if !defined(DIM) #define DIM(array) (sizeof (array)/sizeof ((array)[0])) #endif @@ -124,7 +156,11 @@ typedef struct _ISDN_ADAPTER* PISDN_ADAPTER; typedef void (* DIVA_DI_PRINTF) (unsigned char *, ...); -extern DIVA_DI_PRINTF dprintf; +#include "debuglib.h" + +#define dtrc(p) DBG_PRV0(p) +#define dbug(a,p) DBG_PRV1(p) + typedef struct e_info_s E_INFO ; @@ -146,8 +182,21 @@ /* ** memory allocation */ -void* diva_os_malloc (unsigned long flags, unsigned long size); -void diva_os_free (unsigned long flags, void* ptr); +static __inline__ void* diva_os_malloc (unsigned long flags, unsigned long size) +{ + void *ret = NULL; + + if (size) { + ret = (void *) vmalloc((unsigned int) size); + } + return (ret); +} +static __inline__ void diva_os_free (unsigned long flags, void* ptr) +{ + if (ptr) { + vfree(ptr); + } +} /* ** use skbuffs for message buffer @@ -161,8 +210,17 @@ /* ** mSeconds waiting */ -void diva_os_sleep(dword mSec); -void diva_os_wait(dword mSec); +static __inline__ void diva_os_sleep(dword mSec) +{ + unsigned long timeout = HZ * mSec / 1000 + 1; + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(timeout); +} +static __inline__ void diva_os_wait(dword mSec) +{ + mdelay(mSec); +} /* ** PCI Configuration space access @@ -173,8 +231,8 @@ /* ** I/O Port utilities */ -int diva_os_register_io_port (int register, unsigned long port, unsigned long length, const char* name); - +int diva_os_register_io_port (void *adapter, int register, unsigned long port, + unsigned long length, const char* name, int id); /* ** I/O port access abstraction */ @@ -197,14 +255,6 @@ void diva_os_remove_irq (void* context, byte irq); #define diva_os_in_irq() in_irq() - -/* -** module locking -*/ -/* -#define DIVA_LOCK_MODULE MOD_INC_USE_COUNT -#define DIVA_UNLOCK_MODULE MOD_DEC_USE_COUNT -*/ /* ** Spin Lock framework diff -Nru a/drivers/isdn/hardware/eicon/s_4bri.c b/drivers/isdn/hardware/eicon/s_4bri.c --- a/drivers/isdn/hardware/eicon/s_4bri.c Thu Sep 11 23:03:11 2003 +++ b/drivers/isdn/hardware/eicon/s_4bri.c Thu Sep 11 23:03:11 2003 @@ -55,8 +55,8 @@ * check for trapped MIPS 46xx CPU, dump exception frame */ + base = DIVA_OS_MEM_ATTACH_CONTROL(IoAdapter); offset = IoAdapter->ControllerNumber * (IoAdapter->MemorySize >> factor) ; - base = IoAdapter->ram - offset - ((IoAdapter->MemorySize >> factor) - MQ_SHARED_RAM_SIZE) ; TrapID = READ_DWORD(&base[0x80]) ; @@ -75,8 +75,10 @@ if ( (regs[0] >= offset) && (regs[0] < offset + (IoAdapter->MemorySize >> factor) - 1) ) { - if ( !(Xlog = (word *)diva_os_malloc (0, MAX_XLOG_SIZE)) ) + if ( !(Xlog = (word *)diva_os_malloc (0, MAX_XLOG_SIZE)) ) { + DIVA_OS_MEM_DETACH_CONTROL(IoAdapter, base); return ; + } size = offset + (IoAdapter->MemorySize >> factor) - regs[0] ; if ( size > MAX_XLOG_SIZE ) @@ -89,7 +91,7 @@ diva_os_free (0, Xlog) ; IoAdapter->trapped = 2 ; } - + DIVA_OS_MEM_DETACH_CONTROL(IoAdapter, base); } /* -------------------------------------------------------------------------- @@ -97,10 +99,10 @@ -------------------------------------------------------------------------- */ static void reset_qBri_hardware (PISDN_ADAPTER IoAdapter) { word volatile *qBriReset ; - dword volatile *qBriCntrl ; + byte volatile *qBriCntrl ; + byte volatile *p ; - qBriReset = (word volatile *)IoAdapter->prom ; - qBriCntrl = (dword volatile *)(&IoAdapter->ctlReg[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_RISC) : (MQ_BREG_RISC)]); + qBriReset = (word volatile *)DIVA_OS_MEM_ATTACH_PROM(IoAdapter); WRITE_WORD(qBriReset, READ_WORD(qBriReset) | PLX9054_SOFT_RESET) ; diva_os_wait (1) ; WRITE_WORD(qBriReset, READ_WORD(qBriReset) & ~PLX9054_SOFT_RESET) ; @@ -109,34 +111,40 @@ diva_os_wait (1) ; WRITE_WORD(qBriReset, READ_WORD(qBriReset) & ~PLX9054_RELOAD_EEPROM) ; diva_os_wait (1); + DIVA_OS_MEM_DETACH_PROM(IoAdapter, qBriReset); - WRITE_DWORD(qBriCntrl, 0) ; + qBriCntrl = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); + p = &qBriCntrl[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_RISC) : (MQ_BREG_RISC)]; + WRITE_DWORD(p, 0) ; + DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, qBriCntrl); DBG_TRC(("resetted board @ reset addr 0x%08lx", qBriReset)) - DBG_TRC(("resetted board @ cntrl addr 0x%08lx", qBriCntrl)) - + DBG_TRC(("resetted board @ cntrl addr 0x%08lx", p)) } /* -------------------------------------------------------------------------- Start Card CPU -------------------------------------------------------------------------- */ void start_qBri_hardware (PISDN_ADAPTER IoAdapter) { - dword volatile *qBriReset ; + byte volatile *qBriReset ; + byte volatile *p ; - qBriReset = (dword volatile *)(&IoAdapter->ctlReg[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_RISC) : (MQ_BREG_RISC)]); + p = (byte volatile *)DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); + qBriReset = &p[(DIVA_4BRI_REVISION(IoAdapter)) ? (MQ2_BREG_RISC) : (MQ_BREG_RISC)]; WRITE_DWORD(qBriReset, MQ_RISC_COLD_RESET_MASK) ; diva_os_wait (2) ; WRITE_DWORD(qBriReset, MQ_RISC_WARM_RESET_MASK | MQ_RISC_COLD_RESET_MASK) ; diva_os_wait (10) ; + DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p); DBG_TRC(("started processor @ addr 0x%08lx", qBriReset)) - } /* -------------------------------------------------------------------------- Stop Card CPU -------------------------------------------------------------------------- */ static void stop_qBri_hardware (PISDN_ADAPTER IoAdapter) { + byte volatile *p ; dword volatile *qBriReset ; dword volatile *qBriIrq ; dword volatile *qBriIsacDspReset ; @@ -147,16 +155,24 @@ if ( IoAdapter->ControllerNumber > 0 ) return ; - qBriReset = (dword volatile *)(&IoAdapter->ctlReg[reset_offset]) ; - qBriIrq = (dword volatile *)(&IoAdapter->ctlReg[irq_offset]) ; - qBriIsacDspReset = (dword volatile *)(&IoAdapter->ctlReg[hw_offset]); + p = (byte volatile *)DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); + qBriReset = (dword volatile *)&p[reset_offset]; + qBriIsacDspReset = (dword volatile *)&p[hw_offset]; /* * clear interrupt line (reset Local Interrupt Test Register) */ WRITE_DWORD(qBriReset, 0) ; WRITE_DWORD(qBriIsacDspReset, 0) ; - IoAdapter->reset[PLX9054_INTCSR] = 0x00 ; /* disable PCI interrupts */ + DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p); + + p = (byte volatile *)DIVA_OS_MEM_ATTACH_RESET(IoAdapter); + p[PLX9054_INTCSR] = 0x00 ; /* disable PCI interrupts */ + DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); + + p = (byte volatile *)DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); + qBriIrq = (dword volatile *)&p[irq_offset]; WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF) ; + DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p); DBG_TRC(("stopped processor @ addr 0x%08lx", qBriReset)) @@ -260,7 +276,7 @@ int bit ; byte *File ; dword code, FileLength ; - word volatile *addr = (word volatile *)IoAdapter->prom ; + word volatile *addr = (word volatile *)DIVA_OS_MEM_ATTACH_PROM(IoAdapter); word val, baseval = FPGA_CS | FPGA_PROG ; @@ -291,8 +307,10 @@ File = qBri_check_FPGAsrc (IoAdapter, "ds4bri.bit", &FileLength, &code) ; } - if ( !File ) + if ( !File ) { + DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr); return (0) ; + } /* * prepare download, pulse PROGRAM pin down. */ @@ -306,6 +324,7 @@ { DBG_FTL(("FPGA download: acknowledge for FPGA memory clear missing")) xdiFreeFile (File) ; + DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr); return (0) ; } /* @@ -329,6 +348,8 @@ diva_os_wait (100) ; val = READ_WORD(addr) ; + DIVA_OS_MEM_DETACH_PROM(IoAdapter, addr); + if ( !(val & FPGA_BUSY) ) { DBG_FTL(("FPGA download: chip remains in busy state (0x%04x)", val)) @@ -343,12 +364,10 @@ Download protocol code to the adapter -------------------------------------------------------------------------- */ -#define DOWNLOAD_ADDR(IoAdapter) (&IoAdapter->ram[IoAdapter->downloadAddr & (IoAdapter->MemorySize - 1)]) - - static int qBri_protocol_load (PISDN_ADAPTER BaseIoAdapter, PISDN_ADAPTER IoAdapter) { PISDN_ADAPTER HighIoAdapter; + byte *p; dword FileLength ; dword *sharedRam, *File; dword Addr, ProtOffset, SharedRamOffset, i; @@ -436,7 +455,8 @@ return (0) ; } IoAdapter->downloadAddr = 0 ; - sharedRam = (dword *)DOWNLOAD_ADDR(IoAdapter) ; + p = DIVA_OS_MEM_ATTACH_RAM(IoAdapter); + sharedRam = (dword *)&p[IoAdapter->downloadAddr & (IoAdapter->MemorySize - 1)]; memcpy (sharedRam, File, FileLength) ; DBG_TRC(("Download addr 0x%08x len %ld - virtual 0x%08x", @@ -449,10 +469,12 @@ DBG_FTL(("File=0x%x, sharedRam=0x%x", File, sharedRam)) DBG_BLK(( (char *)File, 256)) DBG_BLK(( (char *)sharedRam, 256)) + DIVA_OS_MEM_DETACH_RAM(IoAdapter, p); xdiFreeFile (File) ; return (0) ; } + DIVA_OS_MEM_DETACH_RAM(IoAdapter, p); xdiFreeFile (File) ; return (1) ; @@ -466,6 +488,7 @@ PISDN_ADAPTER IoAdapter; word i ; dword *sharedRam ; + byte *p; i = 0 ; @@ -485,12 +508,14 @@ IoAdapter->downloadAddr + length)) return (-1) ; } - sharedRam = (dword*)(&BaseIoAdapter->ram[IoAdapter->downloadAddr & - (IoAdapter->MemorySize - 1)]) ; - + p = DIVA_OS_MEM_ATTACH_RAM(BaseIoAdapter); + sharedRam = (dword*)&p[IoAdapter->downloadAddr & (IoAdapter->MemorySize - 1)]; - if ( fp->sysFileRead (fp, sharedRam, length) != length ) + if ( fp->sysFileRead (fp, sharedRam, length) != length ) { + DIVA_OS_MEM_DETACH_RAM(BaseIoAdapter, p); return (-1) ; + } + DIVA_OS_MEM_DETACH_RAM(BaseIoAdapter, p); IoAdapter->downloadAddr += length ; IoAdapter->downloadAddr = (IoAdapter->downloadAddr + 3) & (~3) ; @@ -509,6 +534,7 @@ word download_count, i ; dword *sharedRam ; dword FileLength ; + byte *p; if ( !(fp = OsOpenFile (DSP_TELINDUS_FILE)) ) { DBG_FTL(("qBri_telindus_load: %s not found!", DSP_TELINDUS_FILE)) @@ -553,8 +579,8 @@ * store # of download files extracted from the archive and download table */ HighIoAdapter->downloadAddr = HighIoAdapter->DspCodeBaseAddr ; - sharedRam = (dword *)(&BaseIoAdapter->ram[HighIoAdapter->downloadAddr & - (IoAdapter->MemorySize - 1)]) ; + p = DIVA_OS_MEM_ATTACH_RAM(BaseIoAdapter); + sharedRam = (dword *)&p[HighIoAdapter->downloadAddr & (IoAdapter->MemorySize - 1)]; WRITE_DWORD(&(sharedRam[0]), (dword)download_count); memcpy (&sharedRam[1], &download_table[0], sizeof(download_table)) ; @@ -563,6 +589,7 @@ if ( memcmp (&sharedRam[1], &download_table, download_count) ) { DBG_FTL(("%s: Dsp Memory test failed!", IoAdapter->Properties.Name)) } + DIVA_OS_MEM_DETACH_RAM(BaseIoAdapter, p); return (FileLength) ; } @@ -588,6 +615,7 @@ dword phys_start_addr; dword end_addr; byte* sharedRam = 0; + byte *p; if (task) { if (!(fp = OsOpenFile (task))) { @@ -657,18 +685,22 @@ } fp->sysFileSeek (fp, 0, OS_SEEK_SET); - sharedRam = &BaseIoAdapter->ram[phys_start_addr]; + p = DIVA_OS_MEM_ATTACH_RAM(BaseIoAdapter); + sharedRam = &p[phys_start_addr]; if ((dword)fp->sysFileRead (fp, sharedRam, FileLength) != FileLength) { + DIVA_OS_MEM_DETACH_RAM(BaseIoAdapter, p); OsCloseFile (fp) ; DBG_ERR(("Can't read image [%s]", task)) return (0); } + DIVA_OS_MEM_DETACH_RAM(BaseIoAdapter, p); OsCloseFile (fp) ; } + p = DIVA_OS_MEM_ATTACH_RAM(BaseIoAdapter); if (!link_addr) { - link_addr = &BaseIoAdapter->ram[OFFS_DSP_CODE_BASE_ADDR]; + link_addr = &p[OFFS_DSP_CODE_BASE_ADDR]; } DBG_TRC(("Write task [%s] link %08lx at %08lx", @@ -681,6 +713,8 @@ link_addr[2] = (byte)((start_addr >> 16) & 0xff); link_addr[3] = (byte)((start_addr >> 24) & 0xff); + DIVA_OS_MEM_DETACH_RAM(BaseIoAdapter, p); + return (task ? &sharedRam[DIVA_MIPS_TASK_IMAGE_LINK_OFFS] : 0); } @@ -691,6 +725,7 @@ dword i, offset, controller ; word *signature ; int factor = (IoAdapter->tasks == 1) ? 1 : 2; + byte *p; PISDN_ADAPTER Slave ; @@ -751,7 +786,8 @@ Slave->reset = IoAdapter->reset ; Slave->ctlReg = IoAdapter->ctlReg ; Slave->prom = IoAdapter->prom ; - Slave->reset = IoAdapter->reset ; + Slave->Config = IoAdapter->Config ; + Slave->Control = IoAdapter->Control ; if ( !qBri_protocol_load (IoAdapter, Slave) ) return (0) ; @@ -782,9 +818,11 @@ { Slave = IoAdapter->QuadroList->QuadroAdapter[i] ; Slave->ram += (IoAdapter->MemorySize >> factor) - MQ_SHARED_RAM_SIZE ; + p = DIVA_OS_MEM_ATTACH_RAM(Slave); DBG_TRC(("Configure instance %d shared memory @ 0x%08lx", - Slave->ControllerNumber, Slave->ram)) - memset (Slave->ram, '\0', 256) ; + Slave->ControllerNumber, p)) + memset (p, '\0', 256) ; + DIVA_OS_MEM_DETACH_RAM(Slave, p); diva_configure_protocol (Slave); } @@ -792,7 +830,8 @@ * start adapter */ start_qBri_hardware (IoAdapter) ; - signature = (word *)(&IoAdapter->ram[0x1E]) ; + p = DIVA_OS_MEM_ATTACH_RAM(IoAdapter); + signature = (word *)(&p[0x1E]) ; /* * wait for signature in shared memory (max. 3 seconds) */ @@ -802,12 +841,14 @@ if ( signature[0] == 0x4447 ) { + DIVA_OS_MEM_DETACH_RAM(IoAdapter, p); DBG_TRC(("Protocol startup time %d.%02d seconds", (i / 100), (i % 100) )) return (1) ; } } + DIVA_OS_MEM_DETACH_RAM(IoAdapter, p); DBG_FTL(("%s: Adapter selftest failed (0x%04X)!", IoAdapter->Properties.Name, signature[0] >> 16)) qBri_cpu_trapped (IoAdapter) ; @@ -829,16 +870,23 @@ word i ; int serviced = 0 ; + byte *p; + p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); - if ( !(IoAdapter->reset[PLX9054_INTCSR] & 0x80) ) + if ( !(p[PLX9054_INTCSR] & 0x80) ) { + DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); return (0) ; + } + DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); /* * clear interrupt line (reset Local Interrupt Test Register) */ - qBriIrq = (dword volatile *)(&IoAdapter->ctlReg[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST) : (MQ_BREG_IRQ_TEST)]); + p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); + qBriIrq = (dword volatile *)(&p[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST) : (MQ_BREG_IRQ_TEST)]); WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF) ; + DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p); for ( i = 0 ; i < IoAdapter->tasks; ++i ) { @@ -861,15 +909,21 @@ -------------------------------------------------------------------------- */ static void disable_qBri_interrupt (PISDN_ADAPTER IoAdapter) { dword volatile *qBriIrq ; + byte *p; if ( IoAdapter->ControllerNumber > 0 ) return ; - qBriIrq = (dword volatile *)(&IoAdapter->ctlReg[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST) : (MQ_BREG_IRQ_TEST)]); /* * clear interrupt line (reset Local Interrupt Test Register) */ - IoAdapter->reset[PLX9054_INTCSR] = 0x00 ; /* disable PCI interrupts */ + p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); + p[PLX9054_INTCSR] = 0x00 ; /* disable PCI interrupts */ + DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); + + p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); + qBriIrq = (dword volatile *)(&p[DIVA_4BRI_REVISION(IoAdapter) ? (MQ2_BREG_IRQ_TEST) : (MQ_BREG_IRQ_TEST)]); WRITE_DWORD(qBriIrq, MQ_IRQ_REQ_OFF) ; + DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p); } /* -------------------------------------------------------------------------- diff -Nru a/drivers/isdn/hardware/eicon/s_bri.c b/drivers/isdn/hardware/eicon/s_bri.c --- a/drivers/isdn/hardware/eicon/s_bri.c Thu Sep 11 23:03:13 2003 +++ b/drivers/isdn/hardware/eicon/s_bri.c Thu Sep 11 23:03:13 2003 @@ -45,15 +45,16 @@ word *Xlog ; dword regs[4], i, size ; Xdesc xlogDesc ; + byte *Port; /* * first read pointers and trap frame */ if ( !(Xlog = (word *)diva_os_malloc (0, MAX_XLOG_SIZE)) ) return ; - addrHi = IoAdapter->port - + ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH) ; - addrLo = IoAdapter->port + ADDR ; - ioaddr = IoAdapter->port + DATA ; + Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter); + addrHi = Port + ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH) ; + addrLo = Port + ADDR ; + ioaddr = Port + DATA ; outpp (addrHi, 0) ; outppw (addrLo, 0) ; for ( i = 0 ; i < 0x100 ; Xlog[i++] = inppw(ioaddr) ) ; @@ -95,21 +96,28 @@ outpp (addrHi, (byte)((BRI_UNCACHED_ADDR (IoAdapter->MemoryBase + IoAdapter->MemorySize - BRI_SHARED_RAM_SIZE)) >> 16)) ; outppw (addrLo, 0x00) ; + DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port); } /* --------------------------------------------------------------------- Reset hardware --------------------------------------------------------------------- */ static void reset_bri_hardware (PISDN_ADAPTER IoAdapter) { - outpp (IoAdapter->ctlReg, 0x00) ; + byte *p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); + outpp (p, 0x00) ; + DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p); } /* --------------------------------------------------------------------- Halt system --------------------------------------------------------------------- */ static void stop_bri_hardware (PISDN_ADAPTER IoAdapter) { - if (IoAdapter->reset) { - outpp (IoAdapter->reset, 0x00) ; /* disable interrupts ! */ - } - outpp (IoAdapter->ctlReg, 0x00) ; /* clear int, halt cpu */ + byte *p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); + if (p) { + outpp (p, 0x00) ; /* disable interrupts ! */ + } + DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); + p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); + outpp (p, 0x00) ; /* clear int, halt cpu */ + DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p); } #if !defined(DIVA_USER_MODE_CARD_CONFIG) /* { */ /* --------------------------------------------------------------------- @@ -121,6 +129,7 @@ byte* addrHi, *addrLo, *ioaddr ; char *FileName = &IoAdapter->Protocol[0] ; dword Addr, i ; + byte *Port; /* ------------------------------------------------------------------- Try to load protocol code. 'File' points to memory location that does contain entire protocol code @@ -173,10 +182,10 @@ DBG_FTL(("Protocol code '%s' too big (%ld)", FileName, FileLength)) return (0) ; } - addrHi = IoAdapter->port - + ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH) ; - addrLo = IoAdapter->port + ADDR ; - ioaddr = IoAdapter->port + DATA ; + Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter); + addrHi = Port + ((IoAdapter->Properties.Bus == BUS_PCI) ? M_PCI_ADDRH : ADDRH) ; + addrLo = Port + ADDR ; + ioaddr = Port + DATA ; /* * set start address for download (use autoincrement mode !) */ @@ -204,12 +213,14 @@ test = inppw (ioaddr) ; if ( test != File[i/2] ) { + DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port); DBG_FTL(("%s: Memory test failed! (%d - 0x%04X/0x%04X)", IoAdapter->Properties.Name, i, test, File[i/2])) xdiFreeFile (File); return (0) ; } } + DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port); xdiFreeFile (File); return (FileLength) ; } @@ -290,6 +301,7 @@ t_dsp_portable_desc download_table[DSP_MAX_DOWNLOAD_COUNT] ; word download_count ; dword FileLength ; + byte *Port; if (!pinfo) { DBG_ERR (("A: out of memory s_bri at %d", __LINE__)) return (0); @@ -299,11 +311,11 @@ return (0) ; } FileLength = fp->sysFileSize ; + Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter); pinfo->IoAdapter = IoAdapter ; - pinfo->AddrLo = IoAdapter->port + ADDR ; - pinfo->AddrHi = IoAdapter->port +\ - (IoAdapter->Properties.Bus == BUS_PCI ? M_PCI_ADDRH : ADDRH); - pinfo->Data = (word*)(IoAdapter->port + DATA) ; + pinfo->AddrLo = Port + ADDR ; + pinfo->AddrHi = Port + (IoAdapter->Properties.Bus == BUS_PCI ? M_PCI_ADDRH : ADDRH); + pinfo->Data = (word*)(Port + DATA) ; pinfo->DownloadPos = (IoAdapter->DspCodeBaseAddr +\ sizeof(dword) + sizeof(download_table) + 3) & (~3) ; fp->sysLoadDesc = (void *)pinfo; @@ -317,6 +329,7 @@ &download_count, NULL, &download_table[0]) ; if ( error ) { + DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port); DBG_FTL(("download file error: %s", error)) OsCloseFile (fp) ; diva_os_free (0, pinfo); @@ -335,23 +348,25 @@ * copy download table to board */ outppw_buffer (pinfo->Data, &download_table[0], sizeof(download_table)) ; + DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port); diva_os_free (0, pinfo); return (FileLength) ; } /******************************************************************************/ static int load_bri_hardware (PISDN_ADAPTER IoAdapter) { dword i ; - byte* addrHi, *addrLo, *ioaddr ; + byte* addrHi, *addrLo, *ioaddr, *p ; dword test ; + byte *Port; if ( IoAdapter->Properties.Card != CARD_MAE ) { return (FALSE) ; } - addrHi = IoAdapter->port \ - + ((IoAdapter->Properties.Bus==BUS_PCI) ? M_PCI_ADDRH : ADDRH); - addrLo = IoAdapter->port + ADDR ; - ioaddr = IoAdapter->port + DATA ; reset_bri_hardware (IoAdapter) ; + Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter); + addrHi = Port + ((IoAdapter->Properties.Bus==BUS_PCI) ? M_PCI_ADDRH : ADDRH); + addrLo = Port + ADDR ; + ioaddr = Port + DATA ; diva_os_wait (100); /* * recover @@ -366,6 +381,7 @@ IoAdapter->MemorySize - BRI_SHARED_RAM_SIZE)) >> 16)) ; outppw (addrLo, 0) ; for ( i = 0 ; i < 0x8000 ; outppw (ioaddr, 0), ++i ) ; + DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port); diva_os_wait (100) ; /* * download protocol and dsp files @@ -396,6 +412,11 @@ return (FALSE) ; break ; } + + Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter); + addrHi = Port + ((IoAdapter->Properties.Bus==BUS_PCI) ? M_PCI_ADDRH : ADDRH); + addrLo = Port + ADDR ; + ioaddr = Port + DATA ; /* * clear signature */ @@ -408,13 +429,20 @@ * copy parameters */ diva_configure_protocol (IoAdapter); + DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port); /* * start the protocol code */ - outpp (IoAdapter->ctlReg, 0x08) ; + p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); + outpp (p, 0x08) ; + DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p); /* * wait for signature (max. 3 seconds) */ + Port = DIVA_OS_MEM_ATTACH_PORT(IoAdapter); + addrHi = Port + ((IoAdapter->Properties.Bus==BUS_PCI) ? M_PCI_ADDRH : ADDRH); + addrLo = Port + ADDR ; + ioaddr = Port + DATA ; for ( i = 0 ; i < 300 ; ++i ) { diva_os_wait (10) ; @@ -424,11 +452,13 @@ test = (dword)inppw (ioaddr) ; if ( test == 0x4447 ) { + DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port); DBG_TRC(("Protocol startup time %d.%02d seconds", (i / 100), (i % 100) )) return (TRUE) ; } } + DIVA_OS_MEM_DETACH_PORT(IoAdapter, Port); DBG_FTL(("%s: Adapter selftest failed (0x%04X)!", IoAdapter->Properties.Name, test)) bri_cpu_trapped (IoAdapter) ; @@ -441,12 +471,18 @@ #endif /* } */ /******************************************************************************/ static int bri_ISR (struct _ISDN_ADAPTER* IoAdapter) { - if ( !(inpp (IoAdapter->ctlReg) & 0x01) ) + byte *p; + + p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); + if ( !(inpp (p) & 0x01) ) { + DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p); return (0) ; + } /* clear interrupt line */ - outpp (IoAdapter->ctlReg, 0x08) ; + outpp (p, 0x08) ; + DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p); IoAdapter->IrqCount++ ; if ( IoAdapter->Initialized ) { diva_os_schedule_soft_isr (&IoAdapter->isr_soft_isr); @@ -457,11 +493,16 @@ Disable IRQ in the card hardware -------------------------------------------------------------------------- */ static void disable_bri_interrupt (PISDN_ADAPTER IoAdapter) { - if ( IoAdapter->reset ) - { - outpp (IoAdapter->reset, 0x00) ; /* disable interrupts ! */ - } - outpp (IoAdapter->ctlReg, 0x00) ; /* clear int, halt cpu */ + byte *p; + p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); + if ( p ) + { + outpp (p, 0x00) ; /* disable interrupts ! */ + } + DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); + p = DIVA_OS_MEM_ATTACH_CTLREG(IoAdapter); + outpp (p, 0x00) ; /* clear int, halt cpu */ + DIVA_OS_MEM_DETACH_CTLREG(IoAdapter, p); } /* ------------------------------------------------------------------------- Fill card entry points diff -Nru a/drivers/isdn/hardware/eicon/s_pri.c b/drivers/isdn/hardware/eicon/s_pri.c --- a/drivers/isdn/hardware/eicon/s_pri.c Thu Sep 11 23:03:14 2003 +++ b/drivers/isdn/hardware/eicon/s_pri.c Thu Sep 11 23:03:14 2003 @@ -54,7 +54,7 @@ /* * check for trapped MIPS 46xx CPU, dump exception frame */ - base = IoAdapter->ram - MP_SHARED_RAM_OFFSET ; + base = DIVA_OS_MEM_ATTACH_ADDRESS(IoAdapter); TrapID = READ_DWORD(&base[0x80]) ; if ( (TrapID == 0x99999999) || (TrapID == 0x99999901) ) { @@ -68,8 +68,10 @@ regs[0] &= IoAdapter->MemorySize - 1 ; if ( (regs[0] < IoAdapter->MemorySize - 1) ) { - if ( !(Xlog = (word *)diva_os_malloc (0, MAX_XLOG_SIZE)) ) + if ( !(Xlog = (word *)diva_os_malloc (0, MAX_XLOG_SIZE)) ) { + DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, base); return ; + } size = IoAdapter->MemorySize - regs[0] ; if ( size > MAX_XLOG_SIZE ) size = MAX_XLOG_SIZE ; @@ -81,24 +83,29 @@ diva_os_free (0, Xlog) ; IoAdapter->trapped = 2 ; } + DIVA_OS_MEM_DETACH_ADDRESS(IoAdapter, base); } /* ------------------------------------------------------------------------- Hardware reset of PRI card ------------------------------------------------------------------------- */ static void reset_pri_hardware (PISDN_ADAPTER IoAdapter) { - *IoAdapter->reset = _MP_RISC_RESET | _MP_LED1 | _MP_LED2 ; + byte *p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); + *p = _MP_RISC_RESET | _MP_LED1 | _MP_LED2 ; diva_os_wait (50) ; - *IoAdapter->reset = 0x00 ; + *p = 0x00 ; diva_os_wait (50) ; + DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); } /* ------------------------------------------------------------------------- Stop Card Hardware ------------------------------------------------------------------------- */ static void stop_pri_hardware (PISDN_ADAPTER IoAdapter) { dword i; - dword volatile *cfgReg = (dword volatile *)IoAdapter->cfg ; + byte *p; + dword volatile *cfgReg = (dword volatile *)DIVA_OS_MEM_ATTACH_CFG(IoAdapter); cfgReg[3] = 0x00000000 ; cfgReg[1] = 0x00000000 ; + DIVA_OS_MEM_DETACH_CFG(IoAdapter, cfgReg); IoAdapter->a.ram_out (&IoAdapter->a, &RAM->SWReg, SWREG_HALT_CPU) ; i = 0 ; while ( (i < 100) && (IoAdapter->a.ram_in (&IoAdapter->a, &RAM->SWReg) != 0) ) @@ -107,21 +114,25 @@ i++ ; } DBG_TRC(("%s: PRI stopped (%d)", IoAdapter->Name, i)) + cfgReg = (dword volatile *)DIVA_OS_MEM_ATTACH_CFG(IoAdapter); WRITE_DWORD(&cfgReg[0],((dword)(~0x03E00000))); + DIVA_OS_MEM_DETACH_CFG(IoAdapter, cfgReg); diva_os_wait (1) ; - *IoAdapter->reset = _MP_RISC_RESET | _MP_LED1 | _MP_LED2 ; + p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); + *p = _MP_RISC_RESET | _MP_LED1 | _MP_LED2 ; + DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); } #if !defined(DIVA_USER_MODE_CARD_CONFIG) /* { */ /* ------------------------------------------------------------------------- Load protocol code to the PRI Card ------------------------------------------------------------------------- */ -#define DOWNLOAD_ADDR(IoAdapter) \ - (&IoAdapter->ram[IoAdapter->downloadAddr & (IoAdapter->MemorySize - 1)]) +#define DOWNLOAD_ADDR(IoAdapter) (IoAdapter->downloadAddr & (IoAdapter->MemorySize - 1)) static int pri_protocol_load (PISDN_ADAPTER IoAdapter) { dword FileLength ; dword *File ; dword *sharedRam ; dword Addr ; + byte *p; if (!(File = (dword *)xdiLoadArchive (IoAdapter, &FileLength, 0))) { return (0) ; } @@ -172,14 +183,17 @@ return (0) ; } IoAdapter->downloadAddr = MP_UNCACHED_ADDR (MP_PROTOCOL_OFFSET) ; - sharedRam = (dword *)DOWNLOAD_ADDR(IoAdapter) ; + p = DIVA_OS_MEM_ATTACH_RAM(IoAdapter); + sharedRam = (dword *)(&p[DOWNLOAD_ADDR(IoAdapter)]); memcpy (sharedRam, File, FileLength) ; if ( memcmp (sharedRam, File, FileLength) ) { + DIVA_OS_MEM_DETACH_RAM(IoAdapter, p); DBG_FTL(("%s: Memory test failed!", IoAdapter->Properties.Name)) xdiFreeFile (File); return (0) ; } + DIVA_OS_MEM_DETACH_RAM(IoAdapter, p); xdiFreeFile (File); return (1) ; } @@ -228,8 +242,8 @@ static dword diva_pri_detect_dsps (PISDN_ADAPTER IoAdapter) { - /* byte* base = a->resources.pci.addr[2]; */ - byte* base = IoAdapter->reset - MP_RESET ; + byte* base; + byte* p; dword ret = 0, DspCount = 0 ; dword row_offset[] = { 0x00000000, @@ -242,14 +256,18 @@ byte *dsp_addr_port, *dsp_data_port, row_state; int dsp_row = 0, dsp_index, dsp_num; IoAdapter->InitialDspInfo &= 0xffff ; - /* if (!base || !a->xdi_adapter.reset) */ - if (!base || !IoAdapter->reset) + p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); + if (!p) { + DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); return (0); } - /* *(volatile byte*)(a->xdi_adapter.reset) = _MP_RISC_RESET | _MP_DSP_RESET; */ - *(volatile byte*)(IoAdapter->reset) = _MP_RISC_RESET | _MP_DSP_RESET; + *(volatile byte*)(p) = _MP_RISC_RESET | _MP_DSP_RESET; + DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); diva_os_wait (5) ; + + base = DIVA_OS_MEM_ATTACH_CONTROL(IoAdapter); + for (dsp_num = 0; dsp_num < 30; dsp_num++) { dsp_row = dsp_num / 7 + 1; dsp_index = dsp_num % 7; @@ -264,8 +282,10 @@ DspCount++ ; } } - /* *(volatile byte*)(a->xdi_adapter.reset) = _MP_RISC_RESET | _MP_LED1 | _MP_LED2; */ - *(volatile byte*)(IoAdapter->reset) = _MP_RISC_RESET | _MP_LED1 | _MP_LED2; + DIVA_OS_MEM_DETACH_CONTROL(IoAdapter, base); + + p = DIVA_OS_MEM_ATTACH_RESET(IoAdapter); + *(volatile byte*)(p) = _MP_RISC_RESET | _MP_LED1 | _MP_LED2; diva_os_wait (50) ; /* Verify modules @@ -301,7 +321,8 @@ ((ret >> (3*7)) & 0x7F) ? "Y" : "N")) DBG_LOG(("+-----------------------+")) DBG_LOG(("DSP's(present-absent):%08x-%08x", ret, ~ret & 0x3fffffff)) - *(volatile byte*)(IoAdapter->reset) = 0 ; + *(volatile byte*)(p) = 0 ; + DIVA_OS_MEM_DETACH_RESET(IoAdapter, p); diva_os_wait (50) ; IoAdapter->InitialDspInfo |= DspCount << 16 ; return (ret); @@ -312,6 +333,7 @@ static long pri_download_buffer (OsFileHandle *fp, long length, void **addr) { PISDN_ADAPTER IoAdapter = (PISDN_ADAPTER)fp->sysLoadDesc ; dword *sharedRam ; + byte *p; *addr = (void *)IoAdapter->downloadAddr ; if ( ((dword) length) > IoAdapter->DspCodeBaseAddr + IoAdapter->MaxDspCodeSize - IoAdapter->downloadAddr ) @@ -321,11 +343,15 @@ IoAdapter->downloadAddr + length)) return (-1) ; } - sharedRam = (dword *)DOWNLOAD_ADDR(IoAdapter) ; - if ( fp->sysFileRead (fp, sharedRam, length) != length ) + p = DIVA_OS_MEM_ATTACH_RAM(IoAdapter); + sharedRam = (dword *)(&p[DOWNLOAD_ADDR(IoAdapter)]); + if ( fp->sysFileRead (fp, sharedRam, length) != length ) { + DIVA_OS_MEM_DETACH_RAM(IoAdapter, p); return (-1) ; + } IoAdapter->downloadAddr += length ; IoAdapter->downloadAddr = (IoAdapter->downloadAddr + 3) & (~3) ; + DIVA_OS_MEM_DETACH_RAM(IoAdapter, p); return (0) ; } /* ------------------------------------------------------------------------- @@ -338,6 +364,7 @@ word download_count ; dword *sharedRam ; dword FileLength ; + byte *p; if ( !(fp = OsOpenFile (DSP_TELINDUS_FILE)) ) return (0) ; IoAdapter->downloadAddr = (IoAdapter->DspCodeBaseAddr @@ -363,9 +390,11 @@ * store # of separate download files extracted from archive */ IoAdapter->downloadAddr = IoAdapter->DspCodeBaseAddr ; - sharedRam = (dword *)DOWNLOAD_ADDR(IoAdapter) ; + p = DIVA_OS_MEM_ATTACH_RAM(IoAdapter); + sharedRam = (dword *)(&p[DOWNLOAD_ADDR(IoAdapter)]); WRITE_DWORD(&(sharedRam[0]), (dword)download_count); memcpy (&sharedRam[1], &download_table[0], sizeof(download_table)) ; + DIVA_OS_MEM_DETACH_RAM(IoAdapter, p); return (FileLength) ; } /* ------------------------------------------------------------------------- @@ -374,14 +403,17 @@ #define MIN_DSPS 0x30000000 static int load_pri_hardware (PISDN_ADAPTER IoAdapter) { dword i ; - struct mp_load *boot = (struct mp_load *)IoAdapter->ram ; - if ( IoAdapter->Properties.Card != CARD_MAEP ) + struct mp_load *boot = (struct mp_load *)DIVA_OS_MEM_ATTACH_RAM(IoAdapter); + if ( IoAdapter->Properties.Card != CARD_MAEP ) { + DIVA_OS_MEM_DETACH_RAM(IoAdapter, boot); return (0) ; + } boot->err = 0 ; #if 0 IoAdapter->rstFnc (IoAdapter) ; #else if ( MIN_DSPS != (MIN_DSPS & diva_pri_detect_dsps(IoAdapter)) ) { /* makes reset */ + DIVA_OS_MEM_DETACH_RAM(IoAdapter, boot); DBG_FTL(("%s: DSP error!", IoAdapter->Properties.Name)) return (0) ; } @@ -394,28 +426,36 @@ diva_os_wait (10) ; if ( i == boot->live ) { + DIVA_OS_MEM_DETACH_RAM(IoAdapter, boot); DBG_FTL(("%s: CPU is not alive!", IoAdapter->Properties.Name)) return (0) ; } if ( boot->err ) { + DIVA_OS_MEM_DETACH_RAM(IoAdapter, boot); DBG_FTL(("%s: Board Selftest failed!", IoAdapter->Properties.Name)) return (0) ; } /* * download protocol and dsp files */ - if ( !xdiSetProtocol (IoAdapter, IoAdapter->ProtocolSuffix) ) + if ( !xdiSetProtocol (IoAdapter, IoAdapter->ProtocolSuffix) ) { + DIVA_OS_MEM_DETACH_RAM(IoAdapter, boot); return (0) ; - if ( !pri_protocol_load (IoAdapter) ) + } + if ( !pri_protocol_load (IoAdapter) ) { + DIVA_OS_MEM_DETACH_RAM(IoAdapter, boot); return (0) ; - if ( !pri_telindus_load (IoAdapter) ) + } + if ( !pri_telindus_load (IoAdapter) ) { + DIVA_OS_MEM_DETACH_RAM(IoAdapter, boot); return (0) ; + } /* * copy configuration parameters */ IoAdapter->ram += MP_SHARED_RAM_OFFSET ; - memset (IoAdapter->ram, '\0', 256) ; + memset (boot + MP_SHARED_RAM_OFFSET, '\0', 256) ; diva_configure_protocol (IoAdapter); /* * start adapter @@ -430,11 +470,13 @@ diva_os_wait (10) ; if ( (boot->signature >> 16) == 0x4447 ) { + DIVA_OS_MEM_DETACH_RAM(IoAdapter, boot); DBG_TRC(("Protocol startup time %d.%02d seconds", (i / 100), (i % 100) )) return (1) ; } } + DIVA_OS_MEM_DETACH_RAM(IoAdapter, boot); DBG_FTL(("%s: Adapter selftest failed (0x%04X)!", IoAdapter->Properties.Name, boot->signature >> 16)) pri_cpu_trapped (IoAdapter) ; @@ -449,12 +491,16 @@ PRI Adapter interrupt Service Routine -------------------------------------------------------------------------- */ static int pri_ISR (struct _ISDN_ADAPTER* IoAdapter) { - if ( !((READ_DWORD((dword *)IoAdapter->cfg)) & 0x80000000) ) + byte *cfg = DIVA_OS_MEM_ATTACH_CFG(IoAdapter); + if ( !((READ_DWORD((dword *)cfg)) & 0x80000000) ) { + DIVA_OS_MEM_DETACH_CFG(IoAdapter, cfg); return (0) ; + } /* clear interrupt line */ - WRITE_DWORD(((dword *)IoAdapter->cfg), (dword)~0x03E00000) ; + WRITE_DWORD(((dword *)cfg), (dword)~0x03E00000) ; + DIVA_OS_MEM_DETACH_CFG(IoAdapter, cfg); IoAdapter->IrqCount++ ; if ( IoAdapter->Initialized ) { @@ -466,10 +512,11 @@ Disable interrupt in the card hardware ------------------------------------------------------------------------- */ static void disable_pri_interrupt (PISDN_ADAPTER IoAdapter) { - dword volatile *cfgReg = (dword volatile *)IoAdapter->cfg ; + dword volatile *cfgReg = (dword volatile *)DIVA_OS_MEM_ATTACH_CFG(IoAdapter) ; cfgReg[3] = 0x00000000 ; cfgReg[1] = 0x00000000 ; WRITE_DWORD(&cfgReg[0], (dword)(~0x03E00000)) ; + DIVA_OS_MEM_DETACH_CFG(IoAdapter, cfgReg); } /* ------------------------------------------------------------------------- Install entry points for PRI Adapter diff -Nru a/drivers/isdn/hardware/eicon/um_idi.c b/drivers/isdn/hardware/eicon/um_idi.c --- a/drivers/isdn/hardware/eicon/um_idi.c Thu Sep 11 23:03:13 2003 +++ b/drivers/isdn/hardware/eicon/um_idi.c Thu Sep 11 23:03:13 2003 @@ -1,4 +1,4 @@ -/* $Id: um_idi.c,v 1.1.2.2 2001/02/11 14:40:41 armin Exp $ */ +/* $Id: um_idi.c,v 1.9 2003/09/09 06:00:47 schindler Exp $ */ #include "platform.h" #include "di_defs.h" @@ -37,6 +37,11 @@ static int process_idi_ind(divas_um_idi_entity_t * e, byte ind); static int write_return_code(divas_um_idi_entity_t * e, byte rc); +/* + * include queue functions + */ +#include "dlist.c" + /* -------------------------------------------------------------------------- MAIN -------------------------------------------------------------------------- */ @@ -171,7 +176,15 @@ ------------------------------------------------------------------------ */ int diva_um_idi_nr_of_adapters(void) { - return (diva_q_get_nr_of_entries(&adapter_q)); + int i = 0; + const diva_entity_queue_t * q = &adapter_q; + const diva_entity_link_t *diva_current = q->head; + + while (diva_current) { + i++; + diva_current = diva_current->next; + } + return(i); } /* ------------------------------------------------------------------------ diff -Nru a/drivers/isdn/hardware/eicon/xdi_adapter.h b/drivers/isdn/hardware/eicon/xdi_adapter.h --- a/drivers/isdn/hardware/eicon/xdi_adapter.h Thu Sep 11 23:03:12 2003 +++ b/drivers/isdn/hardware/eicon/xdi_adapter.h Thu Sep 11 23:03:12 2003 @@ -1,4 +1,4 @@ -/* $Id: xdi_adapter.h,v 1.1.2.3 2001/02/16 08:40:36 armin Exp $ */ +/* $Id: xdi_adapter.h,v 1.5 2003/06/21 17:06:08 schindler Exp $ */ #ifndef __DIVA_OS_XDI_ADAPTER_H__ #define __DIVA_OS_XDI_ADAPTER_H__ @@ -14,7 +14,8 @@ dword bar[8]; /* contains context of appropriate BAR Register */ void *addr[8]; /* same bar, but mapped into memory */ dword length[8]; /* bar length */ - + int mem_type_id[10]; + unsigned int qoffset; byte irq; } divas_pci_card_resources_t; diff -Nru a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c --- a/drivers/isdn/hisax/avma1_cs.c Thu Sep 11 23:03:13 2003 +++ b/drivers/isdn/hisax/avma1_cs.c Thu Sep 11 23:03:13 2003 @@ -438,17 +438,6 @@ DEBUG(0, "avma1cs_release(0x%p)\n", link); - /* - If the device is currently in use, we won't release until it - is actually closed. - */ - if (link->open) { - DEBUG(1, "avma1_cs: release postponed, '%s' still open\n", - link->dev->dev_name); - link->state |= DEV_STALE_CONFIG; - return; - } - /* no unregister function with hisax */ HiSax_closecard(local->node.minor); @@ -463,7 +452,6 @@ if (link->state & DEV_STALE_LINK) avma1cs_detach(link); - } /* avma1cs_release */ /*====================================================================== diff -Nru a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c --- a/drivers/isdn/hisax/config.c Thu Sep 11 23:03:13 2003 +++ b/drivers/isdn/hisax/config.c Thu Sep 11 23:03:13 2003 @@ -2113,7 +2113,7 @@ #include -static struct pci_device_id hisax_pci_tbl[] __initdata = { +static struct pci_device_id hisax_pci_tbl[] = { #ifdef CONFIG_HISAX_FRITZPCI {PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, PCI_ANY_ID, PCI_ANY_ID}, #endif diff -Nru a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c --- a/drivers/isdn/hisax/elsa_cs.c Thu Sep 11 23:03:12 2003 +++ b/drivers/isdn/hisax/elsa_cs.c Thu Sep 11 23:03:12 2003 @@ -442,18 +442,6 @@ DEBUG(0, "elsa_cs_release(0x%p)\n", link); - /* - If the device is currently in use, we won't release until it - is actually closed, because until then, we can't be sure that - no one will try to access the device or its data structures. - */ - if (link->open) { - DEBUG(1, "elsa_cs: release postponed, '%s' " - "still open\n", link->dev->dev_name); - link->state |= DEV_STALE_CONFIG; - return; - } - /* Unlink the device chain */ link->dev = NULL; diff -Nru a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c --- a/drivers/isdn/hisax/sedlbauer_cs.c Thu Sep 11 23:03:12 2003 +++ b/drivers/isdn/hisax/sedlbauer_cs.c Thu Sep 11 23:03:12 2003 @@ -535,18 +535,6 @@ { DEBUG(0, "sedlbauer_release(0x%p)\n", link); - /* - If the device is currently in use, we won't release until it - is actually closed, because until then, we can't be sure that - no one will try to access the device or its data structures. - */ - if (link->open) { - DEBUG(1, "sedlbauer_cs: release postponed, '%s' still open\n", - link->dev->dev_name); - link->state |= DEV_STALE_CONFIG; - return; - } - /* Unlink the device chain */ link->dev = NULL; diff -Nru a/drivers/isdn/hysdn/hysdn_init.c b/drivers/isdn/hysdn/hysdn_init.c --- a/drivers/isdn/hysdn/hysdn_init.c Thu Sep 11 23:03:12 2003 +++ b/drivers/isdn/hysdn/hysdn_init.c Thu Sep 11 23:03:12 2003 @@ -21,7 +21,7 @@ #include "hysdn_defs.h" -static struct pci_device_id hysdn_pci_tbl[] __initdata = { +static struct pci_device_id hysdn_pci_tbl[] = { {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_METRO}, {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2}, {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_ERGO}, diff -Nru a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c --- a/drivers/mtd/maps/sa1100-flash.c Thu Sep 11 23:03:11 2003 +++ b/drivers/mtd/maps/sa1100-flash.c Thu Sep 11 23:03:11 2003 @@ -654,28 +654,21 @@ }, { .name = "SIMpad kernel", .size = 0x00100000, - .offset = 0x00080000, - }, { -#ifdef CONFIG_JFFS2_FS - .name = "SIMpad root jffs2", - .size = MTDPART_SIZ_FULL, - .offset = 0x00180000, -#else - .name = "SIMpad initrd", - .size = 0x00300000, - .offset = 0x00180000, + .offset = MTDPART_OFS_APPEND, }, { +#ifdef CONFIG_ROOT_CRAMFS .name = "SIMpad root cramfs", - .size = 0x00300000, - .offset = 0x00480000, - }, { - .name = "SIMpad usr cramfs", - .size = 0x005c0000, - .offset = 0x00780000, + .size =0x00D80000, + .offset = MTDPART_OFS_APPEND + }, { - .name = "SIMpad usr local", + .name = "SIMpad local jffs2", + .size = MTDPART_SIZ_FULL, + .offset = MTDPART_OFS_APPEND +#else + .name = "SIMpad root jffs2", .size = MTDPART_SIZ_FULL, - .offset = 0x00d40000, + .offset = MTDPART_OFS_APPEND #endif } }; @@ -1244,8 +1237,10 @@ } if (machine_is_simpad()) { info[0].base = SA1100_CS0_PHYS; - info[0].size = SZ_32M; - nr = 1; + info[0].size = SZ_16M; + info[1].base = SA1100_CS1_PHYS; + info[1].size = SZ_16M; + nr = 2; } if (machine_is_stork()) { info[0].base = SA1100_CS0_PHYS; diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c --- a/drivers/net/Space.c Thu Sep 11 23:03:11 2003 +++ b/drivers/net/Space.c Thu Sep 11 23:03:11 2003 @@ -97,7 +97,6 @@ extern int mac8390_probe(struct net_device *dev); extern int mac89x0_probe(struct net_device *dev); extern int mc32_probe(struct net_device *dev); -extern struct net_device *sdla_init(void); extern struct net_device *cops_probe(int unit); extern struct net_device *ltpc_probe(void); @@ -470,10 +469,6 @@ #ifdef CONFIG_LTPC ltpc_probe(); #endif -#ifdef CONFIG_SDLA - sdla_init(); -#endif - } /* diff -Nru a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c --- a/drivers/net/bonding/bond_3ad.c Thu Sep 11 23:03:13 2003 +++ b/drivers/net/bonding/bond_3ad.c Thu Sep 11 23:03:13 2003 @@ -37,6 +37,16 @@ * 2003/05/01 - Shmulik Hen * - Renamed bond_3ad_link_status_changed() to * bond_3ad_handle_link_change() for compatibility with TLB. + * + * 2003/05/20 - Amir Noam + * - Fix long fail over time when releasing last slave of an active + * aggregator - send LACPDU on unbind of slave to tell partner this + * port is no longer aggregatable. + * + * 2003/06/25 - Tsippy Mendelson + * - Send LACPDU as highest priority packet to further fix the above + * problem on very high Tx traffic load where packets may get dropped + * by the slave. */ #include @@ -45,6 +55,7 @@ #include #include #include +#include #include "bonding.h" #include "bond_3ad.h" @@ -905,6 +916,7 @@ skb->mac.raw = skb->data; skb->nh.raw = skb->data + ETH_HLEN; skb->protocol = PKT_TYPE_LACPDU; + skb->priority = TC_PRIO_CONTROL; lacpdu_header = (struct lacpdu_header *)skb_put(skb, length); diff -Nru a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h --- a/drivers/net/bonding/bond_3ad.h Thu Sep 11 23:03:14 2003 +++ b/drivers/net/bonding/bond_3ad.h Thu Sep 11 23:03:14 2003 @@ -165,7 +165,7 @@ // = 0x02 (marker response information) u8 marker_length; // = 0x16 u16 requester_port; // The number assigned to the port by the requester - struct mac_addr requester_system; // The requester’s system id + struct mac_addr requester_system; // The requester's system id u32 requester_transaction_id; // The transaction id allocated by the requester, u16 pad; // = 0 u8 tlv_type_terminator; // = 0x00 diff -Nru a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c --- a/drivers/net/bonding/bond_alb.c Thu Sep 11 23:03:13 2003 +++ b/drivers/net/bonding/bond_alb.c Thu Sep 11 23:03:13 2003 @@ -17,6 +17,13 @@ * * The full GNU General Public License is included in this distribution in the * file called LICENSE. + * + * + * Changes: + * + * 2003/06/25 - Shmulik Hen + * - Fixed signed/unsigned calculation errors that caused load sharing + * to collapse to one slave under very heavy UDP Tx stress. */ #include @@ -246,7 +253,7 @@ { struct slave *slave; struct slave *least_loaded; - u32 curr_gap, max_gap; + s64 curr_gap, max_gap; /* Find the first enabled slave */ slave = bond_get_first_slave(bond); @@ -262,15 +269,15 @@ } least_loaded = slave; - max_gap = (slave->speed * 1000000) - - (SLAVE_TLB_INFO(slave).load * 8); + max_gap = (s64)(slave->speed * 1000000) - + (s64)(SLAVE_TLB_INFO(slave).load * 8); /* Find the slave with the largest gap */ slave = bond_get_next_slave(bond, slave); while (slave) { if (SLAVE_IS_OK(slave)) { - curr_gap = (slave->speed * 1000000) - - (SLAVE_TLB_INFO(slave).load * 8); + curr_gap = (s64)(slave->speed * 1000000) - + (s64)(SLAVE_TLB_INFO(slave).load * 8); if (max_gap < curr_gap) { least_loaded = slave; max_gap = curr_gap; diff -Nru a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c --- a/drivers/net/bonding/bond_main.c Thu Sep 11 23:03:13 2003 +++ b/drivers/net/bonding/bond_main.c Thu Sep 11 23:03:13 2003 @@ -278,7 +278,7 @@ * bonding round-robin mode ignoring links after failover/recovery * * 2003/03/17 - Jay Vosburgh - * - kmalloc fix (GPF_KERNEL to GPF_ATOMIC) reported by + * - kmalloc fix (GFP_KERNEL to GFP_ATOMIC) reported by * Shmulik dot Hen at intel.com. * - Based on discussion on mailing list, changed use of * update_slave_cnt(), created wrapper functions for adding/removing @@ -323,22 +323,22 @@ * 2003/03/18 - Amir Noam , * Tsippy Mendelson and * Shmulik Hen - * - Added support for IEEE 802.3ad Dynamic link aggregation mode. + * - Added support for IEEE 802.3ad Dynamic link aggregation mode. * * 2003/05/01 - Amir Noam - * - Added ABI version control to restore compatibility between - * new/old ifenslave and new/old bonding. + * - Added ABI version control to restore compatibility between + * new/old ifenslave and new/old bonding. * * 2003/05/01 - Shmulik Hen - * - Fixed bug in bond_release_all(): save old value of current_slave - * before setting it to NULL. - * - Changed driver versioning scheme to include version number instead - * of release date (that is already in another field). There are 3 - * fields X.Y.Z where: - * X - Major version - big behavior changes - * Y - Minor version - addition of features - * Z - Extra version - minor changes and bug fixes - * The current version is 1.0.0 as a base line. + * - Fixed bug in bond_release_all(): save old value of current_slave + * before setting it to NULL. + * - Changed driver versioning scheme to include version number instead + * of release date (that is already in another field). There are 3 + * fields X.Y.Z where: + * X - Major version - big behavior changes + * Y - Minor version - addition of features + * Z - Extra version - minor changes and bug fixes + * The current version is 1.0.0 as a base line. * * 2003/05/01 - Tsippy Mendelson and * Amir Noam @@ -371,6 +371,43 @@ * - Added support for Adaptive load balancing mode which is * equivalent to Transmit load balancing + Receive load balancing. * new version - 2.2.0 + * + * 2003/05/15 - Jay Vosburgh + * - Applied fix to activebackup_arp_monitor posted to bonding-devel + * by Tony Cureington . Fixes ARP + * monitor endless failover bug. Version to 2.2.10 + * + * 2003/05/20 - Amir Noam + * - Fixed bug in ABI version control - Don't commit to a specific + * ABI version if receiving unsupported ioctl commands. + * + * 2003/05/22 - Jay Vosburgh + * - Fix ifenslave -c causing bond to loose existing routes; + * added bond_set_mac_address() that doesn't require the + * bond to be down. + * - In conjunction with fix for ifenslave -c, in + * bond_change_active(), changing to the already active slave + * is no longer an error (it successfully does nothing). + * + * 2003/06/30 - Amir Noam + * - Fixed bond_change_active() for ALB/TLB modes. + * Version to 2.2.14. + * + * 2003/07/29 - Amir Noam + * - Fixed ARP monitoring bug. + * Version to 2.2.15. + * + * 2003/07/31 - Willy Tarreau + * - Fixed kernel panic when using ARP monitoring without + * setting bond's IP address. + * Version to 2.2.16. + * + * 2003/08/06 - Amir Noam + * - Back port from 2.6: use alloc_netdev(); fix /proc handling; + * made stats a part of bond struct so no need to allocate + * and free it separately; use standard list operations instead + * of pre-allocated array of bonds. + * Version to 2.3.0. */ #include @@ -415,10 +452,10 @@ #include "bond_3ad.h" #include "bond_alb.h" -#define DRV_VERSION "2.2.0" -#define DRV_RELDATE "April 15, 2003" -#define DRV_NAME "bonding" -#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" +#define DRV_VERSION "2.3.0" +#define DRV_RELDATE "August 6, 2003" +#define DRV_NAME "bonding" +#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" static const char *version = DRV_NAME ".c:v" DRV_VERSION " (" DRV_RELDATE ")\n"; @@ -443,7 +480,7 @@ static int arp_interval = BOND_LINK_ARP_INTERV; static char *arp_ip_target[MAX_ARP_IP_TARGETS] = { NULL, }; -static unsigned long arp_target[MAX_ARP_IP_TARGETS] = { 0, } ; +static u32 arp_target[MAX_ARP_IP_TARGETS] = { 0, } ; static int arp_ip_count = 0; static u32 my_ip = 0; char *arp_target_hw_addr = NULL; @@ -474,8 +511,8 @@ { "balance-xor", BOND_MODE_XOR}, { "broadcast", BOND_MODE_BROADCAST}, { "802.3ad", BOND_MODE_8023AD}, -{ "tlb", BOND_MODE_TLB}, -{ "alb", BOND_MODE_ALB}, +{ "balance-tlb", BOND_MODE_TLB}, +{ "balance-alb", BOND_MODE_ALB}, { NULL, -1}, }; @@ -505,7 +542,7 @@ MODULE_PARM(miimon, "i"); MODULE_PARM_DESC(miimon, "Link check interval in milliseconds"); MODULE_PARM(use_carrier, "i"); -MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; 09 for off, 1 for on (default)"); +MODULE_PARM_DESC(use_carrier, "Use netif_carrier_ok (vs MII ioctls) in miimon; 0 for off, 1 for on (default)"); MODULE_PARM(mode, "s"); MODULE_PARM_DESC(mode, "Mode of operation : 0 for round robin, 1 for active-backup, 2 for xor"); MODULE_PARM(arp_interval, "i"); @@ -545,14 +582,6 @@ static int bond_release_all(struct net_device *master); static int bond_sethwaddr(struct net_device *master, struct net_device *slave); -/* - * bond_get_info is the interface into the /proc filesystem. This is - * a different interface than the BOND_INFO_QUERY ioctl. That is done - * through the generic networking ioctl interface, and bond_info_query - * is the internal function which provides that information. - */ -static int bond_get_info(char *buf, char **start, off_t offset, int length); - /* Caller must hold bond->ptrlock for write */ static inline struct slave* bond_assign_current_slave(struct bonding *bond,struct slave *newslave) @@ -1559,11 +1588,14 @@ #endif bond_set_slave_inactive_flags(new_slave); } - read_lock_irqsave(&(((struct in_device *)slave_dev->ip_ptr)->lock), rflags); - ifap= &(((struct in_device *)slave_dev->ip_ptr)->ifa_list); - ifa = *ifap; - my_ip = ifa->ifa_address; - read_unlock_irqrestore(&(((struct in_device *)slave_dev->ip_ptr)->lock), rflags); + if (((struct in_device *)slave_dev->ip_ptr) != NULL) { + read_lock_irqsave(&(((struct in_device *)slave_dev->ip_ptr)->lock), rflags); + ifap= &(((struct in_device *)slave_dev->ip_ptr)->ifa_list); + ifa = *ifap; + if (ifa != NULL) + my_ip = ifa->ifa_address; + read_unlock_irqrestore(&(((struct in_device *)slave_dev->ip_ptr)->lock), rflags); + } /* if there is a primary slave, remember it */ if (primary != NULL) { @@ -1717,20 +1749,29 @@ } } + /* + * Changing to the current active: do nothing; return success. + */ + if (newactive && (newactive == oldactive)) { + write_unlock_bh(&bond->lock); + return 0; + } + if ((newactive != NULL)&& (oldactive != NULL)&& - (newactive != oldactive)&& (newactive->link == BOND_LINK_UP)&& IS_UP(newactive->dev)) { - bond_set_slave_inactive_flags(oldactive); - bond_set_slave_active_flags(newactive); + if (bond_mode == BOND_MODE_ACTIVEBACKUP) { + bond_set_slave_inactive_flags(oldactive); + bond_set_slave_active_flags(newactive); + } + bond_mc_update(bond, newactive, oldactive); bond_assign_current_slave(bond, newactive); printk("%s : activate %s(old : %s)\n", master_dev->name, newactive->dev->name, oldactive->dev->name); - } - else { + } else { ret = -EINVAL; } write_unlock_bh(&bond->lock); @@ -1929,6 +1970,10 @@ /* release the slave from its bond */ bond_detach_slave(bond, our_slave); + if (bond->primary_slave == our_slave) { + bond->primary_slave = NULL; + } + printk (KERN_INFO "%s: releasing %s interface %s", master->name, (our_slave->state == BOND_STATE_ACTIVE) ? "active" : "backup", @@ -1947,10 +1992,6 @@ master->name); } - if (bond->primary_slave == our_slave) { - bond->primary_slave = NULL; - } - if ((bond_mode == BOND_MODE_TLB) || (bond_mode == BOND_MODE_ALB)) { /* must be called only after the slave has been @@ -2730,10 +2771,8 @@ /* the current slave must tx an arp to ensure backup slaves * rx traffic */ - if ((slave != NULL) && - (((jiffies - slave->dev->last_rx) >= the_delta_in_ticks) && - (my_ip != 0))) { - arp_send_all(slave); + if ((slave != NULL) && (my_ip != 0)) { + arp_send_all(slave); } } @@ -2986,7 +3025,7 @@ } else if (orig_app_abi_ver != app_abi_ver) { printk(KERN_ERR "bonding: Error: already using ifenslave ABI " - "version %d; to upgrade ifenslave to version %d," + "version %d; to upgrade ifenslave to version %d, " "you must first reload bonding.\n", orig_app_abi_ver, app_abi_ver); return -EINVAL; @@ -3285,10 +3324,10 @@ static struct net_device_stats *bond_get_stats(struct net_device *dev) { bonding_t *bond = dev->priv; - struct net_device_stats *stats = bond->stats, *sstats; + struct net_device_stats *stats = &(bond->stats), *sstats; slave_t *slave; - memset(bond->stats, 0, sizeof(struct net_device_stats)); + memset(stats, 0, sizeof(struct net_device_stats)); read_lock_bh(&bond->lock); @@ -3327,132 +3366,136 @@ return stats; } -static int bond_get_info(char *buf, char **start, off_t offset, int length) +#ifdef CONFIG_PROC_FS +static int bond_read_proc(char *buf, char **start, off_t off, int count, int *eof, void *data) { - bonding_t *bond; + struct bonding *bond = (struct bonding *) data; int len = 0; - off_t begin = 0; u16 link; slave_t *slave = NULL; + /* make sure the bond won't be taken away */ + read_lock(&dev_base_lock); + len += sprintf(buf + len, "%s\n", version); - read_lock(&dev_base_lock); - list_for_each_entry(bond, &bond_dev_list, bond_list) { - /* - * This function locks the mutex, so we can't lock it until - * afterwards - */ - link = bond_check_mii_link(bond); + /* + * This function locks the mutex, so we can't lock it until + * afterwards + */ + link = bond_check_mii_link(bond); - len += sprintf(buf + len, "Bonding Mode: %s\n", - bond_mode_name()); + len += sprintf(buf + len, "Bonding Mode: %s\n", + bond_mode_name()); - if ((bond_mode == BOND_MODE_ACTIVEBACKUP) || - (bond_mode == BOND_MODE_TLB) || - (bond_mode == BOND_MODE_ALB)) { - read_lock_bh(&bond->lock); - read_lock(&bond->ptrlock); - if (bond->current_slave != NULL) { - len += sprintf(buf + len, - "Currently Active Slave: %s\n", - bond->current_slave->dev->name); - } - read_unlock(&bond->ptrlock); - read_unlock_bh(&bond->lock); + if ((bond_mode == BOND_MODE_ACTIVEBACKUP) || + (bond_mode == BOND_MODE_TLB) || + (bond_mode == BOND_MODE_ALB)) { + read_lock_bh(&bond->lock); + read_lock(&bond->ptrlock); + if (bond->current_slave != NULL) { + len += sprintf(buf + len, + "Currently Active Slave: %s\n", + bond->current_slave->dev->name); } + read_unlock(&bond->ptrlock); + read_unlock_bh(&bond->lock); + } - len += sprintf(buf + len, "MII Status: "); - len += sprintf(buf + len, - link == BMSR_LSTATUS ? "up\n" : "down\n"); - len += sprintf(buf + len, "MII Polling Interval (ms): %d\n", - miimon); - len += sprintf(buf + len, "Up Delay (ms): %d\n", - updelay * miimon); - len += sprintf(buf + len, "Down Delay (ms): %d\n", - downdelay * miimon); - len += sprintf(buf + len, "Multicast Mode: %s\n", - multicast_mode_name()); + len += sprintf(buf + len, "MII Status: "); + len += sprintf(buf + len, + link == BMSR_LSTATUS ? "up\n" : "down\n"); + len += sprintf(buf + len, "MII Polling Interval (ms): %d\n", + miimon); + len += sprintf(buf + len, "Up Delay (ms): %d\n", + updelay * miimon); + len += sprintf(buf + len, "Down Delay (ms): %d\n", + downdelay * miimon); + len += sprintf(buf + len, "Multicast Mode: %s\n", + multicast_mode_name()); - read_lock_bh(&bond->lock); + read_lock_bh(&bond->lock); - if (bond_mode == BOND_MODE_8023AD) { - struct ad_info ad_info; + if (bond_mode == BOND_MODE_8023AD) { + struct ad_info ad_info; - len += sprintf(buf + len, "\n802.3ad info\n"); + len += sprintf(buf + len, "\n802.3ad info\n"); - if (bond_3ad_get_active_agg_info(bond, &ad_info)) { - len += sprintf(buf + len, "bond %s has no active aggregator\n", bond->device->name); - } else { - len += sprintf(buf + len, "Active Aggregator Info:\n"); + if (bond_3ad_get_active_agg_info(bond, &ad_info)) { + len += sprintf(buf + len, "bond %s has no active aggregator\n", bond->device->name); + } else { + len += sprintf(buf + len, "Active Aggregator Info:\n"); - len += sprintf(buf + len, "\tAggregator ID: %d\n", ad_info.aggregator_id); - len += sprintf(buf + len, "\tNumber of ports: %d\n", ad_info.ports); - len += sprintf(buf + len, "\tActor Key: %d\n", ad_info.actor_key); - len += sprintf(buf + len, "\tPartner Key: %d\n", ad_info.partner_key); - len += sprintf(buf + len, "\tPartner Mac Address: %02x:%02x:%02x:%02x:%02x:%02x\n", - ad_info.partner_system[0], - ad_info.partner_system[1], - ad_info.partner_system[2], - ad_info.partner_system[3], - ad_info.partner_system[4], - ad_info.partner_system[5]); - } + len += sprintf(buf + len, "\tAggregator ID: %d\n", ad_info.aggregator_id); + len += sprintf(buf + len, "\tNumber of ports: %d\n", ad_info.ports); + len += sprintf(buf + len, "\tActor Key: %d\n", ad_info.actor_key); + len += sprintf(buf + len, "\tPartner Key: %d\n", ad_info.partner_key); + len += sprintf(buf + len, "\tPartner Mac Address: %02x:%02x:%02x:%02x:%02x:%02x\n", + ad_info.partner_system[0], + ad_info.partner_system[1], + ad_info.partner_system[2], + ad_info.partner_system[3], + ad_info.partner_system[4], + ad_info.partner_system[5]); } + } - for (slave = bond->prev; slave != (slave_t *)bond; - slave = slave->prev) { - len += sprintf(buf + len, "\nSlave Interface: %s\n", slave->dev->name); - - len += sprintf(buf + len, "MII Status: "); - - len += sprintf(buf + len, - slave->link == BOND_LINK_UP ? - "up\n" : "down\n"); - len += sprintf(buf + len, "Link Failure Count: %d\n", - slave->link_failure_count); - - if (app_abi_ver >= 1) { - len += sprintf(buf + len, - "Permanent HW addr: %02x:%02x:%02x:%02x:%02x:%02x\n", - slave->perm_hwaddr[0], - slave->perm_hwaddr[1], - slave->perm_hwaddr[2], - slave->perm_hwaddr[3], - slave->perm_hwaddr[4], - slave->perm_hwaddr[5]); - } + for (slave = bond->prev; slave != (slave_t *)bond; + slave = slave->prev) { + len += sprintf(buf + len, "\nSlave Interface: %s\n", slave->dev->name); - if (bond_mode == BOND_MODE_8023AD) { - struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator; + len += sprintf(buf + len, "MII Status: "); - if (agg) { - len += sprintf(buf + len, "Aggregator ID: %d\n", - agg->aggregator_identifier); - } else { - len += sprintf(buf + len, "Aggregator ID: N/A\n"); - } - } - } - read_unlock_bh(&bond->lock); + len += sprintf(buf + len, + slave->link == BOND_LINK_UP ? + "up\n" : "down\n"); + len += sprintf(buf + len, "Link Failure Count: %d\n", + slave->link_failure_count); - /* - * Figure out the calcs for the /proc/net interface - */ - *start = buf + (offset - begin); - len -= (offset - begin); - if (len > length) { - len = length; + if (app_abi_ver >= 1) { + len += sprintf(buf + len, + "Permanent HW addr: %02x:%02x:%02x:%02x:%02x:%02x\n", + slave->perm_hwaddr[0], + slave->perm_hwaddr[1], + slave->perm_hwaddr[2], + slave->perm_hwaddr[3], + slave->perm_hwaddr[4], + slave->perm_hwaddr[5]); } - if (len < 0) { - len = 0; + + if (bond_mode == BOND_MODE_8023AD) { + struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator; + + if (agg) { + len += sprintf(buf + len, "Aggregator ID: %d\n", + agg->aggregator_identifier); + } else { + len += sprintf(buf + len, "Aggregator ID: N/A\n"); + } } + } + read_unlock_bh(&bond->lock); + /* + * Figure out the calcs for the /proc/net interface + */ + if (len <= off + count) { + *eof = 1; } + *start = buf + off; + len -= off; + if (len > count) { + len = count; + } + if (len < 0) { + len = 0; + } + read_unlock(&dev_base_lock); return len; } +#endif /* CONFIG_PROC_FS */ static int bond_event(struct notifier_block *this, unsigned long event, void *ptr) @@ -3460,8 +3503,9 @@ struct net_device *event_dev = (struct net_device *)ptr; struct net_device *master = event_dev->master; - if (event == NETDEV_UNREGISTER && master != NULL) + if ((event == NETDEV_UNREGISTER) && (master != NULL)) { bond_release(master, event_dev); + } return NOTIFY_DONE; } @@ -3470,9 +3514,34 @@ .notifier_call = bond_event, }; +static void bond_deinit(struct net_device *dev) +{ + struct bonding *bond = dev->priv; + + list_del(&bond->bond_list); + +#ifdef CONFIG_PROC_FS + remove_proc_entry("info", bond->bond_proc_dir); + remove_proc_entry(dev->name, proc_net); +#endif +} + +static void bond_free_all(void) +{ + struct bonding *bond, *nxt; + + list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) { + struct net_device *dev = bond->device; + + unregister_netdev(dev); + bond_deinit(dev); + kfree(dev); + } +} + static int __init bond_init(struct net_device *dev) { - bonding_t *bond; + struct bonding *bond; int count; #ifdef BONDING_DEBUG @@ -3483,9 +3552,7 @@ /* initialize rwlocks */ rwlock_init(&bond->lock); rwlock_init(&bond->ptrlock); - - /* space is reserved for stats in alloc_netdev call. */ - bond->stats = (struct net_device_stats *)(bond + 1); + bond->next = bond->prev = (slave_t *)bond; bond->current_slave = NULL; bond->current_arp_slave = NULL; @@ -3560,8 +3627,8 @@ bond->bond_proc_dir->owner = THIS_MODULE; bond->bond_proc_info_file = - create_proc_info_entry("info", 0, bond->bond_proc_dir, - bond_get_info); + create_proc_read_entry("info", 0, bond->bond_proc_dir, + bond_read_proc, bond); if (bond->bond_proc_info_file == NULL) { printk(KERN_ERR "%s: Cannot init /proc/net/%s/info\n", dev->name, dev->name); @@ -3571,8 +3638,8 @@ bond->bond_proc_info_file->owner = THIS_MODULE; #endif /* CONFIG_PROC_FS */ - list_add_tail(&bond->bond_list, &bond_dev_list); + return 0; } @@ -3605,6 +3672,7 @@ return -1; } + static int __init bonding_init(void) { int no; @@ -3811,7 +3879,7 @@ arp_interval = 0; } else { u32 ip = in_aton(arp_ip_target[arp_ip_count]); - *(u32 *)(arp_ip_target[arp_ip_count]) = ip; + arp_target[arp_ip_count] = ip; } } @@ -3850,50 +3918,62 @@ primary = NULL; } - register_netdevice_notifier(&bond_netdev_notifier); + rtnl_lock(); + err = 0; for (no = 0; no < max_bonds; no++) { struct net_device *dev; - char name[IFNAMSIZ]; - snprintf(name, IFNAMSIZ, "bond%d", no); + dev = alloc_netdev(sizeof(struct bonding), "", ether_setup); + if (!dev) { + err = -ENOMEM; + goto out_err; + } - dev = alloc_netdev(sizeof(bonding_t) - + sizeof(struct net_device_stats), - name, ether_setup); - if (!dev) - return -ENOMEM; + err = dev_alloc_name(dev, "bond%d"); + if (err < 0) { + kfree(dev); + goto out_err; + } + + /* bond_init() must be called after dev_alloc_name() (for the + * /proc files), but before register_netdevice(), because we + * need to set function pointers. + */ + err = bond_init(dev); + if (err < 0) { + kfree(dev); + goto out_err; + } - dev->init = bond_init; SET_MODULE_OWNER(dev); - if ( (err = register_netdev(dev)) ) { -#ifdef BONDING_DEBUG - printk(KERN_INFO "%s: register_netdev failed %d\n", - dev->name, err); -#endif + err = register_netdevice(dev); + if (err < 0) { + bond_deinit(dev); kfree(dev); - return err; - } + goto out_err; + } } + + rtnl_unlock(); + register_netdevice_notifier(&bond_netdev_notifier); + return 0; + +out_err: + rtnl_unlock(); + + /* free and unregister all bonds that were successfully added */ + bond_free_all(); + + return err; } static void __exit bonding_exit(void) { - struct bonding *bond, *nxt; - unregister_netdevice_notifier(&bond_netdev_notifier); - - list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list) { - struct net_device *dev = bond->device; -#ifdef CONFIG_PROC_FS - remove_proc_entry("info", bond->bond_proc_dir); - remove_proc_entry(dev->name, proc_net); -#endif - unregister_netdev(dev); - free_netdev(dev); - } + bond_free_all(); } module_init(bonding_init); diff -Nru a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h --- a/drivers/net/bonding/bonding.h Thu Sep 11 23:03:11 2003 +++ b/drivers/net/bonding/bonding.h Thu Sep 11 23:03:11 2003 @@ -99,7 +99,7 @@ rwlock_t ptrlock; struct timer_list mii_timer; struct timer_list arp_timer; - struct net_device_stats *stats; + struct net_device_stats stats; #ifdef CONFIG_PROC_FS struct proc_dir_entry *bond_proc_dir; struct proc_dir_entry *bond_proc_info_file; diff -Nru a/drivers/net/dgrs.c b/drivers/net/dgrs.c --- a/drivers/net/dgrs.c Thu Sep 11 23:03:11 2003 +++ b/drivers/net/dgrs.c Thu Sep 11 23:03:11 2003 @@ -120,7 +120,7 @@ #include "dgrs_asstruct.h" #include "dgrs_bcomm.h" -static struct pci_device_id dgrs_pci_tbl[] __initdata = { +static struct pci_device_id dgrs_pci_tbl[] = { { SE6_PCI_VENDOR_ID, SE6_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, }, { } /* Terminating entry */ }; diff -Nru a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h --- a/drivers/net/e1000/e1000.h Thu Sep 11 23:03:11 2003 +++ b/drivers/net/e1000/e1000.h Thu Sep 11 23:03:11 2003 @@ -122,7 +122,12 @@ #define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */ #define AUTO_ALL_MODES 0 -#define E1000_EEPROM_APME 4 +#define E1000_EEPROM_APME 0x0400 + +#ifndef E1000_MASTER_SLAVE +/* Switch to override PHY master/slave setting */ +#define E1000_MASTER_SLAVE e1000_ms_hw_default +#endif /* only works for sizes that are powers of 2 */ #define E1000_ROUNDUP(i, size) ((i) = (((i) + (size) - 1) & ~((size) - 1))) @@ -180,6 +185,7 @@ spinlock_t stats_lock; atomic_t irq_sem; struct work_struct tx_timeout_task; + uint8_t fc_autoneg; struct timer_list blink_timer; unsigned long led_status; @@ -194,6 +200,7 @@ uint32_t tx_head_addr; uint32_t tx_fifo_size; atomic_t tx_fifo_stall; + boolean_t pcix_82544; /* RX */ struct e1000_desc_ring rx_ring; diff -Nru a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c --- a/drivers/net/e1000/e1000_ethtool.c Thu Sep 11 23:03:12 2003 +++ b/drivers/net/e1000/e1000_ethtool.c Thu Sep 11 23:03:12 2003 @@ -190,6 +190,55 @@ return 0; } +static int +e1000_ethtool_gpause(struct e1000_adapter *adapter, + struct ethtool_pauseparam *epause) +{ + struct e1000_hw *hw = &adapter->hw; + + epause->autoneg = + (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); + + if(hw->fc == e1000_fc_rx_pause) + epause->rx_pause = 1; + else if(hw->fc == e1000_fc_tx_pause) + epause->tx_pause = 1; + else if(hw->fc == e1000_fc_full) { + epause->rx_pause = 1; + epause->tx_pause = 1; + } + + return 0; +} + +static int +e1000_ethtool_spause(struct e1000_adapter *adapter, + struct ethtool_pauseparam *epause) +{ + struct e1000_hw *hw = &adapter->hw; + + adapter->fc_autoneg = epause->autoneg; + + if(epause->rx_pause && epause->tx_pause) + hw->fc = e1000_fc_full; + else if(epause->rx_pause && !epause->tx_pause) + hw->fc = e1000_fc_rx_pause; + else if(!epause->rx_pause && epause->tx_pause) + hw->fc = e1000_fc_tx_pause; + else if(!epause->rx_pause && !epause->tx_pause) + hw->fc = e1000_fc_none; + + hw->original_fc = hw->fc; + + if(netif_running(adapter->netdev)) { + e1000_down(adapter); + e1000_up(adapter); + } else + e1000_reset(adapter); + + return 0; +} + static void e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter, struct ethtool_drvinfo *drvinfo) @@ -958,9 +1007,13 @@ case e1000_82544: case e1000_82540: case e1000_82545: + case e1000_82545_rev_3: case e1000_82546: + case e1000_82546_rev_3: case e1000_82541: + case e1000_82541_rev_2: case e1000_82547: + case e1000_82547_rev_2: return e1000_integrated_phy_loopback(adapter); break; @@ -983,9 +1036,12 @@ { uint32_t rctl; - if(adapter->hw.media_type == e1000_media_type_fiber) { + if(adapter->hw.media_type == e1000_media_type_fiber || + adapter->hw.media_type == e1000_media_type_internal_serdes) { if(adapter->hw.mac_type == e1000_82545 || - adapter->hw.mac_type == e1000_82546) + adapter->hw.mac_type == e1000_82546 || + adapter->hw.mac_type == e1000_82545_rev_3 || + adapter->hw.mac_type == e1000_82546_rev_3) return e1000_set_phy_loopback(adapter); else { rctl = E1000_READ_REG(&adapter->hw, RCTL); @@ -1010,9 +1066,12 @@ E1000_WRITE_REG(&adapter->hw, RCTL, rctl); if(adapter->hw.media_type == e1000_media_type_copper || - (adapter->hw.media_type == e1000_media_type_fiber && + ((adapter->hw.media_type == e1000_media_type_fiber || + adapter->hw.media_type == e1000_media_type_internal_serdes) && (adapter->hw.mac_type == e1000_82545 || - adapter->hw.mac_type == e1000_82546))) { + adapter->hw.mac_type == e1000_82546 || + adapter->hw.mac_type == e1000_82545_rev_3 || + adapter->hw.mac_type == e1000_82546_rev_3))) { adapter->hw.autoneg = TRUE; e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_reg); if(phy_reg & MII_CR_LOOPBACK) { @@ -1114,7 +1173,7 @@ e1000_down(adapter); else e1000_reset(adapter); - + if(e1000_reg_test(adapter, &data[0])) eth_test->flags |= ETH_TEST_FL_FAILED; @@ -1162,6 +1221,7 @@ return; case E1000_DEV_ID_82546EB_FIBER: + case E1000_DEV_ID_82546GB_FIBER: /* Wake events only supported on port A for dual fiber */ if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) { wol->supported = 0; @@ -1200,6 +1260,7 @@ return wol->wolopts ? -EOPNOTSUPP : 0; case E1000_DEV_ID_82546EB_FIBER: + case E1000_DEV_ID_82546GB_FIBER: /* Wake events only supported on port A for dual fiber */ if(E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1) return wol->wolopts ? -EOPNOTSUPP : 0; @@ -1436,6 +1497,19 @@ addr += offsetof(struct ethtool_eeprom, data); return e1000_ethtool_seeprom(adapter, &eeprom, addr); + } + case ETHTOOL_GPAUSEPARAM: { + struct ethtool_pauseparam epause = {ETHTOOL_GPAUSEPARAM}; + e1000_ethtool_gpause(adapter, &epause); + if(copy_to_user(addr, &epause, sizeof(epause))) + return -EFAULT; + return 0; + } + case ETHTOOL_SPAUSEPARAM: { + struct ethtool_pauseparam epause; + if(copy_from_user(&epause, addr, sizeof(epause))) + return -EFAULT; + return e1000_ethtool_spause(adapter, &epause); } case ETHTOOL_GSTATS: { struct { diff -Nru a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c --- a/drivers/net/e1000/e1000_hw.c Thu Sep 11 23:03:14 2003 +++ b/drivers/net/e1000/e1000_hw.c Thu Sep 11 23:03:14 2003 @@ -34,14 +34,15 @@ static int32_t e1000_set_phy_type(struct e1000_hw *hw); static void e1000_phy_init_script(struct e1000_hw *hw); -static int32_t e1000_setup_fiber_link(struct e1000_hw *hw); static int32_t e1000_setup_copper_link(struct e1000_hw *hw); +static int32_t e1000_setup_fiber_serdes_link(struct e1000_hw *hw); +static int32_t e1000_adjust_serdes_amplitude(struct e1000_hw *hw); static int32_t e1000_phy_force_speed_duplex(struct e1000_hw *hw); static int32_t e1000_config_mac_to_phy(struct e1000_hw *hw); -static int32_t e1000_force_mac_fc(struct e1000_hw *hw); static void e1000_raise_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl); static void e1000_lower_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl); -static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, uint32_t data, uint16_t count); +static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, uint32_t data, + uint16_t count); static uint16_t e1000_shift_in_mdi_bits(struct e1000_hw *hw); static int32_t e1000_phy_reset_dsp(struct e1000_hw *hw); static int32_t e1000_write_eeprom_spi(struct e1000_hw *hw, uint16_t offset, @@ -52,13 +53,30 @@ static int32_t e1000_spi_eeprom_ready(struct e1000_hw *hw); static void e1000_raise_ee_clk(struct e1000_hw *hw, uint32_t *eecd); static void e1000_lower_ee_clk(struct e1000_hw *hw, uint32_t *eecd); -static void e1000_shift_out_ee_bits(struct e1000_hw *hw, uint16_t data, uint16_t count); +static void e1000_shift_out_ee_bits(struct e1000_hw *hw, uint16_t data, + uint16_t count); +static int32_t e1000_write_phy_reg_ex(struct e1000_hw *hw, uint32_t reg_addr, + uint16_t phy_data); +static int32_t e1000_read_phy_reg_ex(struct e1000_hw *hw,uint32_t reg_addr, + uint16_t *phy_data); static uint16_t e1000_shift_in_ee_bits(struct e1000_hw *hw, uint16_t count); static int32_t e1000_acquire_eeprom(struct e1000_hw *hw); static void e1000_release_eeprom(struct e1000_hw *hw); static void e1000_standby_eeprom(struct e1000_hw *hw); static int32_t e1000_id_led_init(struct e1000_hw * hw); +static int32_t e1000_set_vco_speed(struct e1000_hw *hw); +/* IGP cable length table */ +static const +uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = + { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25, + 25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120}; /****************************************************************************** @@ -100,50 +118,41 @@ DEBUGFUNC("e1000_phy_init_script"); if(hw->phy_init_script) { - msec_delay(10); + msec_delay(20); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x0000); e1000_write_phy_reg(hw,0x0000,0x0140); msec_delay(5); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F95); - e1000_write_phy_reg(hw,0x0015,0x0001); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F71); - e1000_write_phy_reg(hw,0x0011,0xBD21); + if(hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547) { + e1000_write_phy_reg(hw, 0x1F95, 0x0001); + + e1000_write_phy_reg(hw, 0x1F71, 0xBD21); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F79); - e1000_write_phy_reg(hw,0x0019,0x0018); + e1000_write_phy_reg(hw, 0x1F79, 0x0018); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F30); - e1000_write_phy_reg(hw,0x0010,0x1600); + e1000_write_phy_reg(hw, 0x1F30, 0x1600); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F31); - e1000_write_phy_reg(hw,0x0011,0x0014); + e1000_write_phy_reg(hw, 0x1F31, 0x0014); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F32); - e1000_write_phy_reg(hw,0x0012,0x161C); + e1000_write_phy_reg(hw, 0x1F32, 0x161C); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F94); - e1000_write_phy_reg(hw,0x0014,0x0003); + e1000_write_phy_reg(hw, 0x1F94, 0x0003); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F96); - e1000_write_phy_reg(hw,0x0016,0x003F); + e1000_write_phy_reg(hw, 0x1F96, 0x003F); - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x2010); - e1000_write_phy_reg(hw,0x0010,0x0008); + e1000_write_phy_reg(hw, 0x2010, 0x0008); + } else { + e1000_write_phy_reg(hw, 0x1F73, 0x0099); + } - e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x0000); - e1000_write_phy_reg(hw,0x0000,0x3300); + e1000_write_phy_reg(hw, 0x0000, 0x3300); if(hw->mac_type == e1000_82547) { uint16_t fused, fine, coarse; /* Move to analog registers page */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_ANALOG_REGS_PAGE); - e1000_read_phy_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS, &fused); if(!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) { @@ -158,17 +167,14 @@ } else if(coarse == IGP01E1000_ANALOG_FUSE_COARSE_THRESH) fine -= IGP01E1000_ANALOG_FUSE_FINE_10; - fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) | - (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) | + fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) | + (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) | (coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK); e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_CONTROL, fused); - e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_BYPASS, + e1000_write_phy_reg(hw, IGP01E1000_ANALOG_FUSE_BYPASS, IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL); } - /* Return to first page of registers */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_IEEE_REGS_PAGE); } } } @@ -218,32 +224,89 @@ case E1000_DEV_ID_82545EM_FIBER: hw->mac_type = e1000_82545; break; + case E1000_DEV_ID_82545GM_COPPER: + case E1000_DEV_ID_82545GM_FIBER: + case E1000_DEV_ID_82545GM_SERDES: + hw->mac_type = e1000_82545_rev_3; + break; case E1000_DEV_ID_82546EB_COPPER: case E1000_DEV_ID_82546EB_FIBER: case E1000_DEV_ID_82546EB_QUAD_COPPER: hw->mac_type = e1000_82546; break; + case E1000_DEV_ID_82546GB_COPPER: + case E1000_DEV_ID_82546GB_FIBER: + case E1000_DEV_ID_82546GB_SERDES: + hw->mac_type = e1000_82546_rev_3; + break; case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541EP: + case E1000_DEV_ID_82541EI_MOBILE: hw->mac_type = e1000_82541; break; + case E1000_DEV_ID_82541ER: + case E1000_DEV_ID_82541GI: + case E1000_DEV_ID_82541GI_MOBILE: + hw->mac_type = e1000_82541_rev_2; + break; case E1000_DEV_ID_82547EI: hw->mac_type = e1000_82547; break; + case E1000_DEV_ID_82547GI: + hw->mac_type = e1000_82547_rev_2; + break; default: /* Should never have loaded on this device */ return -E1000_ERR_MAC_TYPE; } - return E1000_SUCCESS; } + +/***************************************************************************** + * Set media type and TBI compatibility. + * + * hw - Struct containing variables accessed by shared code + * **************************************************************************/ +void +e1000_set_media_type(struct e1000_hw *hw) +{ + uint32_t status; + + DEBUGFUNC("e1000_set_media_type"); + + if(hw->mac_type != e1000_82543) { + /* tbi_compatibility is only valid on 82543 */ + hw->tbi_compatibility_en = FALSE; + } + + switch (hw->device_id) { + case E1000_DEV_ID_82545GM_SERDES: + case E1000_DEV_ID_82546GB_SERDES: + hw->media_type = e1000_media_type_internal_serdes; + break; + default: + if(hw->mac_type >= e1000_82543) { + status = E1000_READ_REG(hw, STATUS); + if(status & E1000_STATUS_TBIMODE) { + hw->media_type = e1000_media_type_fiber; + /* tbi_compatibility not valid on fiber */ + hw->tbi_compatibility_en = FALSE; + } else { + hw->media_type = e1000_media_type_copper; + } + } else { + /* This is an 82542 (fiber only) */ + hw->media_type = e1000_media_type_fiber; + } + } +} + /****************************************************************************** * Reset the transmit and receive units; mask and clear all interrupts. * * hw - Struct containing variables accessed by shared code *****************************************************************************/ -void +int32_t e1000_reset_hw(struct e1000_hw *hw) { uint32_t ctrl; @@ -280,49 +343,75 @@ */ msec_delay(10); - /* Issue a global reset to the MAC. This will reset the chip's - * transmit, receive, DMA, and link units. It will not effect - * the current PCI configuration. The global reset bit is self- - * clearing, and should clear within a microsecond. - */ - DEBUGOUT("Issuing a global reset to MAC\n"); ctrl = E1000_READ_REG(hw, CTRL); /* Must reset the PHY before resetting the MAC */ if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_PHY_RST)); - msec_delay(5); + msec_delay(5); } + /* Issue a global reset to the MAC. This will reset the chip's + * transmit, receive, DMA, and link units. It will not effect + * the current PCI configuration. The global reset bit is self- + * clearing, and should clear within a microsecond. + */ + DEBUGOUT("Issuing a global reset to MAC\n"); + switch(hw->mac_type) { case e1000_82544: case e1000_82540: case e1000_82545: case e1000_82546: case e1000_82541: + case e1000_82541_rev_2: /* These controllers can't ack the 64-bit write when issuing the * reset, so use IO-mapping as a workaround to issue the reset */ E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST)); break; + case e1000_82545_rev_3: + case e1000_82546_rev_3: + /* Reset is performed on a shadow of the control register */ + E1000_WRITE_REG(hw, CTRL_DUP, (ctrl | E1000_CTRL_RST)); + break; default: E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_RST)); break; } - /* Force a reload from the EEPROM if necessary */ - if(hw->mac_type < e1000_82540) { - /* Wait for reset to complete */ - udelay(10); - ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_EE_RST; - E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); - E1000_WRITE_FLUSH(hw); - /* Wait for EEPROM reload */ - msec_delay(2); - } else { - /* Wait for EEPROM reload (it happens automatically) */ - msec_delay(5); - /* Dissable HW ARPs on ASF enabled adapters */ + /* After MAC reset, force reload of EEPROM to restore power-on settings to + * device. Later controllers reload the EEPROM automatically, so just wait + * for reload to complete. + */ + switch(hw->mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: + case e1000_82543: + case e1000_82544: + /* Wait for reset to complete */ + udelay(10); + ctrl_ext = E1000_READ_REG(hw, CTRL_EXT); + ctrl_ext |= E1000_CTRL_EXT_EE_RST; + E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); + E1000_WRITE_FLUSH(hw); + /* Wait for EEPROM reload */ + msec_delay(2); + break; + case e1000_82541: + case e1000_82541_rev_2: + case e1000_82547: + case e1000_82547_rev_2: + /* Wait for EEPROM reload */ + msec_delay(20); + break; + default: + /* Wait for EEPROM reload (it happens automatically) */ + msec_delay(5); + break; + } + + /* Disable HW ARPs on ASF enabled adapters */ + if(hw->mac_type >= e1000_82540) { manc = E1000_READ_REG(hw, MANC); manc &= ~(E1000_MANC_ARP_EN); E1000_WRITE_REG(hw, MANC, manc); @@ -350,6 +439,8 @@ if(hw->pci_cmd_word & CMD_MEM_WRT_INVALIDATE) e1000_pci_set_mwi(hw); } + + return E1000_SUCCESS; } /****************************************************************************** @@ -366,7 +457,7 @@ int32_t e1000_init_hw(struct e1000_hw *hw) { - uint32_t ctrl, status; + uint32_t ctrl; uint32_t i; int32_t ret_val; uint16_t pcix_cmd_word; @@ -377,31 +468,13 @@ DEBUGFUNC("e1000_init_hw"); /* Initialize Identification LED */ - ret_val = e1000_id_led_init(hw); - if(ret_val < 0) { + if((ret_val = e1000_id_led_init(hw))) { DEBUGOUT("Error Initializing Identification LED\n"); return ret_val; } - /* Set the Media Type and exit with error if it is not valid. */ - if(hw->mac_type != e1000_82543) { - /* tbi_compatibility is only valid on 82543 */ - hw->tbi_compatibility_en = FALSE; - } - - if(hw->mac_type >= e1000_82543) { - status = E1000_READ_REG(hw, STATUS); - if(status & E1000_STATUS_TBIMODE) { - hw->media_type = e1000_media_type_fiber; - /* tbi_compatibility not valid on fiber */ - hw->tbi_compatibility_en = FALSE; - } else { - hw->media_type = e1000_media_type_copper; - } - } else { - /* This is an 82542 (fiber only) */ - hw->media_type = e1000_media_type_fiber; - } + /* Set the media type and TBI compatibility */ + e1000_set_media_type(hw); /* Disabling VLAN filtering. */ DEBUGOUT("Initializing the IEEE VLAN\n"); @@ -446,21 +519,30 @@ E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR); } - /* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */ - if(hw->bus_type == e1000_bus_type_pcix) { - e1000_read_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd_word); - e1000_read_pci_cfg(hw, PCIX_STATUS_REGISTER_HI, &pcix_stat_hi_word); - cmd_mmrbc = (pcix_cmd_word & PCIX_COMMAND_MMRBC_MASK) >> - PCIX_COMMAND_MMRBC_SHIFT; - stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >> - PCIX_STATUS_HI_MMRBC_SHIFT; - if(stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K) - stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K; - if(cmd_mmrbc > stat_mmrbc) { - pcix_cmd_word &= ~PCIX_COMMAND_MMRBC_MASK; - pcix_cmd_word |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT; - e1000_write_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd_word); + switch(hw->mac_type) { + case e1000_82545_rev_3: + case e1000_82546_rev_3: + break; + default: + /* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */ + if(hw->bus_type == e1000_bus_type_pcix) { + e1000_read_pci_cfg(hw, PCIX_COMMAND_REGISTER, &pcix_cmd_word); + e1000_read_pci_cfg(hw, PCIX_STATUS_REGISTER_HI, + &pcix_stat_hi_word); + cmd_mmrbc = (pcix_cmd_word & PCIX_COMMAND_MMRBC_MASK) >> + PCIX_COMMAND_MMRBC_SHIFT; + stat_mmrbc = (pcix_stat_hi_word & PCIX_STATUS_HI_MMRBC_MASK) >> + PCIX_STATUS_HI_MMRBC_SHIFT; + if(stat_mmrbc == PCIX_STATUS_HI_MMRBC_4K) + stat_mmrbc = PCIX_STATUS_HI_MMRBC_2K; + if(cmd_mmrbc > stat_mmrbc) { + pcix_cmd_word &= ~PCIX_COMMAND_MMRBC_MASK; + pcix_cmd_word |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT; + e1000_write_pci_cfg(hw, PCIX_COMMAND_REGISTER, + &pcix_cmd_word); + } } + break; } /* Call a subroutine to configure the link and setup flow control. */ @@ -484,6 +566,46 @@ } /****************************************************************************** + * Adjust SERDES output amplitude based on EEPROM setting. + * + * hw - Struct containing variables accessed by shared code. + *****************************************************************************/ +static int32_t +e1000_adjust_serdes_amplitude(struct e1000_hw *hw) +{ + uint16_t eeprom_data; + int32_t ret_val; + + DEBUGFUNC("e1000_adjust_serdes_amplitude"); + + if(hw->media_type != e1000_media_type_internal_serdes) + return E1000_SUCCESS; + + switch(hw->mac_type) { + case e1000_82545_rev_3: + case e1000_82546_rev_3: + break; + default: + return E1000_SUCCESS; + } + + if ((ret_val = e1000_read_eeprom(hw, EEPROM_SERDES_AMPLITUDE, 1, + &eeprom_data))) { + return ret_val; + } + + if(eeprom_data != EEPROM_RESERVED_WORD) { + /* Adjust SERDES output amplitude only. */ + eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK; + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL, + eeprom_data))) + return ret_val; + } + + return E1000_SUCCESS; +} + +/****************************************************************************** * Configures flow control and link settings. * * hw - Struct containing variables accessed by shared code @@ -554,9 +676,9 @@ } /* Call the necessary subroutine to configure the link. */ - ret_val = (hw->media_type == e1000_media_type_fiber) ? - e1000_setup_fiber_link(hw) : - e1000_setup_copper_link(hw); + ret_val = (hw->media_type == e1000_media_type_copper) ? + e1000_setup_copper_link(hw) : + e1000_setup_fiber_serdes_link(hw); /* Initialize the flow control address, type, and PAUSE timer * registers to their default values. This is done even if flow @@ -595,7 +717,7 @@ } /****************************************************************************** - * Sets up link for a fiber based adapter + * Sets up link for a fiber based or serdes based adapter * * hw - Struct containing variables accessed by shared code * @@ -604,28 +726,37 @@ * and receiver are not enabled. *****************************************************************************/ static int32_t -e1000_setup_fiber_link(struct e1000_hw *hw) +e1000_setup_fiber_serdes_link(struct e1000_hw *hw) { uint32_t ctrl; uint32_t status; uint32_t txcw = 0; uint32_t i; - uint32_t signal; + uint32_t signal = 0; int32_t ret_val; - DEBUGFUNC("e1000_setup_fiber_link"); + DEBUGFUNC("e1000_setup_fiber_serdes_link"); - /* On adapters with a MAC newer that 82544, SW Defineable pin 1 will be + /* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be * set when the optics detect a signal. On older adapters, it will be - * cleared when there is a signal + * cleared when there is a signal. This applies to fiber media only. + * If we're on serdes media, adjust the output amplitude to value set in + * the EEPROM. */ ctrl = E1000_READ_REG(hw, CTRL); - if(hw->mac_type > e1000_82544) signal = E1000_CTRL_SWDPIN1; - else signal = 0; + if(hw->media_type == e1000_media_type_fiber) + signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0; + + if((ret_val = e1000_adjust_serdes_amplitude(hw))) + return ret_val; /* Take the link out of reset */ ctrl &= ~(E1000_CTRL_LRST); + /* Adjust VCO speed to improve BER performance */ + if((ret_val = e1000_set_vco_speed(hw))) + return ret_val; + e1000_config_collision_dist(hw); /* Check for a software override of the flow control settings, and setup @@ -692,8 +823,10 @@ * indication in the Device Status Register. Time-out if a link isn't * seen in 500 milliseconds seconds (Auto-negotiation should complete in * less than 500 milliseconds even if the other end is doing it in SW). + * For internal serdes, we just assume a signal is present, then poll. */ - if((E1000_READ_REG(hw, CTRL) & E1000_CTRL_SWDPIN1) == signal) { + if(hw->media_type == e1000_media_type_internal_serdes || + (E1000_READ_REG(hw, CTRL) & E1000_CTRL_SWDPIN1) == signal) { DEBUGOUT("Looking for Link\n"); for(i = 0; i < (LINK_UP_TIMEOUT / 10); i++) { msec_delay(10); @@ -701,19 +834,20 @@ if(status & E1000_STATUS_LU) break; } if(i == (LINK_UP_TIMEOUT / 10)) { - /* AutoNeg failed to achieve a link, so we'll call - * e1000_check_for_link. This routine will force the link up if we - * detect a signal. This will allow us to communicate with - * non-autonegotiating link partners. - */ DEBUGOUT("Never got a valid link from auto-neg!!!\n"); hw->autoneg_failed = 1; - ret_val = e1000_check_for_link(hw); - if(ret_val < 0) { - DEBUGOUT("Error while checking for link\n"); - return ret_val; + if(hw->media_type == e1000_media_type_fiber) { + /* AutoNeg failed to achieve a link, so we'll call + * e1000_check_for_link. This routine will force the link up if + * we detect a signal. This will allow us to communicate with + * non-autonegotiating link partners. + */ + if((ret_val = e1000_check_for_link(hw))) { + DEBUGOUT("Error while checking for link\n"); + return ret_val; + } + hw->autoneg_failed = 0; } - hw->autoneg_failed = 0; } else { hw->autoneg_failed = 0; DEBUGOUT("Valid Link Found\n"); @@ -721,7 +855,7 @@ } else { DEBUGOUT("No Signal Detected\n"); } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -756,233 +890,281 @@ } /* Make sure we have a valid PHY */ - ret_val = e1000_detect_gig_phy(hw); - if(ret_val < 0) { + if((ret_val = e1000_detect_gig_phy(hw))) { DEBUGOUT("Error, did not detect valid phy.\n"); return ret_val; } DEBUGOUT1("Phy ID = %x \n", hw->phy_id); - if (hw->phy_type == e1000_phy_igp) { + if(hw->mac_type <= e1000_82543 || + hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 || + hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2) + hw->phy_reset_disable = FALSE; - ret_val = e1000_phy_reset(hw); - if(ret_val < 0) { - DEBUGOUT("Error Resetting the PHY\n"); - return ret_val; - } + if(!hw->phy_reset_disable) { + if (hw->phy_type == e1000_phy_igp) { - /* Wait 10ms for MAC to configure PHY from eeprom settings */ - msec_delay(15); + if((ret_val = e1000_phy_reset(hw))) { + DEBUGOUT("Error Resetting the PHY\n"); + return ret_val; + } - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0000) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + /* Wait 10ms for MAC to configure PHY from eeprom settings */ + msec_delay(15); - /* Configure activity LED after PHY reset */ - led_ctrl = E1000_READ_REG(hw, LEDCTL); - led_ctrl &= IGP_ACTIVITY_LED_MASK; - led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); - E1000_WRITE_REG(hw, LEDCTL, led_ctrl); - - if(hw->autoneg_advertised == ADVERTISE_1000_FULL) { - /* Disable SmartSpeed */ - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } - /* Set auto Master/Slave resolution process */ - if(e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; + /* Configure activity LED after PHY reset */ + led_ctrl = E1000_READ_REG(hw, LEDCTL); + led_ctrl &= IGP_ACTIVITY_LED_MASK; + led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); + E1000_WRITE_REG(hw, LEDCTL, led_ctrl); + + /* disable lplu d3 during driver init */ + if((ret_val = e1000_set_d3_lplu_state(hw, FALSE))) { + DEBUGOUT("Error Disabling LPLU D3\n"); + return ret_val; } - phy_data &= ~CR_1000T_MS_ENABLE; - if(e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; + + /* Configure mdi-mdix settings */ + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, + &phy_data))) + return ret_val; + + if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { + hw->dsp_config_state = e1000_dsp_config_disabled; + /* Force MDI for IGP B-0 PHY */ + phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX | + IGP01E1000_PSCR_FORCE_MDI_MDIX); + hw->mdix = 1; + + } else { + hw->dsp_config_state = e1000_dsp_config_enabled; + phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; + + switch (hw->mdix) { + case 1: + phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; + break; + case 2: + phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX; + break; + case 0: + default: + phy_data |= IGP01E1000_PSCR_AUTO_MDIX; + break; + } } - } + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, + phy_data))) + return ret_val; - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + /* set auto-master slave resolution settings */ + if(hw->autoneg) { + e1000_ms_type phy_ms_setting = hw->master_slave; + + if(hw->ffe_config_state == e1000_ffe_config_active) + hw->ffe_config_state = e1000_ffe_config_enabled; + + if(hw->dsp_config_state == e1000_dsp_config_activated) + hw->dsp_config_state = e1000_dsp_config_enabled; + + /* when autonegotiation advertisment is only 1000Mbps then we + * should disable SmartSpeed and enable Auto MasterSlave + * resolution as hardware default. */ + if(hw->autoneg_advertised == ADVERTISE_1000_FULL) { + /* Disable SmartSpeed */ + if((ret_val = e1000_read_phy_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + &phy_data))) + return ret_val; + phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; + if((ret_val = e1000_write_phy_reg(hw, + IGP01E1000_PHY_PORT_CONFIG, + phy_data))) + return ret_val; + /* Set auto Master/Slave resolution process */ + if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, + &phy_data))) + return ret_val; + phy_data &= ~CR_1000T_MS_ENABLE; + if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, + phy_data))) + return ret_val; + } - /* Force MDI for IGP PHY */ - phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX | - IGP01E1000_PSCR_FORCE_MDI_MDIX); + if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, + &phy_data))) + return ret_val; - hw->mdix = 1; + /* load defaults for future use */ + hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ? + ((phy_data & CR_1000T_MS_VALUE) ? + e1000_ms_force_master : + e1000_ms_force_slave) : + e1000_ms_auto; + + switch (phy_ms_setting) { + case e1000_ms_force_master: + phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); + break; + case e1000_ms_force_slave: + phy_data |= CR_1000T_MS_ENABLE; + phy_data &= ~(CR_1000T_MS_VALUE); + break; + case e1000_ms_auto: + phy_data &= ~CR_1000T_MS_ENABLE; + default: + break; + } + if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, + phy_data))) + return ret_val; + } + } else { + /* Enable CRS on TX. This must be set for half-duplex operation. */ + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, + &phy_data))) + return ret_val; - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - } else { - /* Enable CRS on TX. This must be set for half-duplex operation. */ - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; + /* Options: + * MDI/MDI-X = 0 (default) + * 0 - Auto for all speeds + * 1 - MDI mode + * 2 - MDI-X mode + * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) + */ + phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - /* Options: - * MDI/MDI-X = 0 (default) - * 0 - Auto for all speeds - * 1 - MDI mode - * 2 - MDI-X mode - * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) - */ - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; + switch (hw->mdix) { + case 1: + phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; + break; + case 2: + phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; + break; + case 3: + phy_data |= M88E1000_PSCR_AUTO_X_1000T; + break; + case 0: + default: + phy_data |= M88E1000_PSCR_AUTO_X_MODE; + break; + } - switch (hw->mdix) { - case 1: - phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; - break; - case 2: - phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; - break; - case 3: - phy_data |= M88E1000_PSCR_AUTO_X_1000T; - break; - case 0: - default: - phy_data |= M88E1000_PSCR_AUTO_X_MODE; - break; - } + /* Options: + * disable_polarity_correction = 0 (default) + * Automatic Correction for Reversed Cable Polarity + * 0 - Disabled + * 1 - Enabled + */ + phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; + if(hw->disable_polarity_correction == 1) + phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, + phy_data))) + return ret_val; - /* Options: - * disable_polarity_correction = 0 (default) - * Automatic Correction for Reversed Cable Polarity - * 0 - Disabled - * 1 - Enabled - */ - phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; - if(hw->disable_polarity_correction == 1) - phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; - if(e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + /* Force TX_CLK in the Extended PHY Specific Control Register + * to 25MHz clock. + */ + if((ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, + &phy_data))) + return ret_val; - /* Force TX_CLK in the Extended PHY Specific Control Register - * to 25MHz clock. - */ - if(e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data |= M88E1000_EPSCR_TX_CLK_25; + phy_data |= M88E1000_EPSCR_TX_CLK_25; - if (hw->phy_revision < M88E1011_I_REV_4) { - /* Configure Master and Slave downshift values */ - phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); - phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); - if(e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; + if (hw->phy_revision < M88E1011_I_REV_4) { + /* Configure Master and Slave downshift values */ + phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | + M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); + phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | + M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); + if((ret_val = e1000_write_phy_reg(hw, + M88E1000_EXT_PHY_SPEC_CTRL, + phy_data))) + return ret_val; } - } - /* SW Reset the PHY so all changes take effect */ - ret_val = e1000_phy_reset(hw); - if(ret_val < 0) { - DEBUGOUT("Error Resetting the PHY\n"); - return ret_val; + /* SW Reset the PHY so all changes take effect */ + if((ret_val = e1000_phy_reset(hw))) { + DEBUGOUT("Error Resetting the PHY\n"); + return ret_val; + } } - } - /* Options: - * autoneg = 1 (default) - * PHY will advertise value(s) parsed from - * autoneg_advertised and fc - * autoneg = 0 - * PHY will be set to 10H, 10F, 100H, or 100F - * depending on value parsed from forced_speed_duplex. - */ + /* Options: + * autoneg = 1 (default) + * PHY will advertise value(s) parsed from + * autoneg_advertised and fc + * autoneg = 0 + * PHY will be set to 10H, 10F, 100H, or 100F + * depending on value parsed from forced_speed_duplex. + */ + + /* Is autoneg enabled? This is enabled by default or by software + * override. If so, call e1000_phy_setup_autoneg routine to parse the + * autoneg_advertised and fc options. If autoneg is NOT enabled, then + * the user should have provided a speed/duplex override. If so, then + * call e1000_phy_force_speed_duplex to parse and set this up. + */ + if(hw->autoneg) { + /* Perform some bounds checking on the hw->autoneg_advertised + * parameter. If this variable is zero, then set it to the default. + */ + hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT; - /* Is autoneg enabled? This is enabled by default or by software override. - * If so, call e1000_phy_setup_autoneg routine to parse the - * autoneg_advertised and fc options. If autoneg is NOT enabled, then the - * user should have provided a speed/duplex override. If so, then call - * e1000_phy_force_speed_duplex to parse and set this up. - */ - if(hw->autoneg) { - /* Perform some bounds checking on the hw->autoneg_advertised - * parameter. If this variable is zero, then set it to the default. - */ - hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT; + /* If autoneg_advertised is zero, we assume it was not defaulted + * by the calling code so we set to advertise full capability. + */ + if(hw->autoneg_advertised == 0) + hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT; - /* If autoneg_advertised is zero, we assume it was not defaulted - * by the calling code so we set to advertise full capability. - */ - if(hw->autoneg_advertised == 0) - hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT; + DEBUGOUT("Reconfiguring auto-neg advertisement params\n"); + if((ret_val = e1000_phy_setup_autoneg(hw))) { + DEBUGOUT("Error Setting up Auto-Negotiation\n"); + return ret_val; + } + DEBUGOUT("Restarting Auto-Neg\n"); - DEBUGOUT("Reconfiguring auto-neg advertisement params\n"); - ret_val = e1000_phy_setup_autoneg(hw); - if(ret_val < 0) { - DEBUGOUT("Error Setting up Auto-Negotiation\n"); - return ret_val; - } - DEBUGOUT("Restarting Auto-Neg\n"); + /* Restart auto-negotiation by setting the Auto Neg Enable bit and + * the Auto Neg Restart bit in the PHY control register. + */ + if((ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data))) + return ret_val; - /* Restart auto-negotiation by setting the Auto Neg Enable bit and - * the Auto Neg Restart bit in the PHY control register. - */ - if(e1000_read_phy_reg(hw, PHY_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); - if(e1000_write_phy_reg(hw, PHY_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); + if((ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data))) + return ret_val; - /* Does the user want to wait for Auto-Neg to complete here, or - * check at a later time (for example, callback routine). - */ - if(hw->wait_autoneg_complete) { - ret_val = e1000_wait_autoneg(hw); - if(ret_val < 0) { - DEBUGOUT("Error while waiting for autoneg to complete\n"); + /* Does the user want to wait for Auto-Neg to complete here, or + * check at a later time (for example, callback routine). + */ + if(hw->wait_autoneg_complete) { + if((ret_val = e1000_wait_autoneg(hw))) { + DEBUGOUT("Error while waiting for autoneg to complete\n"); + return ret_val; + } + } + hw->get_link_status = TRUE; + } else { + DEBUGOUT("Forcing speed and duplex\n"); + if((ret_val = e1000_phy_force_speed_duplex(hw))) { + DEBUGOUT("Error Forcing Speed and Duplex\n"); return ret_val; } } - hw->get_link_status = TRUE; - } else { - DEBUGOUT("Forcing speed and duplex\n"); - ret_val = e1000_phy_force_speed_duplex(hw); - if(ret_val < 0) { - DEBUGOUT("Error Forcing Speed and Duplex\n"); - return ret_val; - } - } + } /* !hw->phy_reset_disable */ /* Check link status. Wait up to 100 microseconds for link to become * valid. */ for(i = 0; i < 10; i++) { - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; + if(phy_data & MII_SR_LINK_STATUS) { /* We have link, so we need to finish the config process: * 1) Set up the MAC to the current PHY speed/duplex @@ -995,25 +1177,31 @@ if(hw->mac_type >= e1000_82544) { e1000_config_collision_dist(hw); } else { - ret_val = e1000_config_mac_to_phy(hw); - if(ret_val < 0) { + if((ret_val = e1000_config_mac_to_phy(hw))) { DEBUGOUT("Error configuring MAC to PHY settings\n"); return ret_val; - } + } } - ret_val = e1000_config_fc_after_link_up(hw); - if(ret_val < 0) { + if((ret_val = e1000_config_fc_after_link_up(hw))) { DEBUGOUT("Error Configuring Flow Control\n"); return ret_val; } DEBUGOUT("Valid link established!!!\n"); - return 0; + + if(hw->phy_type == e1000_phy_igp) { + if((ret_val = e1000_config_dsp_after_link_change(hw, TRUE))) { + DEBUGOUT("Error Configuring DSP after link up\n"); + return ret_val; + } + } + DEBUGOUT("Valid link established!!!\n"); + return E1000_SUCCESS; } udelay(10); } DEBUGOUT("Unable to establish link!!!\n"); - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -1024,22 +1212,20 @@ int32_t e1000_phy_setup_autoneg(struct e1000_hw *hw) { + int32_t ret_val; uint16_t mii_autoneg_adv_reg; uint16_t mii_1000t_ctrl_reg; DEBUGFUNC("e1000_phy_setup_autoneg"); /* Read the MII Auto-Neg Advertisement Register (Address 4). */ - if(e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, + &mii_autoneg_adv_reg))) + return ret_val; /* Read the MII 1000Base-T Control Register (Address 9). */ - if(e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg))) + return ret_val; /* Need to parse both autoneg_advertised and fc and set up * the appropriate PHY registers. First we will parse for @@ -1145,18 +1331,16 @@ return -E1000_ERR_CONFIG; } - if(e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, + mii_autoneg_adv_reg))) + return ret_val; DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); - if(e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } - return 0; + if((ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg))) + return ret_val; + + return E1000_SUCCESS; } /****************************************************************************** @@ -1192,10 +1376,8 @@ ctrl &= ~E1000_CTRL_ASDE; /* Read the MII Control Register. */ - if(e1000_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg))) + return ret_val; /* We need to disable autoneg in order to force link and duplex. */ @@ -1241,19 +1423,18 @@ E1000_WRITE_REG(hw, CTRL, ctrl); if (hw->phy_type == e1000_phy_m88) { - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, + &phy_data))) + return ret_val; /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI * forced whenever speed are duplex are forced. */ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - if(e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, + phy_data))) + return ret_val; + DEBUGOUT1("M88E1000 PSCR: %x \n", phy_data); /* Need to reset the PHY or these changes will be ignored */ @@ -1262,26 +1443,23 @@ /* Clear Auto-Crossover to force MDI manually. IGP requires MDI * forced whenever speed or duplex are forced. */ - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, + &phy_data))) + return ret_val; phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, + phy_data))) + return ret_val; } /* Write back the modified PHY MII control register. */ - if(e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } udelay(1); + if((ret_val = e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg))) + return ret_val; + /* The wait_autoneg_complete flag may be a little misleading here. * Since we are forcing speed and duplex, Auto-Neg is not enabled. @@ -1300,22 +1478,18 @@ /* Read the MII Status Register and wait for Auto-Neg Complete bit * to be set. */ - if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) + return ret_val; + + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) + return ret_val; + if(mii_status_reg & MII_SR_LINK_STATUS) break; msec_delay(100); } if(i == 0) { /* We didn't get link */ /* Reset the DSP and wait again for link. */ - - ret_val = e1000_phy_reset_dsp(hw); - if(ret_val < 0) { + if((ret_val = e1000_phy_reset_dsp(hw))) { DEBUGOUT("Error Resetting PHY DSP\n"); return ret_val; } @@ -1327,14 +1501,11 @@ /* Read the MII Status Register and wait for Auto-Neg Complete bit * to be set. */ - if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) + return ret_val; + + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) + return ret_val; } } @@ -1343,30 +1514,29 @@ * Extended PHY Specific Control Register to 25MHz clock. This value * defaults back to a 2.5MHz clock when the PHY is reset. */ - if(e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, + &phy_data))) + return ret_val; + phy_data |= M88E1000_EPSCR_TX_CLK_25; - if(e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, + phy_data))) + return ret_val; /* In addition, because of the s/w reset above, we need to enable CRS on * TX. This must be set for both full and half duplex operation. */ - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, + &phy_data))) + return ret_val; + phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - if(e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, + phy_data))) + return ret_val; + } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -1406,6 +1576,7 @@ e1000_config_mac_to_phy(struct e1000_hw *hw) { uint32_t ctrl; + int32_t ret_val; uint16_t phy_data; DEBUGFUNC("e1000_config_mac_to_phy"); @@ -1421,10 +1592,10 @@ * registers depending on negotiated values. */ if (hw->phy_type == e1000_phy_igp) { - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, + &phy_data))) + return ret_val; + if(phy_data & IGP01E1000_PSSR_FULL_DUPLEX) ctrl |= E1000_CTRL_FD; else ctrl &= ~E1000_CTRL_FD; @@ -1440,10 +1611,10 @@ IGP01E1000_PSSR_SPEED_100MBPS) ctrl |= E1000_CTRL_SPD_100; } else { - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, + &phy_data))) + return ret_val; + if(phy_data & M88E1000_PSSR_DPLX) ctrl |= E1000_CTRL_FD; else ctrl &= ~E1000_CTRL_FD; @@ -1459,7 +1630,7 @@ } /* Write the configured values back to the Device Control Reg. */ E1000_WRITE_REG(hw, CTRL, ctrl); - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -1473,7 +1644,7 @@ * by the PHY rather than the MAC. Software must also configure these * bits when link is forced on a fiber connection. *****************************************************************************/ -static int32_t +int32_t e1000_force_mac_fc(struct e1000_hw *hw) { uint32_t ctrl; @@ -1526,7 +1697,7 @@ ctrl &= (~E1000_CTRL_TFCE); E1000_WRITE_REG(hw, CTRL, ctrl); - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -1557,9 +1728,9 @@ * configuration of the MAC to match the "fc" parameter. */ if(((hw->media_type == e1000_media_type_fiber) && (hw->autoneg_failed)) || + ((hw->media_type == e1000_media_type_internal_serdes) && (hw->autoneg_failed)) || ((hw->media_type == e1000_media_type_copper) && (!hw->autoneg))) { - ret_val = e1000_force_mac_fc(hw); - if(ret_val < 0) { + if((ret_val = e1000_force_mac_fc(hw))) { DEBUGOUT("Error forcing flow control settings\n"); return ret_val; } @@ -1575,14 +1746,10 @@ * has completed. We read this twice because this reg has * some "sticky" (latched) bits. */ - if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - DEBUGOUT("PHY Read Error \n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg) < 0) { - DEBUGOUT("PHY Read Error \n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) + return ret_val; + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg))) + return ret_val; if(mii_status_reg & MII_SR_AUTONEG_COMPLETE) { /* The AutoNeg process has completed, so we now need to @@ -1591,14 +1758,12 @@ * Register (Address 5) to determine how flow control was * negotiated. */ - if(e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_nway_adv_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_LP_ABILITY, &mii_nway_lp_ability_reg) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, + &mii_nway_adv_reg))) + return ret_val; + if((ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY, + &mii_nway_lp_ability_reg))) + return ret_val; /* Two bits in the Auto Negotiation Advertisement Register * (Address 4) and two bits in the Auto Negotiation Base @@ -1704,7 +1869,7 @@ hw->original_fc == e1000_fc_tx_pause) { hw->fc = e1000_fc_none; DEBUGOUT("Flow Control = NONE.\r\n"); - } else { + } else if(!hw->fc_strict_ieee) { hw->fc = e1000_fc_rx_pause; DEBUGOUT("Flow Control = RX PAUSE frames only.\r\n"); } @@ -1713,7 +1878,10 @@ * negotiated to HALF DUPLEX, flow control should not be * enabled per IEEE 802.3 spec. */ - e1000_get_speed_and_duplex(hw, &speed, &duplex); + if((ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex))) { + DEBUGOUT("Error getting link speed and duplex\n"); + return ret_val; + } if(duplex == HALF_DUPLEX) hw->fc = e1000_fc_none; @@ -1721,16 +1889,15 @@ /* Now we call a subroutine to actually force the MAC * controller to use the correct flow control settings. */ - ret_val = e1000_force_mac_fc(hw); - if(ret_val < 0) { + if((ret_val = e1000_force_mac_fc(hw))) { DEBUGOUT("Error forcing flow control settings\n"); return ret_val; - } + } } else { DEBUGOUT("Copper PHY and Auto Neg has not completed.\r\n"); } } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -1747,19 +1914,19 @@ uint32_t ctrl; uint32_t status; uint32_t rctl; - uint32_t signal; + uint32_t signal = 0; int32_t ret_val; uint16_t phy_data; uint16_t lp_capability; DEBUGFUNC("e1000_check_for_link"); - /* On adapters with a MAC newer that 82544, SW Defineable pin 1 will be + /* On adapters with a MAC newer than 82544, SW Defineable pin 1 will be * set when the optics detect a signal. On older adapters, it will be - * cleared when there is a signal + * cleared when there is a signal. This applies to fiber media only. */ - if(hw->mac_type > e1000_82544) signal = E1000_CTRL_SWDPIN1; - else signal = 0; + if(hw->media_type == e1000_media_type_fiber) + signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0; ctrl = E1000_READ_REG(hw, CTRL); status = E1000_READ_REG(hw, STATUS); @@ -1777,14 +1944,10 @@ * of the PHY. * Read the register twice since the link bit is sticky. */ - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; if(phy_data & MII_SR_LINK_STATUS) { hw->get_link_status = FALSE; @@ -1794,6 +1957,7 @@ } else { /* No link detected */ + e1000_config_dsp_after_link_change(hw, FALSE); return 0; } @@ -1802,6 +1966,9 @@ */ if(!hw->autoneg) return -E1000_ERR_CONFIG; + /* optimize the dsp settings for the igp phy */ + e1000_config_dsp_after_link_change(hw, TRUE); + /* We have a M88E1000 PHY and Auto-Neg is enabled. If we * have Si on board that is 82544 or newer, Auto * Speed Detection takes care of MAC speed/duplex @@ -1813,8 +1980,7 @@ if(hw->mac_type >= e1000_82544) e1000_config_collision_dist(hw); else { - ret_val = e1000_config_mac_to_phy(hw); - if(ret_val < 0) { + if((ret_val = e1000_config_mac_to_phy(hw))) { DEBUGOUT("Error configuring MAC to PHY settings\n"); return ret_val; } @@ -1824,8 +1990,7 @@ * need to restore the desired flow control settings because we may * have had to re-autoneg with a different link partner. */ - ret_val = e1000_config_fc_after_link_up(hw); - if(ret_val < 0) { + if((ret_val = e1000_config_fc_after_link_up(hw))) { DEBUGOUT("Error configuring flow control\n"); return ret_val; } @@ -1840,10 +2005,9 @@ * partner is TBI-based, and we turn on TBI Compatibility. */ if(hw->tbi_compatibility_en) { - if(e1000_read_phy_reg(hw, PHY_LP_ABILITY, &lp_capability) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY, + &lp_capability))) + return ret_val; if(lp_capability & (NWAY_LPAR_10T_HD_CAPS | NWAY_LPAR_10T_FD_CAPS | NWAY_LPAR_100TX_HD_CAPS | @@ -1900,8 +2064,7 @@ E1000_WRITE_REG(hw, CTRL, ctrl); /* Configure Flow Control after forcing link up. */ - ret_val = e1000_config_fc_after_link_up(hw); - if(ret_val < 0) { + if((ret_val = e1000_config_fc_after_link_up(hw))) { DEBUGOUT("Error configuring flow control\n"); return ret_val; } @@ -1918,7 +2081,7 @@ E1000_WRITE_REG(hw, TXCW, hw->txcw); E1000_WRITE_REG(hw, CTRL, (ctrl & ~E1000_CTRL_SLU)); } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -1928,12 +2091,14 @@ * speed - Speed of the connection * duplex - Duplex setting of the connection *****************************************************************************/ -void +int32_t e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t *speed, uint16_t *duplex) { uint32_t status; + int32_t ret_val; + uint16_t phy_data; DEBUGFUNC("e1000_get_speed_and_duplex"); @@ -1962,6 +2127,27 @@ *speed = SPEED_1000; *duplex = FULL_DUPLEX; } + + /* IGP01 PHY may advertise full duplex operation after speed downgrade even + * if it is operating at half duplex. Here we set the duplex settings to + * match the duplex in the link partner's capabilities. + */ + if(hw->phy_type == e1000_phy_igp && hw->speed_downgraded) { + if((ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_EXP, &phy_data))) + return ret_val; + + if(!(phy_data & NWAY_ER_LP_NWAY_CAPS)) + *duplex = HALF_DUPLEX; + else { + if((ret_val == e1000_read_phy_reg(hw, PHY_LP_ABILITY, &phy_data))) + return ret_val; + if((*speed == SPEED_100 && !(phy_data & NWAY_LPAR_100TX_FD_CAPS)) || + (*speed == SPEED_10 && !(phy_data & NWAY_LPAR_10T_FD_CAPS))) + *duplex = HALF_DUPLEX; + } + } + + return E1000_SUCCESS; } /****************************************************************************** @@ -1972,6 +2158,7 @@ int32_t e1000_wait_autoneg(struct e1000_hw *hw) { + int32_t ret_val; uint16_t i; uint16_t phy_data; @@ -1983,20 +2170,16 @@ /* Read the MII Status Register and wait for Auto-Neg * Complete bit to be set. */ - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; if(phy_data & MII_SR_AUTONEG_COMPLETE) { - return 0; + return E1000_SUCCESS; } msec_delay(100); } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -2010,11 +2193,11 @@ uint32_t *ctrl) { /* Raise the clock input to the Management Data Clock (by setting the MDC - * bit), and then delay 2 microseconds. + * bit), and then delay 10 microseconds. */ E1000_WRITE_REG(hw, CTRL, (*ctrl | E1000_CTRL_MDC)); E1000_WRITE_FLUSH(hw); - udelay(2); + udelay(10); } /****************************************************************************** @@ -2028,11 +2211,11 @@ uint32_t *ctrl) { /* Lower the clock input to the Management Data Clock (by clearing the MDC - * bit), and then delay 2 microseconds. + * bit), and then delay 10 microseconds. */ E1000_WRITE_REG(hw, CTRL, (*ctrl & ~E1000_CTRL_MDC)); E1000_WRITE_FLUSH(hw); - udelay(2); + udelay(10); } /****************************************************************************** @@ -2076,7 +2259,7 @@ E1000_WRITE_REG(hw, CTRL, ctrl); E1000_WRITE_FLUSH(hw); - udelay(2); + udelay(10); e1000_raise_mdi_clk(hw, &ctrl); e1000_lower_mdi_clk(hw, &ctrl); @@ -2138,8 +2321,8 @@ } /***************************************************************************** -* Reads the value from a PHY register -* +* Reads the value from a PHY register, if the value is on a specific non zero +* page, sets the page first. * hw - Struct containing variables accessed by shared code * reg_addr - address of the PHY register to read ******************************************************************************/ @@ -2148,11 +2331,33 @@ uint32_t reg_addr, uint16_t *phy_data) { + uint32_t ret_val; + + DEBUGFUNC("e1000_read_phy_reg"); + + if(hw->phy_type == e1000_phy_igp && + (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { + if((ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, + (uint16_t)reg_addr))) + return ret_val; + } + + ret_val = e1000_read_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr, + phy_data); + + return ret_val; +} + +int32_t +e1000_read_phy_reg_ex(struct e1000_hw *hw, + uint32_t reg_addr, + uint16_t *phy_data) +{ uint32_t i; uint32_t mdic = 0; const uint32_t phy_addr = 1; - DEBUGFUNC("e1000_read_phy_reg"); + DEBUGFUNC("e1000_read_phy_reg_ex"); if(reg_addr > MAX_PHY_REG_ADDRESS) { DEBUGOUT1("PHY Address %d is out of range\n", reg_addr); @@ -2172,7 +2377,7 @@ /* Poll the ready bit to see if the MDI read completed */ for(i = 0; i < 64; i++) { - udelay(10); + udelay(50); mdic = E1000_READ_REG(hw, MDIC); if(mdic & E1000_MDIC_READY) break; } @@ -2214,7 +2419,7 @@ */ *phy_data = e1000_shift_in_mdi_bits(hw); } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -2229,11 +2434,33 @@ uint32_t reg_addr, uint16_t phy_data) { + uint32_t ret_val; + + DEBUGFUNC("e1000_write_phy_reg"); + + if(hw->phy_type == e1000_phy_igp && + (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { + if((ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, + (uint16_t)reg_addr))) + return ret_val; + } + + ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr, + phy_data); + + return ret_val; +} + +int32_t +e1000_write_phy_reg_ex(struct e1000_hw *hw, + uint32_t reg_addr, + uint16_t phy_data) +{ uint32_t i; uint32_t mdic = 0; const uint32_t phy_addr = 1; - DEBUGFUNC("e1000_write_phy_reg"); + DEBUGFUNC("e1000_write_phy_reg_ex"); if(reg_addr > MAX_PHY_REG_ADDRESS) { DEBUGOUT1("PHY Address %d is out of range\n", reg_addr); @@ -2254,7 +2481,7 @@ /* Poll the ready bit to see if the MDI read completed */ for(i = 0; i < 64; i++) { - udelay(10); + udelay(50); mdic = E1000_READ_REG(hw, MDIC); if(mdic & E1000_MDIC_READY) break; } @@ -2284,7 +2511,7 @@ e1000_shift_out_mdi_bits(hw, mdic, 32); } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -2329,11 +2556,6 @@ udelay(150); if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0000) < 0) { - DEBUGOUT("PHY Write Error\n"); - return; - } - /* Configure activity LED after PHY reset */ led_ctrl = E1000_READ_REG(hw, LEDCTL); led_ctrl &= IGP_ACTIVITY_LED_MASK; @@ -2352,24 +2574,26 @@ int32_t e1000_phy_reset(struct e1000_hw *hw) { + int32_t ret_val; uint16_t phy_data; DEBUGFUNC("e1000_phy_reset"); - if(e1000_read_phy_reg(hw, PHY_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data |= MII_CR_RESET; - if(e1000_write_phy_reg(hw, PHY_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } - udelay(1); - if (hw->phy_type == e1000_phy_igp) { + if(hw->mac_type != e1000_82541_rev_2) { + if((ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data))) + return ret_val; + + phy_data |= MII_CR_RESET; + if((ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data))) + return ret_val; + + udelay(1); + } else e1000_phy_hw_reset(hw); + + if(hw->phy_type == e1000_phy_igp) e1000_phy_init_script(hw); - } - return 0; + + return E1000_SUCCESS; } /****************************************************************************** @@ -2380,23 +2604,21 @@ int32_t e1000_detect_gig_phy(struct e1000_hw *hw) { + int32_t phy_init_status, ret_val; uint16_t phy_id_high, phy_id_low; boolean_t match = FALSE; - int32_t phy_init_status; DEBUGFUNC("e1000_detect_gig_phy"); /* Read the PHY ID Registers to identify which PHY is onboard. */ - if(e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high))) + return ret_val; + hw->phy_id = (uint32_t) (phy_id_high << 16); udelay(20); - if(e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low))) + return ret_val; + hw->phy_id |= (uint32_t) (phy_id_low & PHY_REVISION_MASK); hw->phy_revision = (uint32_t) phy_id_low & ~PHY_REVISION_MASK; @@ -2409,11 +2631,15 @@ break; case e1000_82540: case e1000_82545: + case e1000_82545_rev_3: case e1000_82546: + case e1000_82546_rev_3: if(hw->phy_id == M88E1011_I_PHY_ID) match = TRUE; break; case e1000_82541: + case e1000_82541_rev_2: case e1000_82547: + case e1000_82547_rev_2: if(hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE; break; default: @@ -2424,7 +2650,7 @@ if ((match) && (phy_init_status == E1000_SUCCESS)) { DEBUGOUT1("PHY ID 0x%X detected\n", hw->phy_id); - return 0; + return E1000_SUCCESS; } DEBUGOUT1("Invalid PHY ID 0x%X\n", hw->phy_id); return -E1000_ERR_PHY; @@ -2438,17 +2664,16 @@ static int32_t e1000_phy_reset_dsp(struct e1000_hw *hw) { - int32_t ret_val = -E1000_ERR_PHY; + int32_t ret_val; DEBUGFUNC("e1000_phy_reset_dsp"); do { - if(e1000_write_phy_reg(hw, 29, 0x001d) < 0) break; - if(e1000_write_phy_reg(hw, 30, 0x00c1) < 0) break; - if(e1000_write_phy_reg(hw, 30, 0x0000) < 0) break; - ret_val = 0; + if((ret_val = e1000_write_phy_reg(hw, 29, 0x001d))) break; + if((ret_val = e1000_write_phy_reg(hw, 30, 0x00c1))) break; + if((ret_val = e1000_write_phy_reg(hw, 30, 0x0000))) break; + ret_val = E1000_SUCCESS; } while(0); - if(ret_val < 0) DEBUGOUT("PHY Write Error\n"); return ret_val; } @@ -2459,8 +2684,10 @@ * phy_info - PHY information structure ******************************************************************************/ int32_t -e1000_phy_igp_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info) +e1000_phy_igp_get_info(struct e1000_hw *hw, + struct e1000_phy_info *phy_info) { + int32_t ret_val; uint16_t phy_data, polarity, min_length, max_length, average; DEBUGFUNC("e1000_phy_igp_get_info"); @@ -2476,13 +2703,14 @@ phy_info->polarity_correction = e1000_polarity_reversal_enabled; /* Check polarity status */ - if(e1000_check_polarity(hw, &polarity) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_check_polarity(hw, &polarity))) + return ret_val; phy_info->cable_polarity = polarity; - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, + &phy_data))) + return ret_val; phy_info->mdix_mode = (phy_data & IGP01E1000_PSSR_MDIX) >> IGP01E1000_PSSR_MDIX_SHIFT; @@ -2490,8 +2718,8 @@ if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == IGP01E1000_PSSR_SPEED_1000MBPS) { /* Local/Remote Receiver Information are only valid at 1000 Mbps */ - if(e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data))) + return ret_val; phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >> SR_1000T_LOCAL_RX_STATUS_SHIFT; @@ -2499,8 +2727,8 @@ SR_1000T_REMOTE_RX_STATUS_SHIFT; /* Get cable length */ - if(e1000_get_cable_length(hw, &min_length, &max_length) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_get_cable_length(hw, &min_length, &max_length))) + return ret_val; /* transalte to old method */ average = (max_length + min_length) / 2; @@ -2527,8 +2755,10 @@ * phy_info - PHY information structure ******************************************************************************/ int32_t -e1000_phy_m88_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info) +e1000_phy_m88_get_info(struct e1000_hw *hw, + struct e1000_phy_info *phy_info) { + int32_t ret_val; uint16_t phy_data, polarity; DEBUGFUNC("e1000_phy_m88_get_info"); @@ -2537,8 +2767,8 @@ * and it stored in the hw->speed_downgraded parameter. */ phy_info->downshift = hw->speed_downgraded; - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data))) + return ret_val; phy_info->extended_10bt_distance = (phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >> @@ -2548,13 +2778,13 @@ M88E1000_PSCR_POLARITY_REVERSAL_SHIFT; /* Check polarity status */ - if(e1000_check_polarity(hw, &polarity) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_check_polarity(hw, &polarity))) + return ret_val; phy_info->cable_polarity = polarity; - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data))) + return ret_val; phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX) >> M88E1000_PSSR_MDIX_SHIFT; @@ -2566,8 +2796,8 @@ phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> M88E1000_PSSR_CABLE_LENGTH_SHIFT); - if(e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data))) + return ret_val; phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >> SR_1000T_LOCAL_RX_STATUS_SHIFT; @@ -2589,6 +2819,7 @@ e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info) { + int32_t ret_val; uint16_t phy_data; DEBUGFUNC("e1000_phy_get_info"); @@ -2607,20 +2838,18 @@ return -E1000_ERR_CONFIG; } - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; + + if((ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data))) + return ret_val; + if((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) { DEBUGOUT("PHY info is only valid if link is up\n"); return -E1000_ERR_CONFIG; } - if (hw->phy_type == e1000_phy_igp) + if(hw->phy_type == e1000_phy_igp) return e1000_phy_igp_get_info(hw, phy_info); else return e1000_phy_m88_get_info(hw, phy_info); @@ -2636,7 +2865,7 @@ hw->mdix = 1; return -E1000_ERR_CONFIG; } - return 0; + return E1000_SUCCESS; } @@ -2668,7 +2897,9 @@ break; case e1000_82540: case e1000_82545: + case e1000_82545_rev_3: case e1000_82546: + case e1000_82546_rev_3: eeprom->type = e1000_eeprom_microwire; eeprom->opcode_bits = 3; eeprom->delay_usec = 50; @@ -2681,8 +2912,9 @@ } break; case e1000_82541: + case e1000_82541_rev_2: case e1000_82547: - default: + case e1000_82547_rev_2: if (eecd & E1000_EECD_TYPE) { eeprom->type = e1000_eeprom_spi; eeprom->opcode_bits = 8; @@ -2707,6 +2939,18 @@ } } break; + default: + eeprom->type = e1000_eeprom_spi; + eeprom->opcode_bits = 8; + eeprom->delay_usec = 1; + if (eecd & E1000_EECD_ADDR_BITS) { + eeprom->page_size = 32; + eeprom->address_bits = 16; + } else { + eeprom->page_size = 8; + eeprom->address_bits = 8; + } + break; } if (eeprom->type == e1000_eeprom_spi) { @@ -2715,28 +2959,28 @@ eeprom_size &= EEPROM_SIZE_MASK; switch (eeprom_size) { - case EEPROM_SIZE_16KB: - eeprom->word_size = 8192; - break; - case EEPROM_SIZE_8KB: - eeprom->word_size = 4096; - break; - case EEPROM_SIZE_4KB: - eeprom->word_size = 2048; - break; - case EEPROM_SIZE_2KB: - eeprom->word_size = 1024; - break; - case EEPROM_SIZE_1KB: - eeprom->word_size = 512; - break; - case EEPROM_SIZE_512B: - eeprom->word_size = 256; - break; - case EEPROM_SIZE_128B: - default: - eeprom->word_size = 64; - break; + case EEPROM_SIZE_16KB: + eeprom->word_size = 8192; + break; + case EEPROM_SIZE_8KB: + eeprom->word_size = 4096; + break; + case EEPROM_SIZE_4KB: + eeprom->word_size = 2048; + break; + case EEPROM_SIZE_2KB: + eeprom->word_size = 1024; + break; + case EEPROM_SIZE_1KB: + eeprom->word_size = 512; + break; + case EEPROM_SIZE_512B: + eeprom->word_size = 256; + break; + case EEPROM_SIZE_128B: + default: + eeprom->word_size = 64; + break; } } } @@ -2841,7 +3085,8 @@ * hw - Struct containing variables accessed by shared code *****************************************************************************/ static uint16_t -e1000_shift_in_ee_bits(struct e1000_hw *hw, uint16_t count) +e1000_shift_in_ee_bits(struct e1000_hw *hw, + uint16_t count) { uint32_t eecd; uint32_t i; @@ -3101,13 +3346,17 @@ } /* Prepare the EEPROM for reading */ - if (e1000_acquire_eeprom(hw) != E1000_SUCCESS) + if(e1000_acquire_eeprom(hw) != E1000_SUCCESS) return -E1000_ERR_EEPROM; if(eeprom->type == e1000_eeprom_spi) { + uint16_t word_in; uint8_t read_opcode = EEPROM_READ_OPCODE_SPI; - if(e1000_spi_eeprom_ready(hw)) return -E1000_ERR_EEPROM; + if(e1000_spi_eeprom_ready(hw)) { + e1000_release_eeprom(hw); + return -E1000_ERR_EEPROM; + } e1000_standby_eeprom(hw); @@ -3118,30 +3367,35 @@ /* Send the READ command (opcode + addr) */ e1000_shift_out_ee_bits(hw, read_opcode, eeprom->opcode_bits); e1000_shift_out_ee_bits(hw, (uint16_t)(offset*2), eeprom->address_bits); - } - else if(eeprom->type == e1000_eeprom_microwire) { - /* Send the READ command (opcode + addr) */ - e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE_MICROWIRE, - eeprom->opcode_bits); - e1000_shift_out_ee_bits(hw, offset, eeprom->address_bits); - } - /* Read the data. The address of the eeprom internally increments with - * each word (microwire) or byte (spi) being read, saving on the overhead - * of eeprom setup and tear-down. The address counter will roll over if - * reading beyond the size of the eeprom, thus allowing the entire memory - * to be read starting from any offset. */ - for (i = 0; i < words; i++) { - uint16_t word_in = e1000_shift_in_ee_bits(hw, 16); - if (eeprom->type == e1000_eeprom_spi) - word_in = (word_in >> 8) | (word_in << 8); - data[i] = word_in; + /* Read the data. The address of the eeprom internally increments with + * each byte (spi) being read, saving on the overhead of eeprom setup + * and tear-down. The address counter will roll over if reading beyond + * the size of the eeprom, thus allowing the entire memory to be read + * starting from any offset. */ + for (i = 0; i < words; i++) { + word_in = e1000_shift_in_ee_bits(hw, 16); + data[i] = (word_in >> 8) | (word_in << 8); + } + } else if(eeprom->type == e1000_eeprom_microwire) { + for (i = 0; i < words; i++) { + /* Send the READ command (opcode + addr) */ + e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE_MICROWIRE, + eeprom->opcode_bits); + e1000_shift_out_ee_bits(hw, (uint16_t)(offset + i), + eeprom->address_bits); + + /* Read the data. For microwire, each word requires the overhead + * of eeprom setup and tear-down. */ + data[i] = e1000_shift_in_ee_bits(hw, 16); + e1000_standby_eeprom(hw); + } } /* End this read operation */ e1000_release_eeprom(hw); - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -3169,9 +3423,9 @@ checksum += eeprom_data; } - if(checksum == (uint16_t) EEPROM_SUM) { - return 0; - } else { + if(checksum == (uint16_t) EEPROM_SUM) + return E1000_SUCCESS; + else { DEBUGOUT("EEPROM Checksum Invalid\n"); return -E1000_ERR_EEPROM; } @@ -3205,7 +3459,7 @@ DEBUGOUT("EEPROM Write Error\n"); return -E1000_ERR_EEPROM; } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -3403,7 +3657,7 @@ e1000_shift_out_ee_bits(hw, 0, (uint16_t)(eeprom->address_bits - 2)); - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -3437,7 +3691,7 @@ /* Save word 1 in lower half of part_num */ *part_num |= eeprom_data; - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -3463,7 +3717,7 @@ hw->perm_mac_addr[i] = (uint8_t) (eeprom_data & 0x00FF); hw->perm_mac_addr[i+1] = (uint8_t) (eeprom_data >> 8); } - if((hw->mac_type == e1000_82546) && + if(((hw->mac_type == e1000_82546) || (hw->mac_type == e1000_82546_rev_3)) && (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { if(hw->perm_mac_addr[5] & 0x01) hw->perm_mac_addr[5] &= ~(0x01); @@ -3472,7 +3726,7 @@ } for(i = 0; i < NODE_ADDRESS_SIZE; i++) hw->mac_addr[i] = hw->perm_mac_addr[i]; - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -3748,7 +4002,7 @@ if(hw->mac_type < e1000_82540) { /* Nothing to do */ - return 0; + return E1000_SUCCESS; } ledctl = E1000_READ_REG(hw, LEDCTL); @@ -3799,7 +4053,7 @@ break; } } - return 0; + return E1000_SUCCESS; } /****************************************************************************** @@ -3811,49 +4065,48 @@ e1000_setup_led(struct e1000_hw *hw) { uint32_t ledctl; + int32_t ret_val = E1000_SUCCESS; DEBUGFUNC("e1000_setup_led"); - switch(hw->device_id) { - case E1000_DEV_ID_82542: - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82543GC_COPPER: - case E1000_DEV_ID_82544EI_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - case E1000_DEV_ID_82544GC_COPPER: - case E1000_DEV_ID_82544GC_LOM: + switch(hw->mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: + case e1000_82543: + case e1000_82544: /* No setup necessary */ break; - case E1000_DEV_ID_82545EM_FIBER: - case E1000_DEV_ID_82546EB_FIBER: - ledctl = E1000_READ_REG(hw, LEDCTL); - /* Save current LEDCTL settings */ - hw->ledctl_default = ledctl; - /* Turn off LED0 */ - ledctl &= ~(E1000_LEDCTL_LED0_IVRT | - E1000_LEDCTL_LED0_BLINK | - E1000_LEDCTL_LED0_MODE_MASK); - ledctl |= (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT); - E1000_WRITE_REG(hw, LEDCTL, ledctl); - break; - case E1000_DEV_ID_82540EP: - case E1000_DEV_ID_82540EP_LOM: - case E1000_DEV_ID_82540EP_LP: - case E1000_DEV_ID_82540EM: - case E1000_DEV_ID_82540EM_LOM: - case E1000_DEV_ID_82545EM_COPPER: - case E1000_DEV_ID_82546EB_COPPER: - case E1000_DEV_ID_82546EB_QUAD_COPPER: - case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541EP: - case E1000_DEV_ID_82547EI: - E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); - break; + case e1000_82541: + case e1000_82547: + case e1000_82541_rev_2: + case e1000_82547_rev_2: + /* Turn off PHY Smart Power Down (if enabled) */ + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, + &hw->phy_spd_default))) + return ret_val; + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, + (uint16_t)(hw->phy_spd_default & + ~IGP01E1000_GMII_SPD)))) + return ret_val; + /* Fall Through */ default: - DEBUGOUT("Invalid device ID\n"); - return -E1000_ERR_CONFIG; + if(hw->media_type == e1000_media_type_fiber) { + ledctl = E1000_READ_REG(hw, LEDCTL); + /* Save current LEDCTL settings */ + hw->ledctl_default = ledctl; + /* Turn off LED0 */ + ledctl &= ~(E1000_LEDCTL_LED0_IVRT | + E1000_LEDCTL_LED0_BLINK | + E1000_LEDCTL_LED0_MODE_MASK); + ledctl |= (E1000_LEDCTL_MODE_LED_OFF << + E1000_LEDCTL_LED0_MODE_SHIFT); + E1000_WRITE_REG(hw, LEDCTL, ledctl); + } else if(hw->media_type == e1000_media_type_copper) + E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); + break; } - return 0; + + return E1000_SUCCESS; } /****************************************************************************** @@ -3864,39 +4117,33 @@ int32_t e1000_cleanup_led(struct e1000_hw *hw) { + int32_t ret_val = E1000_SUCCESS; + DEBUGFUNC("e1000_cleanup_led"); - switch(hw->device_id) { - case E1000_DEV_ID_82542: - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82543GC_COPPER: - case E1000_DEV_ID_82544EI_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - case E1000_DEV_ID_82544GC_COPPER: - case E1000_DEV_ID_82544GC_LOM: + switch(hw->mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: + case e1000_82543: + case e1000_82544: /* No cleanup necessary */ break; - case E1000_DEV_ID_82540EP: - case E1000_DEV_ID_82540EP_LOM: - case E1000_DEV_ID_82540EP_LP: - case E1000_DEV_ID_82540EM: - case E1000_DEV_ID_82540EM_LOM: - case E1000_DEV_ID_82545EM_COPPER: - case E1000_DEV_ID_82545EM_FIBER: - case E1000_DEV_ID_82546EB_COPPER: - case E1000_DEV_ID_82546EB_FIBER: - case E1000_DEV_ID_82546EB_QUAD_COPPER: - case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541EP: - case E1000_DEV_ID_82547EI: + case e1000_82541: + case e1000_82547: + case e1000_82541_rev_2: + case e1000_82547_rev_2: + /* Turn on PHY Smart Power Down (if previously enabled) */ + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, + hw->phy_spd_default))) + return ret_val; + /* Fall Through */ + default: /* Restore LEDCTL settings */ E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_default); break; - default: - DEBUGOUT("Invalid device ID\n"); - return -E1000_ERR_CONFIG; } - return 0; + + return E1000_SUCCESS; } /****************************************************************************** @@ -3907,50 +4154,44 @@ int32_t e1000_led_on(struct e1000_hw *hw) { - uint32_t ctrl; + uint32_t ctrl = E1000_READ_REG(hw, CTRL); DEBUGFUNC("e1000_led_on"); - switch(hw->device_id) { - case E1000_DEV_ID_82542: - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82543GC_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - ctrl = E1000_READ_REG(hw, CTRL); + switch(hw->mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: + case e1000_82543: /* Set SW Defineable Pin 0 to turn on the LED */ ctrl |= E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; - E1000_WRITE_REG(hw, CTRL, ctrl); - break; - case E1000_DEV_ID_82544EI_COPPER: - case E1000_DEV_ID_82544GC_COPPER: - case E1000_DEV_ID_82544GC_LOM: - case E1000_DEV_ID_82545EM_FIBER: - case E1000_DEV_ID_82546EB_FIBER: - ctrl = E1000_READ_REG(hw, CTRL); - /* Clear SW Defineable Pin 0 to turn on the LED */ - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - E1000_WRITE_REG(hw, CTRL, ctrl); break; - case E1000_DEV_ID_82540EP: - case E1000_DEV_ID_82540EP_LOM: - case E1000_DEV_ID_82540EP_LP: - case E1000_DEV_ID_82540EM: - case E1000_DEV_ID_82540EM_LOM: - case E1000_DEV_ID_82545EM_COPPER: - case E1000_DEV_ID_82546EB_COPPER: - case E1000_DEV_ID_82546EB_QUAD_COPPER: - case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541EP: - case E1000_DEV_ID_82547EI: - E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode2); + case e1000_82544: + if(hw->media_type == e1000_media_type_fiber) { + /* Set SW Defineable Pin 0 to turn on the LED */ + ctrl |= E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; + } else { + /* Clear SW Defineable Pin 0 to turn on the LED */ + ctrl &= ~E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; + } break; default: - DEBUGOUT("Invalid device ID\n"); - return -E1000_ERR_CONFIG; + if(hw->media_type == e1000_media_type_fiber) { + /* Clear SW Defineable Pin 0 to turn on the LED */ + ctrl &= ~E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; + } else if(hw->media_type == e1000_media_type_copper) { + E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode2); + return E1000_SUCCESS; + } + break; } - return 0; + + E1000_WRITE_REG(hw, CTRL, ctrl); + + return E1000_SUCCESS; } /****************************************************************************** @@ -3961,50 +4202,44 @@ int32_t e1000_led_off(struct e1000_hw *hw) { - uint32_t ctrl; + uint32_t ctrl = E1000_READ_REG(hw, CTRL); DEBUGFUNC("e1000_led_off"); - switch(hw->device_id) { - case E1000_DEV_ID_82542: - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82543GC_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - ctrl = E1000_READ_REG(hw, CTRL); + switch(hw->mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: + case e1000_82543: /* Clear SW Defineable Pin 0 to turn off the LED */ ctrl &= ~E1000_CTRL_SWDPIN0; ctrl |= E1000_CTRL_SWDPIO0; - E1000_WRITE_REG(hw, CTRL, ctrl); break; - case E1000_DEV_ID_82544EI_COPPER: - case E1000_DEV_ID_82544GC_COPPER: - case E1000_DEV_ID_82544GC_LOM: - case E1000_DEV_ID_82545EM_FIBER: - case E1000_DEV_ID_82546EB_FIBER: - ctrl = E1000_READ_REG(hw, CTRL); - /* Set SW Defineable Pin 0 to turn off the LED */ - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - E1000_WRITE_REG(hw, CTRL, ctrl); - break; - case E1000_DEV_ID_82540EP: - case E1000_DEV_ID_82540EP_LOM: - case E1000_DEV_ID_82540EP_LP: - case E1000_DEV_ID_82540EM: - case E1000_DEV_ID_82540EM_LOM: - case E1000_DEV_ID_82545EM_COPPER: - case E1000_DEV_ID_82546EB_COPPER: - case E1000_DEV_ID_82546EB_QUAD_COPPER: - case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541EP: - case E1000_DEV_ID_82547EI: - E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); + case e1000_82544: + if(hw->media_type == e1000_media_type_fiber) { + /* Clear SW Defineable Pin 0 to turn off the LED */ + ctrl &= ~E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; + } else { + /* Set SW Defineable Pin 0 to turn off the LED */ + ctrl |= E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; + } break; default: - DEBUGOUT("Invalid device ID\n"); - return -E1000_ERR_CONFIG; + if(hw->media_type == e1000_media_type_fiber) { + /* Set SW Defineable Pin 0 to turn off the LED */ + ctrl |= E1000_CTRL_SWDPIN0; + ctrl |= E1000_CTRL_SWDPIO0; + } else if(hw->media_type == e1000_media_type_copper) { + E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); + return E1000_SUCCESS; + } + break; } - return 0; + + E1000_WRITE_REG(hw, CTRL, ctrl); + + return E1000_SUCCESS; } /****************************************************************************** @@ -4127,8 +4362,7 @@ DEBUGFUNC("e1000_update_adaptive"); if(hw->adaptive_ifs) { - if((hw->collision_delta * hw->ifs_ratio) > - hw->tx_packet_delta) { + if((hw->collision_delta * hw->ifs_ratio) > hw->tx_packet_delta) { if(hw->tx_packet_delta > MIN_NUM_XMITS) { hw->in_ifs_mode = TRUE; if(hw->current_ifs_val < hw->ifs_max_val) { @@ -4140,8 +4374,7 @@ } } } else { - if((hw->in_ifs_mode == TRUE) && - (hw->tx_packet_delta <= MIN_NUM_XMITS)) { + if(hw->in_ifs_mode && (hw->tx_packet_delta <= MIN_NUM_XMITS)) { hw->current_ifs_val = 0; hw->in_ifs_mode = FALSE; E1000_WRITE_REG(hw, AIT, 0); @@ -4324,7 +4557,8 @@ * min_length - The estimated minimum length * max_length - The estimated maximum length * - * returns: E1000_SUCCESS / -E1000_ERR_XXX + * returns: - E1000_ERR_XXX + * E1000_SUCCESS * * This function always returns a ranged length (minimum & maximum). * So for M88 phy's, this function interprets the one value returned from the @@ -4332,9 +4566,11 @@ * For IGP phy's, the function calculates the range by the AGC registers. *****************************************************************************/ int32_t -e1000_get_cable_length(struct e1000_hw *hw, uint16_t *min_length, +e1000_get_cable_length(struct e1000_hw *hw, + uint16_t *min_length, uint16_t *max_length) { + int32_t ret_val; uint16_t agc_value = 0; uint16_t cur_agc, min_agc = IGP01E1000_AGC_LENGTH_TABLE_SIZE; uint16_t i, phy_data; @@ -4345,8 +4581,9 @@ /* Use old method for Phy older than IGP */ if(hw->phy_type == e1000_phy_m88) { - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, + &phy_data))) + return ret_val; /* Convert the enum value to ranged values */ switch((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> @@ -4376,19 +4613,16 @@ break; } } else if(hw->phy_type == e1000_phy_igp) { /* For IGP PHY */ - uint16_t agc_reg_array[IGP01E1000_PHY_AGC_NUM] = {IGP01E1000_PHY_AGC_A, + uint16_t agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = + {IGP01E1000_PHY_AGC_A, IGP01E1000_PHY_AGC_B, IGP01E1000_PHY_AGC_C, IGP01E1000_PHY_AGC_D}; /* Read the AGC registers for all channels */ - for(i = 0; i < IGP01E1000_PHY_AGC_NUM; i++) { - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - agc_reg_array[i]) != E1000_SUCCESS) - return -E1000_ERR_PHY; - if(e1000_read_phy_reg(hw, agc_reg_array[i] & - IGP01E1000_PHY_PAGE_SELECT, &phy_data) != - E1000_SUCCESS) - return -E1000_ERR_PHY; + for(i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { + + if((ret_val = e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data))) + return ret_val; cur_agc = phy_data >> IGP01E1000_AGC_LENGTH_SHIFT; @@ -4404,20 +4638,15 @@ min_agc = cur_agc; } - /* Return to page 0 */ - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0) != - E1000_SUCCESS) - return -E1000_ERR_PHY; - /* Remove the minimal AGC result for length < 50m */ - if(agc_value < IGP01E1000_PHY_AGC_NUM * e1000_igp_cable_length_50) { + if(agc_value < IGP01E1000_PHY_CHANNEL_NUM * e1000_igp_cable_length_50) { agc_value -= min_agc; /* Get the average length of the remaining 3 channels */ - agc_value /= (IGP01E1000_PHY_AGC_NUM - 1); + agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1); } else { /* Get the average length of all the 4 channels. */ - agc_value /= IGP01E1000_PHY_AGC_NUM; + agc_value /= IGP01E1000_PHY_CHANNEL_NUM; } /* Set the range of the calculated length. */ @@ -4439,7 +4668,8 @@ * polarity - output parameter : 0 - Polarity is not reversed * 1 - Polarity is reversed. * - * returns: E1000_SUCCESS / -E1000_ERR_XXX + * returns: - E1000_ERR_XXX + * E1000_SUCCESS * * For phy's older then IGP, this function simply reads the polarity bit in the * Phy Status register. For IGP phy's, this bit is valid only if link speed is @@ -4448,22 +4678,26 @@ * IGP01E1000_PHY_PCS_INIT_REG. *****************************************************************************/ int32_t -e1000_check_polarity(struct e1000_hw *hw, uint16_t *polarity) +e1000_check_polarity(struct e1000_hw *hw, + uint16_t *polarity) { + int32_t ret_val; uint16_t phy_data; DEBUGFUNC("e1000_check_polarity"); if(hw->phy_type == e1000_phy_m88) { /* return the Polarity bit in the Status register. */ - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, + &phy_data))) + return ret_val; *polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) >> M88E1000_PSSR_REV_POLARITY_SHIFT; } else if(hw->phy_type == e1000_phy_igp) { /* Read the Status register to check the speed */ - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data) < 0) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, + &phy_data))) + return ret_val; /* If speed is 1000 Mbps, must read the IGP01E1000_PHY_PCS_INIT_REG to * find the polarity status */ @@ -4471,18 +4705,9 @@ IGP01E1000_PSSR_SPEED_1000MBPS) { /* Read the GIG initialization PCS register (0x00B4) */ - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_PHY_PCS_INIT_REG) < 0) - return -E1000_ERR_PHY; - - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG & - IGP01E1000_PHY_PAGE_SELECT, &phy_data) < 0) - return -E1000_ERR_PHY; - - /* Return to page 0 */ - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0) != - E1000_SUCCESS) - return -E1000_ERR_PHY; + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG, + &phy_data))) + return ret_val; /* Check the polarity bits */ *polarity = (phy_data & IGP01E1000_PHY_POLARITY_MASK) ? 1 : 0; @@ -4502,7 +4727,8 @@ * downshift - output parameter : 0 - No Downshift ocured. * 1 - Downshift ocured. * - * returns: E1000_SUCCESS / -E1000_ERR_XXX + * returns: - E1000_ERR_XXX + * E1000_SUCCESS * * For phy's older then IGP, this function reads the Downshift bit in the Phy * Specific Status register. For IGP phy's, it reads the Downgrade bit in the @@ -4512,25 +4738,287 @@ int32_t e1000_check_downshift(struct e1000_hw *hw) { + int32_t ret_val; uint16_t phy_data; DEBUGFUNC("e1000_check_downshift"); if(hw->phy_type == e1000_phy_igp) { - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH, + &phy_data))) + return ret_val; + hw->speed_downgraded = (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0; } else if(hw->phy_type == e1000_phy_m88) { - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, + &phy_data))) + return ret_val; + hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >> - M88E1000_PSSR_DOWNSHIFT_SHIFT; + M88E1000_PSSR_DOWNSHIFT_SHIFT; } + return E1000_SUCCESS; +} + +/***************************************************************************** + * + * 82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a + * gigabit link is achieved to improve link quality. + * + * hw: Struct containing variables accessed by shared code + * + * returns: - E1000_ERR_PHY if fail to read/write the PHY + * E1000_SUCCESS at any other case. + * + ****************************************************************************/ + +int32_t +e1000_config_dsp_after_link_change(struct e1000_hw *hw, + boolean_t link_up) +{ + int32_t ret_val; + uint16_t phy_data, speed, duplex, i; + uint16_t dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = + {IGP01E1000_PHY_AGC_PARAM_A, + IGP01E1000_PHY_AGC_PARAM_B, + IGP01E1000_PHY_AGC_PARAM_C, + IGP01E1000_PHY_AGC_PARAM_D}; + uint16_t min_length, max_length; + + DEBUGFUNC("e1000_config_dsp_after_link_change"); + + if(hw->phy_type != e1000_phy_igp) + return E1000_SUCCESS; + + if(link_up) { + if((ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex))) { + DEBUGOUT("Error getting link speed and duplex\n"); + return ret_val; + } + + if(speed == SPEED_1000) { + + e1000_get_cable_length(hw, &min_length, &max_length); + + if((hw->dsp_config_state == e1000_dsp_config_enabled) && + min_length >= e1000_igp_cable_length_50) { + + for(i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { + if((ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i], + &phy_data))) + return ret_val; + + phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; + + if((ret_val = e1000_write_phy_reg(hw, dsp_reg_array[i], + phy_data))) + return ret_val; + } + hw->dsp_config_state = e1000_dsp_config_activated; + } + + if((hw->ffe_config_state == e1000_ffe_config_enabled) && + (min_length < e1000_igp_cable_length_50)) { + + uint16_t ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20; + uint32_t idle_errs = 0; + + /* clear previous idle error counts */ + if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, + &phy_data))) + return ret_val; + + for(i = 0; i < ffe_idle_err_timeout; i++) { + udelay(1000); + if((ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, + &phy_data))) + return ret_val; + + idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT); + if(idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) { + hw->ffe_config_state = e1000_ffe_config_active; + + if((ret_val = e1000_write_phy_reg(hw, + IGP01E1000_PHY_DSP_FFE, + IGP01E1000_PHY_DSP_FFE_CM_CP))) + return ret_val; + break; + } + + if(idle_errs) + ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_100; + } + } + } + } else { + if(hw->dsp_config_state == e1000_dsp_config_activated) { + if((ret_val = e1000_write_phy_reg(hw, 0x0000, + IGP01E1000_IEEE_FORCE_GIGA))) + return ret_val; + for(i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { + if((ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i], + &phy_data))) + return ret_val; + + phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; + phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS; + + if((ret_val = e1000_write_phy_reg(hw,dsp_reg_array[i], + phy_data))) + return ret_val; + } + + if((ret_val = e1000_write_phy_reg(hw, 0x0000, + IGP01E1000_IEEE_RESTART_AUTONEG))) + return ret_val; + + hw->dsp_config_state = e1000_dsp_config_enabled; + } + + if(hw->ffe_config_state == e1000_ffe_config_active) { + if((ret_val = e1000_write_phy_reg(hw, 0x0000, + IGP01E1000_IEEE_FORCE_GIGA))) + return ret_val; + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_DSP_FFE, + IGP01E1000_PHY_DSP_FFE_DEFAULT))) + return ret_val; + + if((ret_val = e1000_write_phy_reg(hw, 0x0000, + IGP01E1000_IEEE_RESTART_AUTONEG))) + return ret_val; + hw->ffe_config_state = e1000_ffe_config_enabled; + } + } + return E1000_SUCCESS; +} + +/***************************************************************************** + * + * This function sets the lplu state according to the active flag. When + * activating lplu this function also disables smart speed and vise versa. + * lplu will not be activated unless the device autonegotiation advertisment + * meets standards of either 10 or 10/100 or 10/100/1000 at all duplexes. + * hw: Struct containing variables accessed by shared code + * active - true to enable lplu false to disable lplu. + * + * returns: - E1000_ERR_PHY if fail to read/write the PHY + * E1000_SUCCESS at any other case. + * + ****************************************************************************/ + +int32_t +e1000_set_d3_lplu_state(struct e1000_hw *hw, + boolean_t active) +{ + int32_t ret_val; + uint16_t phy_data; + DEBUGFUNC("e1000_set_d3_lplu_state"); + + if(!((hw->mac_type == e1000_82541_rev_2) || + (hw->mac_type == e1000_82547_rev_2))) + return E1000_SUCCESS; + + /* During driver activity LPLU should not be used or it will attain link + * from the lowest speeds starting from 10Mbps. The capability is used for + * Dx transitions and states */ + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data))) + return ret_val; + + if(!active) { + phy_data &= ~IGP01E1000_GMII_FLEX_SPD; + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data))) + return ret_val; + + /* LPLU and SmartSpeed are mutually exclusive. LPLU is used during + * Dx states where the power conservation is most important. During + * driver activity we should enable SmartSpeed, so performance is + * maintained. */ + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + &phy_data))) + return ret_val; + + phy_data |= IGP01E1000_PSCFR_SMART_SPEED; + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + phy_data))) + return ret_val; + + } else if((hw->autoneg_advertised == AUTONEG_ADVERTISE_SPEED_DEFAULT) || + (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL ) || + (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_100_ALL)) { + + phy_data |= IGP01E1000_GMII_FLEX_SPD; + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data))) + return ret_val; + + /* When LPLU is enabled we should disable SmartSpeed */ + if((ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + &phy_data))) + return ret_val; + + phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; + if((ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + phy_data))) + return ret_val; + + } + return E1000_SUCCESS; +} + +/****************************************************************************** + * Change VCO speed register to improve Bit Error Rate performance of SERDES. + * + * hw - Struct containing variables accessed by shared code + *****************************************************************************/ +static int32_t +e1000_set_vco_speed(struct e1000_hw *hw) +{ + int32_t ret_val; + uint16_t default_page = 0; + uint16_t phy_data; + + DEBUGFUNC("e1000_set_vco_speed"); + + switch(hw->mac_type) { + case e1000_82545_rev_3: + case e1000_82546_rev_3: + break; + default: + return E1000_SUCCESS; + } + + /* Set PHY register 30, page 5, bit 8 to 0 */ + + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, + &default_page))) + return ret_val; + + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005))) + return ret_val; + + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data))) + return ret_val; + + phy_data &= ~M88E1000_PHY_VCO_REG_BIT8; + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data))) + return ret_val; + + /* Set PHY register 30, page 4, bit 11 to 1 */ + + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004))) + return ret_val; + + if((ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data))) + return ret_val; + + phy_data |= M88E1000_PHY_VCO_REG_BIT11; + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data))) + return ret_val; + + if((ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, + default_page))) + return ret_val; + return E1000_SUCCESS; } diff -Nru a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h --- a/drivers/net/e1000/e1000_hw.h Thu Sep 11 23:03:13 2003 +++ b/drivers/net/e1000/e1000_hw.h Thu Sep 11 23:03:13 2003 @@ -33,9 +33,9 @@ #ifndef _E1000_HW_H_ #define _E1000_HW_H_ - #include "e1000_osdep.h" + /* Forward declarations of structures used by the shared code */ struct e1000_hw; struct e1000_hw_stats; @@ -50,9 +50,13 @@ e1000_82544, e1000_82540, e1000_82545, + e1000_82545_rev_3, e1000_82546, + e1000_82546_rev_3, e1000_82541, + e1000_82541_rev_2, e1000_82547, + e1000_82547_rev_2, e1000_num_macs } e1000_mac_type; @@ -67,6 +71,7 @@ typedef enum { e1000_media_type_copper = 0, e1000_media_type_fiber = 1, + e1000_media_type_internal_serdes = 2, e1000_num_media_types } e1000_media_type; @@ -90,7 +95,8 @@ typedef enum { e1000_bus_type_unknown = 0, e1000_bus_type_pci, - e1000_bus_type_pcix + e1000_bus_type_pcix, + e1000_bus_type_reserved } e1000_bus_type; /* PCI bus speeds */ @@ -108,7 +114,8 @@ typedef enum { e1000_bus_width_unknown = 0, e1000_bus_width_32, - e1000_bus_width_64 + e1000_bus_width_64, + e1000_bus_width_reserved } e1000_bus_width; /* PHY status info structure and supporting enums */ @@ -186,6 +193,26 @@ e1000_phy_undefined = 0xFF } e1000_phy_type; +typedef enum { + e1000_ms_hw_default = 0, + e1000_ms_force_master, + e1000_ms_force_slave, + e1000_ms_auto +} e1000_ms_type; + +typedef enum { + e1000_ffe_config_enabled = 0, + e1000_ffe_config_active, + e1000_ffe_config_blocked +} e1000_ffe_config; + +typedef enum { + e1000_dsp_config_disabled = 0, + e1000_dsp_config_enabled, + e1000_dsp_config_activated, + e1000_dsp_config_undefined = 0xFF +} e1000_dsp_config; + struct e1000_phy_info { e1000_cable_length cable_length; e1000_10bt_ext_dist_enable extended_10bt_distance; @@ -224,9 +251,10 @@ /* Function prototypes */ /* Initialization */ -void e1000_reset_hw(struct e1000_hw *hw); +int32_t e1000_reset_hw(struct e1000_hw *hw); int32_t e1000_init_hw(struct e1000_hw *hw); int32_t e1000_set_mac_type(struct e1000_hw *hw); +void e1000_set_media_type(struct e1000_hw *hw); /* Link Configuration */ int32_t e1000_setup_link(struct e1000_hw *hw); @@ -234,8 +262,9 @@ void e1000_config_collision_dist(struct e1000_hw *hw); int32_t e1000_config_fc_after_link_up(struct e1000_hw *hw); int32_t e1000_check_for_link(struct e1000_hw *hw); -void e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t * speed, uint16_t * duplex); +int32_t e1000_get_speed_and_duplex(struct e1000_hw *hw, uint16_t * speed, uint16_t * duplex); int32_t e1000_wait_autoneg(struct e1000_hw *hw); +int32_t e1000_force_mac_fc(struct e1000_hw *hw); /* PHY */ int32_t e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *phy_data); @@ -292,6 +321,8 @@ uint32_t e1000_read_reg_io(struct e1000_hw *hw, uint32_t offset); void e1000_io_write(struct e1000_hw *hw, uint32_t port, uint32_t value); void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value); +int32_t e1000_config_dsp_after_link_change(struct e1000_hw *hw, boolean_t link_up); +int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active); #define E1000_READ_REG_IO(a, reg) \ e1000_read_reg_io((a), E1000_##reg) @@ -313,13 +344,22 @@ #define E1000_DEV_ID_82540EP_LP 0x101E #define E1000_DEV_ID_82545EM_COPPER 0x100F #define E1000_DEV_ID_82545EM_FIBER 0x1011 +#define E1000_DEV_ID_82545GM_COPPER 0x1026 +#define E1000_DEV_ID_82545GM_FIBER 0x1027 +#define E1000_DEV_ID_82545GM_SERDES 0x1028 #define E1000_DEV_ID_82546EB_COPPER 0x1010 #define E1000_DEV_ID_82546EB_FIBER 0x1012 #define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D #define E1000_DEV_ID_82541EI 0x1013 -#define E1000_DEV_ID_82541EP 0x1018 +#define E1000_DEV_ID_82541EI_MOBILE 0x1018 +#define E1000_DEV_ID_82541ER 0x1078 +#define E1000_DEV_ID_82547GI 0x1075 +#define E1000_DEV_ID_82541GI 0x1076 +#define E1000_DEV_ID_82541GI_MOBILE 0x1077 +#define E1000_DEV_ID_82546GB_COPPER 0x1079 +#define E1000_DEV_ID_82546GB_FIBER 0x107A +#define E1000_DEV_ID_82546GB_SERDES 0x107B #define E1000_DEV_ID_82547EI 0x1019 -#define NUM_DEV_IDS 20 #define NODE_ADDRESS_SIZE 6 #define ETH_LENGTH_OF_ADDRESS 6 @@ -385,7 +425,7 @@ E1000_IMS_RXSEQ | \ E1000_IMS_LSC) -/* The number of high/low register pairs in the RAR. The RAR (Receive Address +/* Number of high/low register pairs in the RAR. The RAR (Receive Address * Registers) holds the directed and multicast addresses that we monitor. We * reserve one of these spots for our directed address, allowing us room for * E1000_RAR_ENTRIES - 1 multicast addresses. @@ -539,7 +579,7 @@ volatile uint32_t high; /* receive address high */ }; -/* The number of entries in the Multicast Table Array (MTA). */ +/* Number of entries in the Multicast Table Array (MTA). */ #define E1000_NUM_MTA_REGISTERS 128 /* IPv4 Address Table Entry */ @@ -599,6 +639,7 @@ * A - register array */ #define E1000_CTRL 0x00000 /* Device Control - RW */ +#define E1000_CTRL_DUP 0x00004 /* Device Control Duplicate (Shadow) - RW */ #define E1000_STATUS 0x00008 /* Device Status - RO */ #define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ #define E1000_EERD 0x00014 /* EEPROM Read - RW */ @@ -934,6 +975,9 @@ e1000_bus_width bus_width; e1000_bus_type bus_type; struct e1000_eeprom_info eeprom; + e1000_ms_type master_slave; + e1000_ms_type original_master_slave; + e1000_ffe_config ffe_config_state; uint32_t io_base; uint32_t phy_id; uint32_t phy_revision; @@ -950,6 +994,8 @@ uint32_t ledctl_default; uint32_t ledctl_mode1; uint32_t ledctl_mode2; + uint16_t phy_spd_default; + uint16_t dsp_reset_counter; uint16_t autoneg_advertised; uint16_t pci_cmd_word; uint16_t fc_high_water; @@ -974,10 +1020,13 @@ uint8_t perm_mac_addr[NODE_ADDRESS_SIZE]; boolean_t disable_polarity_correction; boolean_t speed_downgraded; + e1000_dsp_config dsp_config_state; boolean_t get_link_status; boolean_t tbi_compatibility_en; boolean_t tbi_compatibility_on; + boolean_t phy_reset_disable; boolean_t fc_send_xon; + boolean_t fc_strict_ieee; boolean_t report_tx_early; boolean_t adaptive_ifs; boolean_t ifs_params_forced; @@ -1059,7 +1108,7 @@ #define E1000_EECD_PRES 0x00000100 /* EEPROM Present */ #define E1000_EECD_SIZE 0x00000200 /* EEPROM Size (0=64 word 1=256 word) */ #define E1000_EECD_ADDR_BITS 0x00000400 /* EEPROM Addressing bits based on type - * (0-small, 1-large) */ + * (0-small, 1-large) */ #define E1000_EECD_TYPE 0x00002000 /* EEPROM Type (1-SPI, 0-Microwire) */ #ifndef E1000_EEPROM_GRANT_ATTEMPTS #define E1000_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM # attempts to gain grant */ @@ -1121,22 +1170,22 @@ #define E1000_MDIC_ERROR 0x40000000 /* LED Control */ -#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F -#define E1000_LEDCTL_LED0_MODE_SHIFT 0 -#define E1000_LEDCTL_LED0_IVRT 0x00000040 -#define E1000_LEDCTL_LED0_BLINK 0x00000080 -#define E1000_LEDCTL_LED1_MODE_MASK 0x00000F00 -#define E1000_LEDCTL_LED1_MODE_SHIFT 8 -#define E1000_LEDCTL_LED1_IVRT 0x00004000 -#define E1000_LEDCTL_LED1_BLINK 0x00008000 -#define E1000_LEDCTL_LED2_MODE_MASK 0x000F0000 -#define E1000_LEDCTL_LED2_MODE_SHIFT 16 -#define E1000_LEDCTL_LED2_IVRT 0x00400000 -#define E1000_LEDCTL_LED2_BLINK 0x00800000 -#define E1000_LEDCTL_LED3_MODE_MASK 0x0F000000 -#define E1000_LEDCTL_LED3_MODE_SHIFT 24 -#define E1000_LEDCTL_LED3_IVRT 0x40000000 -#define E1000_LEDCTL_LED3_BLINK 0x80000000 +#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F +#define E1000_LEDCTL_LED0_MODE_SHIFT 0 +#define E1000_LEDCTL_LED0_IVRT 0x00000040 +#define E1000_LEDCTL_LED0_BLINK 0x00000080 +#define E1000_LEDCTL_LED1_MODE_MASK 0x00000F00 +#define E1000_LEDCTL_LED1_MODE_SHIFT 8 +#define E1000_LEDCTL_LED1_IVRT 0x00004000 +#define E1000_LEDCTL_LED1_BLINK 0x00008000 +#define E1000_LEDCTL_LED2_MODE_MASK 0x000F0000 +#define E1000_LEDCTL_LED2_MODE_SHIFT 16 +#define E1000_LEDCTL_LED2_IVRT 0x00400000 +#define E1000_LEDCTL_LED2_BLINK 0x00800000 +#define E1000_LEDCTL_LED3_MODE_MASK 0x0F000000 +#define E1000_LEDCTL_LED3_MODE_SHIFT 24 +#define E1000_LEDCTL_LED3_IVRT 0x40000000 +#define E1000_LEDCTL_LED3_BLINK 0x80000000 #define E1000_LEDCTL_MODE_LINK_10_1000 0x0 #define E1000_LEDCTL_MODE_LINK_100_1000 0x1 @@ -1159,109 +1208,109 @@ #define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */ /* Interrupt Cause Read */ -#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */ -#define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */ -#define E1000_ICR_LSC 0x00000004 /* Link Status Change */ -#define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */ -#define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */ -#define E1000_ICR_RXO 0x00000040 /* rx overrun */ -#define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */ -#define E1000_ICR_MDAC 0x00000200 /* MDIO access complete */ -#define E1000_ICR_RXCFG 0x00000400 /* RX /c/ ordered set */ -#define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */ -#define E1000_ICR_GPI_EN1 0x00001000 /* GP Int 1 */ -#define E1000_ICR_GPI_EN2 0x00002000 /* GP Int 2 */ -#define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */ -#define E1000_ICR_TXD_LOW 0x00008000 -#define E1000_ICR_SRPD 0x00010000 +#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */ +#define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */ +#define E1000_ICR_LSC 0x00000004 /* Link Status Change */ +#define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */ +#define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */ +#define E1000_ICR_RXO 0x00000040 /* rx overrun */ +#define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */ +#define E1000_ICR_MDAC 0x00000200 /* MDIO access complete */ +#define E1000_ICR_RXCFG 0x00000400 /* RX /c/ ordered set */ +#define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */ +#define E1000_ICR_GPI_EN1 0x00001000 /* GP Int 1 */ +#define E1000_ICR_GPI_EN2 0x00002000 /* GP Int 2 */ +#define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */ +#define E1000_ICR_TXD_LOW 0x00008000 +#define E1000_ICR_SRPD 0x00010000 /* Interrupt Cause Set */ -#define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ -#define E1000_ICS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ -#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ -#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ -#define E1000_ICS_RXO E1000_ICR_RXO /* rx overrun */ -#define E1000_ICS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ -#define E1000_ICS_MDAC E1000_ICR_MDAC /* MDIO access complete */ -#define E1000_ICS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ -#define E1000_ICS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ -#define E1000_ICS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ -#define E1000_ICS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ -#define E1000_ICS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ -#define E1000_ICS_TXD_LOW E1000_ICR_TXD_LOW -#define E1000_ICS_SRPD E1000_ICR_SRPD +#define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ +#define E1000_ICS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ +#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */ +#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ +#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ +#define E1000_ICS_RXO E1000_ICR_RXO /* rx overrun */ +#define E1000_ICS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ +#define E1000_ICS_MDAC E1000_ICR_MDAC /* MDIO access complete */ +#define E1000_ICS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ +#define E1000_ICS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ +#define E1000_ICS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ +#define E1000_ICS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ +#define E1000_ICS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ +#define E1000_ICS_TXD_LOW E1000_ICR_TXD_LOW +#define E1000_ICS_SRPD E1000_ICR_SRPD /* Interrupt Mask Set */ -#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ -#define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ -#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ -#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ -#define E1000_IMS_RXO E1000_ICR_RXO /* rx overrun */ -#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ -#define E1000_IMS_MDAC E1000_ICR_MDAC /* MDIO access complete */ -#define E1000_IMS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ -#define E1000_IMS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ -#define E1000_IMS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ -#define E1000_IMS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ -#define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ -#define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW -#define E1000_IMS_SRPD E1000_ICR_SRPD +#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ +#define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ +#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */ +#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ +#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ +#define E1000_IMS_RXO E1000_ICR_RXO /* rx overrun */ +#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ +#define E1000_IMS_MDAC E1000_ICR_MDAC /* MDIO access complete */ +#define E1000_IMS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ +#define E1000_IMS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ +#define E1000_IMS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ +#define E1000_IMS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ +#define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ +#define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW +#define E1000_IMS_SRPD E1000_ICR_SRPD /* Interrupt Mask Clear */ -#define E1000_IMC_TXDW E1000_ICR_TXDW /* Transmit desc written back */ -#define E1000_IMC_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ -#define E1000_IMC_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_IMC_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ -#define E1000_IMC_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ -#define E1000_IMC_RXO E1000_ICR_RXO /* rx overrun */ -#define E1000_IMC_RXT0 E1000_ICR_RXT0 /* rx timer intr */ -#define E1000_IMC_MDAC E1000_ICR_MDAC /* MDIO access complete */ -#define E1000_IMC_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ -#define E1000_IMC_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ -#define E1000_IMC_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ -#define E1000_IMC_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ -#define E1000_IMC_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ -#define E1000_IMC_TXD_LOW E1000_ICR_TXD_LOW -#define E1000_IMC_SRPD E1000_ICR_SRPD +#define E1000_IMC_TXDW E1000_ICR_TXDW /* Transmit desc written back */ +#define E1000_IMC_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ +#define E1000_IMC_LSC E1000_ICR_LSC /* Link Status Change */ +#define E1000_IMC_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ +#define E1000_IMC_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ +#define E1000_IMC_RXO E1000_ICR_RXO /* rx overrun */ +#define E1000_IMC_RXT0 E1000_ICR_RXT0 /* rx timer intr */ +#define E1000_IMC_MDAC E1000_ICR_MDAC /* MDIO access complete */ +#define E1000_IMC_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ +#define E1000_IMC_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ +#define E1000_IMC_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ +#define E1000_IMC_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ +#define E1000_IMC_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ +#define E1000_IMC_TXD_LOW E1000_ICR_TXD_LOW +#define E1000_IMC_SRPD E1000_ICR_SRPD /* Receive Control */ -#define E1000_RCTL_RST 0x00000001 /* Software reset */ -#define E1000_RCTL_EN 0x00000002 /* enable */ -#define E1000_RCTL_SBP 0x00000004 /* store bad packet */ -#define E1000_RCTL_UPE 0x00000008 /* unicast promiscuous enable */ -#define E1000_RCTL_MPE 0x00000010 /* multicast promiscuous enab */ -#define E1000_RCTL_LPE 0x00000020 /* long packet enable */ -#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */ -#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */ -#define E1000_RCTL_LBM_SLP 0x00000080 /* serial link loopback mode */ -#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ -#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */ -#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min threshold size */ -#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min threshold size */ -#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ -#define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0 */ -#define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1 */ -#define E1000_RCTL_MO_2 0x00002000 /* multicast offset 13:2 */ -#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */ -#define E1000_RCTL_MDR 0x00004000 /* multicast desc ring 0 */ -#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */ +#define E1000_RCTL_RST 0x00000001 /* Software reset */ +#define E1000_RCTL_EN 0x00000002 /* enable */ +#define E1000_RCTL_SBP 0x00000004 /* store bad packet */ +#define E1000_RCTL_UPE 0x00000008 /* unicast promiscuous enable */ +#define E1000_RCTL_MPE 0x00000010 /* multicast promiscuous enab */ +#define E1000_RCTL_LPE 0x00000020 /* long packet enable */ +#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */ +#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */ +#define E1000_RCTL_LBM_SLP 0x00000080 /* serial link loopback mode */ +#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ +#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */ +#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min threshold size */ +#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min threshold size */ +#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ +#define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0 */ +#define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1 */ +#define E1000_RCTL_MO_2 0x00002000 /* multicast offset 13:2 */ +#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */ +#define E1000_RCTL_MDR 0x00004000 /* multicast desc ring 0 */ +#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */ /* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */ -#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */ -#define E1000_RCTL_SZ_1024 0x00010000 /* rx buffer size 1024 */ -#define E1000_RCTL_SZ_512 0x00020000 /* rx buffer size 512 */ -#define E1000_RCTL_SZ_256 0x00030000 /* rx buffer size 256 */ +#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */ +#define E1000_RCTL_SZ_1024 0x00010000 /* rx buffer size 1024 */ +#define E1000_RCTL_SZ_512 0x00020000 /* rx buffer size 512 */ +#define E1000_RCTL_SZ_256 0x00030000 /* rx buffer size 256 */ /* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */ -#define E1000_RCTL_SZ_16384 0x00010000 /* rx buffer size 16384 */ -#define E1000_RCTL_SZ_8192 0x00020000 /* rx buffer size 8192 */ -#define E1000_RCTL_SZ_4096 0x00030000 /* rx buffer size 4096 */ -#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */ -#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */ -#define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */ -#define E1000_RCTL_DPF 0x00400000 /* discard pause frames */ -#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */ -#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */ +#define E1000_RCTL_SZ_16384 0x00010000 /* rx buffer size 16384 */ +#define E1000_RCTL_SZ_8192 0x00020000 /* rx buffer size 8192 */ +#define E1000_RCTL_SZ_4096 0x00030000 /* rx buffer size 4096 */ +#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */ +#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */ +#define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */ +#define E1000_RCTL_DPF 0x00400000 /* discard pause frames */ +#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */ +#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */ /* Receive Descriptor */ #define E1000_RDT_DELAY 0x0000ffff /* Delay timer (1=1024us) */ @@ -1426,15 +1475,17 @@ #define EEPROM_SIZE_128B 0x0000 #define EEPROM_SIZE_MASK 0x1C00 - /* EEPROM Word Offsets */ -#define EEPROM_COMPAT 0x0003 -#define EEPROM_ID_LED_SETTINGS 0x0004 -#define EEPROM_INIT_CONTROL1_REG 0x000A -#define EEPROM_INIT_CONTROL2_REG 0x000F -#define EEPROM_CFG 0x0012 -#define EEPROM_FLASH_VERSION 0x0032 -#define EEPROM_CHECKSUM_REG 0x003F +#define EEPROM_COMPAT 0x0003 +#define EEPROM_ID_LED_SETTINGS 0x0004 +#define EEPROM_SERDES_AMPLITUDE 0x0006 /* For SERDES output amplitude adjustment. */ +#define EEPROM_INIT_CONTROL1_REG 0x000A +#define EEPROM_INIT_CONTROL2_REG 0x000F +#define EEPROM_INIT_CONTROL3_PORT_B 0x0014 +#define EEPROM_INIT_CONTROL3_PORT_A 0x0024 +#define EEPROM_CFG 0x0012 +#define EEPROM_FLASH_VERSION 0x0032 +#define EEPROM_CHECKSUM_REG 0x003F /* Word definitions for ID LED Settings */ #define ID_LED_RESERVED_0000 0x0000 @@ -1458,6 +1509,9 @@ #define IGP_LED3_MODE 0x07000000 +/* Mask bits for SERDES amplitude adjustment in Word 6 of the EEPROM */ +#define EEPROM_SERDES_AMPLITUDE_MASK 0x000F + /* Mask bits for fields in Word 0x0a of the EEPROM */ #define EEPROM_WORD0A_ILOS 0x0010 #define EEPROM_WORD0A_SWDPIO 0x01E0 @@ -1479,6 +1533,8 @@ #define EEPROM_NODE_ADDRESS_BYTE_0 0 #define EEPROM_PBA_BYTE_1 8 +#define EEPROM_RESERVED_WORD 0xFFFF + /* EEPROM Map Sizes (Byte Counts) */ #define PBA_SIZE 4 @@ -1490,7 +1546,7 @@ #define E1000_HDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE #define E1000_COLD_SHIFT 12 -/* The number of Transmit and Receive Descriptors must be a multiple of 8 */ +/* Number of Transmit and Receive Descriptors must be a multiple of 8 */ #define REQ_TX_DESCRIPTOR_MULTIPLE 8 #define REQ_RX_DESCRIPTOR_MULTIPLE 8 @@ -1557,35 +1613,30 @@ #define PCIX_STATUS_HI_MMRBC_2K 0x2 -/* The number of bits that we need to shift right to move the "pause" - * bits from the EEPROM (bits 13:12) to the "pause" (bits 8:7) field - * in the TXCW register +/* Number of bits required to shift right the "pause" bits from the + * EEPROM (bits 13:12) to the "pause" (bits 8:7) field in the TXCW register. */ #define PAUSE_SHIFT 5 -/* The number of bits that we need to shift left to move the "SWDPIO" - * bits from the EEPROM (bits 8:5) to the "SWDPIO" (bits 25:22) field - * in the CTRL register +/* Number of bits required to shift left the "SWDPIO" bits from the + * EEPROM (bits 8:5) to the "SWDPIO" (bits 25:22) field in the CTRL register. */ #define SWDPIO_SHIFT 17 -/* The number of bits that we need to shift left to move the "SWDPIO_EXT" - * bits from the EEPROM word F (bits 7:4) to the bits 11:8 of The - * Extended CTRL register. - * in the CTRL register +/* Number of bits required to shift left the "SWDPIO_EXT" bits from the + * EEPROM word F (bits 7:4) to the bits 11:8 of The Extended CTRL register. */ #define SWDPIO__EXT_SHIFT 4 -/* The number of bits that we need to shift left to move the "ILOS" - * bit from the EEPROM (bit 4) to the "ILOS" (bit 7) field - * in the CTRL register +/* Number of bits required to shift left the "ILOS" bit from the EEPROM + * (bit 4) to the "ILOS" (bit 7) field in the CTRL register. */ #define ILOS_SHIFT 3 #define RECEIVE_BUFFER_ALIGN_SIZE (256) -/* The number of milliseconds we wait for auto-negotiation to complete */ +/* Number of milliseconds we wait for auto-negotiation to complete */ #define LINK_UP_TIMEOUT 500 #define E1000_TX_BUFFER_SIZE ((uint32_t)1514) @@ -1668,7 +1719,16 @@ #define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */ #define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */ +#define M88E1000_PHY_EXT_CTRL 0x1A /* PHY extend control register */ +#define M88E1000_PHY_PAGE_SELECT 0x1D /* Reg 29 for page number setting */ +#define M88E1000_PHY_GEN_CONTROL 0x1E /* Its meaning depends on reg 29 */ +#define M88E1000_PHY_VCO_REG_BIT8 0x100 /* Bits 8 & 11 are adjusted for */ +#define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */ + #define IGP01E1000_IEEE_REGS_PAGE 0x0000 +#define IGP01E1000_IEEE_RESTART_AUTONEG 0x3300 +#define IGP01E1000_IEEE_FORCE_GIGA 0x0140 + /* IGP01E1000 Specific Registers */ #define IGP01E1000_PHY_PORT_CONFIG 0x10 /* PHY Specific Port Config Register */ #define IGP01E1000_PHY_PORT_STATUS 0x11 /* PHY Specific Status Register */ @@ -1684,17 +1744,35 @@ #define IGP01E1000_PHY_AGC_C 0x1472 #define IGP01E1000_PHY_AGC_D 0x1872 -/* Number of AGC registers */ -#define IGP01E1000_PHY_AGC_NUM 4 +/* IGP01E1000 DSP Reset Register */ +#define IGP01E1000_PHY_DSP_RESET 0x1F33 +#define IGP01E1000_PHY_DSP_SET 0x1F71 +#define IGP01E1000_PHY_DSP_FFE 0x1F35 + +#define IGP01E1000_PHY_CHANNEL_NUM 4 +#define IGP01E1000_PHY_AGC_PARAM_A 0x1171 +#define IGP01E1000_PHY_AGC_PARAM_B 0x1271 +#define IGP01E1000_PHY_AGC_PARAM_C 0x1471 +#define IGP01E1000_PHY_AGC_PARAM_D 0x1871 + +#define IGP01E1000_PHY_EDAC_MU_INDEX 0xC000 +#define IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS 0x8000 + +#define IGP01E1000_PHY_ANALOG_TX_STATE 0x2890 +#define IGP01E1000_PHY_ANALOG_CLASS_A 0x2000 +#define IGP01E1000_PHY_FORCE_ANALOG_ENABLE 0x0004 +#define IGP01E1000_PHY_DSP_FFE_CM_CP 0x0069 +#define IGP01E1000_PHY_DSP_FFE_DEFAULT 0x002A /* IGP01E1000 PCS Initialization register - stores the polarity status when * speed = 1000 Mbps. */ #define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 +#define IGP01E1000_PHY_PCS_CTRL_REG 0x00B5 #define IGP01E1000_ANALOG_REGS_PAGE 0x20C0 #define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ - +#define MAX_PHY_MULTI_PAGE_REG 0xF /*Registers that are equal on all pages*/ /* PHY Control Register */ #define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ #define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */ @@ -1808,8 +1886,11 @@ #define SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */ #define SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master, 0=Slave */ #define SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */ -#define SR_1000T_REMOTE_RX_STATUS_SHIFT 12 -#define SR_1000T_LOCAL_RX_STATUS_SHIFT 13 +#define SR_1000T_REMOTE_RX_STATUS_SHIFT 12 +#define SR_1000T_LOCAL_RX_STATUS_SHIFT 13 +#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT 5 +#define FFE_IDLE_ERR_COUNT_TIMEOUT_20 20 +#define FFE_IDLE_ERR_COUNT_TIMEOUT_100 100 /* Extended Status Register */ #define IEEE_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */ @@ -1901,7 +1982,6 @@ #define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */ #define M88E1000_EPSCR_TX_CLK_0 0x0000 /* NO TX_CLK */ - /* IGP01E1000 Specific Port Config Register - R/W */ #define IGP01E1000_PSCFR_AUTO_MDIX_PAR_DETECT 0x0010 #define IGP01E1000_PSCFR_PRE_EN 0x0020 @@ -1952,6 +2032,11 @@ #define IGP01E1000_MSE_CHANNEL_B 0x0F00 #define IGP01E1000_MSE_CHANNEL_A 0xF000 +/* IGP01E1000 DSP reset macros */ +#define DSP_RESET_ENABLE 0x0 +#define DSP_RESET_DISABLE 0x2 +#define E1000_MAX_DSP_RESETS 10 + /* IGP01E1000 AGC Registers */ #define IGP01E1000_AGC_LENGTH_SHIFT 7 /* Coarse - 13:11, Fine - 10:7 */ @@ -1962,18 +2047,6 @@ /* The precision of the length is +/- 10 meters */ #define IGP01E1000_AGC_RANGE 10 -/* IGP cable length table */ -static const -uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = - { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25, - 25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90, - 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120}; - /* IGP01E1000 PCS Initialization register */ /* bits 3:6 in the PCS registers stores the channels polarity */ #define IGP01E1000_PHY_POLARITY_MASK 0x0078 @@ -1982,11 +2055,12 @@ #define IGP01E1000_GMII_FLEX_SPD 0x10 /* Enable flexible speed * on Link-Up */ #define IGP01E1000_GMII_SPD 0x20 /* Enable SPD */ + /* IGP01E1000 Analog Register */ -#define IGP01E1000_ANALOG_SPARE_FUSE_STATUS 0x0011 -#define IGP01E1000_ANALOG_FUSE_STATUS 0x0010 -#define IGP01E1000_ANALOG_FUSE_CONTROL 0x001C -#define IGP01E1000_ANALOG_FUSE_BYPASS 0x001E +#define IGP01E1000_ANALOG_SPARE_FUSE_STATUS 0x20D1 +#define IGP01E1000_ANALOG_FUSE_STATUS 0x20D0 +#define IGP01E1000_ANALOG_FUSE_CONTROL 0x20DC +#define IGP01E1000_ANALOG_FUSE_BYPASS 0x20DE #define IGP01E1000_ANALOG_FUSE_POLY_MASK 0xF000 #define IGP01E1000_ANALOG_FUSE_FINE_MASK 0x0F80 @@ -2032,5 +2106,8 @@ #define ADVERTISE_1000_HALF 0x0010 #define ADVERTISE_1000_FULL 0x0020 #define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x002F /* Everything but 1000-Half */ +#define AUTONEG_ADVERTISE_10_100_ALL 0x000F /* All 10/100 speeds*/ +#define AUTONEG_ADVERTISE_10_ALL 0x0003 /* 10Mbps Full & Half speeds*/ + #endif /* _E1000_HW_H_ */ diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c --- a/drivers/net/e1000/e1000_main.c Thu Sep 11 23:03:12 2003 +++ b/drivers/net/e1000/e1000_main.c Thu Sep 11 23:03:12 2003 @@ -30,6 +30,22 @@ /* Change Log * + * 5.2.16 8/8/03 + * o Added support for new controllers: 82545GM, 82546GB, 82541/7_B1 + * o Bug fix: reset h/w before first EEPROM read because we don't know + * who may have been messing with the device before we got there. + * [Dave Johnson (ddj -a-t- cascv.brown.edu)] + * o Bug fix: read the correct work from EEPROM to detect programmed + * WoL settings. + * o Bug fix: TSO would hang if space left in FIFO was being miscalculated + * when mss dropped without a correspoding drop in the DMA buffer size. + * o ASF for Fiber nics isn't supported. + * o Bug fix: Workaround added for potential hang with 82544 running in + * PCI-X if send buffer terminates within an evenly-aligned dword. + * o Feature: Add support for ethtool flow control setting. + * o Feature: Add support for ethtool TSO setting. + * o Feature: Increase default Tx Descriptor count to 1024 for >= 82544. + * * 5.1.13 5/28/03 * o Bug fix: request_irq() failure resulted in freeing resources twice! * [Don Fry (brazilnut@us.ibm.com)] @@ -39,18 +55,11 @@ * o Cleanup: s/int/unsigned int/ for descriptor ring indexes. * * 5.1.11 5/6/03 - * o Feature: Added support for 82546EB (Quad-port) hardware. - * o Feature: Added support for Diagnostics through Ethtool. - * o Cleanup: Removed /proc support. - * o Cleanup: Removed proprietary IDIAG interface. - * o Bug fix: TSO bug fixes. - * - * 5.0.42 3/5/03 */ char e1000_driver_name[] = "e1000"; char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; -char e1000_driver_version[] = "5.1.13-k2"; +char e1000_driver_version[] = "5.2.16-k1"; char e1000_copyright[] = "Copyright (c) 1999-2003 Intel Corporation."; /* e1000_pci_tbl - PCI Device ID Table @@ -71,15 +80,28 @@ {0x8086, 0x100D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x100E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x100F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1012, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1015, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x101D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0x8086, 0x1013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1018, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x101D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1026, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1027, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1075, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1076, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1077, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1078, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1079, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x107A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x107B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* required last entry */ {0,} }; @@ -426,6 +448,11 @@ if(pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; + /* before reading the EEPROM, reset the controller to + * put the device in a known good starting state */ + + e1000_reset_hw(&adapter->hw); + /* make sure the EEPROM is good */ if(e1000_validate_eeprom_checksum(&adapter->hw) < 0) { @@ -457,7 +484,7 @@ adapter->phy_info_timer.function = &e1000_update_phy_info; adapter->phy_info_timer.data = (unsigned long) adapter; - INIT_WORK(&adapter->tx_timeout_task, + INIT_WORK(&adapter->tx_timeout_task, (void (*)(void *))e1000_tx_timeout_task, netdev); register_netdev(netdev); @@ -476,12 +503,28 @@ * enable the ACPI Magic Packet filter */ - e1000_read_eeprom(&adapter->hw, EEPROM_INIT_CONTROL2_REG,1, &eeprom_data); - if((adapter->hw.mac_type >= e1000_82544) && - (eeprom_data & E1000_EEPROM_APME)) + switch(adapter->hw.mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: + case e1000_82543: + break; + case e1000_82546: + case e1000_82546_rev_3: + if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1) + && (adapter->hw.media_type == e1000_media_type_copper)) { + e1000_read_eeprom(&adapter->hw, + EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); + break; + } + /* Fall Through */ + default: + e1000_read_eeprom(&adapter->hw, + EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); + break; + } + if(eeprom_data & E1000_EEPROM_APME) adapter->wol |= E1000_WUFC_MAG; - /* reset the hardware with the new settings */ e1000_reset(adapter); @@ -516,7 +559,8 @@ struct e1000_adapter *adapter = netdev->priv; uint32_t manc; - if(adapter->hw.mac_type >= e1000_82540) { + if(adapter->hw.mac_type >= e1000_82540 && + adapter->hw.media_type == e1000_media_type_copper) { manc = E1000_READ_REG(&adapter->hw, MANC); if(manc & E1000_MANC_SMBUS_EN) { manc |= E1000_MANC_ARP_EN; @@ -584,21 +628,13 @@ hw->fc_pause_time = E1000_FC_PAUSE_TIME; hw->fc_send_xon = 1; - if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) + if((hw->mac_type == e1000_82541) || + (hw->mac_type == e1000_82547) || + (hw->mac_type == e1000_82541_rev_2) || + (hw->mac_type == e1000_82547_rev_2)) hw->phy_init_script = 1; - /* Media type - copper or fiber */ - - if(hw->mac_type >= e1000_82543) { - uint32_t status = E1000_READ_REG(hw, STATUS); - - if(status & E1000_STATUS_TBIMODE) - hw->media_type = e1000_media_type_fiber; - else - hw->media_type = e1000_media_type_copper; - } else { - hw->media_type = e1000_media_type_fiber; - } + e1000_set_media_type(hw); if(hw->mac_type < e1000_82543) hw->report_tx_early = 0; @@ -614,6 +650,7 @@ if(hw->media_type == e1000_media_type_copper) { hw->mdix = AUTO_ALL_MODES; hw->disable_polarity_correction = FALSE; + hw->master_slave = E1000_MASTER_SLAVE; } atomic_set(&adapter->irq_sem, 1); @@ -763,7 +800,8 @@ tipg |= DEFAULT_82542_TIPG_IPGR2 << E1000_TIPG_IPGR2_SHIFT; break; default: - if(adapter->hw.media_type == e1000_media_type_fiber) + if(adapter->hw.media_type == e1000_media_type_fiber || + adapter->hw.media_type == e1000_media_type_internal_serdes) tipg = DEFAULT_82543_TIPG_IPGT_FIBER; else tipg = DEFAULT_82543_TIPG_IPGT_COPPER; @@ -798,6 +836,12 @@ adapter->txd_cmd |= E1000_TXD_CMD_RS; else adapter->txd_cmd |= E1000_TXD_CMD_RPS; + + /* Cache if we're 82544 running in PCI-X because we'll + * need this to apply a workaround later in the send path. */ + if(adapter->hw.mac_type == e1000_82544 && + adapter->hw.bus_type == e1000_bus_type_pcix) + adapter->pcix_82544 = 1; } /** @@ -1490,11 +1534,18 @@ { struct e1000_desc_ring *tx_ring = &adapter->tx_ring; struct e1000_buffer *buffer_info; - int len = skb->len; + unsigned int len = skb->len, max_per_txd = E1000_MAX_DATA_PER_TXD; unsigned int offset = 0, size, count = 0, i; #ifdef NETIF_F_TSO - unsigned int tso = skb_shinfo(skb)->tso_size; + unsigned int mss = skb_shinfo(skb)->tso_size; + /* The controller does a simple calculation to + * make sure there is enough room in the FIFO before + * initiating the DMA for each buffer. The calc is: + * 4 = ceil(buffer len/mss). To make sure we don't + * overrun the FIFO, adjust the max buffer len if mss + * drops. */ + if(mss) max_per_txd = min(mss << 2, max_per_txd); #endif unsigned int nr_frags = skb_shinfo(skb)->nr_frags; unsigned int f; @@ -1504,13 +1555,20 @@ while(len) { buffer_info = &tx_ring->buffer_info[i]; - size = min(len, E1000_MAX_DATA_PER_TXD); + size = min(len, max_per_txd); #ifdef NETIF_F_TSO /* Workaround for premature desc write-backs * in TSO mode. Append 4-byte sentinel desc */ - if(tso && !nr_frags && size == len && size > 4) + if(mss && !nr_frags && size == len && size > 8) size -= 4; #endif + /* Workaround for potential 82544 hang in PCI-X. Avoid + * terminating buffers within evenly-aligned dwords. */ + if(adapter->pcix_82544 && + !((unsigned long)(skb->data + offset + size - 1) & 4) && + size > 4) + size -= 4; + buffer_info->length = size; buffer_info->dma = pci_map_single(adapter->pdev, @@ -1530,22 +1588,30 @@ frag = &skb_shinfo(skb)->frags[f]; len = frag->size; - offset = 0; + offset = frag->page_offset; while(len) { buffer_info = &tx_ring->buffer_info[i]; - size = min(len, E1000_MAX_DATA_PER_TXD); + size = min(len, max_per_txd); #ifdef NETIF_F_TSO /* Workaround for premature desc write-backs * in TSO mode. Append 4-byte sentinel desc */ - if(tso && f == (nr_frags-1) && size == len && size > 4) + if(mss && f == (nr_frags-1) && size == len && size > 8) size -= 4; #endif + /* Workaround for potential 82544 hang in PCI-X. + * Avoid terminating buffers within evenly-aligned + * dwords. */ + if(adapter->pcix_82544 && + !((unsigned long)(frag->page+offset+size-1) & 4) && + size > 4) + size -= 4; + buffer_info->length = size; buffer_info->dma = pci_map_page(adapter->pdev, frag->page, - frag->page_offset + offset, + offset, size, PCI_DMA_TODEVICE); buffer_info->time_stamp = jiffies; @@ -1556,6 +1622,31 @@ if(++i == tx_ring->count) i = 0; } } + + if(E1000_DESC_UNUSED(&adapter->tx_ring) < count) { + + /* There aren't enough descriptors available to queue up + * this send, so undo the mapping and abort the send. + * We could have done the check before we mapped the skb, + * but because of all the workarounds (above), it's too + * difficult to predict how many we're going to need.*/ + i = first; + + while(count--) { + buffer_info = &tx_ring->buffer_info[i]; + if(buffer_info->dma) { + pci_unmap_page(adapter->pdev, + buffer_info->dma, + buffer_info->length, + PCI_DMA_TODEVICE); + buffer_info->dma = 0; + } + if(++i == tx_ring->count) i = 0; + } + + return 0; + } + i = (i == 0) ? tx_ring->count - 1 : i - 1; tx_ring->buffer_info[i].skb = skb; tx_ring->buffer_info[first].next_to_watch = i; @@ -1650,29 +1741,19 @@ return 0; } -/* Tx Descriptors needed, worst case */ -#define TXD_USE_COUNT(S) (((S) >> E1000_MAX_TXD_PWR) + \ - (((S) & (E1000_MAX_DATA_PER_TXD - 1)) ? 1 : 0)) -#define DESC_NEEDED TXD_USE_COUNT(MAX_JUMBO_FRAME_SIZE) + \ - MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1 - static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct e1000_adapter *adapter = netdev->priv; unsigned int first; unsigned int tx_flags = 0; + int count; if(skb->len <= 0) { dev_kfree_skb_any(skb); return 0; } - if(E1000_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED) { - netif_stop_queue(netdev); - return 1; - } - if(adapter->hw.mac_type == e1000_82547) { if(e1000_82547_fifo_workaround(adapter, skb)) { netif_stop_queue(netdev); @@ -1693,7 +1774,12 @@ else if(e1000_tx_csum(adapter, skb)) tx_flags |= E1000_TX_FLAGS_CSUM; - e1000_tx_queue(adapter, e1000_tx_map(adapter, skb, first), tx_flags); + if((count = e1000_tx_map(adapter, skb, first))) + e1000_tx_queue(adapter, count, tx_flags); + else { + netif_stop_queue(netdev); + return 1; + } netdev->trans_start = jiffies; @@ -2001,6 +2087,7 @@ !e1000_clean_tx_irq(adapter)) break; #endif + return IRQ_HANDLED; } @@ -2387,7 +2474,7 @@ uint16_t mii_reg; uint16_t spddplx; - if(adapter->hw.media_type == e1000_media_type_fiber) + if(adapter->hw.media_type != e1000_media_type_copper) return -EOPNOTSUPP; switch (cmd) { @@ -2659,7 +2746,7 @@ case SYS_DOWN: case SYS_HALT: case SYS_POWER_OFF: - while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) { + while((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) { if(pci_dev_driver(pdev) == &e1000_driver) e1000_suspend(pdev, 3); } @@ -2706,7 +2793,8 @@ E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); } - if(adapter->hw.media_type == e1000_media_type_fiber) { + if(adapter->hw.media_type == e1000_media_type_fiber || + adapter->hw.media_type == e1000_media_type_internal_serdes) { /* keep the laser running in D3 */ ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA; @@ -2726,7 +2814,8 @@ pci_save_state(pdev, adapter->pci_state); - if(adapter->hw.mac_type >= e1000_82540) { + if(adapter->hw.mac_type >= e1000_82540 && + adapter->hw.media_type == e1000_media_type_copper) { manc = E1000_READ_REG(&adapter->hw, MANC); if(manc & E1000_MANC_SMBUS_EN) { manc |= E1000_MANC_ARP_EN; @@ -2764,7 +2853,8 @@ netif_device_attach(netdev); - if(adapter->hw.mac_type >= e1000_82540) { + if(adapter->hw.mac_type >= e1000_82540 && + adapter->hw.media_type == e1000_media_type_copper) { manc = E1000_READ_REG(&adapter->hw, MANC); manc &= ~(E1000_MANC_ARP_EN); E1000_WRITE_REG(&adapter->hw, MANC, manc); diff -Nru a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h --- a/drivers/net/e1000/e1000_osdep.h Thu Sep 11 23:03:11 2003 +++ b/drivers/net/e1000/e1000_osdep.h Thu Sep 11 23:03:11 2003 @@ -55,10 +55,13 @@ #define CMD_MEM_WRT_INVALIDATE PCI_COMMAND_INVALIDATE typedef enum { +#undef FALSE FALSE = 0, +#undef TRUE TRUE = 1 } boolean_t; +#undef ASSERT #define ASSERT(x) if(!(x)) BUG() #define MSGOUT(S, A, B) printk(KERN_DEBUG S "\n", A, B) diff -Nru a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c --- a/drivers/net/e1000/e1000_param.c Thu Sep 11 23:03:13 2003 +++ b/drivers/net/e1000/e1000_param.c Thu Sep 11 23:03:13 2003 @@ -140,7 +140,7 @@ * Valid Range: 0, 1 * - 0 - disables all checksum offload * - 1 - enables receive IP/TCP/UDP checksum offload - * on 82543 based NICs + * on 82543 and newer -based NICs * * Default Value: 1 */ @@ -458,6 +458,7 @@ switch(adapter->hw.media_type) { case e1000_media_type_fiber: + case e1000_media_type_internal_serdes: e1000_check_fiber_options(adapter); break; case e1000_media_type_copper: @@ -601,7 +602,7 @@ switch (speed + dplx) { case 0: - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; if(Speed[bd] != OPTION_UNSET || Duplex[bd] != OPTION_UNSET) printk(KERN_INFO "Speed and duplex autonegotiation enabled\n"); @@ -609,14 +610,14 @@ case HALF_DUPLEX: printk(KERN_INFO "Half Duplex specified without Speed\n"); printk(KERN_INFO "Using Autonegotiation at Half Duplex only\n"); - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_10_HALF | ADVERTISE_100_HALF; break; case FULL_DUPLEX: printk(KERN_INFO "Full Duplex specified without Speed\n"); printk(KERN_INFO "Using Autonegotiation at Full Duplex only\n"); - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_10_FULL | ADVERTISE_100_FULL | ADVERTISE_1000_FULL; @@ -624,38 +625,38 @@ case SPEED_10: printk(KERN_INFO "10 Mbps Speed specified without Duplex\n"); printk(KERN_INFO "Using Autonegotiation at 10 Mbps only\n"); - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_10_HALF | ADVERTISE_10_FULL; break; case SPEED_10 + HALF_DUPLEX: printk(KERN_INFO "Forcing to 10 Mbps Half Duplex\n"); - adapter->hw.autoneg = 0; + adapter->hw.autoneg = adapter->fc_autoneg = 0; adapter->hw.forced_speed_duplex = e1000_10_half; adapter->hw.autoneg_advertised = 0; break; case SPEED_10 + FULL_DUPLEX: printk(KERN_INFO "Forcing to 10 Mbps Full Duplex\n"); - adapter->hw.autoneg = 0; + adapter->hw.autoneg = adapter->fc_autoneg = 0; adapter->hw.forced_speed_duplex = e1000_10_full; adapter->hw.autoneg_advertised = 0; break; case SPEED_100: printk(KERN_INFO "100 Mbps Speed specified without Duplex\n"); printk(KERN_INFO "Using Autonegotiation at 100 Mbps only\n"); - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_100_HALF | ADVERTISE_100_FULL; break; case SPEED_100 + HALF_DUPLEX: printk(KERN_INFO "Forcing to 100 Mbps Half Duplex\n"); - adapter->hw.autoneg = 0; + adapter->hw.autoneg = adapter->fc_autoneg = 0; adapter->hw.forced_speed_duplex = e1000_100_half; adapter->hw.autoneg_advertised = 0; break; case SPEED_100 + FULL_DUPLEX: printk(KERN_INFO "Forcing to 100 Mbps Full Duplex\n"); - adapter->hw.autoneg = 0; + adapter->hw.autoneg = adapter->fc_autoneg = 0; adapter->hw.forced_speed_duplex = e1000_100_full; adapter->hw.autoneg_advertised = 0; break; @@ -663,20 +664,20 @@ printk(KERN_INFO "1000 Mbps Speed specified without Duplex\n"); printk(KERN_INFO "Using Autonegotiation at 1000 Mbps Full Duplex only\n"); - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; break; case SPEED_1000 + HALF_DUPLEX: printk(KERN_INFO "Half Duplex is not supported at 1000 Mbps\n"); printk(KERN_INFO "Using Autonegotiation at 1000 Mbps Full Duplex only\n"); - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; break; case SPEED_1000 + FULL_DUPLEX: printk(KERN_INFO "Using Autonegotiation at 1000 Mbps Full Duplex only\n"); - adapter->hw.autoneg = 1; + adapter->hw.autoneg = adapter->fc_autoneg = 1; adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; break; default: diff -Nru a/drivers/net/fc/iph5526.c b/drivers/net/fc/iph5526.c --- a/drivers/net/fc/iph5526.c Thu Sep 11 23:03:11 2003 +++ b/drivers/net/fc/iph5526.c Thu Sep 11 23:03:11 2003 @@ -110,7 +110,7 @@ #define ALIGNED_ADDR(addr, len) ((((unsigned long)(addr) + (len - 1)) & ~(len - 1)) - (unsigned long)(addr)) -static struct pci_device_id iph5526_pci_tbl[] __initdata = { +static struct pci_device_id iph5526_pci_tbl[] = { { PCI_VENDOR_ID_INTERPHASE, PCI_DEVICE_ID_INTERPHASE_5526, PCI_ANY_ID, PCI_ANY_ID, }, { PCI_VENDOR_ID_INTERPHASE, PCI_DEVICE_ID_INTERPHASE_55x6, PCI_ANY_ID, PCI_ANY_ID, }, { } /* Terminating entry */ diff -Nru a/drivers/net/hamachi.c b/drivers/net/hamachi.c --- a/drivers/net/hamachi.c Thu Sep 11 23:03:14 2003 +++ b/drivers/net/hamachi.c Thu Sep 11 23:03:14 2003 @@ -178,7 +178,7 @@ #include #include -static char version[] __initdata = +static char version[] __devinitdata = KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n" KERN_INFO " Some modifications by Eric kasten \n" KERN_INFO " Further modifications by Keith Underwood \n"; @@ -569,7 +569,7 @@ static void set_rx_mode(struct net_device *dev); -static int __init hamachi_init_one (struct pci_dev *pdev, +static int __devinit hamachi_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { struct hamachi_private *hmp; @@ -794,7 +794,7 @@ return ret; } -static int __init read_eeprom(long ioaddr, int location) +static int __devinit read_eeprom(long ioaddr, int location) { int bogus_cnt = 1000; diff -Nru a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c --- a/drivers/net/hamradio/bpqether.c Thu Sep 11 23:03:12 2003 +++ b/drivers/net/hamradio/bpqether.c Thu Sep 11 23:03:12 2003 @@ -389,8 +389,6 @@ return buf; } -#define BPQ_PROC_START ((void *)1) - static void *bpq_seq_start(struct seq_file *seq, loff_t *pos) { int i = 1; @@ -399,7 +397,7 @@ rcu_read_lock(); if (*pos == 0) - return BPQ_PROC_START; + return SEQ_START_TOKEN; list_for_each_entry(bpqdev, &bpq_devices, bpq_list) { if (i == *pos) @@ -414,7 +412,7 @@ ++*pos; - if (v == BPQ_PROC_START) + if (v == SEQ_START_TOKEN) p = bpq_devices.next; else p = ((struct bpqdev *)v)->bpq_list.next; @@ -431,7 +429,7 @@ static int bpq_seq_show(struct seq_file *seq, void *v) { - if (v == BPQ_PROC_START) + if (v == SEQ_START_TOKEN) seq_puts(seq, "dev ether destination accept from\n"); else { diff -Nru a/drivers/net/hp100.c b/drivers/net/hp100.c --- a/drivers/net/hp100.c Thu Sep 11 23:03:12 2003 +++ b/drivers/net/hp100.c Thu Sep 11 23:03:12 2003 @@ -284,7 +284,7 @@ #define HP100_PCI_IDS_SIZE (sizeof(hp100_pci_ids)/sizeof(struct hp100_pci_id)) -static struct pci_device_id hp100_pci_tbl[] __initdata = { +static struct pci_device_id hp100_pci_tbl[] = { {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585A, PCI_ANY_ID, PCI_ANY_ID,}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585B, PCI_ANY_ID, PCI_ANY_ID,}, {PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_ENET100VG4, PCI_ANY_ID, PCI_ANY_ID,}, diff -Nru a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c --- a/drivers/net/irda/via-ircc.c Thu Sep 11 23:03:11 2003 +++ b/drivers/net/irda/via-ircc.c Thu Sep 11 23:03:11 2003 @@ -107,7 +107,7 @@ void hwreset(struct via_ircc_cb *self); static int via_ircc_dma_xmit(struct via_ircc_cb *self, u16 iobase); static int upload_rxdata(struct via_ircc_cb *self, int iobase); -static int __init via_init_one (struct pci_dev *pcidev, const struct pci_device_id *id); +static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_device_id *id); static void __exit via_remove_one (struct pci_dev *pdev); /* Should use udelay() instead, even if we are x86 only - Jean II */ @@ -121,7 +121,7 @@ } } -static struct pci_device_id via_pci_tbl[] __initdata = { +static struct pci_device_id via_pci_tbl[] = { { PCI_VENDOR_ID_VIA, DeviceID1, PCI_ANY_ID, PCI_ANY_ID,0,0,0 }, { PCI_VENDOR_ID_VIA, DeviceID2, PCI_ANY_ID, PCI_ANY_ID,0,0,1 }, { PCI_VENDOR_ID_VIA, DeviceID3, PCI_ANY_ID, PCI_ANY_ID,0,0,2 }, @@ -168,7 +168,7 @@ } -static int __init via_init_one (struct pci_dev *pcidev, const struct pci_device_id *id) +static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_device_id *id) { int rc; u8 temp,oldPCI_40,oldPCI_44,bTmp,bTmp1; @@ -326,7 +326,7 @@ * Open driver instance * */ -static __init int via_ircc_open(int i, chipio_t * info, unsigned int id) +static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id) { struct net_device *dev; struct via_ircc_cb *self; diff -Nru a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c --- a/drivers/net/pcmcia/3c574_cs.c Thu Sep 11 23:03:11 2003 +++ b/drivers/net/pcmcia/3c574_cs.c Thu Sep 11 23:03:11 2003 @@ -263,16 +263,6 @@ static dev_link_t *dev_list; -static void flush_stale_links(void) -{ - dev_link_t *link, *next; - for (link = dev_list; link; link = next) { - next = link->next; - if (link->state & DEV_STALE_LINK) - tc574_detach(link); - } -} - /* tc574_attach() creates an "instance" of the driver, allocating local data structures for one device. The device is registered @@ -288,7 +278,6 @@ int i, ret; DEBUG(0, "3c574_attach()\n"); - flush_stale_links(); /* Create the PC card device object. */ dev = alloc_etherdev(sizeof(struct el3_private)); @@ -375,10 +364,8 @@ if (link->state & DEV_CONFIG) { tc574_release(link); - if (link->state & DEV_STALE_CONFIG) { - link->state |= DEV_STALE_LINK; + if (link->state & DEV_STALE_CONFIG) return; - } } if (link->handle) @@ -583,7 +570,9 @@ link->state &= ~DEV_CONFIG; -} /* tc574_release */ + if (link->state & DEV_STALE_CONFIG) + tc574_detach(link); +} /* The card status event handler. Mostly, this schedules other diff -Nru a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c --- a/drivers/net/pcmcia/3c589_cs.c Thu Sep 11 23:03:14 2003 +++ b/drivers/net/pcmcia/3c589_cs.c Thu Sep 11 23:03:14 2003 @@ -176,24 +176,6 @@ /*====================================================================== - This bit of code is used to avoid unregistering network devices - at inappropriate times. 2.2 and later kernels are fairly picky - about when this can happen. - -======================================================================*/ - -static void flush_stale_links(void) -{ - dev_link_t *link, *next; - for (link = dev_list; link; link = next) { - next = link->next; - if (link->state & DEV_STALE_LINK) - tc589_detach(link); - } -} - -/*====================================================================== - tc589_attach() creates an "instance" of the driver, allocating local data structures for one device. The device is registered with Card Services. @@ -209,7 +191,6 @@ int i, ret; DEBUG(0, "3c589_attach()\n"); - flush_stale_links(); /* Create new ethernet device */ dev = alloc_etherdev(sizeof(struct el3_private)); @@ -297,10 +278,8 @@ if (link->state & DEV_CONFIG) { tc589_release(link); - if (link->state & DEV_STALE_CONFIG) { - link->state |= DEV_STALE_LINK; + if (link->state & DEV_STALE_CONFIG) return; - } } if (link->handle) @@ -466,8 +445,10 @@ CardServices(ReleaseIRQ, link->handle, &link->irq); link->state &= ~DEV_CONFIG; - -} /* tc589_release */ + + if (link->state & DEV_STALE_CONFIG) + tc589_detach(link); +} /*====================================================================== diff -Nru a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c --- a/drivers/net/pcmcia/axnet_cs.c Thu Sep 11 23:03:12 2003 +++ b/drivers/net/pcmcia/axnet_cs.c Thu Sep 11 23:03:12 2003 @@ -142,24 +142,6 @@ /*====================================================================== - This bit of code is used to avoid unregistering network devices - at inappropriate times. 2.2 and later kernels are fairly picky - about when this can happen. - -======================================================================*/ - -static void flush_stale_links(void) -{ - dev_link_t *link, *next; - for (link = dev_list; link; link = next) { - next = link->next; - if (link->state & DEV_STALE_LINK) - axnet_detach(link); - } -} - -/*====================================================================== - We never need to do anything when a axnet device is "initialized" by the net software, because we only register already-found cards. @@ -187,7 +169,6 @@ int i, ret; DEBUG(0, "axnet_attach()\n"); - flush_stale_links(); /* Create new ethernet device */ info = kmalloc(sizeof(*info), GFP_KERNEL); @@ -258,10 +239,8 @@ if (link->state & DEV_CONFIG) { axnet_release(link); - if (link->state & DEV_STALE_CONFIG) { - link->state |= DEV_STALE_LINK; + if (link->state & DEV_STALE_CONFIG) return; - } } if (link->handle) @@ -547,7 +526,9 @@ link->state &= ~DEV_CONFIG; -} /* axnet_release */ + if (link->state & DEV_STALE_CONFIG) + axnet_detach(link); +} /*====================================================================== diff -Nru a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c --- a/drivers/net/pcmcia/com20020_cs.c Thu Sep 11 23:03:12 2003 +++ b/drivers/net/pcmcia/com20020_cs.c Thu Sep 11 23:03:12 2003 @@ -147,24 +147,6 @@ /*====================================================================== - This bit of code is used to avoid unregistering network devices - at inappropriate times. 2.2 and later kernels are fairly picky - about when this can happen. - -======================================================================*/ - -static void flush_stale_links(void) -{ - dev_link_t *link, *next; - for (link = dev_list; link; link = next) { - next = link->next; - if (link->state & DEV_STALE_LINK) - com20020_detach(link); - } -} - -/*====================================================================== - com20020_attach() creates an "instance" of the driver, allocating local data structures for one device. The device is registered with Card Services. @@ -181,7 +163,6 @@ struct arcnet_local *lp; DEBUG(0, "com20020_attach()\n"); - flush_stale_links(); /* Create new network device */ link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); @@ -290,10 +271,8 @@ if (link->state & DEV_CONFIG) { com20020_release(link); - if (link->state & DEV_STALE_CONFIG) { - link->state |= DEV_STALE_LINK; + if (link->state & DEV_STALE_CONFIG) return; - } } if (link->handle) @@ -484,7 +463,9 @@ link->state &= ~(DEV_CONFIG | DEV_RELEASE_PENDING); -} /* com20020_release */ + if (link->state & DEV_STALE_CONFIG) + com20020_detach(link); +} /*====================================================================== diff -Nru a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c --- a/drivers/net/pcmcia/fmvj18x_cs.c Thu Sep 11 23:03:13 2003 +++ b/drivers/net/pcmcia/fmvj18x_cs.c Thu Sep 11 23:03:13 2003 @@ -242,24 +242,6 @@ #define BANK_1U 0x24 /* bank 1 (CONFIG_1) */ #define BANK_2U 0x28 /* bank 2 (CONFIG_1) */ -/*====================================================================== - - This bit of code is used to avoid unregistering network devices - at inappropriate times. 2.2 and later kernels are fairly picky - about when this can happen. - -======================================================================*/ - -static void flush_stale_links(void) -{ - dev_link_t *link, *next; - for (link = dev_list; link; link = next) { - next = link->next; - if (link->state & DEV_STALE_LINK) - fmvj18x_detach(link); - } -} - static dev_link_t *fmvj18x_attach(void) { local_info_t *lp; @@ -269,7 +251,6 @@ int i, ret; DEBUG(0, "fmvj18x_attach()\n"); - flush_stale_links(); /* Make up a FMVJ18x specific data structure */ dev = alloc_etherdev(sizeof(local_info_t)); @@ -353,10 +334,8 @@ if (link->state & DEV_CONFIG) { fmvj18x_release(link); - if (link->state & DEV_STALE_CONFIG) { - link->state |= DEV_STALE_LINK; + if (link->state & DEV_STALE_CONFIG) return; - } } /* Break the link with Card Services */ @@ -762,8 +741,10 @@ CardServices(ReleaseIRQ, link->handle, &link->irq); link->state &= ~DEV_CONFIG; - -} /* fmvj18x_release */ + + if (link->state & DEV_STALE_CONFIG) + fmvj18x_detach(link); +} /*====================================================================*/ diff -Nru a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c --- a/drivers/net/pcmcia/ibmtr_cs.c Thu Sep 11 23:03:12 2003 +++ b/drivers/net/pcmcia/ibmtr_cs.c Thu Sep 11 23:03:12 2003 @@ -139,24 +139,6 @@ struct tok_info ti; } ibmtr_dev_t; -/*====================================================================== - - This bit of code is used to avoid unregistering network devices - at inappropriate times. 2.2 and later kernels are fairly picky - about when this can happen. - -======================================================================*/ - -static void flush_stale_links(void) -{ - dev_link_t *link, *next; - for (link = dev_list; link; link = next) { - next = link->next; - if (link->state & DEV_STALE_LINK) - ibmtr_detach(link); - } -} - static void netdev_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { @@ -184,7 +166,6 @@ int i, ret; DEBUG(0, "ibmtr_attach()\n"); - flush_stale_links(); /* Create new token-ring device */ dev = alloc_trdev(sizeof(*info)); @@ -273,10 +254,8 @@ } if (link->state & DEV_CONFIG) { ibmtr_release(link); - if (link->state & DEV_STALE_CONFIG) { - link->state |= DEV_STALE_LINK; + if (link->state & DEV_STALE_CONFIG) return; - } } if (link->handle) @@ -446,7 +425,9 @@ link->state &= ~DEV_CONFIG; -} /* ibmtr_release */ + if (link->state & DEV_STALE_CONFIG) + ibmtr_detach(link); +} /*====================================================================== diff -Nru a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c --- a/drivers/net/pcmcia/nmclan_cs.c Thu Sep 11 23:03:11 2003 +++ b/drivers/net/pcmcia/nmclan_cs.c Thu Sep 11 23:03:11 2003 @@ -449,21 +449,6 @@ static void nmclan_detach(dev_link_t *); /* ---------------------------------------------------------------------------- -flush_stale_links - Clean up stale device structures ----------------------------------------------------------------------------- */ - -static void flush_stale_links(void) -{ - dev_link_t *link, *next; - for (link = dev_list; link; link = next) { - next = link->next; - if (link->state & DEV_STALE_LINK) - nmclan_detach(link); - } -} - -/* ---------------------------------------------------------------------------- nmclan_attach Creates an "instance" of the driver, allocating local data structures for one device. The device is registered with Card @@ -480,7 +465,6 @@ DEBUG(0, "nmclan_attach()\n"); DEBUG(1, "%s\n", rcsid); - flush_stale_links(); /* Create new ethernet device */ dev = alloc_etherdev(sizeof(mace_private)); @@ -569,10 +553,8 @@ if (link->state & DEV_CONFIG) { nmclan_release(link); - if (link->state & DEV_STALE_CONFIG) { - link->state |= DEV_STALE_LINK; + if (link->state & DEV_STALE_CONFIG) return; - } } if (link->handle) @@ -843,7 +825,9 @@ link->state &= ~DEV_CONFIG; -} /* nmclan_release */ + if (link->state & DEV_STALE_CONFIG) + nmclan_detach(link); +} /* ---------------------------------------------------------------------------- nmclan_event diff -Nru a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c --- a/drivers/net/pcmcia/pcnet_cs.c Thu Sep 11 23:03:13 2003 +++ b/drivers/net/pcmcia/pcnet_cs.c Thu Sep 11 23:03:13 2003 @@ -239,24 +239,6 @@ /*====================================================================== - This bit of code is used to avoid unregistering network devices - at inappropriate times. 2.2 and later kernels are fairly picky - about when this can happen. - -======================================================================*/ - -static void flush_stale_links(void) -{ - dev_link_t *link, *next; - for (link = dev_list; link; link = next) { - next = link->next; - if (link->state & DEV_STALE_LINK) - pcnet_detach(link); - } -} - -/*====================================================================== - We never need to do anything when a pcnet device is "initialized" by the net software, because we only register already-found cards. @@ -284,7 +266,6 @@ int i, ret; DEBUG(0, "pcnet_attach()\n"); - flush_stale_links(); /* Create new ethernet device */ info = kmalloc(sizeof(*info), GFP_KERNEL); @@ -356,10 +337,8 @@ if (link->state & DEV_CONFIG) { pcnet_release(link); - if (link->state & DEV_STALE_CONFIG) { - link->state |= DEV_STALE_LINK; + if (link->state & DEV_STALE_CONFIG) return; - } } if (link->handle) @@ -821,7 +800,9 @@ link->state &= ~DEV_CONFIG; -} /* pcnet_release */ + if (link->state & DEV_STALE_CONFIG) + pcnet_detach(link); +} /*====================================================================== diff -Nru a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c --- a/drivers/net/pcmcia/smc91c92_cs.c Thu Sep 11 23:03:13 2003 +++ b/drivers/net/pcmcia/smc91c92_cs.c Thu Sep 11 23:03:13 2003 @@ -307,24 +307,6 @@ /*====================================================================== - This bit of code is used to avoid unregistering network devices - at inappropriate times. 2.2 and later kernels are fairly picky - about when this can happen. - -======================================================================*/ - -static void flush_stale_links(void) -{ - dev_link_t *link, *next; - for (link = dev_list; link; link = next) { - next = link->next; - if (link->state & DEV_STALE_LINK) - smc91c92_detach(link); - } -} - -/*====================================================================== - smc91c92_attach() creates an "instance" of the driver, allocating local data structures for one device. The device is registered with Card Services. @@ -340,7 +322,6 @@ int i, ret; DEBUG(0, "smc91c92_attach()\n"); - flush_stale_links(); /* Create new ethernet device */ dev = alloc_etherdev(sizeof(struct smc_private)); @@ -432,10 +413,8 @@ if (link->state & DEV_CONFIG) { smc91c92_release(link); - if (link->state & DEV_STALE_CONFIG) { - link->state |= DEV_STALE_LINK; + if (link->state & DEV_STALE_CONFIG) return; - } } if (link->handle) @@ -1103,7 +1082,9 @@ link->state &= ~DEV_CONFIG; -} /* smc91c92_release */ + if (link->state & DEV_STALE_CONFIG) + smc91c92_detach(link); +} /*====================================================================== diff -Nru a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c --- a/drivers/net/pcmcia/xirc2ps_cs.c Thu Sep 11 23:03:12 2003 +++ b/drivers/net/pcmcia/xirc2ps_cs.c Thu Sep 11 23:03:12 2003 @@ -390,17 +390,6 @@ static int do_stop(struct net_device *dev); /*=============== Helper functions =========================*/ -static void -flush_stale_links(void) -{ - dev_link_t *link, *next; - for (link = dev_list; link; link = next) { - next = link->next; - if (link->state & DEV_STALE_LINK) - xirc2ps_detach(link); - } -} - static int get_tuple_data(int fn, client_handle_t handle, tuple_t *tuple) { @@ -602,7 +591,6 @@ int err; DEBUG(0, "attach()\n"); - flush_stale_links(); /* Allocate the device structure */ dev = alloc_etherdev(sizeof(local_info_t)); @@ -687,13 +675,8 @@ * the release() function is called, that will trigger a proper * detach(). */ - if (link->state & DEV_CONFIG) { + if (link->state & DEV_CONFIG) xirc2ps_release(link); - if (link->state & DEV_STALE_CONFIG) { - link->state |= DEV_STALE_LINK; - return; - } - } /* Break the link with Card Services */ if (link->handle) @@ -1183,19 +1166,6 @@ DEBUG(0, "release(0x%p)\n", link); -#if 0 - /* - * If the device is currently in use, we won't release until it - * is actually closed. - */ - if (link->open) { - DEBUG(0, "release postponed, '%s' " - "still open\n", link->dev->dev_name); - link->state |= DEV_STALE_CONFIG; - return; - } -#endif - if (link->win) { struct net_device *dev = link->priv; local_info_t *local = dev->priv; @@ -2030,9 +2000,6 @@ SelectPage(0); link->open--; - if (link->state & DEV_STALE_CONFIG) - xirc2ps_release(link); - return 0; } diff -Nru a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c --- a/drivers/net/ppp_generic.c Thu Sep 11 23:03:14 2003 +++ b/drivers/net/ppp_generic.c Thu Sep 11 23:03:14 2003 @@ -792,7 +792,7 @@ /* Called at boot time if ppp is compiled into the kernel, or at module load time (from init_module) if compiled as a module. */ -int __init ppp_init(void) +static int __init ppp_init(void) { int err; @@ -801,6 +801,8 @@ if (!err) { err = devfs_mk_cdev(MKDEV(PPP_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "ppp"); + if (err) + unregister_chrdev(PPP_MAJOR, "ppp"); } if (err) diff -Nru a/drivers/net/pppoe.c b/drivers/net/pppoe.c --- a/drivers/net/pppoe.c Thu Sep 11 23:03:13 2003 +++ b/drivers/net/pppoe.c Thu Sep 11 23:03:13 2003 @@ -986,7 +986,7 @@ struct pppox_opt *po; char *dev_name; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { seq_puts(seq, "Id Address Device\n"); goto out; } @@ -1025,7 +1025,7 @@ loff_t l = *pos; read_lock_bh(&pppoe_hash_lock); - return l ? pppoe_get_idx(--l) : (void *)1; + return l ? pppoe_get_idx(--l) : SEQ_START_TOKEN; } static void *pppoe_seq_next(struct seq_file *seq, void *v, loff_t *pos) @@ -1033,7 +1033,7 @@ struct pppox_opt *po; ++*pos; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { po = pppoe_get_idx(0); goto out; } diff -Nru a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c --- a/drivers/net/skfp/skfddi.c Thu Sep 11 23:03:11 2003 +++ b/drivers/net/skfp/skfddi.c Thu Sep 11 23:03:11 2003 @@ -182,7 +182,7 @@ extern void enable_tx_irq(struct s_smc *smc, u_short queue); extern void mac_drv_clear_txd(struct s_smc *smc); -static struct pci_device_id skfddi_pci_tbl[] __initdata = { +static struct pci_device_id skfddi_pci_tbl[] = { { PCI_VENDOR_ID_SK, PCI_DEVICE_ID_SK_FP, PCI_ANY_ID, PCI_ANY_ID, }, { } /* Terminating entry */ }; diff -Nru a/drivers/net/slip.c b/drivers/net/slip.c --- a/drivers/net/slip.c Thu Sep 11 23:03:14 2003 +++ b/drivers/net/slip.c Thu Sep 11 23:03:14 2003 @@ -1389,9 +1389,8 @@ */ do { if (busy) { - current->state = TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ / 10); - current->state = TASK_RUNNING; } busy = 0; diff -Nru a/drivers/net/sunhme.c b/drivers/net/sunhme.c --- a/drivers/net/sunhme.c Thu Sep 11 23:03:12 2003 +++ b/drivers/net/sunhme.c Thu Sep 11 23:03:12 2003 @@ -179,7 +179,7 @@ where it could be referenced at any time due to hot plugging, the __initdata reference should be removed. */ -struct pci_device_id happymeal_pci_ids[] __initdata = { +struct pci_device_id happymeal_pci_ids[] = { { .vendor = PCI_VENDOR_ID_SUN, .device = PCI_DEVICE_ID_SUN_HAPPYMEAL, diff -Nru a/drivers/net/tc35815.c b/drivers/net/tc35815.c --- a/drivers/net/tc35815.c Thu Sep 11 23:03:11 2003 +++ b/drivers/net/tc35815.c Thu Sep 11 23:03:11 2003 @@ -448,7 +448,7 @@ /* Index to functions, as function prototypes. */ -static int __init tc35815_probe1(struct pci_dev *pdev, unsigned int base_addr, unsigned int irq); +static int __devinit tc35815_probe1(struct pci_dev *pdev, unsigned int base_addr, unsigned int irq); static int tc35815_open(struct net_device *dev); static int tc35815_send_packet(struct sk_buff *skb, struct net_device *dev); @@ -526,7 +526,7 @@ return -ENODEV; } -static int __init tc35815_probe1(struct pci_dev *pdev, unsigned int base_addr, unsigned int irq) +static int __devinit tc35815_probe1(struct pci_dev *pdev, unsigned int base_addr, unsigned int irq) { static unsigned version_printed = 0; int i; diff -Nru a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c --- a/drivers/net/tokenring/abyss.c Thu Sep 11 23:03:11 2003 +++ b/drivers/net/tokenring/abyss.c Thu Sep 11 23:03:11 2003 @@ -40,7 +40,7 @@ #include "tms380tr.h" #include "abyss.h" /* Madge-specific constants */ -static char version[] __initdata = +static char version[] __devinitdata = "abyss.c: v1.02 23/11/2000 by Adam Fritzler\n"; #define ABYSS_IO_EXTENT 64 @@ -92,7 +92,7 @@ outw(val, dev->base_addr + reg); } -static int __init abyss_attach(struct pci_dev *pdev, const struct pci_device_id *ent) +static int __devinit abyss_attach(struct pci_dev *pdev, const struct pci_device_id *ent) { static int versionprinted; struct net_device *dev; diff -Nru a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c --- a/drivers/net/tokenring/olympic.c Thu Sep 11 23:03:13 2003 +++ b/drivers/net/tokenring/olympic.c Thu Sep 11 23:03:13 2003 @@ -210,14 +210,13 @@ pci_set_master(pdev); if ((i = pci_request_regions(pdev,"olympic"))) { - return i ; - } ; + goto op_disable_dev; + } dev = alloc_trdev(sizeof(struct olympic_private)) ; - if (!dev) { - pci_release_regions(pdev) ; - return -ENOMEM ; + i = -ENOMEM; + goto op_free_dev; } olympic_priv = dev->priv ; @@ -231,10 +230,12 @@ dev->base_addr=pci_resource_start(pdev, 0); dev->init=NULL; /* Must be NULL otherwise we get called twice */ olympic_priv->olympic_card_name = pci_name(pdev); + olympic_priv->pdev = pdev; olympic_priv->olympic_mmio = ioremap(pci_resource_start(pdev,1),256); olympic_priv->olympic_lap = ioremap(pci_resource_start(pdev,2),2048); -#warning check ioremap return value - olympic_priv->pdev = pdev ; + if (!olympic_priv->olympic_mmio || !olympic_priv->olympic_lap) { + goto op_free_iomap; + } if ((pkt_buf_sz[card_no] < 100) || (pkt_buf_sz[card_no] > 18000) ) olympic_priv->pkt_buf_sz = PKT_BUF_SZ ; @@ -246,12 +247,8 @@ olympic_priv->olympic_message_level = message_level[card_no] ; olympic_priv->olympic_network_monitor = network_monitor[card_no]; - if((i = olympic_init(dev))) { - iounmap(olympic_priv->olympic_mmio) ; - iounmap(olympic_priv->olympic_lap) ; - kfree(dev) ; - pci_release_regions(pdev) ; - return i ; + if ((i = olympic_init(dev))) { + goto op_free_iomap; } dev->open=&olympic_open; @@ -275,6 +272,20 @@ printk("Olympic: Network Monitor information: /proc/%s\n",proc_name); } return 0 ; + +op_free_iomap: + if (olympic_priv->olympic_mmio) + iounmap(olympic_priv->olympic_mmio); + if (olympic_priv->olympic_lap) + iounmap(olympic_priv->olympic_lap); + +op_free_dev: + free_netdev(dev); + pci_release_regions(pdev); + +op_disable_dev: + pci_disable_device(pdev); + return i; } static int __devinit olympic_init(struct net_device *dev) diff -Nru a/drivers/net/tokenring/tmspci.c b/drivers/net/tokenring/tmspci.c --- a/drivers/net/tokenring/tmspci.c Thu Sep 11 23:03:13 2003 +++ b/drivers/net/tokenring/tmspci.c Thu Sep 11 23:03:13 2003 @@ -40,7 +40,7 @@ #include "tms380tr.h" -static char version[] __initdata = +static char version[] __devinitdata = "tmspci.c: v1.02 23/11/2000 by Adam Fritzler\n"; #define TMS_PCI_IO_EXTENT 32 @@ -91,7 +91,7 @@ outw(val, dev->base_addr + reg); } -static int __init tms_pci_attach(struct pci_dev *pdev, const struct pci_device_id *ent) +static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_device_id *ent) { static int versionprinted; struct net_device *dev; diff -Nru a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c --- a/drivers/net/tulip/de2104x.c Thu Sep 11 23:03:13 2003 +++ b/drivers/net/tulip/de2104x.c Thu Sep 11 23:03:13 2003 @@ -50,7 +50,7 @@ #include /* These identify the driver base version and may not be removed. */ -static char version[] __initdata = +static char version[] = KERN_INFO DRV_NAME " PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n"; MODULE_AUTHOR("Jeff Garzik "); @@ -1932,7 +1932,7 @@ goto fill_defaults; } -static int __init de_init_one (struct pci_dev *pdev, +static int __devinit de_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) { struct net_device *dev; diff -Nru a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c --- a/drivers/net/tulip/de4x5.c Thu Sep 11 23:03:11 2003 +++ b/drivers/net/tulip/de4x5.c Thu Sep 11 23:03:11 2003 @@ -480,7 +480,7 @@ #include "de4x5.h" -static char version[] __initdata = "de4x5.c:V0.546 2001/02/22 davies@maniac.ultranet.com\n"; +static char version[] __devinitdata = "de4x5.c:V0.546 2001/02/22 davies@maniac.ultranet.com\n"; #define c_char const char #define TWIDDLE(a) (u_short)le16_to_cpu(get_unaligned((u_short *)(a))) @@ -1082,7 +1082,7 @@ } -static int __init +static int __devinit de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev) { char name[DE4X5_NAME_LENGTH + 1]; @@ -2132,7 +2132,7 @@ ** DECchips, we can find the base SROM irrespective of the BIOS scan direction. ** For single port cards this is a time waster... */ -static void __init +static void __devinit srom_search(struct net_device *dev, struct pci_dev *pdev) { u_char pb; @@ -2213,7 +2213,7 @@ ** kernels use the V0.535[n] drivers. */ -static int __init de4x5_pci_probe (struct pci_dev *pdev, +static int __devinit de4x5_pci_probe (struct pci_dev *pdev, const struct pci_device_id *ent) { u_char pb, pbus = 0, dev_num, dnum = 0, timer; diff -Nru a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c --- a/drivers/net/wan/cosa.c Thu Sep 11 23:03:11 2003 +++ b/drivers/net/wan/cosa.c Thu Sep 11 23:03:11 2003 @@ -326,11 +326,11 @@ /* Ioctls */ static int cosa_start(struct cosa_data *cosa, int address); static int cosa_reset(struct cosa_data *cosa); -static int cosa_download(struct cosa_data *cosa, struct cosa_download *d); -static int cosa_readmem(struct cosa_data *cosa, struct cosa_download *d); +static int cosa_download(struct cosa_data *cosa, unsigned long a); +static int cosa_readmem(struct cosa_data *cosa, unsigned long a); /* COSA/SRP ROM monitor */ -static int download(struct cosa_data *cosa, char *data, int addr, int len); +static int download(struct cosa_data *cosa, const char *data, int addr, int len); static int startmicrocode(struct cosa_data *cosa, int address); static int readmem(struct cosa_data *cosa, char *data, int addr, int len); static int cosa_reset_and_read_id(struct cosa_data *cosa, char *id); @@ -1033,11 +1033,10 @@ } /* High-level function to download data into COSA memory. Calls download() */ -static inline int cosa_download(struct cosa_data *cosa, struct cosa_download *d) +static inline int cosa_download(struct cosa_data *cosa, unsigned long arg) { + struct cosa_download d; int i; - int addr, len; - char *code; if (cosa->usage > 1) printk(KERN_INFO "%s: WARNING: download of microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n", @@ -1047,38 +1046,36 @@ cosa->name, cosa->firmware_status); return -EPERM; } - - if (verify_area(VERIFY_READ, d, sizeof(*d)) || - __get_user(addr, &(d->addr)) || - __get_user(len, &(d->len)) || - __get_user(code, &(d->code))) + + if (copy_from_user(&d, (void __user *) arg, sizeof(d))) return -EFAULT; - if (addr < 0 || addr > COSA_MAX_FIRMWARE_SIZE) + if (d.addr < 0 || d.addr > COSA_MAX_FIRMWARE_SIZE) return -EINVAL; - if (len < 0 || len > COSA_MAX_FIRMWARE_SIZE) + if (d.len < 0 || d.len > COSA_MAX_FIRMWARE_SIZE) return -EINVAL; + /* If something fails, force the user to reset the card */ cosa->firmware_status &= ~(COSA_FW_RESET|COSA_FW_DOWNLOAD); - if ((i=download(cosa, code, len, addr)) < 0) { + i = download(cosa, d.code, d.len, d.addr); + if (i < 0) { printk(KERN_NOTICE "cosa%d: microcode download failed: %d\n", cosa->num, i); return -EIO; } printk(KERN_INFO "cosa%d: downloading microcode - 0x%04x bytes at 0x%04x\n", - cosa->num, len, addr); + cosa->num, d.len, d.addr); cosa->firmware_status |= COSA_FW_RESET|COSA_FW_DOWNLOAD; return 0; } /* High-level function to read COSA memory. Calls readmem() */ -static inline int cosa_readmem(struct cosa_data *cosa, struct cosa_download *d) +static inline int cosa_readmem(struct cosa_data *cosa, unsigned long arg) { + struct cosa_download d; int i; - int addr, len; - char *code; if (cosa->usage > 1) printk(KERN_INFO "cosa%d: WARNING: readmem requested with " @@ -1090,22 +1087,20 @@ return -EPERM; } - if (verify_area(VERIFY_READ, d, sizeof(*d)) || - __get_user(addr, &(d->addr)) || - __get_user(len, &(d->len)) || - __get_user(code, &(d->code))) + if (copy_from_user(&d, (void __user *) arg, sizeof(d))) return -EFAULT; /* If something fails, force the user to reset the card */ cosa->firmware_status &= ~COSA_FW_RESET; - if ((i=readmem(cosa, code, len, addr)) < 0) { + i = readmem(cosa, d.code, d.len, d.addr); + if (i < 0) { printk(KERN_NOTICE "cosa%d: reading memory failed: %d\n", cosa->num, i); return -EIO; } printk(KERN_INFO "cosa%d: reading card memory - 0x%04x bytes at 0x%04x\n", - cosa->num, len, addr); + cosa->num, d.len, d.addr); cosa->firmware_status |= COSA_FW_RESET; return 0; } @@ -1171,11 +1166,12 @@ case COSAIODOWNLD: /* Download the firmware */ if (!capable(CAP_SYS_RAWIO)) return -EACCES; - return cosa_download(cosa, (struct cosa_download *)arg); + + return cosa_download(cosa, arg); case COSAIORMEM: if (!capable(CAP_SYS_RAWIO)) return -EACCES; - return cosa_readmem(cosa, (struct cosa_download *)arg); + return cosa_readmem(cosa, arg); case COSAIORTYPE: return cosa_gettype(cosa, (char *)arg); case COSAIORIDSTR: @@ -1405,7 +1401,7 @@ * by a single space. Monitor has to reply with a space. Now the download * begins. After the download monitor replies with "\r\n." (CR LF dot). */ -static int download(struct cosa_data *cosa, char *microcode, int length, int address) +static int download(struct cosa_data *cosa, const char *microcode, int length, int address) { int i; diff -Nru a/drivers/net/wan/cosa.h b/drivers/net/wan/cosa.h --- a/drivers/net/wan/cosa.h Thu Sep 11 23:03:12 2003 +++ b/drivers/net/wan/cosa.h Thu Sep 11 23:03:12 2003 @@ -73,19 +73,19 @@ #define COSAIORSET _IO('C',0xf0) /* Start microcode at given address */ -#define COSAIOSTRT _IOW('C',0xf1,sizeof(int)) +#define COSAIOSTRT _IOW('C',0xf1, int) /* Read the block from the device memory */ -#define COSAIORMEM _IOR('C',0xf2,sizeof(struct cosa_download *)) +#define COSAIORMEM _IOWR('C',0xf2, struct cosa_download) /* Write the block to the device memory (i.e. download the microcode) */ -#define COSAIODOWNLD _IOW('C',0xf2,sizeof(struct cosa_download *)) +#define COSAIODOWNLD _IOW('C',0xf2, struct cosa_download) /* Read the device type (one of "srp", "cosa", and "cosa8" for now) */ -#define COSAIORTYPE _IOR('C',0xf3,sizeof(char *)) +#define COSAIORTYPE _IOR('C',0xf3, char *) /* Read the device identification string */ -#define COSAIORIDSTR _IOR('C',0xf4,sizeof(char *)) +#define COSAIORIDSTR _IOR('C',0xf4, char *) /* Maximum length of the identification string. */ #define COSA_MAX_ID_STRING 128 @@ -100,7 +100,7 @@ #define COSAIONRCHANS _IO('C',0xf8) /* Set the driver for the bus-master operations */ -#define COSAIOBMSET _IOW('C', 0xf9, sizeof(unsigned short)) +#define COSAIOBMSET _IOW('C', 0xf9, unsigned short) #define COSA_BM_OFF 0 /* Bus-mastering off - use ISA DMA (default) */ #define COSA_BM_ON 1 /* Bus-mastering on - faster but untested */ diff -Nru a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c --- a/drivers/net/wan/dlci.c Thu Sep 11 23:03:12 2003 +++ b/drivers/net/wan/dlci.c Thu Sep 11 23:03:12 2003 @@ -58,64 +58,9 @@ static const char version[] = "DLCI driver v0.35, 4 Jan 1997, mike.mclagan@linux.org"; static LIST_HEAD(dlci_devs); -static spinlock_t dlci_dev_lock = SPIN_LOCK_UNLOCKED; -static char *basename[16]; static void dlci_setup(struct net_device *); -/* allow FRAD's to register their name as a valid FRAD */ -int register_frad(const char *name) -{ - int i; - - if (!name) - return(-EINVAL); - - for (i=0;idevname); if (!slave) - return(-ENODEV); - - if (slave->type != ARPHRD_FRAD) { - dev_put(slave); - return(-EINVAL); - } - - /* check for registration */ - for (i=0;idevname, basename[i], strlen(basename[i])) == 0) && - (strlen(dlci->devname) > strlen(basename[i]))) - break; + return -ENODEV; - if (i == sizeof(basename) / sizeof(char *)) { - dev_put(slave); - return(-EINVAL); - } + if (slave->type != ARPHRD_FRAD || slave->priv == NULL) + goto err1; /* create device name */ master = alloc_netdev( sizeof(struct dlci_local), "dlci%d", dlci_setup); if (!master) { - dev_put(slave); - return(-ENOMEM); + err = -ENOMEM; + goto err1; } - err = register_netdev(master); - if (err < 0) { - dev_put(slave); - kfree(master); - return(err); + /* make sure same slave not already registered */ + rtnl_lock(); + list_for_each_entry(dlp, &dlci_devs, list) { + if (dlp->slave == slave) { + err = -EBUSY; + goto err2; + } } + err = dev_alloc_name(master, master->name); + if (err < 0) + goto err2; + *(short *)(master->dev_addr) = dlci->dlci; dlp = (struct dlci_local *) master->priv; @@ -461,22 +398,27 @@ dlp->master = master; flp = slave->priv; - err = flp ? (*flp->assoc)(slave, master) : -EINVAL; + err = (*flp->assoc)(slave, master); if (err < 0) - { - unregister_netdev(master); - dev_put(slave); - free_netdev(master); - return(err); - } + goto err2; + + err = register_netdevice(master); + if (err < 0) + goto err2; strcpy(dlci->devname, master->name); - spin_lock_bh(&dlci_dev_lock); list_add(&dlp->list, &dlci_devs); - spin_unlock_bh(&dlci_dev_lock); + rtnl_unlock(); return(0); + + err2: + rtnl_unlock(); + kfree(master); + err1: + dev_put(slave); + return(err); } static int dlci_del(struct dlci_add *dlci) @@ -499,21 +441,18 @@ slave = dlp->slave; flp = slave->priv; + rtnl_lock(); err = (*flp->deassoc)(slave, master); - if (err) - return(err); - + if (!err) { + list_del(&dlp->list); - spin_lock_bh(&dlci_dev_lock); - list_del(&dlp->list); - spin_unlock_bh(&dlci_dev_lock); + unregister_netdevice(master); - unregister_netdev(master); - - dev_put(slave); - free_netdev(master); + dev_put(slave); + } + rtnl_unlock(); - return(0); + return(err); } static int dlci_ioctl(unsigned int cmd, void *arg) @@ -560,6 +499,7 @@ dev->hard_header = dlci_header; dev->get_stats = dlci_get_stats; dev->change_mtu = dlci_change_mtu; + dev->destructor = free_netdev; dlp->receive = dlci_receive; @@ -569,31 +509,54 @@ } -int __init init_dlci(void) +/* if slave is unregistering, then cleanup master */ +static int dlci_dev_event(struct notifier_block *unused, + unsigned long event, void *ptr) +{ + struct net_device *dev = (struct net_device *) ptr; + + if (event == NETDEV_UNREGISTER) { + struct dlci_local *dlp; + + list_for_each_entry(dlp, &dlci_devs, list) { + if (dlp->slave == dev) { + list_del(&dlp->list); + unregister_netdevice(dlp->master); + dev_put(dlp->slave); + break; + } + } + } + return NOTIFY_DONE; +} + +static struct notifier_block dlci_notifier = { + .notifier_call = dlci_dev_event, +}; + +static int __init init_dlci(void) { - int i; dlci_ioctl_set(dlci_ioctl); + register_netdevice_notifier(&dlci_notifier); printk("%s.\n", version); - for(i=0;imaster); + unregister_netdevice(dlp->master); dev_put(dlp->slave); - free_netdev(dlp->master); } - + rtnl_unlock(); } module_init(init_dlci); diff -Nru a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c --- a/drivers/net/wan/dscc4.c Thu Sep 11 23:03:11 2003 +++ b/drivers/net/wan/dscc4.c Thu Sep 11 23:03:11 2003 @@ -693,7 +693,7 @@ kfree(ppriv); } -static int __init dscc4_init_one(struct pci_dev *pdev, +static int __devinit dscc4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { struct dscc4_pci_priv *priv; diff -Nru a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c --- a/drivers/net/wan/sdla.c Thu Sep 11 23:03:14 2003 +++ b/drivers/net/wan/sdla.c Thu Sep 11 23:03:14 2003 @@ -60,8 +60,6 @@ static const char* version = "SDLA driver v0.30, 12 Sep 1996, mike.mclagan@linux.org"; -static const char* devname = "sdla"; - static unsigned int valid_port[] __initdata = { 0x250, 0x270, 0x280, 0x300, 0x350, 0x360, 0x380, 0x390}; static unsigned int valid_mem[] __initdata = { @@ -1626,41 +1624,16 @@ static void setup_sdla(struct net_device *dev) { + struct frad_local *flp = dev->priv; + + netdev_boot_setup_check(dev); + + SET_MODULE_OWNER(dev); dev->flags = 0; dev->type = 0xFFFF; dev->hard_header_len = 0; dev->addr_len = 0; dev->mtu = SDLA_MAX_MTU; -} - -static int frad_registered; - -struct net_device * __init sdla_init(void) -{ - struct net_device *dev; - struct frad_local *flp; - int err = -ENOMEM; - - if (!frad_registered) { - err = register_frad(devname); - if (err) { - printk(KERN_ERR "%s: frad registration failed %d\n", - devname, err); - return ERR_PTR(err); - } - frad_registered = 1; - printk("%s.\n", version); - } - - - dev = alloc_netdev(sizeof(struct frad_local), "sdla0", setup_sdla); - if (!dev) - goto out; - - SET_MODULE_OWNER(dev); - netdev_boot_setup_check(dev); - - flp = dev->priv; dev->open = sdla_open; dev->stop = sdla_close; @@ -1680,48 +1653,41 @@ flp->timer.expires = 1; flp->timer.data = (unsigned long) dev; flp->timer.function = sdla_poll; - - err = register_netdev(dev); - if (err) - goto out1; - return dev; -out1: - kfree(dev); -out: - return ERR_PTR(err); } -#ifdef MODULE -static struct net_device *sdla0; +static struct net_device *sdla; static int __init init_sdla(void) { - int result = 0; + int err; - sdla0 = sdla_init(); - if (IS_ERR(sdla0)) - result = PTR_ERR(sdla0); + printk("%s.\n", version); - return result; + sdla = alloc_netdev(sizeof(struct frad_local), "sdla0", setup_sdla); + if (!sdla) + return -ENOMEM; + + err = register_netdev(sdla); + if (err) + free_netdev(sdla); + + return err; } static void __exit exit_sdla(void) { struct frad_local *flp; - unregister_netdev(sdla0); - if (sdla0->irq) - free_irq(sdla0->irq, sdla0); + unregister_netdev(sdla); + if (sdla->irq) + free_irq(sdla->irq, sdla); - flp = sdla0->priv; + flp = sdla->priv; del_timer_sync(&flp->timer); - free_netdev(sdla0); - - unregister_frad(devname); + free_netdev(sdla); } MODULE_LICENSE("GPL"); module_init(init_sdla); module_exit(exit_sdla); -#endif diff -Nru a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c --- a/drivers/net/wan/sdladrv.c Thu Sep 11 23:03:11 2003 +++ b/drivers/net/wan/sdladrv.c Thu Sep 11 23:03:11 2003 @@ -201,7 +201,7 @@ * Note: All data must be explicitly initialized!!! */ -static struct pci_device_id sdladrv_pci_tbl[] __initdata = { +static struct pci_device_id sdladrv_pci_tbl[] = { { V3_VENDOR_ID, V3_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, }, { } /* Terminating entry */ }; diff -Nru a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c --- a/drivers/net/wireless/airo_cs.c Thu Sep 11 23:03:13 2003 +++ b/drivers/net/wireless/airo_cs.c Thu Sep 11 23:03:13 2003 @@ -163,24 +163,6 @@ /*====================================================================== - This bit of code is used to avoid unregistering network devices - at inappropriate times. 2.2 and later kernels are fairly picky - about when this can happen. - - ======================================================================*/ - -static void flush_stale_links(void) -{ - dev_link_t *link, *next; - for (link = dev_list; link; link = next) { - next = link->next; - if (link->state & DEV_STALE_LINK) - airo_detach(link); - } -} - -/*====================================================================== - airo_attach() creates an "instance" of the driver, allocating local data structures for one device. The device is registered with Card Services. @@ -199,8 +181,7 @@ int ret, i; DEBUG(0, "airo_attach()\n"); - flush_stale_links(); - + /* Initialize the dev_link_t structure */ link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); if (!link) { @@ -285,10 +266,8 @@ if (link->state & DEV_CONFIG) { airo_release(link); - if (link->state & DEV_STALE_CONFIG) { - link->state |= DEV_STALE_LINK; + if (link->state & DEV_STALE_CONFIG) return; - } } if ( ((local_info_t*)link->priv)->eth_dev ) { @@ -554,8 +533,10 @@ if (link->irq.AssignedIRQ) CardServices(ReleaseIRQ, link->handle, &link->irq); link->state &= ~DEV_CONFIG; - -} /* airo_release */ + + if (link->state & DEV_STALE_CONFIG) + airo_detach(link); +} /*====================================================================== diff -Nru a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c --- a/drivers/net/wireless/atmel_cs.c Thu Sep 11 23:03:12 2003 +++ b/drivers/net/wireless/atmel_cs.c Thu Sep 11 23:03:12 2003 @@ -176,24 +176,6 @@ /*====================================================================== - This bit of code is used to avoid unregistering network devices - at inappropriate times. 2.2 and later kernels are fairly picky - about when this can happen. - - ======================================================================*/ - -static void flush_stale_links(void) -{ - dev_link_t *link, *next; - for (link = dev_list; link; link = next) { - next = link->next; - if (link->state & DEV_STALE_LINK) - atmel_detach(link); - } -} - -/*====================================================================== - atmel_attach() creates an "instance" of the driver, allocating local data structures for one device. The device is registered with Card Services. @@ -212,8 +194,7 @@ int ret, i; DEBUG(0, "atmel_attach()\n"); - flush_stale_links(); - + /* Initialize the dev_link_t structure */ link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); if (!link) { @@ -296,29 +277,19 @@ if (*linkp == NULL) return; - if ( link->state & DEV_CONFIG ) { + if (link->state & DEV_CONFIG) atmel_release(link); - if ( link->state & DEV_STALE_CONFIG ) { - link->state |= DEV_STALE_LINK; - return; - } - } - /* Break the link with Card Services */ if (link->handle) CardServices(DeregisterClient, link->handle); - - - + /* Unlink device structure, free pieces */ *linkp = link->next; - if (link->priv) { + if (link->priv) kfree(link->priv); - } kfree(link); - -} /* atmel_detach */ +} /*====================================================================== diff -Nru a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c --- a/drivers/net/wireless/netwave_cs.c Thu Sep 11 23:03:14 2003 +++ b/drivers/net/wireless/netwave_cs.c Thu Sep 11 23:03:14 2003 @@ -211,7 +211,6 @@ insertion */ static dev_link_t *netwave_attach(void); /* Create instance */ static void netwave_detach(dev_link_t *); /* Destroy instance */ -static void netwave_flush_stale_links(void); /* Destroy all staled instances */ /* Hardware configuration */ static void netwave_doreset(ioaddr_t iobase, u_char* ramBase); @@ -444,9 +443,6 @@ DEBUG(0, "netwave_attach()\n"); - /* Perform some cleanup */ - netwave_flush_stale_links(); - /* Initialize the dev_link_t structure */ dev = alloc_etherdev(sizeof(netwave_private)); if (!dev) @@ -553,7 +549,6 @@ if (link->state & DEV_STALE_CONFIG) { DEBUG(1, "netwave_cs: detach postponed, '%s' still " "locked\n", link->dev->dev_name); - link->state |= DEV_STALE_LINK; return; } } @@ -581,31 +576,6 @@ } /* netwave_detach */ /* - * Function netwave_flush_stale_links (void) - * - * This deletes all driver "instances" that need to be deleted. - * Sometimes, netwave_detach can't be performed following a call from - * cardmgr (device still open) and the device is put in a STALE_LINK - * state. - * This function is in charge of making the cleanup... - */ -static void netwave_flush_stale_links(void) -{ - dev_link_t * link; /* Current node in linked list */ - dev_link_t * next; /* Next node in linked list */ - - DEBUG(1, "netwave_flush_stale_links(0x%p)\n", dev_list); - - /* Go through the list */ - for (link = dev_list; link; link = next) { - next = link->next; - /* Check if in need of being removed */ - if(link->state & DEV_STALE_LINK) - netwave_detach(link); - } -} /* netwave_flush_stale_links */ - -/* * Wireless Handler : get protocol name */ static int netwave_get_name(struct net_device *dev, @@ -1181,9 +1151,11 @@ CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIRQ, link->handle, &link->irq); - link->state &= ~(DEV_CONFIG | DEV_STALE_CONFIG); + link->state &= ~DEV_CONFIG; -} /* netwave_release */ + if (link->state & DEV_STALE_CONFIG) + netwave_detach(link); +} /* * Function netwave_event (event, priority, args) @@ -1755,8 +1727,6 @@ { pcmcia_unregister_driver(&netwave_driver); - /* Do some cleanup of the device list */ - netwave_flush_stale_links(); if (dev_list != NULL) /* Critical situation */ printk("netwave_cs: devices remaining when removing module\n"); } diff -Nru a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c --- a/drivers/net/wireless/orinoco_cs.c Thu Sep 11 23:03:13 2003 +++ b/drivers/net/wireless/orinoco_cs.c Thu Sep 11 23:03:13 2003 @@ -153,24 +153,6 @@ CardServices(ReportError, handle, &err); } - -/* Remove zombie instances (card removed, detach pending) */ -static void -flush_stale_links(void) -{ - dev_link_t *link, *next; - - TRACE_ENTER(""); - - for (link = dev_list; link; link = next) { - next = link->next; - if (link->state & DEV_STALE_LINK) { - orinoco_cs_detach(link); - } - } - TRACE_EXIT(""); -} - /* * This creates an "instance" of the driver, allocating local data * structures for one device. The device is registered with Card @@ -189,9 +171,6 @@ client_reg_t client_reg; int ret, i; - /* A bit of cleanup */ - flush_stale_links(); - dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset); if (! dev) return NULL; @@ -266,13 +245,8 @@ return; } - if (link->state & DEV_CONFIG) { + if (link->state & DEV_CONFIG) orinoco_cs_release(link); - if (link->state & DEV_CONFIG) { - link->state |= DEV_STALE_LINK; - return; - } - } /* Break the link with Card Services */ if (link->handle) diff -Nru a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c --- a/drivers/net/wireless/ray_cs.c Thu Sep 11 23:03:12 2003 +++ b/drivers/net/wireless/ray_cs.c Thu Sep 11 23:03:12 2003 @@ -138,7 +138,7 @@ static void verify_dl_startup(u_long); /* Prototypes for interrpt time functions **********************************/ -static void ray_interrupt (int reg, void *dev_id, struct pt_regs *regs); +static irqreturn_t ray_interrupt (int reg, void *dev_id, struct pt_regs *regs); static void clear_interrupt(ray_dev_t *local); static void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs, unsigned int pkt_addr, int rx_len); @@ -319,24 +319,6 @@ static char rcsid[] = "Raylink/WebGear wireless LAN - Corey "; -/*====================================================================== - - This bit of code is used to avoid unregistering network devices - at inappropriate times. 2.2 and later kernels are fairly picky - about when this can happen. - -======================================================================*/ - -static void flush_stale_links(void) -{ - dev_link_t *link, *next; - for (link = dev_list; link; link = next) { - next = link->next; - if (link->state & DEV_STALE_LINK) - ray_detach(link); - } -} - /*============================================================================= ray_attach() creates an "instance" of the driver, allocating local data structures for one device. The device is registered @@ -354,7 +336,6 @@ struct net_device *dev; DEBUG(1, "ray_attach()\n"); - flush_stale_links(); /* Initialize the dev_link_t structure */ link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); @@ -484,10 +465,8 @@ */ if (link->state & DEV_CONFIG) { ray_release(link); - if(link->state & DEV_STALE_CONFIG) { - link->state |= DEV_STALE_LINK; + if(link->state & DEV_STALE_CONFIG) return; - } } /* Break the link with Card Services */ @@ -932,7 +911,11 @@ if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseIRQ ret = %x\n",i); DEBUG(2,"ray_release ending\n"); -} /* ray_release */ + + if (link->state & DEV_STALE_CONFIG) + ray_detach(link); +} + /*============================================================================= The card status event handler. Mostly, this schedules other stuff to run after an event is received. A CARD_REMOVAL event @@ -2050,7 +2033,7 @@ /*============================================================================= * All routines below here are run at interrupt time. =============================================================================*/ -static void ray_interrupt(int irq, void *dev_id, struct pt_regs * regs) +static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs) { struct net_device *dev = (struct net_device *)dev_id; dev_link_t *link; @@ -2063,7 +2046,7 @@ UCHAR status; if (dev == NULL) /* Note that we want interrupts with dev->start == 0 */ - return; + return IRQ_NONE; DEBUG(4,"ray_cs: interrupt for *dev=%p\n",dev); @@ -2071,7 +2054,7 @@ link = (dev_link_t *)local->finder; if ( ! (link->state & DEV_PRESENT) || link->state & DEV_SUSPEND ) { DEBUG(2,"ray_cs interrupt from device not present or suspended.\n"); - return; + return IRQ_NONE; } rcsindex = readb(&((struct scb *)(local->sram))->rcs_index); @@ -2079,7 +2062,7 @@ { DEBUG(1,"ray_cs interrupt bad rcsindex = 0x%x\n",rcsindex); clear_interrupt(local); - return; + return IRQ_HANDLED; } if (rcsindex < NUMBER_OF_CCS) /* If it's a returned CCS */ { @@ -2235,6 +2218,7 @@ writeb(CCS_BUFFER_FREE, &prcs->buffer_status); } clear_interrupt(local); + return IRQ_HANDLED; } /* ray_interrupt */ /*===========================================================================*/ static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs) diff -Nru a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c --- a/drivers/net/wireless/strip.c Thu Sep 11 23:03:13 2003 +++ b/drivers/net/wireless/strip.c Thu Sep 11 23:03:13 2003 @@ -965,8 +965,6 @@ return (buffer); } -#define STRIP_PROC_HEADER ((void *)1) - /* get Nth element of the linked list */ static struct strip *strip_get_idx(loff_t pos) { @@ -984,7 +982,7 @@ static void *strip_seq_start(struct seq_file *seq, loff_t *pos) { rcu_read_lock(); - return *pos ? strip_get_idx(*pos - 1) : STRIP_PROC_HEADER; + return *pos ? strip_get_idx(*pos - 1) : SEQ_START_TOKEN; } static void *strip_seq_next(struct seq_file *seq, void *v, loff_t *pos) @@ -993,7 +991,7 @@ struct strip *s; ++*pos; - if (v == STRIP_PROC_HEADER) + if (v == SEQ_START_TOKEN) return strip_get_idx(1); s = v; @@ -1149,7 +1147,7 @@ */ static int strip_seq_show(struct seq_file *seq, void *v) { - if (v == STRIP_PROC_HEADER) + if (v == SEQ_START_TOKEN) seq_printf(seq, "strip_version: %s\n", StripVersion); else strip_seq_status_info(seq, (const struct strip *)v); diff -Nru a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c --- a/drivers/net/wireless/wavelan_cs.c Thu Sep 11 23:03:12 2003 +++ b/drivers/net/wireless/wavelan_cs.c Thu Sep 11 23:03:12 2003 @@ -4175,50 +4175,14 @@ CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIRQ, link->handle, &link->irq); - link->state &= ~(DEV_CONFIG | DEV_STALE_CONFIG); + link->state &= ~DEV_CONFIG; #ifdef DEBUG_CONFIG_TRACE printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name); #endif -} /* wv_pcmcia_release */ -/*------------------------------------------------------------------*/ -/* - * Sometimes, wavelan_detach can't be performed following a call from - * cardmgr (device still open, pcmcia_release not done) and the device - * is put in a STALE_LINK state and remains in memory. - * - * This function run through our current list of device and attempt - * another time to remove them. We hope that since last time the - * device has properly been closed. - * - * (called by wavelan_attach() & cleanup_module()) - */ -static void -wv_flush_stale_links(void) -{ - dev_link_t * link; /* Current node in linked list */ - dev_link_t * next; /* Next node in linked list */ - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "-> wv_flush_stale_links(0x%p)\n", dev_list); -#endif - - /* Go through the list */ - for (link = dev_list; link; link = next) - { - next = link->next; - - /* Check if in need of being removed */ - if((link->state & DEV_STALE_LINK) || - (! (link->state & DEV_PRESENT))) - wavelan_detach(link); - - } - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "<- wv_flush_stale_links()\n"); -#endif + if (link->state & DEV_STALE_CONFIG) + wavelan_detach(link); } /************************ INTERRUPT HANDLING ************************/ @@ -4705,9 +4669,6 @@ printk(KERN_DEBUG "-> wavelan_attach()\n"); #endif - /* Perform some cleanup */ - wv_flush_stale_links(); - /* Initialize the dev_link_t structure */ link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); if (!link) return NULL; @@ -4859,7 +4820,6 @@ printk(KERN_DEBUG "wavelan_detach: detach postponed," " '%s' still locked\n", link->dev->dev_name); #endif - link->state |= DEV_STALE_LINK; return; } } @@ -5039,9 +4999,6 @@ static void __exit exit_wavelan_cs(void) { - /* Do some cleanup of the device list */ - wv_flush_stale_links(); - pcmcia_unregister_driver(&wavelan_driver); } diff -Nru a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h --- a/drivers/net/wireless/wavelan_cs.p.h Thu Sep 11 23:03:13 2003 +++ b/drivers/net/wireless/wavelan_cs.p.h Thu Sep 11 23:03:13 2003 @@ -761,8 +761,7 @@ static inline int wv_pcmcia_config(dev_link_t *); /* Configure the pcmcia interface */ static void - wv_pcmcia_release(dev_link_t *),/* Remove a device */ - wv_flush_stale_links(void); /* "detach" all possible devices */ + wv_pcmcia_release(dev_link_t *);/* Remove a device */ /* ---------------------- INTERRUPT HANDLING ---------------------- */ static irqreturn_t wavelan_interrupt(int, /* Interrupt handler */ diff -Nru a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c --- a/drivers/net/wireless/wl3501_cs.c Thu Sep 11 23:03:11 2003 +++ b/drivers/net/wireless/wl3501_cs.c Thu Sep 11 23:03:11 2003 @@ -82,7 +82,7 @@ MODULE_PARM(pc_debug, "i"); #define dprintk(n, format, args...) \ { if (pc_debug > (n)) \ - printk(KERN_INFO "%s: " format "\n", __FUNCTION__, ##args); } + printk(KERN_INFO "%s: " format "\n", __FUNCTION__ , ##args); } #else #define dprintk(n, format, args...) #endif @@ -638,8 +638,10 @@ .sig_id = WL3501_SIG_JOIN_REQ, .timeout = 10, .ds_pset = { - .el.id = IW_MGMT_INFO_ELEMENT_DS_PARAMETER_SET, - .el.len = 1, + .el = { + .id = IW_MGMT_INFO_ELEMENT_DS_PARAMETER_SET, + .len = 1, + }, .chan = this->chan, }, }; @@ -655,13 +657,17 @@ .beacon_period = 400, .dtim_period = 1, .ds_pset = { - .el.id = IW_MGMT_INFO_ELEMENT_DS_PARAMETER_SET, - .el.len = 1, + .el = { + .id = IW_MGMT_INFO_ELEMENT_DS_PARAMETER_SET, + .len = 1, + }, .chan = this->chan, }, .bss_basic_rset = { - .el.id = IW_MGMT_INFO_ELEMENT_SUPPORTED_RATES, - .el.len = 2, + .el = { + .id = IW_MGMT_INFO_ELEMENT_SUPPORTED_RATES, + .len = 2, + }, .data_rate_labels = { [0] = IW_MGMT_RATE_LABEL_MANDATORY | IW_MGMT_RATE_LABEL_1MBIT, @@ -670,8 +676,10 @@ }, }, .operational_rset = { - .el.id = IW_MGMT_INFO_ELEMENT_SUPPORTED_RATES, - .el.len = 2, + .el = { + .id = IW_MGMT_INFO_ELEMENT_SUPPORTED_RATES, + .len = 2, + }, .data_rate_labels = { [0] = IW_MGMT_RATE_LABEL_MANDATORY | IW_MGMT_RATE_LABEL_1MBIT, @@ -680,8 +688,10 @@ }, }, .ibss_pset = { - .el.id = IW_MGMT_INFO_ELEMENT_IBSS_PARAMETER_SET, - .el.len = 2, + .el = { + .id = IW_MGMT_INFO_ELEMENT_IBSS_PARAMETER_SET, + .len = 2, + }, .atim_window = 10, }, .bss_type = wl3501_fw_bss_type(this), @@ -1571,7 +1581,6 @@ printk(KERN_DEBUG "wl3501_cs: detach postponed, '%s' " "still locked\n", link->dev->dev_name); #endif - link->state |= DEV_STALE_LINK; goto out; } @@ -1589,22 +1598,6 @@ return; } -/** - * wl3501_flush_stale_links - Remove zombie instances - * - * Remove zombie instances (card removed, detach pending) - */ -static void wl3501_flush_stale_links(void) -{ - dev_link_t *link, *next; - - for (link = wl3501_dev_list; link; link = next) { - next = link->next; - if (link->state & DEV_STALE_LINK) - wl3501_detach(link); - } -} - static int wl3501_get_name(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { @@ -2033,8 +2026,6 @@ struct net_device *dev; int ret, i; - wl3501_flush_stale_links(); - /* Initialize the dev_link_t structure */ link = kmalloc(sizeof(*link), GFP_KERNEL); if (!link) @@ -2263,7 +2254,7 @@ CardServices(ReleaseIRQ, link->handle, &link->irq); link->state &= ~DEV_CONFIG; - if (link->state & DEV_STALE_LINK) + if (link->state & DEV_STALE_CONFIG) wl3501_detach(link); out: return; diff -Nru a/drivers/parisc/asp.c b/drivers/parisc/asp.c --- a/drivers/parisc/asp.c Thu Sep 11 23:03:14 2003 +++ b/drivers/parisc/asp.c Thu Sep 11 23:03:14 2003 @@ -76,8 +76,6 @@ printk(KERN_INFO "%s version %d at 0x%lx found.\n", asp->name, asp->version, dev->hpa); - snprintf(dev->dev.name, sizeof(dev->dev.name), "%s version %d", - asp->name, asp->version); /* the IRQ ASP should use */ ret = -EBUSY; diff -Nru a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c --- a/drivers/parisc/ccio-dma.c Thu Sep 11 23:03:11 2003 +++ b/drivers/parisc/ccio-dma.c Thu Sep 11 23:03:11 2003 @@ -129,6 +129,92 @@ volatile uint32_t io_io_high; /* Offset 15 */ }; +/* +** IOA Registers +** ------------- +** +** Runway IO_CONTROL Register (+0x38) +** +** The Runway IO_CONTROL register controls the forwarding of transactions. +** +** | 0 ... 13 | 14 15 | 16 ... 21 | 22 | 23 24 | 25 ... 31 | +** | HV | TLB | reserved | HV | mode | reserved | +** +** o mode field indicates the address translation of transactions +** forwarded from Runway to GSC+: +** Mode Name Value Definition +** Off (default) 0 Opaque to matching addresses. +** Include 1 Transparent for matching addresses. +** Peek 3 Map matching addresses. +** +** + "Off" mode: Runway transactions which match the I/O range +** specified by the IO_IO_LOW/IO_IO_HIGH registers will be ignored. +** + "Include" mode: all addresses within the I/O range specified +** by the IO_IO_LOW and IO_IO_HIGH registers are transparently +** forwarded. This is the I/O Adapter's normal operating mode. +** + "Peek" mode: used during system configuration to initialize the +** GSC+ bus. Runway Write_Shorts in the address range specified by +** IO_IO_LOW and IO_IO_HIGH are forwarded through the I/O Adapter +** *AND* the GSC+ address is remapped to the Broadcast Physical +** Address space by setting the 14 high order address bits of the +** 32 bit GSC+ address to ones. +** +** o TLB field affects transactions which are forwarded from GSC+ to Runway. +** "Real" mode is the poweron default. +** +** TLB Mode Value Description +** Real 0 No TLB translation. Address is directly mapped and the +** virtual address is composed of selected physical bits. +** Error 1 Software fills the TLB manually. +** Normal 2 IOA fetches IO TLB misses from IO PDIR (in host memory). +** +** +** IO_IO_LOW_HV +0x60 (HV dependent) +** IO_IO_HIGH_HV +0x64 (HV dependent) +** IO_IO_LOW +0x78 (Architected register) +** IO_IO_HIGH +0x7c (Architected register) +** +** IO_IO_LOW and IO_IO_HIGH set the lower and upper bounds of the +** I/O Adapter address space, respectively. +** +** 0 ... 7 | 8 ... 15 | 16 ... 31 | +** 11111111 | 11111111 | address | +** +** Each LOW/HIGH pair describes a disjoint address space region. +** (2 per GSC+ port). Each incoming Runway transaction address is compared +** with both sets of LOW/HIGH registers. If the address is in the range +** greater than or equal to IO_IO_LOW and less than IO_IO_HIGH the transaction +** for forwarded to the respective GSC+ bus. +** Specify IO_IO_LOW equal to or greater than IO_IO_HIGH to avoid specifying +** an address space region. +** +** In order for a Runway address to reside within GSC+ extended address space: +** Runway Address [0:7] must identically compare to 8'b11111111 +** Runway Address [8:11] must be equal to IO_IO_LOW(_HV)[16:19] +** Runway Address [12:23] must be greater than or equal to +** IO_IO_LOW(_HV)[20:31] and less than IO_IO_HIGH(_HV)[20:31]. +** Runway Address [24:39] is not used in the comparison. +** +** When the Runway transaction is forwarded to GSC+, the GSC+ address is +** as follows: +** GSC+ Address[0:3] 4'b1111 +** GSC+ Address[4:29] Runway Address[12:37] +** GSC+ Address[30:31] 2'b00 +** +** All 4 Low/High registers must be initialized (by PDC) once the lower bus +** is interrogated and address space is defined. The operating system will +** modify the architectural IO_IO_LOW and IO_IO_HIGH registers following +** the PDC initialization. However, the hardware version dependent IO_IO_LOW +** and IO_IO_HIGH registers should not be subsequently altered by the OS. +** +** Writes to both sets of registers will take effect immediately, bypassing +** the queues, which ensures that subsequent Runway transactions are checked +** against the updated bounds values. However reads are queued, introducing +** the possibility of a read being bypassed by a subsequent write to the same +** register. This sequence can be avoided by having software wait for read +** returns before issuing subsequent writes. +*/ + struct ioc { struct ioa_registers *ioc_hpa; /* I/O MMU base address */ u8 *res_map; /* resource map, bit == pdir entry */ @@ -1448,13 +1534,74 @@ (unsigned long)&ioc->ioc_hpa->io_io_low_hv); } -static void expand_ioc_area(struct ioc *ioc, unsigned long size, - unsigned long min, unsigned long max, unsigned long align) +static int expand_resource(struct resource *res, unsigned long size, + unsigned long align) { -#ifdef NASTY_HACK_FOR_K_CLASS - __raw_writel(0xfffff600, (unsigned long)&(ioc->ioc_hpa->io_io_high)); - ioc->mmio_region[0].end = 0xf5ffffff; -#endif + struct resource *temp_res; + unsigned long start = res->start; + unsigned long end ; + + /* see if we can expand above */ + end = (res->end + size + align - 1) & ~(align - 1);; + + temp_res = __request_region(res->parent, res->end, end - res->end, + "expansion"); + if(!temp_res) { + /* now try below */ + start = ((res->start - size + align) & ~(align - 1)) - align; + end = res->end; + temp_res = __request_region(res->parent, start, size, + "expansion"); + if(!temp_res) { + return -ENOMEM; + } + } + release_resource(temp_res); + temp_res = res->parent; + release_resource(res); + res->start = start; + res->end = end; + + /* This could be caused by some sort of race. Basically, if + * this tripped something stole the region we just reserved + * and then released to check for expansion */ + BUG_ON(request_resource(temp_res, res) != 0); + + return 0; +} + +static void expand_ioc_area(struct resource *parent, struct ioc *ioc, + unsigned long size, unsigned long min, + unsigned long max, unsigned long align) +{ + if(ioc == NULL) + /* no IOC, so nothing to expand */ + return; + + if (expand_resource(parent, size, align) != 0) { + printk(KERN_ERR "Unable to expand %s window by 0x%lx\n", + parent->name, size); + return; + } + + /* OK, we have the memory, now expand the window */ + if (parent == &ioc->mmio_region[0]) { + __raw_writel(((parent->start)>>16) | 0xffff0000, + (unsigned long)&(ioc->ioc_hpa->io_io_low)); + __raw_writel(((parent->end)>>16) | 0xffff0000, + (unsigned long)&(ioc->ioc_hpa->io_io_high)); + } else if (parent == &ioc->mmio_region[1]) { + __raw_writel(((parent->start)>>16) | 0xffff0000, + (unsigned long)&(ioc->ioc_hpa->io_io_low_hv)); + __raw_writel(((parent->end)>>16) | 0xffff0000, + (unsigned long)&(ioc->ioc_hpa->io_io_high_hv)); + } else { + /* This should be impossible. It means + * expand_ioc_area got called with a resource that + * didn't belong to the ioc + */ + BUG(); + } } static struct resource *ccio_get_resource(struct ioc* ioc, @@ -1488,7 +1635,7 @@ alignf_data)) return 0; - expand_ioc_area(ioc, size, min, max, align); + expand_ioc_area(parent, ioc, size, min, max, align); return allocate_resource(parent, res, size, min, max, align, alignf, alignf_data); } @@ -1522,7 +1669,6 @@ memset(ioc, 0, sizeof(struct ioc)); ioc->name = dev->id.hversion == U2_IOA_RUNWAY ? "U2" : "UTurn"; - strlcpy(dev->dev.name, ioc->name, sizeof(dev->dev.name)); printk(KERN_INFO "Found %s at 0x%lx\n", ioc->name, dev->hpa); diff -Nru a/drivers/parisc/dino.c b/drivers/parisc/dino.c --- a/drivers/parisc/dino.c Thu Sep 11 23:03:11 2003 +++ b/drivers/parisc/dino.c Thu Sep 11 23:03:11 2003 @@ -401,23 +401,7 @@ { int irq; - /* - * Perform a binary search on set bits. - * `Less than Fatal' and PS2 interrupts aren't supported. - */ - if (mask & 0xf) { - if (mask & 0x3) { - irq = (mask & 0x1) ? 0 : 1; /* PCI INT A, B */ - } else { - irq = (mask & 0x4) ? 2 : 3; /* PCI INT C, D */ - } - } else { - if (mask & 0x30) { - irq = (mask & 0x10) ? 4 : 5; /* PCI INT E, F */ - } else { - irq = (mask & 0x40) ? 6 : 10; /* GSC, RS232 */ - } - } + irq = __ffs(mask); mask &= ~(1< 0) goto ilr_again; - printk("Dino %lx: stuck interrupt %d\n", dino_dev->hba.base_addr, mask); + printk(KERN_ERR "Dino %lx: stuck interrupt %d\n", dino_dev->hba.base_addr, mask); return IRQ_NONE; } return IRQ_HANDLED; @@ -479,15 +463,35 @@ int i; struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->dev)); struct resource *res; + char name[128]; + int size; res = &dino_dev->hba.lmmio_space; res->flags = IORESOURCE_MEM; + size = snprintf(name, sizeof(name), "Dino LMMIO (%s)", bus->dev->bus_id); + res->name = kmalloc(size+1, GFP_KERNEL); + if(res->name) + strcpy((char *)res->name, name); + else + res->name = dino_dev->hba.lmmio_space.name; + if (ccio_allocate_resource(dino_dev->hba.dev, res, _8MB, - (unsigned long) 0xfffffffff0000000UL | _8MB, - 0xffffffffffffffffUL &~ _8MB, _8MB, + F_EXTEND(0xf0000000UL) | _8MB, + F_EXTEND(0xffffffffUL) &~ _8MB, _8MB, NULL, NULL) < 0) { - printk(KERN_WARNING "Dino: Failed to allocate memory region\n"); + struct list_head *ln, *tmp_ln; + + printk(KERN_ERR "Dino: cannot attach bus %s\n", + bus->dev->bus_id); + /* kill the bus, we can't do anything with it */ + list_for_each_safe(ln, tmp_ln, &bus->devices) { + struct pci_dev *dev = pci_dev_b(ln); + + list_del(&dev->global_list); + list_del(&dev->bus_list); + } + return; } bus->resource[1] = res; @@ -495,9 +499,11 @@ /* Now tell dino what range it has */ for (i = 1; i < 31; i++) { - if (res->start == (0xfffffffff0000000UL | i * _8MB)) + if (res->start == F_EXTEND(0xf0000000UL | (i * _8MB))) break; } + DBG("DINO GSC WRITE i=%d, start=%lx, dino addr = %lx\n", + i, res->start, base_addr + DINO_IO_ADDR_EN); gsc_writel(1 << i, base_addr + DINO_IO_ADDR_EN); pci_bus_assign_resources(bus); @@ -521,7 +527,7 @@ ** Set Latency Timer to 0xff (not a shared bus) ** Set CACHELINE_SIZE. */ - dino_cfg_write(dev->bus, dev->devfn, PCI_CACHE_LINE_SIZE, 16, 0xff00 | L1_CACHE_BYTES/4); + dino_cfg_write(dev->bus, dev->devfn, PCI_CACHE_LINE_SIZE, 2, 0xff00 | L1_CACHE_BYTES/4); /* ** Program INT_LINE for card-mode devices. @@ -532,13 +538,13 @@ ** "-1" converts INTA-D (1-4) to PCIINTA-D (0-3) range. ** The additional "-1" adjusts for skewing the IRQ<->slot. */ - dino_cfg_read(dev->bus, dev->devfn, PCI_INTERRUPT_PIN, 8, &irq_pin); + dino_cfg_read(dev->bus, dev->devfn, PCI_INTERRUPT_PIN, 1, &irq_pin); dev->irq = (irq_pin + PCI_SLOT(dev->devfn) - 1) % 4 ; /* Shouldn't really need to do this but it's in case someone tries ** to bypass PCI services and look at the card themselves. */ - dino_cfg_write(dev->bus, dev->devfn, PCI_INTERRUPT_LINE, 8, dev->irq); + dino_cfg_write(dev->bus, dev->devfn, PCI_INTERRUPT_LINE, 1, dev->irq); } @@ -585,8 +591,8 @@ #ifdef __LP64__ /* Sign Extend MMIO addresses */ else if (res->flags & IORESOURCE_MEM) { - res->start |= 0xffffffff00000000UL; - res->end |= 0xffffffff00000000UL; + res->start |= F_EXTEND(0UL); + res->end |= F_EXTEND(0UL); } #endif } @@ -789,8 +795,8 @@ return 0; } -#define CUJO_RAVEN_ADDR 0xfffffffff1000000UL -#define CUJO_FIREHAWK_ADDR 0xfffffffff1604000UL +#define CUJO_RAVEN_ADDR F_EXTEND(0xf1000000UL) +#define CUJO_FIREHAWK_ADDR F_EXTEND(0xf1604000UL) #define CUJO_RAVEN_BADPAGE 0x01003000UL #define CUJO_FIREHAWK_BADPAGE 0x01607000UL @@ -818,9 +824,16 @@ { struct dino_device *dino_dev; // Dino specific control struct const char *version = "unknown"; - const char *name = "Dino"; + const int name_len = 32; + char *name; int is_cujo = 0; + name = kmalloc(name_len, GFP_KERNEL); + if(name) + snprintf(name, name_len, "Dino %s", dev->dev.bus_id); + else + name = "Dino"; + if (is_card_dino(&dev->id)) { version = "3.x (card mode)"; } else { @@ -838,8 +851,6 @@ } printk("%s version %s found at 0x%lx\n", name, version, dev->hpa); - snprintf(dev->dev.name, sizeof(dev->dev.name), - "%s version %s", name, version); if (!request_mem_region(dev->hpa, PAGE_SIZE, name)) { printk(KERN_ERR "DINO: Hey! Someone took my MMIO space (0x%ld)!\n", diff -Nru a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c --- a/drivers/parisc/eisa.c Thu Sep 11 23:03:11 2003 +++ b/drivers/parisc/eisa.c Thu Sep 11 23:03:11 2003 @@ -327,14 +327,13 @@ printk(KERN_INFO "%s EISA Adapter found at 0x%08lx\n", name, dev->hpa); - snprintf(dev->dev.name, sizeof(dev->dev.name), "%s EISA", name); eisa_dev.hba.dev = dev; eisa_dev.hba.iommu = ccio_get_iommu(dev); eisa_dev.hba.lmmio_space.name = "EISA"; - eisa_dev.hba.lmmio_space.start = (unsigned long) 0xfffffffffc000000; - eisa_dev.hba.lmmio_space.end = (unsigned long) 0xffffffffffbfffff; + eisa_dev.hba.lmmio_space.start = F_EXTEND(0xfc000000); + eisa_dev.hba.lmmio_space.end = F_EXTEND(0xffbfffff); eisa_dev.hba.lmmio_space.flags = IORESOURCE_MEM; result = ccio_request_resource(dev, &eisa_dev.hba.lmmio_space); if (result < 0) { diff -Nru a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c --- a/drivers/parisc/hppb.c Thu Sep 11 23:03:12 2003 +++ b/drivers/parisc/hppb.c Thu Sep 11 23:03:12 2003 @@ -70,7 +70,6 @@ card = card->next; } printk(KERN_INFO "Found GeckoBoa at 0x%lx\n", dev->hpa); - snprintf(dev->dev.name, sizeof(dev->dev.name), "GeckoBoa"); card->hpa = dev->hpa; card->mmio_region.name = "HP-PB Bus"; diff -Nru a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c --- a/drivers/parisc/iosapic.c Thu Sep 11 23:03:11 2003 +++ b/drivers/parisc/iosapic.c Thu Sep 11 23:03:11 2003 @@ -643,7 +643,7 @@ if (NULL == isi) { printk(KERN_WARNING MODULE_NAME ": hpa not registered for %s\n", - pcidev->dev.name); + pci_name(pcidev)); return(-1); } diff -Nru a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c --- a/drivers/parisc/lasi.c Thu Sep 11 23:03:13 2003 +++ b/drivers/parisc/lasi.c Thu Sep 11 23:03:13 2003 @@ -185,8 +185,6 @@ lasi->version = gsc_readl(lasi->hpa + LASI_VER) & 0xf; printk(KERN_INFO "%s version %d at 0x%lx found.\n", lasi->name, lasi->version, lasi->hpa); - snprintf(dev->dev.name, sizeof(dev->dev.name), "%s version %d", - lasi->name, lasi->version); /* initialize the chassis LEDs really early */ lasi_led_init(lasi->hpa); diff -Nru a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c --- a/drivers/parisc/lba_pci.c Thu Sep 11 23:03:13 2003 +++ b/drivers/parisc/lba_pci.c Thu Sep 11 23:03:13 2003 @@ -782,7 +782,7 @@ int i; struct pci_dev *dev = pci_dev_b(ln); - DBG("lba_fixup_bus() %s\n", dev->name); + DBG("lba_fixup_bus() %s\n", pci_name(dev)); /* Virtualize Device/Bridge Resources. */ for (i = 0; i < PCI_NUM_RESOURCES; i++) { @@ -1358,8 +1358,6 @@ printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n", MODULE_NAME, version, func_class & 0xf, dev->hpa); - snprintf(dev->dev.name, sizeof(dev->dev.name), "%s version %s", - MODULE_NAME, version); /* Just in case we find some prototypes... */ if (func_class < 2) { diff -Nru a/drivers/parisc/led.c b/drivers/parisc/led.c --- a/drivers/parisc/led.c Thu Sep 11 23:03:12 2003 +++ b/drivers/parisc/led.c Thu Sep 11 23:03:12 2003 @@ -91,7 +91,7 @@ /* LCD_CMD and LCD_DATA for KittyHawk machines */ -#define KITTYHAWK_LCD_CMD (0xfffffffff0190000UL) /* 64bit-ready */ +#define KITTYHAWK_LCD_CMD F_EXTEND(0xf0190000UL) /* 64bit-ready */ #define KITTYHAWK_LCD_DATA (KITTYHAWK_LCD_CMD+1) /* lcd_info is pre-initialized to the values needed to program KittyHawk LCD's diff -Nru a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c --- a/drivers/parisc/sba_iommu.c Thu Sep 11 23:03:13 2003 +++ b/drivers/parisc/sba_iommu.c Thu Sep 11 23:03:13 2003 @@ -1978,8 +1978,6 @@ printk(KERN_INFO "%s found %s at 0x%lx\n", MODULE_NAME, version, dev->hpa); - snprintf(dev->dev.name, sizeof(dev->dev.name), "%s version %s", - MODULE_NAME, version); #ifdef DEBUG_SBA_INIT sba_dump_tlb(dev->hpa); diff -Nru a/drivers/parisc/wax.c b/drivers/parisc/wax.c --- a/drivers/parisc/wax.c Thu Sep 11 23:03:13 2003 +++ b/drivers/parisc/wax.c Thu Sep 11 23:03:13 2003 @@ -83,8 +83,6 @@ wax->version = 0; /* gsc_readb(wax->hpa+WAX_VER); */ printk(KERN_INFO "%s at 0x%lx found.\n", wax->name, wax->hpa); - snprintf(dev->dev.name, sizeof(dev->dev.name), "%s version %d", - wax->name, wax->version); /* Stop wax hissing for a bit */ wax_init_irq(wax); diff -Nru a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h --- a/drivers/pci/hotplug/acpiphp.h Thu Sep 11 23:03:14 2003 +++ b/drivers/pci/hotplug/acpiphp.h Thu Sep 11 23:03:14 2003 @@ -1,12 +1,12 @@ /* * ACPI PCI Hot Plug Controller Driver * - * Copyright (c) 1995,2001 Compaq Computer Corporation - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001 IBM Corp. - * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) - * Copyright (c) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com) - * Copyright (c) 2002,2003 NEC Corporation + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) + * Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com) + * Copyright (C) 2002,2003 NEC Corporation * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c --- a/drivers/pci/hotplug/acpiphp_core.c Thu Sep 11 23:03:13 2003 +++ b/drivers/pci/hotplug/acpiphp_core.c Thu Sep 11 23:03:13 2003 @@ -1,12 +1,12 @@ /* * ACPI PCI Hot Plug Controller Driver * - * Copyright (c) 1995,2001 Compaq Computer Corporation - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001 IBM Corp. - * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) - * Copyright (c) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com) - * Copyright (c) 2002,2003 NEC Corporation + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) + * Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com) + * Copyright (C) 2002,2003 NEC Corporation * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c --- a/drivers/pci/hotplug/acpiphp_glue.c Thu Sep 11 23:03:12 2003 +++ b/drivers/pci/hotplug/acpiphp_glue.c Thu Sep 11 23:03:12 2003 @@ -1,9 +1,9 @@ /* * ACPI PCI HotPlug glue functions to ACPI CA subsystem * - * Copyright (c) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com) - * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) - * Copyright (c) 2002,2003 NEC Corporation + * Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com) + * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) + * Copyright (C) 2002,2003 NEC Corporation * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/acpiphp_pci.c b/drivers/pci/hotplug/acpiphp_pci.c --- a/drivers/pci/hotplug/acpiphp_pci.c Thu Sep 11 23:03:11 2003 +++ b/drivers/pci/hotplug/acpiphp_pci.c Thu Sep 11 23:03:11 2003 @@ -1,12 +1,12 @@ /* * ACPI PCI HotPlug PCI configuration space management * - * Copyright (c) 1995,2001 Compaq Computer Corporation - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001,2002 IBM Corp. - * Copyright (c) 2002 Takayoshi Kochi (t-kochi@bq.jp.nec.com) - * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) - * Copyright (c) 2002 NEC Corporation + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001,2002 IBM Corp. + * Copyright (C) 2002 Takayoshi Kochi (t-kochi@bq.jp.nec.com) + * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) + * Copyright (C) 2002 NEC Corporation * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/acpiphp_res.c b/drivers/pci/hotplug/acpiphp_res.c --- a/drivers/pci/hotplug/acpiphp_res.c Thu Sep 11 23:03:12 2003 +++ b/drivers/pci/hotplug/acpiphp_res.c Thu Sep 11 23:03:12 2003 @@ -1,12 +1,12 @@ /* * ACPI PCI HotPlug Utility functions * - * Copyright (c) 1995,2001 Compaq Computer Corporation - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001 IBM Corp. - * Copyright (c) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) - * Copyright (c) 2002 Takayoshi Kochi (t-kochi@bq.jp.nec.com) - * Copyright (c) 2002 NEC Corporation + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com) + * Copyright (C) 2002 Takayoshi Kochi (t-kochi@bq.jp.nec.com) + * Copyright (C) 2002 NEC Corporation * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/cpci_hotplug.h b/drivers/pci/hotplug/cpci_hotplug.h --- a/drivers/pci/hotplug/cpci_hotplug.h Thu Sep 11 23:03:11 2003 +++ b/drivers/pci/hotplug/cpci_hotplug.h Thu Sep 11 23:03:11 2003 @@ -1,9 +1,9 @@ /* * CompactPCI Hot Plug Core Functions * - * Copyright (c) 2002 SOMA Networks, Inc. - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001 IBM Corp. + * Copyright (C) 2002 SOMA Networks, Inc. + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c --- a/drivers/pci/hotplug/cpci_hotplug_core.c Thu Sep 11 23:03:12 2003 +++ b/drivers/pci/hotplug/cpci_hotplug_core.c Thu Sep 11 23:03:12 2003 @@ -1,9 +1,9 @@ /* * CompactPCI Hot Plug Driver * - * Copyright (c) 2002 SOMA Networks, Inc. - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001 IBM Corp. + * Copyright (C) 2002 SOMA Networks, Inc. + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c --- a/drivers/pci/hotplug/cpci_hotplug_pci.c Thu Sep 11 23:03:13 2003 +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c Thu Sep 11 23:03:13 2003 @@ -1,7 +1,7 @@ /* * CompactPCI Hot Plug Driver PCI functions * - * Copyright (c) 2002 by SOMA Networks, Inc. + * Copyright (C) 2002 by SOMA Networks, Inc. * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h --- a/drivers/pci/hotplug/cpqphp.h Thu Sep 11 23:03:13 2003 +++ b/drivers/pci/hotplug/cpqphp.h Thu Sep 11 23:03:13 2003 @@ -1,9 +1,9 @@ /* * Compaq Hot Plug Controller Driver * - * Copyright (c) 1995,2001 Compaq Computer Corporation - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001 IBM + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c --- a/drivers/pci/hotplug/cpqphp_core.c Thu Sep 11 23:03:11 2003 +++ b/drivers/pci/hotplug/cpqphp_core.c Thu Sep 11 23:03:11 2003 @@ -1,9 +1,9 @@ /* * Compaq Hot Plug Controller Driver * - * Copyright (c) 1995,2001 Compaq Computer Corporation - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001 IBM Corp. + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c --- a/drivers/pci/hotplug/cpqphp_ctrl.c Thu Sep 11 23:03:12 2003 +++ b/drivers/pci/hotplug/cpqphp_ctrl.c Thu Sep 11 23:03:12 2003 @@ -1,9 +1,9 @@ /* * Compaq Hot Plug Controller Driver * - * Copyright (c) 1995,2001 Compaq Computer Corporation - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001 IBM Corp. + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/cpqphp_nvram.c b/drivers/pci/hotplug/cpqphp_nvram.c --- a/drivers/pci/hotplug/cpqphp_nvram.c Thu Sep 11 23:03:13 2003 +++ b/drivers/pci/hotplug/cpqphp_nvram.c Thu Sep 11 23:03:13 2003 @@ -1,9 +1,9 @@ /* * Compaq Hot Plug Controller Driver * - * Copyright (c) 1995,2001 Compaq Computer Corporation - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001 IBM Corp. + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/cpqphp_nvram.h b/drivers/pci/hotplug/cpqphp_nvram.h --- a/drivers/pci/hotplug/cpqphp_nvram.h Thu Sep 11 23:03:13 2003 +++ b/drivers/pci/hotplug/cpqphp_nvram.h Thu Sep 11 23:03:13 2003 @@ -1,8 +1,8 @@ /* * Compaq Hot Plug Controller Driver * - * Copyright (c) 1995,2001 Compaq Computer Corporation - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c --- a/drivers/pci/hotplug/cpqphp_pci.c Thu Sep 11 23:03:14 2003 +++ b/drivers/pci/hotplug/cpqphp_pci.c Thu Sep 11 23:03:14 2003 @@ -1,9 +1,9 @@ /* * Compaq Hot Plug Controller Driver * - * Copyright (c) 1995,2001 Compaq Computer Corporation - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001 IBM Corp. + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c --- a/drivers/pci/hotplug/cpqphp_sysfs.c Thu Sep 11 23:03:14 2003 +++ b/drivers/pci/hotplug/cpqphp_sysfs.c Thu Sep 11 23:03:14 2003 @@ -1,9 +1,9 @@ /* * Compaq Hot Plug Controller Driver * - * Copyright (c) 1995,2001 Compaq Computer Corporation - * Copyright (c) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001 IBM Corp. + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c --- a/drivers/pci/hotplug/fakephp.c Thu Sep 11 23:03:13 2003 +++ b/drivers/pci/hotplug/fakephp.c Thu Sep 11 23:03:13 2003 @@ -1,9 +1,9 @@ /* * Fake PCI Hot Plug Controller Driver * - * Copyright (c) 2003 Greg Kroah-Hartman - * Copyright (c) 2003 IBM Corp. - * Copyright (c) 2003 Rolf Eike Beer + * Copyright (C) 2003 Greg Kroah-Hartman + * Copyright (C) 2003 IBM Corp. + * Copyright (C) 2003 Rolf Eike Beer * * Based on ideas and code from: * Vladimir Kondratiev diff -Nru a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h --- a/drivers/pci/hotplug/ibmphp.h Thu Sep 11 23:03:11 2003 +++ b/drivers/pci/hotplug/ibmphp.h Thu Sep 11 23:03:11 2003 @@ -6,8 +6,8 @@ * * Written By: Jyoti Shah, Tong Yu, Irene Zubarev, IBM Corporation * - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001-2003 IBM Corp. + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001-2003 IBM Corp. * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c --- a/drivers/pci/hotplug/ibmphp_core.c Thu Sep 11 23:03:14 2003 +++ b/drivers/pci/hotplug/ibmphp_core.c Thu Sep 11 23:03:14 2003 @@ -3,8 +3,8 @@ * * Written By: Chuck Cole, Jyoti Shah, Tong Yu, Irene Zubarev, IBM Corporation * - * Copyright (c) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001-2003 IBM Corp. + * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001-2003 IBM Corp. * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c --- a/drivers/pci/hotplug/ibmphp_ebda.c Thu Sep 11 23:03:11 2003 +++ b/drivers/pci/hotplug/ibmphp_ebda.c Thu Sep 11 23:03:11 2003 @@ -3,8 +3,8 @@ * * Written By: Tong Yu, IBM Corporation * - * Copyright (c) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001-2003 IBM Corp. + * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001-2003 IBM Corp. * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c --- a/drivers/pci/hotplug/ibmphp_hpc.c Thu Sep 11 23:03:12 2003 +++ b/drivers/pci/hotplug/ibmphp_hpc.c Thu Sep 11 23:03:12 2003 @@ -3,7 +3,7 @@ * * Written By: Jyoti Shah, IBM Corporation * - * Copyright (c) 2001-2003 IBM Corp. + * Copyright (C) 2001-2003 IBM Corp. * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c --- a/drivers/pci/hotplug/ibmphp_pci.c Thu Sep 11 23:03:11 2003 +++ b/drivers/pci/hotplug/ibmphp_pci.c Thu Sep 11 23:03:11 2003 @@ -3,8 +3,8 @@ * * Written By: Irene Zubarev, IBM Corporation * - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001,2002 IBM Corp. + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001,2002 IBM Corp. * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/ibmphp_res.c b/drivers/pci/hotplug/ibmphp_res.c --- a/drivers/pci/hotplug/ibmphp_res.c Thu Sep 11 23:03:13 2003 +++ b/drivers/pci/hotplug/ibmphp_res.c Thu Sep 11 23:03:13 2003 @@ -3,8 +3,8 @@ * * Written By: Irene Zubarev, IBM Corporation * - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001,2002 IBM Corp. + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001,2002 IBM Corp. * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h --- a/drivers/pci/hotplug/pci_hotplug.h Thu Sep 11 23:03:12 2003 +++ b/drivers/pci/hotplug/pci_hotplug.h Thu Sep 11 23:03:12 2003 @@ -1,9 +1,9 @@ /* * PCI HotPlug Core Functions * - * Copyright (c) 1995,2001 Compaq Computer Corporation - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001 IBM Corp. + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c --- a/drivers/pci/hotplug/pci_hotplug_core.c Thu Sep 11 23:03:13 2003 +++ b/drivers/pci/hotplug/pci_hotplug_core.c Thu Sep 11 23:03:13 2003 @@ -1,8 +1,8 @@ /* * PCI HotPlug Controller Core * - * Copyright (c) 2001-2002 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001-2002 IBM Corp. + * Copyright (C) 2001-2002 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001-2002 IBM Corp. * * All rights reserved. * diff -Nru a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c --- a/drivers/pci/hotplug/pcihp_skeleton.c Thu Sep 11 23:03:12 2003 +++ b/drivers/pci/hotplug/pcihp_skeleton.c Thu Sep 11 23:03:12 2003 @@ -1,8 +1,8 @@ /* * PCI Hot Plug Controller Skeleton Driver - 0.2 * - * Copyright (c) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001,2003 IBM Corp. + * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001,2003 IBM Corp. * * All rights reserved. * diff -Nru a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c --- a/drivers/pci/pci-driver.c Thu Sep 11 23:03:13 2003 +++ b/drivers/pci/pci-driver.c Thu Sep 11 23:03:13 2003 @@ -35,6 +35,173 @@ return NULL; } +/* + * Dynamic device IDs are disabled for !CONFIG_HOTPLUG + */ + +#ifdef CONFIG_HOTPLUG +/** + * pci_device_probe_dynamic() + * + * Walk the dynamic ID list looking for a match. + * returns 0 and sets pci_dev->driver when drv claims pci_dev, else error. + */ +static int +pci_device_probe_dynamic(struct pci_driver *drv, struct pci_dev *pci_dev) +{ + int error = -ENODEV; + struct list_head *pos; + struct dynid *dynid; + + spin_lock(&drv->dynids.lock); + list_for_each(pos, &drv->dynids.list) { + dynid = list_entry(pos, struct dynid, node); + if (pci_match_one_device(&dynid->id, pci_dev)) { + spin_unlock(&drv->dynids.lock); + error = drv->probe(pci_dev, &dynid->id); + if (error >= 0) { + pci_dev->driver = drv; + return 0; + } + return error; + } + } + spin_unlock(&drv->dynids.lock); + return error; +} + +static inline void +dynid_init(struct dynid *dynid) +{ + memset(dynid, 0, sizeof(*dynid)); + INIT_LIST_HEAD(&dynid->node); +} + +/** + * store_new_id + * + * Adds a new dynamic pci device ID to this driver, + * and causes the driver to probe for all devices again. + */ +static inline ssize_t +store_new_id(struct device_driver *driver, const char *buf, size_t count) +{ + struct dynid *dynid; + struct bus_type * bus; + struct pci_driver *pdrv = to_pci_driver(driver); + __u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID, + subdevice=PCI_ANY_ID, class=0, class_mask=0; + unsigned long driver_data=0; + int fields=0; + + fields = sscanf(buf, "%x %x %x %x %x %x %lux", + &vendor, &device, &subvendor, &subdevice, + &class, &class_mask, &driver_data); + if (fields < 0) + return -EINVAL; + + dynid = kmalloc(sizeof(*dynid), GFP_KERNEL); + if (!dynid) + return -ENOMEM; + dynid_init(dynid); + + dynid->id.vendor = vendor; + dynid->id.device = device; + dynid->id.subvendor = subvendor; + dynid->id.subdevice = subdevice; + dynid->id.class = class; + dynid->id.class_mask = class_mask; + dynid->id.driver_data = pdrv->dynids.use_driver_data ? + driver_data : 0UL; + + spin_lock(&pdrv->dynids.lock); + list_add_tail(&pdrv->dynids.list, &dynid->node); + spin_unlock(&pdrv->dynids.lock); + + bus = get_bus(pdrv->driver.bus); + if (bus) { + if (get_driver(&pdrv->driver)) { + down_write(&bus->subsys.rwsem); + driver_attach(&pdrv->driver); + up_write(&bus->subsys.rwsem); + put_driver(&pdrv->driver); + } + put_bus(bus); + } + + return count; +} + +static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); +static inline void +pci_init_dynids(struct pci_dynids *dynids) +{ + memset(dynids, 0, sizeof(*dynids)); + spin_lock_init(&dynids->lock); + INIT_LIST_HEAD(&dynids->list); +} + +static void +pci_free_dynids(struct pci_driver *drv) +{ + struct list_head *pos, *n; + struct dynid *dynid; + + spin_lock(&drv->dynids.lock); + list_for_each_safe(pos, n, &drv->dynids.list) { + dynid = list_entry(pos, struct dynid, node); + list_del(&dynid->node); + kfree(dynid); + } + spin_unlock(&drv->dynids.lock); +} + +static int +pci_create_newid_file(struct pci_driver *drv) +{ + int error = 0; + if (drv->probe != NULL) + error = sysfs_create_file(&drv->driver.kobj, + &driver_attr_new_id.attr); + return error; +} + +static int +pci_bus_match_dynids(const struct pci_dev *pci_dev, struct pci_driver *pci_drv) +{ + struct list_head *pos; + struct dynid *dynid; + + spin_lock(&pci_drv->dynids.lock); + list_for_each(pos, &pci_drv->dynids.list) { + dynid = list_entry(pos, struct dynid, node); + if (pci_match_one_device(&dynid->id, pci_dev)) { + spin_unlock(&pci_drv->dynids.lock); + return 1; + } + } + spin_unlock(&pci_drv->dynids.lock); + return 0; +} + +#else /* !CONFIG_HOTPLUG */ +static inline int pci_device_probe_dynamic(struct pci_driver *drv, struct pci_dev *pci_dev) +{ + return -ENODEV; +} +static inline void dynid_init(struct dynid *dynid) {} +static inline void pci_init_dynids(struct pci_dynids *dynids) {} +static inline void pci_free_dynids(struct pci_driver *drv) {} +static inline int pci_create_newid_file(struct pci_driver *drv) +{ + return 0; +} +static inline int pci_bus_match_dynids(const struct pci_dev *pci_dev, struct pci_driver *pci_drv) +{ + return 0; +} +#endif + /** * pci_match_device - Tell if a PCI device structure has a matching * PCI device id structure @@ -80,36 +247,6 @@ } /** - * pci_device_probe_dynamic() - * - * Walk the dynamic ID list looking for a match. - * returns 0 and sets pci_dev->driver when drv claims pci_dev, else error. - */ -static int -pci_device_probe_dynamic(struct pci_driver *drv, struct pci_dev *pci_dev) -{ - int error = -ENODEV; - struct list_head *pos; - struct dynid *dynid; - - spin_lock(&drv->dynids.lock); - list_for_each(pos, &drv->dynids.list) { - dynid = list_entry(pos, struct dynid, node); - if (pci_match_one_device(&dynid->id, pci_dev)) { - spin_unlock(&drv->dynids.lock); - error = drv->probe(pci_dev, &dynid->id); - if (error >= 0) { - pci_dev->driver = drv; - return 0; - } - return error; - } - } - spin_unlock(&drv->dynids.lock); - return error; -} - -/** * __pci_device_probe() * * returns 0 on success, else error. @@ -178,72 +315,6 @@ return 0; } -static inline void -dynid_init(struct dynid *dynid) -{ - memset(dynid, 0, sizeof(*dynid)); - INIT_LIST_HEAD(&dynid->node); -} - -/** - * store_new_id - * @ pdrv - * @ buf - * @ count - * - * Adds a new dynamic pci device ID to this driver, - * and causes the driver to probe for all devices again. - */ -static inline ssize_t -store_new_id(struct device_driver * driver, const char * buf, size_t count) -{ - struct dynid *dynid; - struct bus_type * bus; - struct pci_driver *pdrv = to_pci_driver(driver); - __u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID, - subdevice=PCI_ANY_ID, class=0, class_mask=0; - unsigned long driver_data=0; - int fields=0; - - fields = sscanf(buf, "%x %x %x %x %x %x %lux", - &vendor, &device, &subvendor, &subdevice, - &class, &class_mask, &driver_data); - if (fields < 0) - return -EINVAL; - - dynid = kmalloc(sizeof(*dynid), GFP_KERNEL); - if (!dynid) - return -ENOMEM; - dynid_init(dynid); - - dynid->id.vendor = vendor; - dynid->id.device = device; - dynid->id.subvendor = subvendor; - dynid->id.subdevice = subdevice; - dynid->id.class = class; - dynid->id.class_mask = class_mask; - dynid->id.driver_data = pdrv->dynids.use_driver_data ? - driver_data : 0UL; - - spin_lock(&pdrv->dynids.lock); - list_add_tail(&pdrv->dynids.list, &dynid->node); - spin_unlock(&pdrv->dynids.lock); - - bus = get_bus(pdrv->driver.bus); - if (bus) { - if (get_driver(&pdrv->driver)) { - down_write(&bus->subsys.rwsem); - driver_attach(&pdrv->driver); - up_write(&bus->subsys.rwsem); - put_driver(&pdrv->driver); - } - put_bus(bus); - } - - return count; -} - -static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); #define kobj_to_pci_driver(obj) container_of(obj, struct device_driver, kobj) #define attr_to_driver_attribute(obj) container_of(obj, struct driver_attribute, attr) @@ -288,40 +359,11 @@ }; static int -pci_populate_driver_dir(struct pci_driver * drv) +pci_populate_driver_dir(struct pci_driver *drv) { - int error = 0; - - if (drv->probe != NULL) - error = sysfs_create_file(&drv->driver.kobj, - &driver_attr_new_id.attr); - return error; + return pci_create_newid_file(drv); } -static inline void -pci_init_dynids(struct pci_dynids *dynids) -{ - memset(dynids, 0, sizeof(*dynids)); - spin_lock_init(&dynids->lock); - INIT_LIST_HEAD(&dynids->list); -} - -static void -pci_free_dynids(struct pci_driver *drv) -{ - struct list_head *pos, *n; - struct dynid *dynid; - - spin_lock(&drv->dynids.lock); - list_for_each_safe(pos, n, &drv->dynids.list) { - dynid = list_entry(pos, struct dynid, node); - list_del(&dynid->node); - kfree(dynid); - } - spin_unlock(&drv->dynids.lock); -} - - /** * pci_register_driver - register a new pci driver * @drv: the driver structure to register @@ -411,8 +453,6 @@ struct pci_driver * pci_drv = to_pci_driver(drv); const struct pci_device_id * ids = pci_drv->id_table; const struct pci_device_id *found_id; - struct list_head *pos; - struct dynid *dynid; if (!ids) return 0; @@ -421,17 +461,7 @@ if (found_id) return 1; - spin_lock(&pci_drv->dynids.lock); - list_for_each(pos, &pci_drv->dynids.list) { - dynid = list_entry(pos, struct dynid, node); - if (pci_match_one_device(&dynid->id, pci_dev)) { - spin_unlock(&pci_drv->dynids.lock); - return 1; - } - } - spin_unlock(&pci_drv->dynids.lock); - - return 0; + return pci_bus_match_dynids(pci_dev, pci_drv); } /** diff -Nru a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c --- a/drivers/pcmcia/cardbus.c Thu Sep 11 23:03:11 2003 +++ b/drivers/pcmcia/cardbus.c Thu Sep 11 23:03:11 2003 @@ -29,18 +29,11 @@ the provisions above, a recipient may use your version of this file under either the MPL or the GPL. - These routines handle allocating resources for Cardbus cards, as - well as setting up and shutting down Cardbus sockets. They are - called from cs.c in response to Request/ReleaseConfiguration and - Request/ReleaseIO calls. - ======================================================================*/ /* - * This file is going away. Cardbus handling has been re-written to be - * more of a PCI bridge thing, and the PCI code basically does all the - * resource handling. This has wrappers to make the rest of the PCMCIA - * subsystem not notice that it's not here any more. + * Cardbus handling has been re-written to be more of a PCI bridge thing, + * and the PCI code basically does all the resource handling. * * Linus, Jan 2000 */ diff -Nru a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c --- a/drivers/pcmcia/cs.c Thu Sep 11 23:03:11 2003 +++ b/drivers/pcmcia/cs.c Thu Sep 11 23:03:11 2003 @@ -244,13 +244,10 @@ static int socket_resume(struct pcmcia_socket *skt); static int socket_suspend(struct pcmcia_socket *skt); -int pcmcia_socket_dev_suspend(struct device *dev, u32 state, u32 level) +int pcmcia_socket_dev_suspend(struct device *dev, u32 state) { struct pcmcia_socket *socket; - if (level != SUSPEND_SAVE_STATE) - return 0; - down_read(&pcmcia_socket_list_rwsem); list_for_each_entry(socket, &pcmcia_socket_list, socket_list) { if (socket->dev.dev != dev) @@ -265,13 +262,10 @@ } EXPORT_SYMBOL(pcmcia_socket_dev_suspend); -int pcmcia_socket_dev_resume(struct device *dev, u32 level) +int pcmcia_socket_dev_resume(struct device *dev) { struct pcmcia_socket *socket; - if (level != RESUME_RESTORE_STATE) - return 0; - down_read(&pcmcia_socket_list_rwsem); list_for_each_entry(socket, &pcmcia_socket_list, socket_list) { if (socket->dev.dev != dev) @@ -657,7 +651,7 @@ pcmcia_error(skt, "unsupported voltage key.\n"); return CS_BAD_TYPE; } - skt->socket.flags = SS_DEBOUNCED; + skt->socket.flags = 0; skt->ops->set_socket(skt, &skt->socket); /* @@ -690,7 +684,6 @@ } #endif send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); - skt->socket.flags &= ~SS_DEBOUNCED; } else { socket_shutdown(skt); cs_socket_put(skt); @@ -739,7 +732,6 @@ } else { send_event(skt, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW); } - skt->socket.flags &= ~SS_DEBOUNCED; } else { socket_shutdown(skt); cs_socket_put(skt); diff -Nru a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h --- a/drivers/pcmcia/cs_internal.h Thu Sep 11 23:03:11 2003 +++ b/drivers/pcmcia/cs_internal.h Thu Sep 11 23:03:11 2003 @@ -100,11 +100,8 @@ /* Flags in socket state */ #define SOCKET_PRESENT 0x0008 #define SOCKET_INUSE 0x0010 -#define SOCKET_SHUTDOWN_PENDING 0x0020 -#define SOCKET_RESET_PENDING 0x0040 #define SOCKET_SUSPEND 0x0080 #define SOCKET_WIN_REQ(i) (0x0100<<(i)) -#define SOCKET_IO_REQ(i) (0x1000<<(i)) #define SOCKET_REGION_INFO 0x4000 #define SOCKET_CARDBUS 0x8000 #define SOCKET_CARDBUS_CONFIG 0x10000 diff -Nru a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c --- a/drivers/pcmcia/hd64465_ss.c Thu Sep 11 23:03:12 2003 +++ b/drivers/pcmcia/hd64465_ss.c Thu Sep 11 23:03:12 2003 @@ -867,19 +867,32 @@ local_irq_restore(flags); } +static int hd64465_suspend(struct device *dev, u32 state, u32 level) +{ + int ret = 0; + if (level == SUSPEND_SAVE_STATE) + ret = pcmcia_socket_dev_suspend(dev, state); + return ret; +} + +static int hd64465_resume(struct device *dev, u32 level) +{ + int ret = 0; + if (level == RESUME_RESTORE_STATE) + ret = pcmcia_socket_dev_resume(dev); + return ret; +} + static struct device_driver hd64465_driver = { .name = "hd64465-pcmcia", .bus = &platform_bus_type, - .suspend = pcmcia_socket_dev_suspend, - .resume = pcmcia_socket_dev_resume, + .suspend = hd64465_suspend, + .resume = hd64465_resume, }; static struct platform_device hd64465_device = { .name = "hd64465-pcmcia", .id = 0, - .dev = { - .name = "hd64465-pcmcia", - }, }; static int __init init_hs(void) diff -Nru a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c --- a/drivers/pcmcia/i82092.c Thu Sep 11 23:03:14 2003 +++ b/drivers/pcmcia/i82092.c Thu Sep 11 23:03:14 2003 @@ -44,12 +44,12 @@ static int i82092aa_socket_suspend (struct pci_dev *dev, u32 state) { - return pcmcia_socket_dev_suspend(&dev->dev, state, SUSPEND_SAVE_STATE); + return pcmcia_socket_dev_suspend(&dev->dev, state); } static int i82092aa_socket_resume (struct pci_dev *dev) { - return pcmcia_socket_dev_resume(&dev->dev, RESUME_RESTORE_STATE); + return pcmcia_socket_dev_resume(&dev->dev); } static struct pci_driver i82092aa_pci_drv = { @@ -92,7 +92,7 @@ static int socket_count; /* shortcut */ -static int __init i82092aa_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) +static int __devinit i82092aa_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { unsigned char configbyte; int i, ret; diff -Nru a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c --- a/drivers/pcmcia/i82365.c Thu Sep 11 23:03:13 2003 +++ b/drivers/pcmcia/i82365.c Thu Sep 11 23:03:13 2003 @@ -1351,11 +1351,27 @@ /*====================================================================*/ +static int i82365_suspend(struct device *dev, u32 state, u32 level) +{ + int ret = 0; + if (level == SUSPEND_SAVE_STATE) + ret = pcmcia_socket_dev_suspend(dev, state); + return ret; +} + +static int i82365_resume(struct device *dev, u32 level) +{ + int ret = 0; + if (level == RESUME_RESTORE_STATE) + ret = pcmcia_socket_dev_resume(dev); + return ret; +} + static struct device_driver i82365_driver = { .name = "i82365", .bus = &platform_bus_type, - .suspend = pcmcia_socket_dev_suspend, - .resume = pcmcia_socket_dev_resume, + .suspend = i82365_suspend, + .resume = i82365_resume, }; static struct platform_device i82365_device = { diff -Nru a/drivers/pcmcia/ricoh.h b/drivers/pcmcia/ricoh.h --- a/drivers/pcmcia/ricoh.h Thu Sep 11 23:03:12 2003 +++ b/drivers/pcmcia/ricoh.h Thu Sep 11 23:03:12 2003 @@ -109,7 +109,7 @@ /* 16-bit IO and memory timing registers */ #define RL5C4XX_16BIT_IO_0 0x0088 /* 16 bit */ -#define RL5C4XX_16BIT_MEM_0 0x0088 /* 16 bit */ +#define RL5C4XX_16BIT_MEM_0 0x008a /* 16 bit */ #define RL5C4XX_SETUP_MASK 0x0007 #define RL5C4XX_SETUP_SHIFT 0 #define RL5C4XX_CMD_MASK 0x01f0 diff -Nru a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c --- a/drivers/pcmcia/sa1100_generic.c Thu Sep 11 23:03:13 2003 +++ b/drivers/pcmcia/sa1100_generic.c Thu Sep 11 23:03:13 2003 @@ -100,13 +100,29 @@ return ret; } +static int sa11x0_drv_pcmcia_suspend(struct device *dev, u32 state, u32 level) +{ + int ret = 0; + if (level == SUSPEND_SAVE_STATE) + ret = pcmcia_socket_dev_suspend(dev, state); + return ret; +} + +static int sa11x0_drv_pcmcia_resume(struct device *dev, u32 level) +{ + int ret = 0; + if (level == RESUME_RESTORE_STATE) + ret = pcmcia_socket_dev_resume(dev); + return ret; +} + static struct device_driver sa11x0_pcmcia_driver = { .probe = sa11x0_drv_pcmcia_probe, .remove = sa11xx_drv_pcmcia_remove, .name = "sa11x0-pcmcia", .bus = &platform_bus_type, - .suspend = pcmcia_socket_dev_suspend, - .resume = pcmcia_socket_dev_resume, + .suspend = sa11x0_drv_pcmcia_suspend, + .resume = sa11x0_drv_pcmcia_resume, }; /* sa11x0_pcmcia_init() diff -Nru a/drivers/pcmcia/sa1100_simpad.c b/drivers/pcmcia/sa1100_simpad.c --- a/drivers/pcmcia/sa1100_simpad.c Thu Sep 11 23:03:14 2003 +++ b/drivers/pcmcia/sa1100_simpad.c Thu Sep 11 23:03:14 2003 @@ -13,6 +13,7 @@ #include #include #include +#include #include "sa1100_generic.h" extern long get_cs3_shadow(void); @@ -25,9 +26,6 @@ static int simpad_pcmcia_hw_init(struct sa1100_pcmcia_socket *skt) { - set_cs3_bit(PCMCIA_RESET); - clear_cs3_bit(PCMCIA_BUFF_DIS); - clear_cs3_bit(PCMCIA_RESET); clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1); @@ -71,7 +69,7 @@ simpad_pcmcia_configure_socket(struct sa1100_pcmcia_socket *skt, const socket_state_t *state) { - unsigned long value, flags; + unsigned long flags; local_irq_save(flags); @@ -82,8 +80,8 @@ break; case 33: - clear_cs3_bit(VCC_3V_EN|EN0); - set_cs3_bit(VCC_5V_EN|EN1); + clear_cs3_bit(VCC_3V_EN|EN1); + set_cs3_bit(VCC_5V_EN|EN0); break; case 50: @@ -99,7 +97,7 @@ return -1; } - /* Silently ignore Vpp, output enable, speaker enable. */ + local_irq_restore(flags); return 0; @@ -113,6 +111,7 @@ static void simpad_pcmcia_socket_suspend(struct sa1100_pcmcia_socket *skt) { sa11xx_disable_irqs(skt, irqs, ARRAY_SIZE(irqs)); + set_cs3_bit(PCMCIA_RESET); } static struct pcmcia_low_level simpad_pcmcia_ops = { diff -Nru a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c --- a/drivers/pcmcia/sa1111_generic.c Thu Sep 11 23:03:12 2003 +++ b/drivers/pcmcia/sa1111_generic.c Thu Sep 11 23:03:12 2003 @@ -171,12 +171,12 @@ static int pcmcia_suspend(struct sa1111_dev *dev, u32 state) { - return pcmcia_socket_dev_suspend(&dev->dev, state, SUSPEND_SAVE_STATE); + return pcmcia_socket_dev_suspend(&dev->dev, state); } static int pcmcia_resume(struct sa1111_dev *dev) { - return pcmcia_socket_dev_resume(&dev->dev, RESUME_RESTORE_STATE); + return pcmcia_socket_dev_resume(&dev->dev); } static struct sa1111_driver pcmcia_driver = { diff -Nru a/drivers/pcmcia/sa11xx_core.c b/drivers/pcmcia/sa11xx_core.c --- a/drivers/pcmcia/sa11xx_core.c Thu Sep 11 23:03:11 2003 +++ b/drivers/pcmcia/sa11xx_core.c Thu Sep 11 23:03:11 2003 @@ -556,7 +556,6 @@ { SS_DMA_MODE, "SS_DMA_MODE" }, { SS_SPKR_ENA, "SS_SPKR_ENA" }, { SS_OUTPUT_ENA, "SS_OUTPUT_ENA" }, - { SS_DEBOUNCED, "SS_DEBOUNCED" }, }; static void diff -Nru a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c --- a/drivers/pcmcia/tcic.c Thu Sep 11 23:03:12 2003 +++ b/drivers/pcmcia/tcic.c Thu Sep 11 23:03:12 2003 @@ -362,11 +362,27 @@ /*====================================================================*/ +static int tcic_drv_suspend(struct device *dev, u32 state, u32 level) +{ + int ret = 0; + if (level == SUSPEND_SAVE_STATE) + ret = pcmcia_socket_dev_suspend(dev, state); + return ret; +} + +static int tcic_drv_resume(struct device *dev, u32 level) +{ + int ret = 0; + if (level == RESUME_RESTORE_STATE) + ret = pcmcia_socket_dev_resume(dev); + return ret; +} + static struct device_driver tcic_driver = { .name = "tcic-pcmcia", .bus = &platform_bus_type, - .suspend = pcmcia_socket_dev_suspend, - .resume = pcmcia_socket_dev_resume, + .suspend = tcic_drv_suspend, + .resume = tcic_drv_resume, }; static struct platform_device tcic_device = { diff -Nru a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c --- a/drivers/pcmcia/yenta_socket.c Thu Sep 11 23:03:13 2003 +++ b/drivers/pcmcia/yenta_socket.c Thu Sep 11 23:03:13 2003 @@ -248,10 +248,6 @@ struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); u16 bridge; - if (state->flags & SS_DEBOUNCED) { - /* The insertion debounce period has ended. Clear any pending insertion events */ - state->flags &= ~SS_DEBOUNCED; /* SS_DEBOUNCED is oneshot */ - } yenta_set_power(socket, state); socket->io_irq = state->io_irq; bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~(CB_BRIDGE_CRST | CB_BRIDGE_INTR); @@ -937,7 +933,7 @@ struct yenta_socket *socket = pci_get_drvdata(dev); int ret; - ret = pcmcia_socket_dev_suspend(&dev->dev, state, SUSPEND_SAVE_STATE); + ret = pcmcia_socket_dev_suspend(&dev->dev, state); if (socket) { if (socket->type && socket->type->save_state) @@ -969,7 +965,7 @@ socket->type->restore_state(socket); } - return pcmcia_socket_dev_resume(&dev->dev, RESUME_RESTORE_STATE); + return pcmcia_socket_dev_resume(&dev->dev); } diff -Nru a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c --- a/drivers/scsi/gdth.c Thu Sep 11 23:03:13 2003 +++ b/drivers/scsi/gdth.c Thu Sep 11 23:03:13 2003 @@ -2048,7 +2048,7 @@ for (j = 0; j < 12; ++j) rtc[j] = CMOS_READ(j); } while (rtc[0] != CMOS_READ(0)); - spin_lock_irqrestore(&rtc_lock, flags); + spin_unlock_irqrestore(&rtc_lock, flags); TRACE2(("gdth_search_drives(): RTC: %x/%x/%x\n",*(ulong32 *)&rtc[0], *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8])); /* 3. send to controller firmware */ diff -Nru a/drivers/scsi/imm.h b/drivers/scsi/imm.h --- a/drivers/scsi/imm.h Thu Sep 11 23:03:11 2003 +++ b/drivers/scsi/imm.h Thu Sep 11 23:03:11 2003 @@ -100,8 +100,9 @@ [IMM_NIBBLE] = "SPP", [IMM_PS2] = "PS/2", [IMM_EPP_8] = "EPP 8 bit", -#ifdef CONFIG_SCSI_IZIP_EPP16 [IMM_EPP_16] = "EPP 16 bit", +#ifdef CONFIG_SCSI_IZIP_EPP16 + [IMM_EPP_32] = "EPP 16 bit", #else [IMM_EPP_32] = "EPP 32 bit", #endif diff -Nru a/drivers/serial/8250.c b/drivers/serial/8250.c --- a/drivers/serial/8250.c Thu Sep 11 23:03:11 2003 +++ b/drivers/serial/8250.c Thu Sep 11 23:03:11 2003 @@ -122,6 +122,7 @@ struct uart_port port; struct timer_list timer; /* "no irq" timer */ struct list_head list; /* ports on this IRQ */ + unsigned int capabilities; /* port capabilities */ unsigned short rev; unsigned char acr; unsigned char ier; @@ -683,6 +684,7 @@ serial_outp(up, UART_LCR, save_lcr); up->port.fifosize = uart_config[up->port.type].dfl_xmit_fifo_size; + up->capabilities = uart_config[up->port.type].flags; if (up->port.type == PORT_UNKNOWN) goto out; @@ -1190,6 +1192,8 @@ unsigned long flags; int retval; + up->capabilities = uart_config[up->port.type].flags; + if (up->port.type == PORT_16C950) { /* Wake up and initialize UART */ up->acr = 0; @@ -1215,7 +1219,7 @@ * Clear the FIFO buffers and disable them. * (they will be reeanbled in set_termios()) */ - if (uart_config[up->port.type].flags & UART_CLEAR_FIFO) { + if (up->capabilities & UART_CLEAR_FIFO) { serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO); serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT); @@ -1428,7 +1432,7 @@ up->rev == 0x5201) quot ++; - if (uart_config[up->port.type].flags & UART_USE_FIFO) { + if (up->capabilities & UART_USE_FIFO) { if (baud < 2400) fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; #ifdef CONFIG_SERIAL_8250_RSA @@ -1489,13 +1493,13 @@ serial_out(up, UART_IER, up->ier); - if (uart_config[up->port.type].flags & UART_STARTECH) { + if (up->capabilities & UART_STARTECH) { serial_outp(up, UART_LCR, 0xBF); serial_outp(up, UART_EFR, termios->c_cflag & CRTSCTS ? UART_EFR_CTS :0); } - if (uart_config[up->port.type].flags & UART_NATSEMI) { + if (up->capabilities & UART_NATSEMI) { /* Switch to bank 2 not bank 1, to avoid resetting EXCR2 */ serial_outp(up, UART_LCR, 0xe0); } else { @@ -1524,7 +1528,7 @@ struct uart_8250_port *up = (struct uart_8250_port *)port; if (state) { /* sleep */ - if (uart_config[up->port.type].flags & UART_STARTECH) { + if (up->capabilities & UART_STARTECH) { /* Arrange to enter sleep mode */ serial_outp(up, UART_LCR, 0xBF); serial_outp(up, UART_EFR, UART_EFR_ECB); @@ -1543,7 +1547,7 @@ up->pm(port, state, oldstate); } else { /* wake */ - if (uart_config[up->port.type].flags & UART_STARTECH) { + if (up->capabilities & UART_STARTECH) { /* Wake up UART */ serial_outp(up, UART_LCR, 0xBF); serial_outp(up, UART_EFR, UART_EFR_ECB); @@ -2101,9 +2105,9 @@ * * Suspend one serial port. */ -void serial8250_suspend_port(int line, u32 level) +void serial8250_suspend_port(int line) { - uart_suspend_port(&serial8250_reg, &serial8250_ports[line].port, level); + uart_suspend_port(&serial8250_reg, &serial8250_ports[line].port); } /** @@ -2112,9 +2116,9 @@ * * Resume one serial port. */ -void serial8250_resume_port(int line, u32 level) +void serial8250_resume_port(int line) { - uart_resume_port(&serial8250_reg, &serial8250_ports[line].port, level); + uart_resume_port(&serial8250_reg, &serial8250_ports[line].port); } static int __init serial8250_init(void) diff -Nru a/drivers/serial/8250.h b/drivers/serial/8250.h --- a/drivers/serial/8250.h Thu Sep 11 23:03:11 2003 +++ b/drivers/serial/8250.h Thu Sep 11 23:03:11 2003 @@ -27,8 +27,8 @@ int serial8250_register_probe(struct serial8250_probe *probe); void serial8250_unregister_probe(struct serial8250_probe *probe); void serial8250_get_irq_map(unsigned int *map); -void serial8250_suspend_port(int line, u32 level); -void serial8250_resume_port(int line, u32 level); +void serial8250_suspend_port(int line); +void serial8250_resume_port(int line); struct old_serial_port { unsigned int uart; diff -Nru a/drivers/serial/8250_cs.c b/drivers/serial/8250_cs.c --- a/drivers/serial/8250_cs.c Thu Sep 11 23:03:12 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,712 +0,0 @@ -/*====================================================================== - - A driver for PCMCIA serial devices - - serial_cs.c 1.134 2002/05/04 05:48:53 - - The contents of this file are subject to the Mozilla Public - License Version 1.1 (the "License"); you may not use this file - except in compliance with the License. You may obtain a copy of - the License at http://www.mozilla.org/MPL/ - - Software distributed under the License is distributed on an "AS - IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - implied. See the License for the specific language governing - rights and limitations under the License. - - The initial developer of the original code is David A. Hinds - . Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - - Alternatively, the contents of this file may be used under the - terms of the GNU General Public License version 2 (the "GPL"), in which - case the provisions of the GPL are applicable instead of the - above. If you wish to allow the use of your version of this file - only under the terms of the GPL and not to allow others to use - your version of this file under the MPL, indicate your decision - by deleting the provisions above and replace them with the notice - and other provisions required by the GPL. If you do not delete - the provisions above, a recipient may use your version of this - file under either the MPL or the GPL. - -======================================================================*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -MODULE_PARM(pc_debug, "i"); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = "serial_cs.c 1.134 2002/05/04 05:48:53 (David Hinds)"; -#else -#define DEBUG(n, args...) -#endif - -/*====================================================================*/ - -/* Parameters that can be set with 'insmod' */ - -/* Bit map of interrupts to choose from */ -static u_int irq_mask = 0xdeb8; -static int irq_list[4] = { -1 }; - -/* Enable the speaker? */ -static int do_sound = 1; -/* Skip strict UART tests? */ -static int buggy_uart; - -MODULE_PARM(irq_mask, "i"); -MODULE_PARM(irq_list, "1-4i"); -MODULE_PARM(do_sound, "i"); -MODULE_PARM(buggy_uart, "i"); - -/*====================================================================*/ - -/* Table of multi-port card ID's */ - -struct multi_id { - u_short manfid; - u_short prodid; - int multi; /* 1 = multifunction, > 1 = # ports */ -}; - -static struct multi_id multi_id[] = { - { MANFID_OMEGA, PRODID_OMEGA_QSP_100, 4 }, - { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232, 2 }, - { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232_D1, 2 }, - { MANFID_QUATECH, PRODID_QUATECH_QUAD_RS232, 4 }, - { MANFID_SOCKET, PRODID_SOCKET_DUAL_RS232, 2 }, - { MANFID_INTEL, PRODID_INTEL_DUAL_RS232, 2 }, - { MANFID_NATINST, PRODID_NATINST_QUAD_RS232, 4 } -}; -#define MULTI_COUNT (sizeof(multi_id)/sizeof(struct multi_id)) - -struct serial_info { - dev_link_t link; - int ndev; - int multi; - int slave; - int manfid; - dev_node_t node[4]; - int line[4]; -}; - -static void serial_config(dev_link_t * link); -static int serial_event(event_t event, int priority, - event_callback_args_t * args); - -static dev_info_t dev_info = "serial_cs"; - -static dev_link_t *serial_attach(void); -static void serial_detach(dev_link_t *); - -static dev_link_t *dev_list = NULL; - -/*====================================================================== - - After a card is removed, serial_remove() will unregister - the serial device(s), and release the PCMCIA configuration. - -======================================================================*/ - -static void serial_remove(dev_link_t *link) -{ - struct serial_info *info = link->priv; - int i; - - link->state &= ~DEV_PRESENT; - - DEBUG(0, "serial_release(0x%p)\n", link); - - /* - * Recheck to see if the device is still configured. - */ - if (info->link.state & DEV_CONFIG) { - for (i = 0; i < info->ndev; i++) - unregister_serial(info->line[i]); - - info->link.dev = NULL; - - if (!info->slave) { - CardServices(ReleaseConfiguration, info->link.handle); - CardServices(ReleaseIO, info->link.handle, &info->link.io); - CardServices(ReleaseIRQ, info->link.handle, &info->link.irq); - } - - info->link.state &= ~DEV_CONFIG; - } -} - -/*====================================================================== - - serial_attach() creates an "instance" of the driver, allocating - local data structures for one device. The device is registered - with Card Services. - -======================================================================*/ - -static dev_link_t *serial_attach(void) -{ - struct serial_info *info; - client_reg_t client_reg; - dev_link_t *link; - int i, ret; - - DEBUG(0, "serial_attach()\n"); - - /* Create new serial device */ - info = kmalloc(sizeof (*info), GFP_KERNEL); - if (!info) - return NULL; - memset(info, 0, sizeof (*info)); - link = &info->link; - link->priv = info; - - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.NumPorts1 = 8; - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; - if (irq_list[0] == -1) - link->irq.IRQInfo2 = irq_mask; - else - for (i = 0; i < 4; i++) - link->irq.IRQInfo2 |= 1 << irq_list[i]; - link->conf.Attributes = CONF_ENABLE_IRQ; - if (do_sound) { - link->conf.Attributes |= CONF_ENABLE_SPKR; - link->conf.Status = CCSR_AUDIO_ENA; - } - link->conf.IntType = INT_MEMORY_AND_IO; - - /* Register with Card Services */ - link->next = dev_list; - dev_list = link; - client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &serial_event; - client_reg.Version = 0x0210; - client_reg.event_callback_args.client_data = link; - ret = CardServices(RegisterClient, &link->handle, &client_reg); - if (ret != CS_SUCCESS) { - cs_error(link->handle, RegisterClient, ret); - serial_detach(link); - return NULL; - } - - return link; -} - -/*====================================================================== - - This deletes a driver "instance". The device is de-registered - with Card Services. If it has been released, all local data - structures are freed. Otherwise, the structures will be freed - when the device is released. - -======================================================================*/ - -static void serial_detach(dev_link_t * link) -{ - struct serial_info *info = link->priv; - dev_link_t **linkp; - int ret; - - DEBUG(0, "serial_detach(0x%p)\n", link); - - /* Locate device structure */ - for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) - if (*linkp == link) - break; - if (*linkp == NULL) - return; - - /* - * Ensure any outstanding scheduled tasks are completed. - */ - flush_scheduled_work(); - - /* - * Ensure that the ports have been released. - */ - serial_remove(link); - - if (link->handle) { - ret = CardServices(DeregisterClient, link->handle); - if (ret != CS_SUCCESS) - cs_error(link->handle, DeregisterClient, ret); - } - - /* Unlink device structure, free bits */ - *linkp = link->next; - kfree(info); -} - -/*====================================================================*/ - -static int setup_serial(struct serial_info * info, ioaddr_t port, int irq) -{ - struct serial_struct serial; - int line; - - memset(&serial, 0, sizeof (serial)); - serial.port = port; - serial.irq = irq; - serial.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ; - if (buggy_uart) - serial.flags |= UPF_BUGGY_UART; - line = register_serial(&serial); - if (line < 0) { - printk(KERN_NOTICE "serial_cs: register_serial() at 0x%04lx," - " irq %d failed\n", (u_long) serial.port, serial.irq); - return -EINVAL; - } - - info->line[info->ndev] = line; - sprintf(info->node[info->ndev].dev_name, "ttyS%d", line); - info->node[info->ndev].major = TTY_MAJOR; - info->node[info->ndev].minor = 0x40 + line; - if (info->ndev > 0) - info->node[info->ndev - 1].next = &info->node[info->ndev]; - info->ndev++; - - return 0; -} - -/*====================================================================*/ - -static int -get_tuple(int fn, client_handle_t handle, tuple_t * tuple, cisparse_t * parse) -{ - int i; - i = CardServices(fn, handle, tuple); - if (i != CS_SUCCESS) - return CS_NO_MORE_ITEMS; - i = CardServices(GetTupleData, handle, tuple); - if (i != CS_SUCCESS) - return i; - return CardServices(ParseTuple, handle, tuple, parse); -} - -#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c) -#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c) - -/*====================================================================*/ - -static int simple_config(dev_link_t * link) -{ - static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; - client_handle_t handle = link->handle; - struct serial_info *info = link->priv; - tuple_t tuple; - u_char buf[256]; - cisparse_t parse; - cistpl_cftable_entry_t *cf = &parse.cftable_entry; - config_info_t config; - int i, j, try; - - /* If the card is already configured, look up the port and irq */ - i = CardServices(GetConfigurationInfo, handle, &config); - if ((i == CS_SUCCESS) && (config.Attributes & CONF_VALID_CLIENT)) { - ioaddr_t port = 0; - if ((config.BasePort2 != 0) && (config.NumPorts2 == 8)) { - port = config.BasePort2; - info->slave = 1; - } else if ((info->manfid == MANFID_OSITECH) && - (config.NumPorts1 == 0x40)) { - port = config.BasePort1 + 0x28; - info->slave = 1; - } - if (info->slave) - return setup_serial(info, port, config.AssignedIRQ); - } - link->conf.Vcc = config.Vcc; - - /* First pass: look for a config entry that looks normal. */ - tuple.TupleData = (cisdata_t *) buf; - tuple.TupleOffset = 0; - tuple.TupleDataMax = 255; - tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - /* Two tries: without IO aliases, then with aliases */ - for (try = 0; try < 2; try++) { - i = first_tuple(handle, &tuple, &parse); - while (i != CS_NO_MORE_ITEMS) { - if (i != CS_SUCCESS) - goto next_entry; - if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = - cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; - if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && - (cf->io.win[0].base != 0)) { - link->conf.ConfigIndex = cf->index; - link->io.BasePort1 = cf->io.win[0].base; - link->io.IOAddrLines = (try == 0) ? - 16 : cf->io.flags & CISTPL_IO_LINES_MASK; - i = - CardServices(RequestIO, link->handle, - &link->io); - if (i == CS_SUCCESS) - goto found_port; - } - next_entry: - i = next_tuple(handle, &tuple, &parse); - } - } - - /* Second pass: try to find an entry that isn't picky about - its base address, then try to grab any standard serial port - address, and finally try to get any free port. */ - i = first_tuple(handle, &tuple, &parse); - while (i != CS_NO_MORE_ITEMS) { - if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && - ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { - link->conf.ConfigIndex = cf->index; - for (j = 0; j < 5; j++) { - link->io.BasePort1 = base[j]; - link->io.IOAddrLines = base[j] ? 16 : 3; - i = CardServices(RequestIO, link->handle, - &link->io); - if (i == CS_SUCCESS) - goto found_port; - } - } - i = next_tuple(handle, &tuple, &parse); - } - - found_port: - if (i != CS_SUCCESS) { - printk(KERN_NOTICE - "serial_cs: no usable port range found, giving up\n"); - cs_error(link->handle, RequestIO, i); - return -1; - } - - i = CardServices(RequestIRQ, link->handle, &link->irq); - if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIRQ, i); - link->irq.AssignedIRQ = 0; - } - if (info->multi && (info->manfid == MANFID_3COM)) - link->conf.ConfigIndex &= ~(0x08); - i = CardServices(RequestConfiguration, link->handle, &link->conf); - if (i != CS_SUCCESS) { - cs_error(link->handle, RequestConfiguration, i); - return -1; - } - - return setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ); -} - -static int multi_config(dev_link_t * link) -{ - client_handle_t handle = link->handle; - struct serial_info *info = link->priv; - tuple_t tuple; - u_char buf[256]; - cisparse_t parse; - cistpl_cftable_entry_t *cf = &parse.cftable_entry; - config_info_t config; - int i, base2 = 0; - - i = CardServices(GetConfigurationInfo, handle, &config); - if (i != CS_SUCCESS) { - cs_error(handle, GetConfigurationInfo, i); - return -1; - } - link->conf.Vcc = config.Vcc; - - tuple.TupleData = (cisdata_t *) buf; - tuple.TupleOffset = 0; - tuple.TupleDataMax = 255; - tuple.Attributes = 0; - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - - /* First, look for a generic full-sized window */ - link->io.NumPorts1 = info->multi * 8; - i = first_tuple(handle, &tuple, &parse); - while (i != CS_NO_MORE_ITEMS) { - /* The quad port cards have bad CIS's, so just look for a - window larger than 8 ports and assume it will be right */ - if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && - (cf->io.win[0].len > 8)) { - link->conf.ConfigIndex = cf->index; - link->io.BasePort1 = cf->io.win[0].base; - link->io.IOAddrLines = - cf->io.flags & CISTPL_IO_LINES_MASK; - i = CardServices(RequestIO, link->handle, &link->io); - base2 = link->io.BasePort1 + 8; - if (i == CS_SUCCESS) - break; - } - i = next_tuple(handle, &tuple, &parse); - } - - /* If that didn't work, look for two windows */ - if (i != CS_SUCCESS) { - link->io.NumPorts1 = link->io.NumPorts2 = 8; - info->multi = 2; - i = first_tuple(handle, &tuple, &parse); - while (i != CS_NO_MORE_ITEMS) { - if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) { - link->conf.ConfigIndex = cf->index; - link->io.BasePort1 = cf->io.win[0].base; - link->io.BasePort2 = cf->io.win[1].base; - link->io.IOAddrLines = - cf->io.flags & CISTPL_IO_LINES_MASK; - i = - CardServices(RequestIO, link->handle, - &link->io); - base2 = link->io.BasePort2; - if (i == CS_SUCCESS) - break; - } - i = next_tuple(handle, &tuple, &parse); - } - } - - if (i != CS_SUCCESS) { - cs_error(link->handle, RequestIO, i); - return -1; - } - - i = CardServices(RequestIRQ, link->handle, &link->irq); - if (i != CS_SUCCESS) { - printk(KERN_NOTICE - "serial_cs: no usable port range found, giving up\n"); - cs_error(link->handle, RequestIRQ, i); - link->irq.AssignedIRQ = 0; - } - /* Socket Dual IO: this enables irq's for second port */ - if (info->multi && (info->manfid == MANFID_SOCKET)) { - link->conf.Present |= PRESENT_EXT_STATUS; - link->conf.ExtStatus = ESR_REQ_ATTN_ENA; - } - i = CardServices(RequestConfiguration, link->handle, &link->conf); - if (i != CS_SUCCESS) { - cs_error(link->handle, RequestConfiguration, i); - return -1; - } - - /* The Oxford Semiconductor OXCF950 cards are in fact single-port: - 8 registers are for the UART, the others are extra registers */ - if (info->manfid == MANFID_OXSEMI) { - if (cf->index == 1 || cf->index == 3) { - setup_serial(info, base2, link->irq.AssignedIRQ); - outb(12, link->io.BasePort1 + 1); - } else { - setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ); - outb(12, base2 + 1); - } - return 0; - } - - setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ); - /* The Nokia cards are not really multiport cards */ - if (info->manfid == MANFID_NOKIA) - return 0; - for (i = 0; i < info->multi - 1; i++) - setup_serial(info, base2 + (8 * i), link->irq.AssignedIRQ); - - return 0; -} - -/*====================================================================== - - serial_config() is scheduled to run after a CARD_INSERTION event - is received, to configure the PCMCIA socket, and to make the - serial device available to the system. - -======================================================================*/ - -#define CS_CHECK(fn, args...) \ -while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed - -void serial_config(dev_link_t * link) -{ - client_handle_t handle = link->handle; - struct serial_info *info = link->priv; - tuple_t tuple; - u_short buf[128]; - cisparse_t parse; - cistpl_cftable_entry_t *cf = &parse.cftable_entry; - int i, last_ret, last_fn; - - DEBUG(0, "serial_config(0x%p)\n", link); - - tuple.TupleData = (cisdata_t *) buf; - tuple.TupleOffset = 0; - tuple.TupleDataMax = 255; - tuple.Attributes = 0; - /* Get configuration register information */ - tuple.DesiredTuple = CISTPL_CONFIG; - last_ret = first_tuple(handle, &tuple, &parse); - if (last_ret != CS_SUCCESS) { - last_fn = ParseTuple; - goto cs_failed; - } - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - - /* Configure card */ - link->state |= DEV_CONFIG; - - /* Is this a compliant multifunction card? */ - tuple.DesiredTuple = CISTPL_LONGLINK_MFC; - tuple.Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; - info->multi = (first_tuple(handle, &tuple, &parse) == CS_SUCCESS); - - /* Is this a multiport card? */ - tuple.DesiredTuple = CISTPL_MANFID; - if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) { - info->manfid = le16_to_cpu(buf[0]); - for (i = 0; i < MULTI_COUNT; i++) - if ((info->manfid == multi_id[i].manfid) && - (le16_to_cpu(buf[1]) == multi_id[i].prodid)) - break; - if (i < MULTI_COUNT) - info->multi = multi_id[i].multi; - } - - /* Another check for dual-serial cards: look for either serial or - multifunction cards that ask for appropriate IO port ranges */ - tuple.DesiredTuple = CISTPL_FUNCID; - if ((info->multi == 0) && - ((first_tuple(handle, &tuple, &parse) != CS_SUCCESS) || - (parse.funcid.func == CISTPL_FUNCID_MULTI) || - (parse.funcid.func == CISTPL_FUNCID_SERIAL))) { - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) { - if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) - info->multi = cf->io.win[0].len >> 3; - if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && - (cf->io.win[1].len == 8)) - info->multi = 2; - } - } - - if (info->multi > 1) - multi_config(link); - else - simple_config(link); - - if (info->ndev == 0) - goto failed; - - if (info->manfid == MANFID_IBM) { - conf_reg_t reg = { 0, CS_READ, 0x800, 0 }; - CS_CHECK(AccessConfigurationRegister, link->handle, ®); - reg.Action = CS_WRITE; - reg.Value = reg.Value | 1; - CS_CHECK(AccessConfigurationRegister, link->handle, ®); - } - - link->dev = &info->node[0]; - link->state &= ~DEV_CONFIG_PENDING; - return; - - cs_failed: - cs_error(link->handle, last_fn, last_ret); - failed: - serial_remove(link); - link->state &= ~DEV_CONFIG_PENDING; -} - -/*====================================================================== - - The card status event handler. Mostly, this schedules other - stuff to run after an event is received. A CARD_REMOVAL event - also sets some flags to discourage the serial drivers from - talking to the ports. - -======================================================================*/ - -static int -serial_event(event_t event, int priority, event_callback_args_t * args) -{ - dev_link_t *link = args->client_data; - struct serial_info *info = link->priv; - - DEBUG(1, "serial_event(0x%06x)\n", event); - - switch (event) { - case CS_EVENT_CARD_REMOVAL: - serial_remove(link); - break; - - case CS_EVENT_CARD_INSERTION: - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - serial_config(link); - break; - - case CS_EVENT_PM_SUSPEND: - link->state |= DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_RESET_PHYSICAL: - if ((link->state & DEV_CONFIG) && !info->slave) - CardServices(ReleaseConfiguration, link->handle); - break; - - case CS_EVENT_PM_RESUME: - link->state &= ~DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_CARD_RESET: - if (DEV_OK(link) && !info->slave) - CardServices(RequestConfiguration, link->handle, - &link->conf); - break; - } - return 0; -} - -static struct pcmcia_driver serial_cs_driver = { - .owner = THIS_MODULE, - .drv = { - .name = "serial_cs", - }, - .attach = serial_attach, - .detach = serial_detach, -}; - -static int __init init_serial_cs(void) -{ - return pcmcia_register_driver(&serial_cs_driver); -} - -static void __exit exit_serial_cs(void) -{ - pcmcia_unregister_driver(&serial_cs_driver); - - /* XXX: this really needs to move into generic code.. */ - while (dev_list != NULL) - serial_detach(dev_list); -} - -module_init(init_serial_cs); -module_exit(exit_serial_cs); - -MODULE_LICENSE("GPL"); diff -Nru a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c --- a/drivers/serial/8250_pci.c Thu Sep 11 23:03:13 2003 +++ b/drivers/serial/8250_pci.c Thu Sep 11 23:03:13 2003 @@ -1600,19 +1600,6 @@ } } -static int pciserial_save_state_one(struct pci_dev *dev, u32 state) -{ - struct serial_private *priv = pci_get_drvdata(dev); - - if (priv) { - int i; - - for (i = 0; i < priv->nr; i++) - serial8250_suspend_port(priv->line[i], SUSPEND_SAVE_STATE); - } - return 0; -} - static int pciserial_suspend_one(struct pci_dev *dev, u32 state) { struct serial_private *priv = pci_get_drvdata(dev); @@ -1621,7 +1608,7 @@ int i; for (i = 0; i < priv->nr; i++) - serial8250_suspend_port(priv->line[i], SUSPEND_POWER_DOWN); + serial8250_suspend_port(priv->line[i]); } return 0; } @@ -1639,10 +1626,8 @@ if (priv->quirk->init) priv->quirk->init(dev); - for (i = 0; i < priv->nr; i++) { - serial8250_resume_port(priv->line[i], RESUME_POWER_ON); - serial8250_resume_port(priv->line[i], RESUME_RESTORE_STATE); - } + for (i = 0; i < priv->nr; i++) + serial8250_resume_port(priv->line[i]); } return 0; } @@ -2040,7 +2025,6 @@ .name = "serial", .probe = pciserial_init_one, .remove = __devexit_p(pciserial_remove_one), - .save_state = pciserial_save_state_one, .suspend = pciserial_suspend_one, .resume = pciserial_resume_one, .id_table = serial_pci_tbl, diff -Nru a/drivers/serial/Kconfig b/drivers/serial/Kconfig --- a/drivers/serial/Kconfig Thu Sep 11 23:03:13 2003 +++ b/drivers/serial/Kconfig Thu Sep 11 23:03:13 2003 @@ -10,6 +10,7 @@ # The new 8250/16550 serial drivers config SERIAL_8250 tristate "8250/16550 and compatible serial support" + select SERIAL_CORE ---help--- This selects whether you want to include the driver for the standard serial ports. The standard answer is Y. People who might say N @@ -41,6 +42,7 @@ config SERIAL_8250_CONSOLE bool "Console on 8250/16550 and compatible serial port" depends on SERIAL_8250=y + select SERIAL_CORE_CONSOLE ---help--- If you say Y here, it will be possible to use a serial port as the system console (the system console is the device which receives all @@ -167,12 +169,14 @@ config SERIAL_ANAKIN bool "Anakin serial port support" depends on ARM && ARCH_ANAKIN + select SERIAL_CORE help ::: To be written ::: config SERIAL_ANAKIN_CONSOLE bool "Console on Anakin serial port" depends on SERIAL_ANAKIN + select SERIAL_CORE_CONSOLE help Even if you say Y here, the currently visible virtual console (/dev/tty0) will still be used as the system console by default, but @@ -190,7 +194,8 @@ config SERIAL_AMBA tristate "ARM AMBA serial port support" - depends on ARM && ARCH_INTEGRATOR + depends on ARM_AMBA + select SERIAL_CORE help This selects the ARM(R) AMBA(R) PrimeCell UART. If you have an Integrator platform, say Y or M here. @@ -200,6 +205,7 @@ config SERIAL_AMBA_CONSOLE bool "Support for console on AMBA serial port" depends on SERIAL_AMBA=y + select SERIAL_CORE_CONSOLE ---help--- Say Y here if you wish to use an AMBA PrimeCell UART as the system console (the system console is the device which receives all kernel @@ -214,18 +220,20 @@ config SERIAL_INTEGRATOR bool - depends on SERIAL_AMBA=y + depends on SERIAL_AMBA && ARCH_INTEGRATOR default y config SERIAL_CLPS711X tristate "CLPS711X serial port support" depends on ARM && ARCH_CLPS711X + select SERIAL_CORE help ::: To be written ::: config SERIAL_CLPS711X_CONSOLE bool "Support for console on CLPS711X serial port" depends on SERIAL_CLPS711X=y + select SERIAL_CORE_CONSOLE help Even if you say Y here, the currently visible virtual console (/dev/tty0) will still be used as the system console by default, but @@ -243,6 +251,7 @@ config SERIAL_21285 tristate "DC21285 serial port support" depends on ARM && FOOTBRIDGE + select SERIAL_CORE help If you have a machine based on a 21285 (Footbridge) StrongARM(R)/ PCI bridge you can enable its onboard serial port by enabling this @@ -258,6 +267,7 @@ config SERIAL_21285_CONSOLE bool "Console on DC21285 serial port" depends on SERIAL_21285=y + select SERIAL_CORE_CONSOLE help If you have enabled the serial port on the 21285 footbridge you can make it the console by answering Y to this option. @@ -272,6 +282,7 @@ config SERIAL_UART00 bool "Excalibur serial port (uart00) support" depends on ARM && ARCH_CAMELOT + select SERIAL_CORE help Say Y here if you want to use the hard logic uart on Excalibur. This driver also supports soft logic implentations of this uart core. @@ -279,6 +290,7 @@ config SERIAL_UART00_CONSOLE bool "Support for console on Excalibur serial port" depends on SERIAL_UART00 + select SERIAL_CORE_CONSOLE help Say Y here if you want to support a serial console on an Excalibur hard logic uart or uart00 IP core. @@ -293,6 +305,7 @@ config SERIAL_SA1100 bool "SA1100 serial port support" depends on ARM && ARCH_SA1100 + select SERIAL_CORE help If you have a machine based on a SA1100/SA1110 StrongARM(R) CPU you can enable its onboard serial port by enabling this option. @@ -302,6 +315,7 @@ config SERIAL_SA1100_CONSOLE bool "Console on SA1100 serial port" depends on SERIAL_SA1100 + select SERIAL_CORE_CONSOLE help If you have enabled the serial port on the SA1100/SA1110 StrongARM CPU you can make it the console by answering Y to this option. @@ -316,6 +330,8 @@ config SERIAL_SUNCORE bool depends on SPARC32 || SPARC64 + select SERIAL_CORE + select SERIAL_CORE_CONSOLE default y config SERIAL_SUNZILOG @@ -352,6 +368,7 @@ config SERIAL_MUX tristate "Serial MUX support" depends on PARISC + select SERIAL_CORE default y ---help--- Saying Y here will enable the hardware MUX serial driver for @@ -369,6 +386,7 @@ config SERIAL_MUX_CONSOLE bool "Support for console on serial MUX" depends on SERIAL_MUX + select SERIAL_CORE_CONSOLE default y config PDC_CONSOLE @@ -406,6 +424,7 @@ config V850E_UART bool "NEC V850E on-chip UART support" depends on V850E_MA1 || V850E_ME2 || V850E_TEG || V850E2_ANNA || V850E_AS85EP1 + select SERIAL_CORE default y config V850E_UARTB @@ -416,10 +435,12 @@ config V850E_UART_CONSOLE bool "Use NEC V850E on-chip UART for console" depends on V850E_UART + select SERIAL_CORE_CONSOLE config SERIAL98 tristate "PC-9800 8251-based primary serial port support" depends on X86_PC9800 + select SERIAL_CORE help If you want to use standard primary serial ports on PC-9800, say Y. Otherwise, say N. @@ -427,16 +448,13 @@ config SERIAL98_CONSOLE bool "Support for console on PC-9800 standard serial port" depends on SERIAL98=y + select SERIAL_CORE_CONSOLE config SERIAL_CORE tristate - default m if SERIAL_AMBA!=y && SERIAL_CLPS711X!=y && SERIAL_21285!=y && !SERIAL_SA1100 && !SERIAL_ANAKIN && !SERIAL_UART00 && SERIAL_8250!=y && SERIAL_MUX!=y && !SERIAL_ROCKETPORT && !SERIAL_SUNCORE && !V850E_UART && SERIAL_PMACZILOG!=y && (SERIAL_AMBA=m || SERIAL_CLPS711X=m || SERIAL_21285=m || SERIAL_8250=m || SERIAL_MUX=m || SERIAL98=m || SERIAL_PMACZILOG=m) - default y if SERIAL_AMBA=y || SERIAL_CLPS711X=y || SERIAL_21285=y || SERIAL_SA1100 || SERIAL_ANAKIN || SERIAL_UART00 || SERIAL_8250=y || SERIAL_MUX=y || SERIAL_ROCKETPORT || SERIAL_SUNCORE || V850E_UART || SERIAL98=y || SERIAL_PMACZILOG=y config SERIAL_CORE_CONSOLE bool - depends on SERIAL_AMBA_CONSOLE || SERIAL_CLPS711X_CONSOLE || SERIAL_21285_CONSOLE || SERIAL_SA1100_CONSOLE || SERIAL_ANAKIN_CONSOLE || SERIAL_UART00_CONSOLE || SERIAL_8250_CONSOLE || SERIAL_MUX_CONSOLE || SERIAL_SUNZILOG_CONSOLE || SERIAL_SUNSU_CONSOLE || SERIAL_SUNSAB_CONSOLE || V850E_UART_CONSOLE || SERIAL98_CONSOLE || SERIAL_PMACZILOG_CONSOLE - default y config SERIAL_68328 bool "68328 serial support" @@ -476,6 +494,7 @@ config SERIAL_PMACZILOG tristate "PowerMac z85c30 ESCC support" depends on PPC_OF + select SERIAL_CORE help This driver supports the Zilog z85C30 serial ports found on PowerMac machines. @@ -484,6 +503,7 @@ config SERIAL_PMACZILOG_CONSOLE bool "Console on PowerMac z85c30 serial port" depends on SERIAL_PMACZILOG=y + select SERIAL_CORE_CONSOLE help If you would like to be able to use the z85c30 serial port on your PowerMac as the console, you can do so by answering diff -Nru a/drivers/serial/Makefile b/drivers/serial/Makefile --- a/drivers/serial/Makefile Thu Sep 11 23:03:12 2003 +++ b/drivers/serial/Makefile Thu Sep 11 23:03:12 2003 @@ -11,10 +11,10 @@ serial-8250-$(CONFIG_SERIAL_8250_HCDP) += 8250_hcdp.o serial-8250-$(CONFIG_SERIAL_8250_ACPI) += 8250_acpi.o -obj-$(CONFIG_SERIAL_CORE) += core.o +obj-$(CONFIG_SERIAL_CORE) += serial_core.o obj-$(CONFIG_SERIAL_21285) += 21285.o obj-$(CONFIG_SERIAL_8250) += 8250.o $(serial-8250-y) -obj-$(CONFIG_SERIAL_8250_CS) += 8250_cs.o +obj-$(CONFIG_SERIAL_8250_CS) += serial_cs.o obj-$(CONFIG_SERIAL_8250_ACORN) += 8250_acorn.o obj-$(CONFIG_SERIAL_ANAKIN) += anakin.o obj-$(CONFIG_SERIAL_AMBA) += amba.o diff -Nru a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c --- a/drivers/serial/clps711x.c Thu Sep 11 23:03:12 2003 +++ b/drivers/serial/clps711x.c Thu Sep 11 23:03:12 2003 @@ -104,7 +104,7 @@ { } -static void clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *regs) { struct uart_port *port = dev_id; struct tty_struct *tty = port->info->tty; @@ -139,7 +139,7 @@ } out: tty_flip_buffer_push(tty); - return; + return IRQ_HANDLED; handle_error: if (ch & UARTDR_PARERR) @@ -180,7 +180,7 @@ goto error_return; } -static void clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *regs) { struct uart_port *port = dev_id; struct circ_buf *xmit = &port->info->xmit; @@ -190,11 +190,11 @@ clps_writel(port->x_char, UARTDR(port)); port->icount.tx++; port->x_char = 0; - return; + return IRQ_HANDLED; } if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { clps711xuart_stop_tx(port, 0); - return; + return IRQ_HANDLED; } count = port->fifosize >> 1; @@ -211,6 +211,8 @@ if (uart_circ_empty(xmit)) clps711xuart_stop_tx(port, 0); + + return IRQ_HANDLED; } static unsigned int clps711xuart_tx_empty(struct uart_port *port) diff -Nru a/drivers/serial/core.c b/drivers/serial/core.c --- a/drivers/serial/core.c Thu Sep 11 23:03:11 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,2432 +0,0 @@ -/* - * linux/drivers/char/core.c - * - * Driver core for serial ports - * - * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. - * - * Copyright 1999 ARM Limited - * Copyright (C) 2000-2001 Deep Blue Solutions Ltd. - * - * 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 - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for serial_state and serial_icounter_struct */ - -#include -#include - -#undef DEBUG -#ifdef DEBUG -#define DPRINTK(x...) printk(x) -#else -#define DPRINTK(x...) do { } while (0) -#endif - -/* - * This is used to lock changes in serial line configuration. - */ -static DECLARE_MUTEX(port_sem); - -#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) - -#define uart_users(state) ((state)->count + ((state)->info ? (state)->info->blocked_open : 0)) - -#ifdef CONFIG_SERIAL_CORE_CONSOLE -#define uart_console(port) ((port)->cons && (port)->cons->index == (port)->line) -#else -#define uart_console(port) (0) -#endif - -static void uart_change_speed(struct uart_state *state, struct termios *old_termios); -static void uart_wait_until_sent(struct tty_struct *tty, int timeout); -static void uart_change_pm(struct uart_state *state, int pm_state); - -/* - * This routine is used by the interrupt handler to schedule processing in - * the software interrupt portion of the driver. - */ -void uart_write_wakeup(struct uart_port *port) -{ - struct uart_info *info = port->info; - tasklet_schedule(&info->tlet); -} - -static void uart_stop(struct tty_struct *tty) -{ - struct uart_state *state = tty->driver_data; - struct uart_port *port = state->port; - unsigned long flags; - - spin_lock_irqsave(&port->lock, flags); - port->ops->stop_tx(port, 1); - spin_unlock_irqrestore(&port->lock, flags); -} - -static void __uart_start(struct tty_struct *tty) -{ - struct uart_state *state = tty->driver_data; - struct uart_port *port = state->port; - - if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf && - !tty->stopped && !tty->hw_stopped) - port->ops->start_tx(port, 1); -} - -static void uart_start(struct tty_struct *tty) -{ - struct uart_state *state = tty->driver_data; - struct uart_port *port = state->port; - unsigned long flags; - - spin_lock_irqsave(&port->lock, flags); - __uart_start(tty); - spin_unlock_irqrestore(&port->lock, flags); -} - -static void uart_tasklet_action(unsigned long data) -{ - struct uart_state *state = (struct uart_state *)data; - struct tty_struct *tty; - - tty = state->info->tty; - if (tty) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - tty->ldisc.write_wakeup(tty); - wake_up_interruptible(&tty->write_wait); - } -} - -static inline void -uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear) -{ - unsigned long flags; - unsigned int old; - - spin_lock_irqsave(&port->lock, flags); - old = port->mctrl; - port->mctrl = (old & ~clear) | set; - if (old != port->mctrl) - port->ops->set_mctrl(port, port->mctrl); - spin_unlock_irqrestore(&port->lock, flags); -} - -#define uart_set_mctrl(port,set) uart_update_mctrl(port,set,0) -#define uart_clear_mctrl(port,clear) uart_update_mctrl(port,0,clear) - -/* - * Startup the port. This will be called once per open. All calls - * will be serialised by the per-port semaphore. - */ -static int uart_startup(struct uart_state *state, int init_hw) -{ - struct uart_info *info = state->info; - struct uart_port *port = state->port; - unsigned long page; - int retval = 0; - - if (info->flags & UIF_INITIALIZED) - return 0; - - /* - * Set the TTY IO error marker - we will only clear this - * once we have successfully opened the port. Also set - * up the tty->alt_speed kludge - */ - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); - - if (port->type == PORT_UNKNOWN) - return 0; - - /* - * Initialise and allocate the transmit and temporary - * buffer. - */ - if (!info->xmit.buf) { - page = get_zeroed_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - - info->xmit.buf = (unsigned char *) page; - info->tmpbuf = info->xmit.buf + UART_XMIT_SIZE; - init_MUTEX(&info->tmpbuf_sem); - uart_circ_clear(&info->xmit); - } - - port->mctrl = 0; - - retval = port->ops->startup(port); - if (retval == 0) { - if (init_hw) { - /* - * Initialise the hardware port settings. - */ - uart_change_speed(state, NULL); - - /* - * Setup the RTS and DTR signals once the - * port is open and ready to respond. - */ - if (info->tty->termios->c_cflag & CBAUD) - uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR); - } - - info->flags |= UIF_INITIALIZED; - - clear_bit(TTY_IO_ERROR, &info->tty->flags); - } - - if (retval && capable(CAP_SYS_ADMIN)) - retval = 0; - - return retval; -} - -/* - * This routine will shutdown a serial port; interrupts are disabled, and - * DTR is dropped if the hangup on close termio flag is on. Calls to - * uart_shutdown are serialised by the per-port semaphore. - */ -static void uart_shutdown(struct uart_state *state) -{ - struct uart_info *info = state->info; - struct uart_port *port = state->port; - - if (!(info->flags & UIF_INITIALIZED)) - return; - - /* - * Turn off DTR and RTS early. - */ - if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) - uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); - - /* - * clear delta_msr_wait queue to avoid mem leaks: we may free - * the irq here so the queue might never be woken up. Note - * that we won't end up waiting on delta_msr_wait again since - * any outstanding file descriptors should be pointing at - * hung_up_tty_fops now. - */ - wake_up_interruptible(&info->delta_msr_wait); - - /* - * Free the IRQ and disable the port. - */ - port->ops->shutdown(port); - - /* - * Ensure that the IRQ handler isn't running on another CPU. - */ - synchronize_irq(port->irq); - - /* - * Free the transmit buffer page. - */ - if (info->xmit.buf) { - free_page((unsigned long)info->xmit.buf); - info->xmit.buf = NULL; - info->tmpbuf = NULL; - } - - /* - * kill off our tasklet - */ - tasklet_kill(&info->tlet); - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); - - info->flags &= ~UIF_INITIALIZED; -} - -/** - * uart_update_timeout - update per-port FIFO timeout. - * @port: uart_port structure describing the port. - * @cflag: termios cflag value - * @quot: uart clock divisor quotient - * - * Set the port FIFO timeout value. The @cflag value should - * reflect the actual hardware settings. - */ -void -uart_update_timeout(struct uart_port *port, unsigned int cflag, - unsigned int baud) -{ - unsigned int bits; - - /* byte size and parity */ - switch (cflag & CSIZE) { - case CS5: - bits = 7; - break; - case CS6: - bits = 8; - break; - case CS7: - bits = 9; - break; - default: - bits = 10; - break; // CS8 - } - - if (cflag & CSTOPB) - bits++; - if (cflag & PARENB) - bits++; - - /* - * The total number of bits to be transmitted in the fifo. - */ - bits = bits * port->fifosize; - - /* - * Figure the timeout to send the above number of bits. - * Add .02 seconds of slop - */ - port->timeout = (HZ * bits) / baud + HZ/50; -} - -EXPORT_SYMBOL(uart_update_timeout); - -/** - * uart_get_baud_rate - return baud rate for a particular port - * @port: uart_port structure describing the port in question. - * @termios: desired termios settings. - * @old: old termios (or NULL) - * @min: minimum acceptable baud rate - * @max: maximum acceptable baud rate - * - * Decode the termios structure into a numeric baud rate, - * taking account of the magic 38400 baud rate (with spd_* - * flags), and mapping the %B0 rate to 9600 baud. - * - * If the new baud rate is invalid, try the old termios setting. - * If it's still invalid, we try 9600 baud. - * - * Update the @termios structure to reflect the baud rate - * we're actually going to be using. - */ -unsigned int -uart_get_baud_rate(struct uart_port *port, struct termios *termios, - struct termios *old, unsigned int min, unsigned int max) -{ - unsigned int try, baud, altbaud = 38400; - unsigned int flags = port->flags & UPF_SPD_MASK; - - if (flags == UPF_SPD_HI) - altbaud = 57600; - if (flags == UPF_SPD_VHI) - altbaud = 115200; - if (flags == UPF_SPD_SHI) - altbaud = 230400; - if (flags == UPF_SPD_WARP) - altbaud = 460800; - - for (try = 0; try < 2; try++) { - baud = tty_termios_baud_rate(termios); - - /* - * The spd_hi, spd_vhi, spd_shi, spd_warp kludge... - * Die! Die! Die! - */ - if (baud == 38400) - baud = altbaud; - - /* - * Special case: B0 rate. - */ - if (baud == 0) - baud = 9600; - - if (baud >= min && baud <= max) - return baud; - - /* - * Oops, the quotient was zero. Try again with - * the old baud rate if possible. - */ - termios->c_cflag &= ~CBAUD; - if (old) { - termios->c_cflag |= old->c_cflag & CBAUD; - old = NULL; - continue; - } - - /* - * As a last resort, if the quotient is zero, - * default to 9600 bps - */ - termios->c_cflag |= B9600; - } - - return 0; -} - -EXPORT_SYMBOL(uart_get_baud_rate); - -/** - * uart_get_divisor - return uart clock divisor - * @port: uart_port structure describing the port. - * @baud: desired baud rate - * - * Calculate the uart clock divisor for the port. - */ -unsigned int -uart_get_divisor(struct uart_port *port, unsigned int baud) -{ - unsigned int quot; - - /* - * Old custom speed handling. - */ - if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) - quot = port->custom_divisor; - else - quot = port->uartclk / (16 * baud); - - return quot; -} - -EXPORT_SYMBOL(uart_get_divisor); - -static void -uart_change_speed(struct uart_state *state, struct termios *old_termios) -{ - struct tty_struct *tty = state->info->tty; - struct uart_port *port = state->port; - struct termios *termios; - - /* - * If we have no tty, termios, or the port does not exist, - * then we can't set the parameters for this port. - */ - if (!tty || !tty->termios || port->type == PORT_UNKNOWN) - return; - - termios = tty->termios; - - /* - * Set flags based on termios cflag - */ - if (termios->c_cflag & CRTSCTS) - state->info->flags |= UIF_CTS_FLOW; - else - state->info->flags &= ~UIF_CTS_FLOW; - - if (termios->c_cflag & CLOCAL) - state->info->flags &= ~UIF_CHECK_CD; - else - state->info->flags |= UIF_CHECK_CD; - - port->ops->set_termios(port, termios, old_termios); -} - -static inline void -__uart_put_char(struct uart_port *port, struct circ_buf *circ, unsigned char c) -{ - unsigned long flags; - - if (!circ->buf) - return; - - spin_lock_irqsave(&port->lock, flags); - if (uart_circ_chars_free(circ) != 0) { - circ->buf[circ->head] = c; - circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1); - } - spin_unlock_irqrestore(&port->lock, flags); -} - -static inline int -__uart_user_write(struct uart_port *port, struct circ_buf *circ, - const unsigned char *buf, int count) -{ - unsigned long flags; - int c, ret = 0; - - if (down_interruptible(&port->info->tmpbuf_sem)) - return -EINTR; - - while (1) { - int c1; - c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) - break; - - c -= copy_from_user(port->info->tmpbuf, buf, c); - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - spin_lock_irqsave(&port->lock, flags); - c1 = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); - if (c1 < c) - c = c1; - memcpy(circ->buf + circ->head, port->info->tmpbuf, c); - circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1); - spin_unlock_irqrestore(&port->lock, flags); - buf += c; - count -= c; - ret += c; - } - up(&port->info->tmpbuf_sem); - - return ret; -} - -static inline int -__uart_kern_write(struct uart_port *port, struct circ_buf *circ, - const unsigned char *buf, int count) -{ - unsigned long flags; - int c, ret = 0; - - spin_lock_irqsave(&port->lock, flags); - while (1) { - c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) - break; - memcpy(circ->buf + circ->head, buf, c); - circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1); - buf += c; - count -= c; - ret += c; - } - spin_unlock_irqrestore(&port->lock, flags); - - return ret; -} - -static void uart_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct uart_state *state = tty->driver_data; - - if (tty) - __uart_put_char(state->port, &state->info->xmit, ch); -} - -static void uart_flush_chars(struct tty_struct *tty) -{ - uart_start(tty); -} - -static int -uart_write(struct tty_struct *tty, int from_user, const unsigned char * buf, - int count) -{ - struct uart_state *state = tty->driver_data; - int ret; - - if (!tty || !state->info->xmit.buf) - return 0; - - if (from_user) - ret = __uart_user_write(state->port, &state->info->xmit, buf, count); - else - ret = __uart_kern_write(state->port, &state->info->xmit, buf, count); - - uart_start(tty); - return ret; -} - -static int uart_write_room(struct tty_struct *tty) -{ - struct uart_state *state = tty->driver_data; - - return uart_circ_chars_free(&state->info->xmit); -} - -static int uart_chars_in_buffer(struct tty_struct *tty) -{ - struct uart_state *state = tty->driver_data; - - return uart_circ_chars_pending(&state->info->xmit); -} - -static void uart_flush_buffer(struct tty_struct *tty) -{ - struct uart_state *state = tty->driver_data; - struct uart_port *port = state->port; - unsigned long flags; - - DPRINTK("uart_flush_buffer(%d) called\n", tty->index); - - spin_lock_irqsave(&port->lock, flags); - uart_circ_clear(&state->info->xmit); - spin_unlock_irqrestore(&port->lock, flags); - wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); -} - -/* - * This function is used to send a high-priority XON/XOFF character to - * the device - */ -static void uart_send_xchar(struct tty_struct *tty, char ch) -{ - struct uart_state *state = tty->driver_data; - struct uart_port *port = state->port; - unsigned long flags; - - if (port->ops->send_xchar) - port->ops->send_xchar(port, ch); - else { - port->x_char = ch; - if (ch) { - spin_lock_irqsave(&port->lock, flags); - port->ops->start_tx(port, 0); - spin_unlock_irqrestore(&port->lock, flags); - } - } -} - -static void uart_throttle(struct tty_struct *tty) -{ - struct uart_state *state = tty->driver_data; - - if (I_IXOFF(tty)) - uart_send_xchar(tty, STOP_CHAR(tty)); - - if (tty->termios->c_cflag & CRTSCTS) - uart_clear_mctrl(state->port, TIOCM_RTS); -} - -static void uart_unthrottle(struct tty_struct *tty) -{ - struct uart_state *state = tty->driver_data; - struct uart_port *port = state->port; - - if (I_IXOFF(tty)) { - if (port->x_char) - port->x_char = 0; - else - uart_send_xchar(tty, START_CHAR(tty)); - } - - if (tty->termios->c_cflag & CRTSCTS) - uart_set_mctrl(port, TIOCM_RTS); -} - -static int uart_get_info(struct uart_state *state, struct serial_struct *retinfo) -{ - struct uart_port *port = state->port; - struct serial_struct tmp; - - memset(&tmp, 0, sizeof(tmp)); - tmp.type = port->type; - tmp.line = port->line; - tmp.port = port->iobase; - if (HIGH_BITS_OFFSET) - tmp.port_high = (long) port->iobase >> HIGH_BITS_OFFSET; - tmp.irq = port->irq; - tmp.flags = port->flags; - tmp.xmit_fifo_size = port->fifosize; - tmp.baud_base = port->uartclk / 16; - tmp.close_delay = state->close_delay; - tmp.closing_wait = state->closing_wait; - tmp.custom_divisor = port->custom_divisor; - tmp.hub6 = port->hub6; - tmp.io_type = port->iotype; - tmp.iomem_reg_shift = port->regshift; - tmp.iomem_base = (void *)port->mapbase; - - if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) - return -EFAULT; - return 0; -} - -static int -uart_set_info(struct uart_state *state, struct serial_struct *newinfo) -{ - struct serial_struct new_serial; - struct uart_port *port = state->port; - unsigned long new_port; - unsigned int change_irq, change_port, old_flags; - unsigned int old_custom_divisor; - int retval = 0; - - if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) - return -EFAULT; - - new_port = new_serial.port; - if (HIGH_BITS_OFFSET) - new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET; - - new_serial.irq = irq_canonicalize(new_serial.irq); - - /* - * This semaphore protects state->count. It is also - * very useful to prevent opens. Also, take the - * port configuration semaphore to make sure that a - * module insertion/removal doesn't change anything - * under us. - */ - down(&state->sem); - - change_irq = new_serial.irq != port->irq; - - /* - * Since changing the 'type' of the port changes its resource - * allocations, we should treat type changes the same as - * IO port changes. - */ - change_port = new_port != port->iobase || - (unsigned long)new_serial.iomem_base != port->mapbase || - new_serial.hub6 != port->hub6 || - new_serial.io_type != port->iotype || - new_serial.iomem_reg_shift != port->regshift || - new_serial.type != port->type; - - old_flags = port->flags; - old_custom_divisor = port->custom_divisor; - - if (!capable(CAP_SYS_ADMIN)) { - retval = -EPERM; - if (change_irq || change_port || - (new_serial.baud_base != port->uartclk / 16) || - (new_serial.close_delay != state->close_delay) || - (new_serial.closing_wait != state->closing_wait) || - (new_serial.xmit_fifo_size != port->fifosize) || - (((new_serial.flags ^ old_flags) & ~UPF_USR_MASK) != 0)) - goto exit; - port->flags = ((port->flags & ~UPF_USR_MASK) | - (new_serial.flags & UPF_USR_MASK)); - port->custom_divisor = new_serial.custom_divisor; - goto check_and_exit; - } - - /* - * Ask the low level driver to verify the settings. - */ - if (port->ops->verify_port) - retval = port->ops->verify_port(port, &new_serial); - - if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) || - (new_serial.baud_base < 9600)) - retval = -EINVAL; - - if (retval) - goto exit; - - if (change_port || change_irq) { - retval = -EBUSY; - - /* - * Make sure that we are the sole user of this port. - */ - if (uart_users(state) > 1) - goto exit; - - /* - * We need to shutdown the serial port at the old - * port/type/irq combination. - */ - uart_shutdown(state); - } - - if (change_port) { - unsigned long old_iobase, old_mapbase; - unsigned int old_type, old_iotype, old_hub6, old_shift; - - old_iobase = port->iobase; - old_mapbase = port->mapbase; - old_type = port->type; - old_hub6 = port->hub6; - old_iotype = port->iotype; - old_shift = port->regshift; - - /* - * Free and release old regions - */ - if (old_type != PORT_UNKNOWN) - port->ops->release_port(port); - - port->iobase = new_port; - port->type = new_serial.type; - port->hub6 = new_serial.hub6; - port->iotype = new_serial.io_type; - port->regshift = new_serial.iomem_reg_shift; - port->mapbase = (unsigned long)new_serial.iomem_base; - - /* - * Claim and map the new regions - */ - if (port->type != PORT_UNKNOWN) { - retval = port->ops->request_port(port); - } else { - /* Always success - Jean II */ - retval = 0; - } - - /* - * If we fail to request resources for the - * new port, try to restore the old settings. - */ - if (retval && old_type != PORT_UNKNOWN) { - port->iobase = old_iobase; - port->type = old_type; - port->hub6 = old_hub6; - port->iotype = old_iotype; - port->regshift = old_shift; - port->mapbase = old_mapbase; - retval = port->ops->request_port(port); - /* - * If we failed to restore the old settings, - * we fail like this. - */ - if (retval) - port->type = PORT_UNKNOWN; - - /* - * We failed anyway. - */ - retval = -EBUSY; - } - } - - port->irq = new_serial.irq; - port->uartclk = new_serial.baud_base * 16; - port->flags = (port->flags & ~UPF_CHANGE_MASK) | - (new_serial.flags & UPF_CHANGE_MASK); - port->custom_divisor = new_serial.custom_divisor; - state->close_delay = new_serial.close_delay * HZ / 100; - state->closing_wait = new_serial.closing_wait * HZ / 100; - port->fifosize = new_serial.xmit_fifo_size; - if (state->info->tty) - state->info->tty->low_latency = - (port->flags & UPF_LOW_LATENCY) ? 1 : 0; - - check_and_exit: - retval = 0; - if (port->type == PORT_UNKNOWN) - goto exit; - if (state->info->flags & UIF_INITIALIZED) { - if (((old_flags ^ port->flags) & UPF_SPD_MASK) || - old_custom_divisor != port->custom_divisor) { - /* If they're setting up a custom divisor or speed, - * instead of clearing it, then bitch about it. No - * need to rate-limit; it's CAP_SYS_ADMIN only. */ - if (port->flags & UPF_SPD_MASK) { - printk(KERN_NOTICE "%s sets custom speed on %s%d. This is deprecated.\n", - current->comm, state->info->tty->driver->name, - state->port->line); - } - uart_change_speed(state, NULL); - } - } else - retval = uart_startup(state, 1); - exit: - up(&state->sem); - return retval; -} - - -/* - * uart_get_lsr_info - get line status register info. - * Note: uart_ioctl protects us against hangups. - */ -static int uart_get_lsr_info(struct uart_state *state, unsigned int *value) -{ - struct uart_port *port = state->port; - unsigned int result; - - result = port->ops->tx_empty(port); - - /* - * If we're about to load something into the transmit - * register, we'll pretend the transmitter isn't empty to - * avoid a race condition (depending on when the transmit - * interrupt happens). - */ - if (port->x_char || - ((uart_circ_chars_pending(&state->info->xmit) > 0) && - !state->info->tty->stopped && !state->info->tty->hw_stopped)) - result &= ~TIOCSER_TEMT; - - return put_user(result, value); -} - -static int uart_tiocmget(struct tty_struct *tty, struct file *file) -{ - struct uart_state *state = tty->driver_data; - struct uart_port *port = state->port; - int result = -EIO; - - down(&state->sem); - if ((!file || !tty_hung_up_p(file)) && - !(tty->flags & (1 << TTY_IO_ERROR))) { - result = port->mctrl; - result |= port->ops->get_mctrl(port); - } - up(&state->sem); - - return result; -} - -static int -uart_tiocmset(struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) -{ - struct uart_state *state = tty->driver_data; - struct uart_port *port = state->port; - int ret = -EIO; - - down(&state->sem); - if ((!file || !tty_hung_up_p(file)) && - !(tty->flags & (1 << TTY_IO_ERROR))) { - uart_update_mctrl(port, set, clear); - ret = 0; - } - up(&state->sem); - return ret; -} - -static void uart_break_ctl(struct tty_struct *tty, int break_state) -{ - struct uart_state *state = tty->driver_data; - struct uart_port *port = state->port; - - BUG_ON(!kernel_locked()); - - down(&state->sem); - - if (port->type != PORT_UNKNOWN) - port->ops->break_ctl(port, break_state); - - up(&state->sem); -} - -static int uart_do_autoconfig(struct uart_state *state) -{ - struct uart_port *port = state->port; - int flags, ret; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - /* - * Take the per-port semaphore. This prevents count from - * changing, and hence any extra opens of the port while - * we're auto-configuring. - */ - if (down_interruptible(&state->sem)) - return -ERESTARTSYS; - - ret = -EBUSY; - if (uart_users(state) == 1) { - uart_shutdown(state); - - /* - * If we already have a port type configured, - * we must release its resources. - */ - if (port->type != PORT_UNKNOWN) - port->ops->release_port(port); - - flags = UART_CONFIG_TYPE; - if (port->flags & UPF_AUTO_IRQ) - flags |= UART_CONFIG_IRQ; - - /* - * This will claim the ports resources if - * a port is found. - */ - port->ops->config_port(port, flags); - - ret = uart_startup(state, 1); - } - up(&state->sem); - return ret; -} - -/* - * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - * - mask passed in arg for lines of interest - * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) - * Caller should use TIOCGICOUNT to see which one it was - */ -static int -uart_wait_modem_status(struct uart_state *state, unsigned long arg) -{ - struct uart_port *port = state->port; - DECLARE_WAITQUEUE(wait, current); - struct uart_icount cprev, cnow; - int ret; - - /* - * note the counters on entry - */ - spin_lock_irq(&port->lock); - memcpy(&cprev, &port->icount, sizeof(struct uart_icount)); - - /* - * Force modem status interrupts on - */ - port->ops->enable_ms(port); - spin_unlock_irq(&port->lock); - - add_wait_queue(&state->info->delta_msr_wait, &wait); - for (;;) { - spin_lock_irq(&port->lock); - memcpy(&cnow, &port->icount, sizeof(struct uart_icount)); - spin_unlock_irq(&port->lock); - - set_current_state(TASK_INTERRUPTIBLE); - - if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { - ret = 0; - break; - } - - schedule(); - - /* see if a signal did it */ - if (signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } - - cprev = cnow; - } - - current->state = TASK_RUNNING; - remove_wait_queue(&state->info->delta_msr_wait, &wait); - - return ret; -} - -/* - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) - * Return: write counters to the user passed counter struct - * NB: both 1->0 and 0->1 transitions are counted except for - * RI where only 0->1 is counted. - */ -static int -uart_get_count(struct uart_state *state, struct serial_icounter_struct *icnt) -{ - struct serial_icounter_struct icount; - struct uart_icount cnow; - struct uart_port *port = state->port; - - spin_lock_irq(&port->lock); - memcpy(&cnow, &port->icount, sizeof(struct uart_icount)); - spin_unlock_irq(&port->lock); - - icount.cts = cnow.cts; - icount.dsr = cnow.dsr; - icount.rng = cnow.rng; - icount.dcd = cnow.dcd; - icount.rx = cnow.rx; - icount.tx = cnow.tx; - icount.frame = cnow.frame; - icount.overrun = cnow.overrun; - icount.parity = cnow.parity; - icount.brk = cnow.brk; - icount.buf_overrun = cnow.buf_overrun; - - return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0; -} - -/* - * Called via sys_ioctl under the BKL. We can use spin_lock_irq() here. - */ -static int -uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, - unsigned long arg) -{ - struct uart_state *state = tty->driver_data; - int ret = -ENOIOCTLCMD; - - BUG_ON(!kernel_locked()); - - /* - * These ioctls don't rely on the hardware to be present. - */ - switch (cmd) { - case TIOCGSERIAL: - ret = uart_get_info(state, (struct serial_struct *)arg); - break; - - case TIOCSSERIAL: - ret = uart_set_info(state, (struct serial_struct *)arg); - break; - - case TIOCSERCONFIG: - ret = uart_do_autoconfig(state); - break; - - case TIOCSERGWILD: /* obsolete */ - case TIOCSERSWILD: /* obsolete */ - ret = 0; - break; - } - - if (ret != -ENOIOCTLCMD) - goto out; - - if (tty->flags & (1 << TTY_IO_ERROR)) { - ret = -EIO; - goto out; - } - - /* - * The following should only be used when hardware is present. - */ - switch (cmd) { - case TIOCMIWAIT: - ret = uart_wait_modem_status(state, arg); - break; - - case TIOCGICOUNT: - ret = uart_get_count(state, (struct serial_icounter_struct *)arg); - break; - } - - if (ret != -ENOIOCTLCMD) - goto out; - - down(&state->sem); - - if (tty_hung_up_p(filp)) { - ret = -EIO; - goto out_up; - } - - /* - * All these rely on hardware being present and need to be - * protected against the tty being hung up. - */ - switch (cmd) { - case TIOCSERGETLSR: /* Get line status register */ - ret = uart_get_lsr_info(state, (unsigned int *)arg); - break; - - default: { - struct uart_port *port = state->port; - if (port->ops->ioctl) - ret = port->ops->ioctl(port, cmd, arg); - break; - } - } - out_up: - up(&state->sem); - out: - return ret; -} - -static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios) -{ - struct uart_state *state = tty->driver_data; - unsigned long flags; - unsigned int cflag = tty->termios->c_cflag; - - BUG_ON(!kernel_locked()); - - /* - * These are the bits that are used to setup various - * flags in the low level driver. - */ -#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) - - if ((cflag ^ old_termios->c_cflag) == 0 && - RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0) - return; - - uart_change_speed(state, old_termios); - - /* Handle transition to B0 status */ - if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) - uart_clear_mctrl(state->port, TIOCM_RTS | TIOCM_DTR); - - /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { - unsigned int mask = TIOCM_DTR; - if (!(cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) - mask |= TIOCM_RTS; - uart_set_mctrl(state->port, mask); - } - - /* Handle turning off CRTSCTS */ - if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) { - spin_lock_irqsave(&state->port->lock, flags); - tty->hw_stopped = 0; - __uart_start(tty); - spin_unlock_irqrestore(&state->port->lock, flags); - } - -#if 0 - /* - * No need to wake up processes in open wait, since they - * sample the CLOCAL flag once, and don't recheck it. - * XXX It's not clear whether the current behavior is correct - * or not. Hence, this may change..... - */ - if (!(old_termios->c_cflag & CLOCAL) && - (tty->termios->c_cflag & CLOCAL)) - wake_up_interruptible(&state->info->open_wait); -#endif -} - -/* - * In 2.4.5, calls to this will be serialized via the BKL in - * linux/drivers/char/tty_io.c:tty_release() - * linux/drivers/char/tty_io.c:do_tty_handup() - */ -static void uart_close(struct tty_struct *tty, struct file *filp) -{ - struct uart_state *state = tty->driver_data; - struct uart_port *port = state->port; - - BUG_ON(!kernel_locked()); - DPRINTK("uart_close(%d) called\n", port->line); - - down(&state->sem); - - if (tty_hung_up_p(filp)) - goto done; - - if ((tty->count == 1) && (state->count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. state->count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - printk("uart_close: bad serial port count; tty->count is 1, " - "state->count is %d\n", state->count); - state->count = 1; - } - if (--state->count < 0) { - printk("rs_close: bad serial port count for %s: %d\n", - tty->name, state->count); - state->count = 0; - } - if (state->count) - goto done; - - /* - * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters by - * setting tty->closing. - */ - tty->closing = 1; - - if (state->closing_wait != USF_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, state->closing_wait); - - /* - * At this point, we stop accepting input. To do this, we - * disable the receive line status interrupts. - */ - if (state->info->flags & UIF_INITIALIZED) { - unsigned long flags; - spin_lock_irqsave(&port->lock, flags); - port->ops->stop_rx(port); - spin_unlock_irqrestore(&port->lock, flags); - /* - * Before we drop DTR, make sure the UART transmitter - * has completely drained; this is especially - * important if there is a transmit FIFO! - */ - uart_wait_until_sent(tty, port->timeout); - } - - uart_shutdown(state); - uart_flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); - tty->closing = 0; - state->info->tty = NULL; - - if (state->info->blocked_open) { - if (state->close_delay) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(state->close_delay); - set_current_state(TASK_RUNNING); - } - } else if (!uart_console(port)) { - uart_change_pm(state, 3); - } - - /* - * Wake up anyone trying to open this port. - */ - state->info->flags &= ~UIF_NORMAL_ACTIVE; - wake_up_interruptible(&state->info->open_wait); - - done: - up(&state->sem); -} - -static void uart_wait_until_sent(struct tty_struct *tty, int timeout) -{ - struct uart_state *state = tty->driver_data; - struct uart_port *port = state->port; - unsigned long char_time, expire; - - BUG_ON(!kernel_locked()); - - if (port->type == PORT_UNKNOWN || port->fifosize == 0) - return; - - /* - * Set the check interval to be 1/5 of the estimated time to - * send a single character, and make it at least 1. The check - * interval should also be less than the timeout. - * - * Note: we have to use pretty tight timings here to satisfy - * the NIST-PCTS. - */ - char_time = (port->timeout - HZ/50) / port->fifosize; - char_time = char_time / 5; - if (char_time == 0) - char_time = 1; - if (timeout && timeout < char_time) - char_time = timeout; - - /* - * If the transmitter hasn't cleared in twice the approximate - * amount of time to send the entire FIFO, it probably won't - * ever clear. This assumes the UART isn't doing flow - * control, which is currently the case. Hence, if it ever - * takes longer than port->timeout, this is probably due to a - * UART bug of some kind. So, we clamp the timeout parameter at - * 2*port->timeout. - */ - if (timeout == 0 || timeout > 2 * port->timeout) - timeout = 2 * port->timeout; - - expire = jiffies + timeout; - - DPRINTK("uart_wait_until_sent(%d), jiffies=%lu, expire=%lu...\n", - port->line, jiffies, expire); - - /* - * Check whether the transmitter is empty every 'char_time'. - * 'timeout' / 'expire' give us the maximum amount of time - * we wait. - */ - while (!port->ops->tx_empty(port)) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(char_time); - if (signal_pending(current)) - break; - if (time_after(jiffies, expire)) - break; - } - set_current_state(TASK_RUNNING); /* might not be needed */ -} - -/* - * This is called with the BKL held in - * linux/drivers/char/tty_io.c:do_tty_hangup() - * We're called from the eventd thread, so we can sleep for - * a _short_ time only. - */ -static void uart_hangup(struct tty_struct *tty) -{ - struct uart_state *state = tty->driver_data; - - BUG_ON(!kernel_locked()); - DPRINTK("uart_hangup(%d)\n", state->port->line); - - down(&state->sem); - if (state->info && state->info->flags & UIF_NORMAL_ACTIVE) { - uart_flush_buffer(tty); - uart_shutdown(state); - state->count = 0; - state->info->flags &= ~UIF_NORMAL_ACTIVE; - state->info->tty = NULL; - wake_up_interruptible(&state->info->open_wait); - wake_up_interruptible(&state->info->delta_msr_wait); - } - up(&state->sem); -} - -/* - * Copy across the serial console cflag setting into the termios settings - * for the initial open of the port. This allows continuity between the - * kernel settings, and the settings init adopts when it opens the port - * for the first time. - */ -static void uart_update_termios(struct uart_state *state) -{ - struct tty_struct *tty = state->info->tty; - struct uart_port *port = state->port; - - if (uart_console(port) && port->cons->cflag) { - tty->termios->c_cflag = port->cons->cflag; - port->cons->cflag = 0; - } - - /* - * If the device failed to grab its irq resources, - * or some other error occurred, don't try to talk - * to the port hardware. - */ - if (!(tty->flags & (1 << TTY_IO_ERROR))) { - /* - * Make termios settings take effect. - */ - uart_change_speed(state, NULL); - - /* - * And finally enable the RTS and DTR signals. - */ - if (tty->termios->c_cflag & CBAUD) - uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS); - } -} - -/* - * Block the open until the port is ready. We must be called with - * the per-port semaphore held. - */ -static int -uart_block_til_ready(struct file *filp, struct uart_state *state) -{ - DECLARE_WAITQUEUE(wait, current); - struct uart_info *info = state->info; - struct uart_port *port = state->port; - - info->blocked_open++; - state->count--; - - add_wait_queue(&info->open_wait, &wait); - while (1) { - set_current_state(TASK_INTERRUPTIBLE); - - /* - * If we have been hung up, tell userspace/restart open. - */ - if (tty_hung_up_p(filp) || info->tty == NULL) - break; - - /* - * If the port has been closed, tell userspace/restart open. - */ - if (!(info->flags & UIF_INITIALIZED)) - break; - - /* - * If non-blocking mode is set, or CLOCAL mode is set, - * we don't want to wait for the modem status lines to - * indicate that the port is ready. - * - * Also, if the port is not enabled/configured, we want - * to allow the open to succeed here. Note that we will - * have set TTY_IO_ERROR for a non-existant port. - */ - if ((filp->f_flags & O_NONBLOCK) || - (info->tty->termios->c_cflag & CLOCAL) || - (info->tty->flags & (1 << TTY_IO_ERROR))) { - break; - } - - /* - * Set DTR to allow modem to know we're waiting. Do - * not set RTS here - we want to make sure we catch - * the data from the modem. - */ - if (info->tty->termios->c_cflag & CBAUD) - uart_set_mctrl(port, TIOCM_DTR); - - /* - * and wait for the carrier to indicate that the - * modem is ready for us. - */ - if (port->ops->get_mctrl(port) & TIOCM_CAR) - break; - - up(&state->sem); - schedule(); - down(&state->sem); - - if (signal_pending(current)) - break; - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&info->open_wait, &wait); - - state->count++; - info->blocked_open--; - - if (signal_pending(current)) - return -ERESTARTSYS; - - if (!info->tty || tty_hung_up_p(filp)) - return -EAGAIN; - - return 0; -} - -static struct uart_state *uart_get(struct uart_driver *drv, int line) -{ - struct uart_state *state; - - down(&port_sem); - state = drv->state + line; - if (down_interruptible(&state->sem)) { - state = ERR_PTR(-ERESTARTSYS); - goto out; - } - - state->count++; - if (!state->port) { - state->count--; - up(&state->sem); - state = ERR_PTR(-ENXIO); - goto out; - } - - if (!state->info) { - state->info = kmalloc(sizeof(struct uart_info), GFP_KERNEL); - if (state->info) { - memset(state->info, 0, sizeof(struct uart_info)); - init_waitqueue_head(&state->info->open_wait); - init_waitqueue_head(&state->info->delta_msr_wait); - - /* - * Link the info into the other structures. - */ - state->port->info = state->info; - - tasklet_init(&state->info->tlet, uart_tasklet_action, - (unsigned long)state); - } else { - state->count--; - up(&state->sem); - state = ERR_PTR(-ENOMEM); - } - } - - out: - up(&port_sem); - return state; -} - -/* - * In 2.4.5, calls to uart_open are serialised by the BKL in - * linux/fs/devices.c:chrdev_open() - * Note that if this fails, then uart_close() _will_ be called. - * - * In time, we want to scrap the "opening nonpresent ports" - * behaviour and implement an alternative way for setserial - * to set base addresses/ports/types. This will allow us to - * get rid of a certain amount of extra tests. - */ -static int uart_open(struct tty_struct *tty, struct file *filp) -{ - struct uart_driver *drv = (struct uart_driver *)tty->driver->driver_state; - struct uart_state *state; - int retval, line = tty->index; - - BUG_ON(!kernel_locked()); - DPRINTK("uart_open(%d) called\n", line); - - /* - * tty->driver->num won't change, so we won't fail here with - * tty->driver_data set to something non-NULL (and therefore - * we won't get caught by uart_close()). - */ - retval = -ENODEV; - if (line >= tty->driver->num) - goto fail; - - /* - * We take the semaphore inside uart_get to guarantee that we won't - * be re-entered while allocating the info structure, or while we - * request any IRQs that the driver may need. This also has the nice - * side-effect that it delays the action of uart_hangup, so we can - * guarantee that info->tty will always contain something reasonable. - */ - state = uart_get(drv, line); - if (IS_ERR(state)) { - retval = PTR_ERR(state); - goto fail; - } - - /* - * Once we set tty->driver_data here, we are guaranteed that - * uart_close() will decrement the driver module use count. - * Any failures from here onwards should not touch the count. - */ - tty->driver_data = state; - tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0; - tty->alt_speed = 0; - state->info->tty = tty; - - /* - * If the port is in the middle of closing, bail out now. - */ - if (tty_hung_up_p(filp)) { - retval = -EAGAIN; - state->count--; - up(&state->sem); - goto fail; - } - - /* - * Make sure the device is in D0 state. - */ - if (state->count == 1) - uart_change_pm(state, 0); - - /* - * Start up the serial port. - */ - retval = uart_startup(state, 0); - - /* - * If we succeeded, wait until the port is ready. - */ - if (retval == 0) - retval = uart_block_til_ready(filp, state); - up(&state->sem); - - /* - * If this is the first open to succeed, adjust things to suit. - */ - if (retval == 0 && !(state->info->flags & UIF_NORMAL_ACTIVE)) { - state->info->flags |= UIF_NORMAL_ACTIVE; - - uart_update_termios(state); - } - - fail: - return retval; -} - -static const char *uart_type(struct uart_port *port) -{ - const char *str = NULL; - - if (port->ops->type) - str = port->ops->type(port); - - if (!str) - str = "unknown"; - - return str; -} - -#ifdef CONFIG_PROC_FS - -static int uart_line_info(char *buf, struct uart_driver *drv, int i) -{ - struct uart_state *state = drv->state + i; - struct uart_port *port = state->port; - char stat_buf[32]; - unsigned int status; - int ret; - - if (!port) - return 0; - - ret = sprintf(buf, "%d: uart:%s port:%08X irq:%d", - port->line, uart_type(port), - port->iobase, port->irq); - - if (port->type == PORT_UNKNOWN) { - strcat(buf, "\n"); - return ret + 1; - } - - if(capable(CAP_SYS_ADMIN)) - { - status = port->ops->get_mctrl(port); - - ret += sprintf(buf + ret, " tx:%d rx:%d", - port->icount.tx, port->icount.rx); - if (port->icount.frame) - ret += sprintf(buf + ret, " fe:%d", - port->icount.frame); - if (port->icount.parity) - ret += sprintf(buf + ret, " pe:%d", - port->icount.parity); - if (port->icount.brk) - ret += sprintf(buf + ret, " brk:%d", - port->icount.brk); - if (port->icount.overrun) - ret += sprintf(buf + ret, " oe:%d", - port->icount.overrun); - -#define INFOBIT(bit,str) \ - if (port->mctrl & (bit)) \ - strncat(stat_buf, (str), sizeof(stat_buf) - \ - strlen(stat_buf) - 2) -#define STATBIT(bit,str) \ - if (status & (bit)) \ - strncat(stat_buf, (str), sizeof(stat_buf) - \ - strlen(stat_buf) - 2) - - stat_buf[0] = '\0'; - stat_buf[1] = '\0'; - INFOBIT(TIOCM_RTS, "|RTS"); - STATBIT(TIOCM_CTS, "|CTS"); - INFOBIT(TIOCM_DTR, "|DTR"); - STATBIT(TIOCM_DSR, "|DSR"); - STATBIT(TIOCM_CAR, "|CD"); - STATBIT(TIOCM_RNG, "|RI"); - if (stat_buf[0]) - stat_buf[0] = ' '; - strcat(stat_buf, "\n"); - - ret += sprintf(buf + ret, stat_buf); - } -#undef STATBIT -#undef INFOBIT - return ret; -} - -static int uart_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct tty_driver *ttydrv = data; - struct uart_driver *drv = ttydrv->driver_state; - int i, len = 0, l; - off_t begin = 0; - - len += sprintf(page, "serinfo:1.0 driver%s%s revision:%s\n", - "", "", ""); - for (i = 0; i < drv->nr && len < PAGE_SIZE - 96; i++) { - l = uart_line_info(page + len, drv, i); - len += l; - if (len + begin > off + count) - goto done; - if (len + begin < off) { - begin += len; - len = 0; - } - } - *eof = 1; - done: - if (off >= len + begin) - return 0; - *start = page + (off - begin); - return (count < begin + len - off) ? count : (begin + len - off); -} -#endif - -#ifdef CONFIG_SERIAL_CORE_CONSOLE -/* - * Check whether an invalid uart number has been specified, and - * if so, search for the first available port that does have - * console support. - */ -struct uart_port * __init -uart_get_console(struct uart_port *ports, int nr, struct console *co) -{ - int idx = co->index; - - if (idx < 0 || idx >= nr || (ports[idx].iobase == 0 && - ports[idx].membase == NULL)) - for (idx = 0; idx < nr; idx++) - if (ports[idx].iobase != 0 || - ports[idx].membase != NULL) - break; - - co->index = idx; - - return ports + idx; -} - -/** - * uart_parse_options - Parse serial port baud/parity/bits/flow contro. - * @options: pointer to option string - * @baud: pointer to an 'int' variable for the baud rate. - * @parity: pointer to an 'int' variable for the parity. - * @bits: pointer to an 'int' variable for the number of data bits. - * @flow: pointer to an 'int' variable for the flow control character. - * - * uart_parse_options decodes a string containing the serial console - * options. The format of the string is , - * eg: 115200n8r - */ -void __init -uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow) -{ - char *s = options; - - *baud = simple_strtoul(s, NULL, 10); - while (*s >= '0' && *s <= '9') - s++; - if (*s) - *parity = *s++; - if (*s) - *bits = *s++ - '0'; - if (*s) - *flow = *s; -} - -struct baud_rates { - unsigned int rate; - unsigned int cflag; -}; - -static struct baud_rates baud_rates[] = { - { 921600, B921600 }, - { 460800, B460800 }, - { 230400, B230400 }, - { 115200, B115200 }, - { 57600, B57600 }, - { 38400, B38400 }, - { 19200, B19200 }, - { 9600, B9600 }, - { 4800, B4800 }, - { 2400, B2400 }, - { 1200, B1200 }, - { 0, B38400 } -}; - -/** - * uart_set_options - setup the serial console parameters - * @port: pointer to the serial ports uart_port structure - * @co: console pointer - * @baud: baud rate - * @parity: parity character - 'n' (none), 'o' (odd), 'e' (even) - * @bits: number of data bits - * @flow: flow control character - 'r' (rts) - */ -int __init -uart_set_options(struct uart_port *port, struct console *co, - int baud, int parity, int bits, int flow) -{ - struct termios termios; - int i; - - memset(&termios, 0, sizeof(struct termios)); - - termios.c_cflag = CREAD | HUPCL | CLOCAL; - - /* - * Construct a cflag setting. - */ - for (i = 0; baud_rates[i].rate; i++) - if (baud_rates[i].rate <= baud) - break; - - termios.c_cflag |= baud_rates[i].cflag; - - if (bits == 7) - termios.c_cflag |= CS7; - else - termios.c_cflag |= CS8; - - switch (parity) { - case 'o': case 'O': - termios.c_cflag |= PARODD; - /*fall through*/ - case 'e': case 'E': - termios.c_cflag |= PARENB; - break; - } - - if (flow == 'r') - termios.c_cflag |= CRTSCTS; - - port->ops->set_termios(port, &termios, NULL); - co->cflag = termios.c_cflag; - - return 0; -} -#endif /* CONFIG_SERIAL_CORE_CONSOLE */ - -static void uart_change_pm(struct uart_state *state, int pm_state) -{ - struct uart_port *port = state->port; - if (port->ops->pm) - port->ops->pm(port, pm_state, state->pm_state); - state->pm_state = pm_state; -} - -int uart_suspend_port(struct uart_driver *drv, struct uart_port *port, u32 level) -{ - struct uart_state *state = drv->state + port->line; - - down(&state->sem); - - switch (level) { - case SUSPEND_SAVE_STATE: - if (state->info && state->info->flags & UIF_INITIALIZED) { - struct uart_ops *ops = port->ops; - - spin_lock_irq(&port->lock); - ops->stop_tx(port, 0); - ops->set_mctrl(port, 0); - ops->stop_rx(port); - spin_unlock_irq(&port->lock); - - /* - * Wait for the transmitter to empty. - */ - while (!ops->tx_empty(port)) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(10*HZ/1000); - } - set_current_state(TASK_RUNNING); - - ops->shutdown(port); - } - break; - - case SUSPEND_POWER_DOWN: - /* - * Disable the console device before suspending. - */ - if (uart_console(port)) - port->cons->flags &= ~CON_ENABLED; - - uart_change_pm(state, 3); - break; - } - - up(&state->sem); - - return 0; -} - -int uart_resume_port(struct uart_driver *drv, struct uart_port *port, u32 level) -{ - struct uart_state *state = drv->state + port->line; - - down(&state->sem); - - switch (level) { - case RESUME_POWER_ON: - uart_change_pm(state, 0); - - /* - * Re-enable the console device after suspending. - */ - if (uart_console(port)) { - uart_change_speed(state, NULL); - port->cons->flags |= CON_ENABLED; - } - break; - - case RESUME_RESTORE_STATE: - if (state->info && state->info->flags & UIF_INITIALIZED) { - struct uart_ops *ops = port->ops; - - ops->set_mctrl(port, 0); - ops->startup(port); - uart_change_speed(state, NULL); - spin_lock_irq(&port->lock); - ops->set_mctrl(port, port->mctrl); - ops->start_tx(port, 0); - spin_unlock_irq(&port->lock); - } - break; - } - - up(&state->sem); - - return 0; -} - -static inline void -uart_report_port(struct uart_driver *drv, struct uart_port *port) -{ - printk("%s%d", drv->dev_name, port->line); - printk(" at "); - switch (port->iotype) { - case UPIO_PORT: - printk("I/O 0x%x", port->iobase); - break; - case UPIO_HUB6: - printk("I/O 0x%x offset 0x%x", port->iobase, port->hub6); - break; - case UPIO_MEM: - printk("MMIO 0x%lx", port->mapbase); - break; - } - printk(" (irq = %d) is a %s\n", port->irq, uart_type(port)); -} - -static void -uart_configure_port(struct uart_driver *drv, struct uart_state *state, - struct uart_port *port) -{ - unsigned int flags; - - /* - * If there isn't a port here, don't do anything further. - */ - if (!port->iobase && !port->mapbase && !port->membase) - return; - - /* - * Now do the auto configuration stuff. Note that config_port - * is expected to claim the resources and map the port for us. - */ - flags = UART_CONFIG_TYPE; - if (port->flags & UPF_AUTO_IRQ) - flags |= UART_CONFIG_IRQ; - if (port->flags & UPF_BOOT_AUTOCONF) { - port->type = PORT_UNKNOWN; - port->ops->config_port(port, flags); - } - - if (port->type != PORT_UNKNOWN) { - unsigned long flags; - - uart_report_port(drv, port); - - /* - * Ensure that the modem control lines are de-activated. - * We probably don't need a spinlock around this, but - */ - spin_lock_irqsave(&port->lock, flags); - port->ops->set_mctrl(port, 0); - spin_unlock_irqrestore(&port->lock, flags); - - /* - * Power down all ports by default, except the - * console if we have one. - */ - if (!uart_console(port)) - uart_change_pm(state, 3); - } -} - -/* - * This reverses the effects of uart_configure_port, hanging up the - * port before removal. - */ -static void -uart_unconfigure_port(struct uart_driver *drv, struct uart_state *state) -{ - struct uart_port *port = state->port; - struct uart_info *info = state->info; - - if (info && info->tty) - tty_vhangup(info->tty); - - down(&state->sem); - - state->info = NULL; - - /* - * Free the port IO and memory resources, if any. - */ - if (port->type != PORT_UNKNOWN) - port->ops->release_port(port); - - /* - * Indicate that there isn't a port here anymore. - */ - port->type = PORT_UNKNOWN; - - /* - * Kill the tasklet, and free resources. - */ - if (info) { - tasklet_kill(&info->tlet); - kfree(info); - } - - up(&state->sem); -} - -static struct tty_operations uart_ops = { - .open = uart_open, - .close = uart_close, - .write = uart_write, - .put_char = uart_put_char, - .flush_chars = uart_flush_chars, - .write_room = uart_write_room, - .chars_in_buffer= uart_chars_in_buffer, - .flush_buffer = uart_flush_buffer, - .ioctl = uart_ioctl, - .throttle = uart_throttle, - .unthrottle = uart_unthrottle, - .send_xchar = uart_send_xchar, - .set_termios = uart_set_termios, - .stop = uart_stop, - .start = uart_start, - .hangup = uart_hangup, - .break_ctl = uart_break_ctl, - .wait_until_sent= uart_wait_until_sent, -#ifdef CONFIG_PROC_FS - .read_proc = uart_read_proc, -#endif - .tiocmget = uart_tiocmget, - .tiocmset = uart_tiocmset, -}; - -/** - * uart_register_driver - register a driver with the uart core layer - * @drv: low level driver structure - * - * Register a uart driver with the core driver. We in turn register - * with the tty layer, and initialise the core driver per-port state. - * - * We have a proc file in /proc/tty/driver which is named after the - * normal driver. - * - * drv->port should be NULL, and the per-port structures should be - * registered using uart_add_one_port after this call has succeeded. - */ -int uart_register_driver(struct uart_driver *drv) -{ - struct tty_driver *normal = NULL; - int i, retval; - - BUG_ON(drv->state); - - /* - * Maybe we should be using a slab cache for this, especially if - * we have a large number of ports to handle. - */ - drv->state = kmalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL); - retval = -ENOMEM; - if (!drv->state) - goto out; - - memset(drv->state, 0, sizeof(struct uart_state) * drv->nr); - - normal = alloc_tty_driver(drv->nr); - if (!normal) - goto out; - - drv->tty_driver = normal; - - normal->owner = drv->owner; - normal->driver_name = drv->driver_name; - normal->devfs_name = drv->devfs_name; - normal->name = drv->dev_name; - normal->major = drv->major; - normal->minor_start = drv->minor; - normal->type = TTY_DRIVER_TYPE_SERIAL; - normal->subtype = SERIAL_TYPE_NORMAL; - normal->init_termios = tty_std_termios; - normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; - normal->driver_state = drv; - tty_set_operations(normal, &uart_ops); - - /* - * Initialise the UART state(s). - */ - for (i = 0; i < drv->nr; i++) { - struct uart_state *state = drv->state + i; - - state->close_delay = 5 * HZ / 10; - state->closing_wait = 30 * HZ; - - init_MUTEX(&state->sem); - } - - retval = tty_register_driver(normal); - out: - if (retval < 0) { - put_tty_driver(normal); - kfree(drv->state); - } - return retval; -} - -/** - * uart_unregister_driver - remove a driver from the uart core layer - * @drv: low level driver structure - * - * Remove all references to a driver from the core driver. The low - * level driver must have removed all its ports via the - * uart_remove_one_port() if it registered them with uart_add_one_port(). - * (ie, drv->port == NULL) - */ -void uart_unregister_driver(struct uart_driver *drv) -{ - struct tty_driver *p = drv->tty_driver; - tty_unregister_driver(p); - put_tty_driver(p); - kfree(drv->state); - drv->tty_driver = NULL; -} - -struct tty_driver *uart_console_device(struct console *co, int *index) -{ - struct uart_driver *p = co->data; - *index = co->index; - return p->tty_driver; -} - -/** - * uart_add_one_port - attach a driver-defined port structure - * @drv: pointer to the uart low level driver structure for this port - * @port: uart port structure to use for this port. - * - * This allows the driver to register its own uart_port structure - * with the core driver. The main purpose is to allow the low - * level uart drivers to expand uart_port, rather than having yet - * more levels of structures. - */ -int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) -{ - struct uart_state *state; - int ret = 0; - - BUG_ON(in_interrupt()); - - if (port->line >= drv->nr) - return -EINVAL; - - state = drv->state + port->line; - - down(&port_sem); - if (state->port) { - ret = -EINVAL; - goto out; - } - - state->port = port; - - spin_lock_init(&port->lock); - port->cons = drv->cons; - port->info = state->info; - - uart_configure_port(drv, state, port); - - /* - * Register the port whether it's detected or not. This allows - * setserial to be used to alter this ports parameters. - */ - tty_register_device(drv->tty_driver, port->line, NULL); - - out: - up(&port_sem); - - return ret; -} - -/** - * uart_remove_one_port - detach a driver defined port structure - * @drv: pointer to the uart low level driver structure for this port - * @port: uart port structure for this port - * - * This unhooks (and hangs up) the specified port structure from the - * core driver. No further calls will be made to the low-level code - * for this port. - */ -int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port) -{ - struct uart_state *state = drv->state + port->line; - - BUG_ON(in_interrupt()); - - if (state->port != port) - printk(KERN_ALERT "Removing wrong port: %p != %p\n", - state->port, port); - - down(&port_sem); - - /* - * Remove the devices from devfs - */ - tty_unregister_device(drv->tty_driver, port->line); - - uart_unconfigure_port(drv, state); - state->port = NULL; - up(&port_sem); - - return 0; -} - -/* - * Are the two ports equivalent? - */ -static int uart_match_port(struct uart_port *port1, struct uart_port *port2) -{ - if (port1->iotype != port2->iotype) - return 0; - - switch (port1->iotype) { - case UPIO_PORT: - return (port1->iobase == port2->iobase); - case UPIO_HUB6: - return (port1->iobase == port2->iobase) && - (port1->hub6 == port2->hub6); - case UPIO_MEM: - return (port1->membase == port2->membase); - } - return 0; -} - -/* - * Try to find an unused uart_state slot for a port. - */ -static struct uart_state * -uart_find_match_or_unused(struct uart_driver *drv, struct uart_port *port) -{ - int i; - - /* - * First, find a port entry which matches. Note: if we do - * find a matching entry, and it has a non-zero use count, - * then we can't register the port. - */ - for (i = 0; i < drv->nr; i++) - if (uart_match_port(drv->state[i].port, port)) - return &drv->state[i]; - - /* - * We didn't find a matching entry, so look for the first - * free entry. We look for one which hasn't been previously - * used (indicated by zero iobase). - */ - for (i = 0; i < drv->nr; i++) - if (drv->state[i].port->type == PORT_UNKNOWN && - drv->state[i].port->iobase == 0 && - drv->state[i].count == 0) - return &drv->state[i]; - - /* - * That also failed. Last resort is to find any currently - * entry which doesn't have a real port associated with it. - */ - for (i = 0; i < drv->nr; i++) - if (drv->state[i].port->type == PORT_UNKNOWN && - drv->state[i].count == 0) - return &drv->state[i]; - - return NULL; -} - -/** - * uart_register_port: register uart settings with a port - * @drv: pointer to the uart low level driver structure for this port - * @port: uart port structure describing the port - * - * Register UART settings with the specified low level driver. Detect - * the type of the port if UPF_BOOT_AUTOCONF is set, and detect the - * IRQ if UPF_AUTO_IRQ is set. - * - * We try to pick the same port for the same IO base address, so that - * when a modem is plugged in, unplugged and plugged back in, it gets - * allocated the same port. - * - * Returns negative error, or positive line number. - */ -int uart_register_port(struct uart_driver *drv, struct uart_port *port) -{ - struct uart_state *state; - int ret; - - down(&port_sem); - - state = uart_find_match_or_unused(drv, port); - - if (state) { - /* - * Ok, we've found a line that we can use. - * - * If we find a port that matches this one, and it appears - * to be in-use (even if it doesn't have a type) we shouldn't - * alter it underneath itself - the port may be open and - * trying to do useful work. - */ - if (uart_users(state) != 0) { - ret = -EBUSY; - goto out; - } - - /* - * If the port is already initialised, don't touch it. - */ - if (state->port->type == PORT_UNKNOWN) { - state->port->iobase = port->iobase; - state->port->membase = port->membase; - state->port->irq = port->irq; - state->port->uartclk = port->uartclk; - state->port->fifosize = port->fifosize; - state->port->regshift = port->regshift; - state->port->iotype = port->iotype; - state->port->flags = port->flags; - state->port->line = state - drv->state; - state->port->mapbase = port->mapbase; - - uart_configure_port(drv, state, state->port); - } - - ret = state->port->line; - } else - ret = -ENOSPC; - out: - up(&port_sem); - return ret; -} - -/** - * uart_unregister_port - de-allocate a port - * @drv: pointer to the uart low level driver structure for this port - * @line: line index previously returned from uart_register_port() - * - * Hang up the specified line associated with the low level driver, - * and mark the port as unused. - */ -void uart_unregister_port(struct uart_driver *drv, int line) -{ - struct uart_state *state; - - if (line < 0 || line >= drv->nr) { - printk(KERN_ERR "Attempt to unregister "); - printk("%s%d", drv->dev_name, line); - printk("\n"); - return; - } - - state = drv->state + line; - - down(&port_sem); - uart_unconfigure_port(drv, state); - up(&port_sem); -} - -EXPORT_SYMBOL(uart_write_wakeup); -EXPORT_SYMBOL(uart_register_driver); -EXPORT_SYMBOL(uart_unregister_driver); -EXPORT_SYMBOL(uart_suspend_port); -EXPORT_SYMBOL(uart_resume_port); -EXPORT_SYMBOL(uart_register_port); -EXPORT_SYMBOL(uart_unregister_port); -EXPORT_SYMBOL(uart_add_one_port); -EXPORT_SYMBOL(uart_remove_one_port); - -MODULE_DESCRIPTION("Serial driver core"); -MODULE_LICENSE("GPL"); diff -Nru a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c --- a/drivers/serial/sa1100.c Thu Sep 11 23:03:11 2003 +++ b/drivers/serial/sa1100.c Thu Sep 11 23:03:11 2003 @@ -862,8 +862,8 @@ { struct sa1100_port *sport = dev_get_drvdata(_dev); - if (sport) - uart_suspend_port(&sa1100_reg, &sport->port, level); + if (sport && level == SUSPEND_DISABLE) + uart_suspend_port(&sa1100_reg, &sport->port); return 0; } @@ -872,8 +872,8 @@ { struct sa1100_port *sport = dev_get_drvdata(_dev); - if (sport) - uart_resume_port(&sa1100_reg, &sport->port, level); + if (sport && level == RESUME_ENABLE) + uart_resume_port(&sa1100_reg, &sport->port); return 0; } diff -Nru a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/serial_core.c Thu Sep 11 23:03:11 2003 @@ -0,0 +1,2420 @@ +/* + * linux/drivers/char/core.c + * + * Driver core for serial ports + * + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. + * + * Copyright 1999 ARM Limited + * Copyright (C) 2000-2001 Deep Blue Solutions Ltd. + * + * 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 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for serial_state and serial_icounter_struct */ + +#include +#include + +#undef DEBUG +#ifdef DEBUG +#define DPRINTK(x...) printk(x) +#else +#define DPRINTK(x...) do { } while (0) +#endif + +/* + * This is used to lock changes in serial line configuration. + */ +static DECLARE_MUTEX(port_sem); + +#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) + +#define uart_users(state) ((state)->count + ((state)->info ? (state)->info->blocked_open : 0)) + +#ifdef CONFIG_SERIAL_CORE_CONSOLE +#define uart_console(port) ((port)->cons && (port)->cons->index == (port)->line) +#else +#define uart_console(port) (0) +#endif + +static void uart_change_speed(struct uart_state *state, struct termios *old_termios); +static void uart_wait_until_sent(struct tty_struct *tty, int timeout); +static void uart_change_pm(struct uart_state *state, int pm_state); + +/* + * This routine is used by the interrupt handler to schedule processing in + * the software interrupt portion of the driver. + */ +void uart_write_wakeup(struct uart_port *port) +{ + struct uart_info *info = port->info; + tasklet_schedule(&info->tlet); +} + +static void uart_stop(struct tty_struct *tty) +{ + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + port->ops->stop_tx(port, 1); + spin_unlock_irqrestore(&port->lock, flags); +} + +static void __uart_start(struct tty_struct *tty) +{ + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; + + if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf && + !tty->stopped && !tty->hw_stopped) + port->ops->start_tx(port, 1); +} + +static void uart_start(struct tty_struct *tty) +{ + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; + unsigned long flags; + + spin_lock_irqsave(&port->lock, flags); + __uart_start(tty); + spin_unlock_irqrestore(&port->lock, flags); +} + +static void uart_tasklet_action(unsigned long data) +{ + struct uart_state *state = (struct uart_state *)data; + struct tty_struct *tty; + + tty = state->info->tty; + if (tty) { + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + tty->ldisc.write_wakeup(tty); + wake_up_interruptible(&tty->write_wait); + } +} + +static inline void +uart_update_mctrl(struct uart_port *port, unsigned int set, unsigned int clear) +{ + unsigned long flags; + unsigned int old; + + spin_lock_irqsave(&port->lock, flags); + old = port->mctrl; + port->mctrl = (old & ~clear) | set; + if (old != port->mctrl) + port->ops->set_mctrl(port, port->mctrl); + spin_unlock_irqrestore(&port->lock, flags); +} + +#define uart_set_mctrl(port,set) uart_update_mctrl(port,set,0) +#define uart_clear_mctrl(port,clear) uart_update_mctrl(port,0,clear) + +/* + * Startup the port. This will be called once per open. All calls + * will be serialised by the per-port semaphore. + */ +static int uart_startup(struct uart_state *state, int init_hw) +{ + struct uart_info *info = state->info; + struct uart_port *port = state->port; + unsigned long page; + int retval = 0; + + if (info->flags & UIF_INITIALIZED) + return 0; + + /* + * Set the TTY IO error marker - we will only clear this + * once we have successfully opened the port. Also set + * up the tty->alt_speed kludge + */ + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + + if (port->type == PORT_UNKNOWN) + return 0; + + /* + * Initialise and allocate the transmit and temporary + * buffer. + */ + if (!info->xmit.buf) { + page = get_zeroed_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + info->xmit.buf = (unsigned char *) page; + info->tmpbuf = info->xmit.buf + UART_XMIT_SIZE; + init_MUTEX(&info->tmpbuf_sem); + uart_circ_clear(&info->xmit); + } + + port->mctrl = 0; + + retval = port->ops->startup(port); + if (retval == 0) { + if (init_hw) { + /* + * Initialise the hardware port settings. + */ + uart_change_speed(state, NULL); + + /* + * Setup the RTS and DTR signals once the + * port is open and ready to respond. + */ + if (info->tty->termios->c_cflag & CBAUD) + uart_set_mctrl(port, TIOCM_RTS | TIOCM_DTR); + } + + info->flags |= UIF_INITIALIZED; + + clear_bit(TTY_IO_ERROR, &info->tty->flags); + } + + if (retval && capable(CAP_SYS_ADMIN)) + retval = 0; + + return retval; +} + +/* + * This routine will shutdown a serial port; interrupts are disabled, and + * DTR is dropped if the hangup on close termio flag is on. Calls to + * uart_shutdown are serialised by the per-port semaphore. + */ +static void uart_shutdown(struct uart_state *state) +{ + struct uart_info *info = state->info; + struct uart_port *port = state->port; + + if (!(info->flags & UIF_INITIALIZED)) + return; + + /* + * Turn off DTR and RTS early. + */ + if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) + uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); + + /* + * clear delta_msr_wait queue to avoid mem leaks: we may free + * the irq here so the queue might never be woken up. Note + * that we won't end up waiting on delta_msr_wait again since + * any outstanding file descriptors should be pointing at + * hung_up_tty_fops now. + */ + wake_up_interruptible(&info->delta_msr_wait); + + /* + * Free the IRQ and disable the port. + */ + port->ops->shutdown(port); + + /* + * Ensure that the IRQ handler isn't running on another CPU. + */ + synchronize_irq(port->irq); + + /* + * Free the transmit buffer page. + */ + if (info->xmit.buf) { + free_page((unsigned long)info->xmit.buf); + info->xmit.buf = NULL; + info->tmpbuf = NULL; + } + + /* + * kill off our tasklet + */ + tasklet_kill(&info->tlet); + if (info->tty) + set_bit(TTY_IO_ERROR, &info->tty->flags); + + info->flags &= ~UIF_INITIALIZED; +} + +/** + * uart_update_timeout - update per-port FIFO timeout. + * @port: uart_port structure describing the port. + * @cflag: termios cflag value + * @quot: uart clock divisor quotient + * + * Set the port FIFO timeout value. The @cflag value should + * reflect the actual hardware settings. + */ +void +uart_update_timeout(struct uart_port *port, unsigned int cflag, + unsigned int baud) +{ + unsigned int bits; + + /* byte size and parity */ + switch (cflag & CSIZE) { + case CS5: + bits = 7; + break; + case CS6: + bits = 8; + break; + case CS7: + bits = 9; + break; + default: + bits = 10; + break; // CS8 + } + + if (cflag & CSTOPB) + bits++; + if (cflag & PARENB) + bits++; + + /* + * The total number of bits to be transmitted in the fifo. + */ + bits = bits * port->fifosize; + + /* + * Figure the timeout to send the above number of bits. + * Add .02 seconds of slop + */ + port->timeout = (HZ * bits) / baud + HZ/50; +} + +EXPORT_SYMBOL(uart_update_timeout); + +/** + * uart_get_baud_rate - return baud rate for a particular port + * @port: uart_port structure describing the port in question. + * @termios: desired termios settings. + * @old: old termios (or NULL) + * @min: minimum acceptable baud rate + * @max: maximum acceptable baud rate + * + * Decode the termios structure into a numeric baud rate, + * taking account of the magic 38400 baud rate (with spd_* + * flags), and mapping the %B0 rate to 9600 baud. + * + * If the new baud rate is invalid, try the old termios setting. + * If it's still invalid, we try 9600 baud. + * + * Update the @termios structure to reflect the baud rate + * we're actually going to be using. + */ +unsigned int +uart_get_baud_rate(struct uart_port *port, struct termios *termios, + struct termios *old, unsigned int min, unsigned int max) +{ + unsigned int try, baud, altbaud = 38400; + unsigned int flags = port->flags & UPF_SPD_MASK; + + if (flags == UPF_SPD_HI) + altbaud = 57600; + if (flags == UPF_SPD_VHI) + altbaud = 115200; + if (flags == UPF_SPD_SHI) + altbaud = 230400; + if (flags == UPF_SPD_WARP) + altbaud = 460800; + + for (try = 0; try < 2; try++) { + baud = tty_termios_baud_rate(termios); + + /* + * The spd_hi, spd_vhi, spd_shi, spd_warp kludge... + * Die! Die! Die! + */ + if (baud == 38400) + baud = altbaud; + + /* + * Special case: B0 rate. + */ + if (baud == 0) + baud = 9600; + + if (baud >= min && baud <= max) + return baud; + + /* + * Oops, the quotient was zero. Try again with + * the old baud rate if possible. + */ + termios->c_cflag &= ~CBAUD; + if (old) { + termios->c_cflag |= old->c_cflag & CBAUD; + old = NULL; + continue; + } + + /* + * As a last resort, if the quotient is zero, + * default to 9600 bps + */ + termios->c_cflag |= B9600; + } + + return 0; +} + +EXPORT_SYMBOL(uart_get_baud_rate); + +/** + * uart_get_divisor - return uart clock divisor + * @port: uart_port structure describing the port. + * @baud: desired baud rate + * + * Calculate the uart clock divisor for the port. + */ +unsigned int +uart_get_divisor(struct uart_port *port, unsigned int baud) +{ + unsigned int quot; + + /* + * Old custom speed handling. + */ + if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) + quot = port->custom_divisor; + else + quot = port->uartclk / (16 * baud); + + return quot; +} + +EXPORT_SYMBOL(uart_get_divisor); + +static void +uart_change_speed(struct uart_state *state, struct termios *old_termios) +{ + struct tty_struct *tty = state->info->tty; + struct uart_port *port = state->port; + struct termios *termios; + + /* + * If we have no tty, termios, or the port does not exist, + * then we can't set the parameters for this port. + */ + if (!tty || !tty->termios || port->type == PORT_UNKNOWN) + return; + + termios = tty->termios; + + /* + * Set flags based on termios cflag + */ + if (termios->c_cflag & CRTSCTS) + state->info->flags |= UIF_CTS_FLOW; + else + state->info->flags &= ~UIF_CTS_FLOW; + + if (termios->c_cflag & CLOCAL) + state->info->flags &= ~UIF_CHECK_CD; + else + state->info->flags |= UIF_CHECK_CD; + + port->ops->set_termios(port, termios, old_termios); +} + +static inline void +__uart_put_char(struct uart_port *port, struct circ_buf *circ, unsigned char c) +{ + unsigned long flags; + + if (!circ->buf) + return; + + spin_lock_irqsave(&port->lock, flags); + if (uart_circ_chars_free(circ) != 0) { + circ->buf[circ->head] = c; + circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1); + } + spin_unlock_irqrestore(&port->lock, flags); +} + +static inline int +__uart_user_write(struct uart_port *port, struct circ_buf *circ, + const unsigned char *buf, int count) +{ + unsigned long flags; + int c, ret = 0; + + if (down_interruptible(&port->info->tmpbuf_sem)) + return -EINTR; + + while (1) { + int c1; + c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); + if (count < c) + c = count; + if (c <= 0) + break; + + c -= copy_from_user(port->info->tmpbuf, buf, c); + if (!c) { + if (!ret) + ret = -EFAULT; + break; + } + spin_lock_irqsave(&port->lock, flags); + c1 = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); + if (c1 < c) + c = c1; + memcpy(circ->buf + circ->head, port->info->tmpbuf, c); + circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1); + spin_unlock_irqrestore(&port->lock, flags); + buf += c; + count -= c; + ret += c; + } + up(&port->info->tmpbuf_sem); + + return ret; +} + +static inline int +__uart_kern_write(struct uart_port *port, struct circ_buf *circ, + const unsigned char *buf, int count) +{ + unsigned long flags; + int c, ret = 0; + + spin_lock_irqsave(&port->lock, flags); + while (1) { + c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE); + if (count < c) + c = count; + if (c <= 0) + break; + memcpy(circ->buf + circ->head, buf, c); + circ->head = (circ->head + c) & (UART_XMIT_SIZE - 1); + buf += c; + count -= c; + ret += c; + } + spin_unlock_irqrestore(&port->lock, flags); + + return ret; +} + +static void uart_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct uart_state *state = tty->driver_data; + + if (tty) + __uart_put_char(state->port, &state->info->xmit, ch); +} + +static void uart_flush_chars(struct tty_struct *tty) +{ + uart_start(tty); +} + +static int +uart_write(struct tty_struct *tty, int from_user, const unsigned char * buf, + int count) +{ + struct uart_state *state = tty->driver_data; + int ret; + + if (!tty || !state->info->xmit.buf) + return 0; + + if (from_user) + ret = __uart_user_write(state->port, &state->info->xmit, buf, count); + else + ret = __uart_kern_write(state->port, &state->info->xmit, buf, count); + + uart_start(tty); + return ret; +} + +static int uart_write_room(struct tty_struct *tty) +{ + struct uart_state *state = tty->driver_data; + + return uart_circ_chars_free(&state->info->xmit); +} + +static int uart_chars_in_buffer(struct tty_struct *tty) +{ + struct uart_state *state = tty->driver_data; + + return uart_circ_chars_pending(&state->info->xmit); +} + +static void uart_flush_buffer(struct tty_struct *tty) +{ + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; + unsigned long flags; + + DPRINTK("uart_flush_buffer(%d) called\n", tty->index); + + spin_lock_irqsave(&port->lock, flags); + uart_circ_clear(&state->info->xmit); + spin_unlock_irqrestore(&port->lock, flags); + wake_up_interruptible(&tty->write_wait); + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); +} + +/* + * This function is used to send a high-priority XON/XOFF character to + * the device + */ +static void uart_send_xchar(struct tty_struct *tty, char ch) +{ + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; + unsigned long flags; + + if (port->ops->send_xchar) + port->ops->send_xchar(port, ch); + else { + port->x_char = ch; + if (ch) { + spin_lock_irqsave(&port->lock, flags); + port->ops->start_tx(port, 0); + spin_unlock_irqrestore(&port->lock, flags); + } + } +} + +static void uart_throttle(struct tty_struct *tty) +{ + struct uart_state *state = tty->driver_data; + + if (I_IXOFF(tty)) + uart_send_xchar(tty, STOP_CHAR(tty)); + + if (tty->termios->c_cflag & CRTSCTS) + uart_clear_mctrl(state->port, TIOCM_RTS); +} + +static void uart_unthrottle(struct tty_struct *tty) +{ + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; + + if (I_IXOFF(tty)) { + if (port->x_char) + port->x_char = 0; + else + uart_send_xchar(tty, START_CHAR(tty)); + } + + if (tty->termios->c_cflag & CRTSCTS) + uart_set_mctrl(port, TIOCM_RTS); +} + +static int uart_get_info(struct uart_state *state, struct serial_struct *retinfo) +{ + struct uart_port *port = state->port; + struct serial_struct tmp; + + memset(&tmp, 0, sizeof(tmp)); + tmp.type = port->type; + tmp.line = port->line; + tmp.port = port->iobase; + if (HIGH_BITS_OFFSET) + tmp.port_high = (long) port->iobase >> HIGH_BITS_OFFSET; + tmp.irq = port->irq; + tmp.flags = port->flags; + tmp.xmit_fifo_size = port->fifosize; + tmp.baud_base = port->uartclk / 16; + tmp.close_delay = state->close_delay; + tmp.closing_wait = state->closing_wait; + tmp.custom_divisor = port->custom_divisor; + tmp.hub6 = port->hub6; + tmp.io_type = port->iotype; + tmp.iomem_reg_shift = port->regshift; + tmp.iomem_base = (void *)port->mapbase; + + if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) + return -EFAULT; + return 0; +} + +static int +uart_set_info(struct uart_state *state, struct serial_struct *newinfo) +{ + struct serial_struct new_serial; + struct uart_port *port = state->port; + unsigned long new_port; + unsigned int change_irq, change_port, old_flags; + unsigned int old_custom_divisor; + int retval = 0; + + if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) + return -EFAULT; + + new_port = new_serial.port; + if (HIGH_BITS_OFFSET) + new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET; + + new_serial.irq = irq_canonicalize(new_serial.irq); + + /* + * This semaphore protects state->count. It is also + * very useful to prevent opens. Also, take the + * port configuration semaphore to make sure that a + * module insertion/removal doesn't change anything + * under us. + */ + down(&state->sem); + + change_irq = new_serial.irq != port->irq; + + /* + * Since changing the 'type' of the port changes its resource + * allocations, we should treat type changes the same as + * IO port changes. + */ + change_port = new_port != port->iobase || + (unsigned long)new_serial.iomem_base != port->mapbase || + new_serial.hub6 != port->hub6 || + new_serial.io_type != port->iotype || + new_serial.iomem_reg_shift != port->regshift || + new_serial.type != port->type; + + old_flags = port->flags; + old_custom_divisor = port->custom_divisor; + + if (!capable(CAP_SYS_ADMIN)) { + retval = -EPERM; + if (change_irq || change_port || + (new_serial.baud_base != port->uartclk / 16) || + (new_serial.close_delay != state->close_delay) || + (new_serial.closing_wait != state->closing_wait) || + (new_serial.xmit_fifo_size != port->fifosize) || + (((new_serial.flags ^ old_flags) & ~UPF_USR_MASK) != 0)) + goto exit; + port->flags = ((port->flags & ~UPF_USR_MASK) | + (new_serial.flags & UPF_USR_MASK)); + port->custom_divisor = new_serial.custom_divisor; + goto check_and_exit; + } + + /* + * Ask the low level driver to verify the settings. + */ + if (port->ops->verify_port) + retval = port->ops->verify_port(port, &new_serial); + + if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) || + (new_serial.baud_base < 9600)) + retval = -EINVAL; + + if (retval) + goto exit; + + if (change_port || change_irq) { + retval = -EBUSY; + + /* + * Make sure that we are the sole user of this port. + */ + if (uart_users(state) > 1) + goto exit; + + /* + * We need to shutdown the serial port at the old + * port/type/irq combination. + */ + uart_shutdown(state); + } + + if (change_port) { + unsigned long old_iobase, old_mapbase; + unsigned int old_type, old_iotype, old_hub6, old_shift; + + old_iobase = port->iobase; + old_mapbase = port->mapbase; + old_type = port->type; + old_hub6 = port->hub6; + old_iotype = port->iotype; + old_shift = port->regshift; + + /* + * Free and release old regions + */ + if (old_type != PORT_UNKNOWN) + port->ops->release_port(port); + + port->iobase = new_port; + port->type = new_serial.type; + port->hub6 = new_serial.hub6; + port->iotype = new_serial.io_type; + port->regshift = new_serial.iomem_reg_shift; + port->mapbase = (unsigned long)new_serial.iomem_base; + + /* + * Claim and map the new regions + */ + if (port->type != PORT_UNKNOWN) { + retval = port->ops->request_port(port); + } else { + /* Always success - Jean II */ + retval = 0; + } + + /* + * If we fail to request resources for the + * new port, try to restore the old settings. + */ + if (retval && old_type != PORT_UNKNOWN) { + port->iobase = old_iobase; + port->type = old_type; + port->hub6 = old_hub6; + port->iotype = old_iotype; + port->regshift = old_shift; + port->mapbase = old_mapbase; + retval = port->ops->request_port(port); + /* + * If we failed to restore the old settings, + * we fail like this. + */ + if (retval) + port->type = PORT_UNKNOWN; + + /* + * We failed anyway. + */ + retval = -EBUSY; + } + } + + port->irq = new_serial.irq; + port->uartclk = new_serial.baud_base * 16; + port->flags = (port->flags & ~UPF_CHANGE_MASK) | + (new_serial.flags & UPF_CHANGE_MASK); + port->custom_divisor = new_serial.custom_divisor; + state->close_delay = new_serial.close_delay * HZ / 100; + state->closing_wait = new_serial.closing_wait * HZ / 100; + port->fifosize = new_serial.xmit_fifo_size; + if (state->info->tty) + state->info->tty->low_latency = + (port->flags & UPF_LOW_LATENCY) ? 1 : 0; + + check_and_exit: + retval = 0; + if (port->type == PORT_UNKNOWN) + goto exit; + if (state->info->flags & UIF_INITIALIZED) { + if (((old_flags ^ port->flags) & UPF_SPD_MASK) || + old_custom_divisor != port->custom_divisor) { + /* If they're setting up a custom divisor or speed, + * instead of clearing it, then bitch about it. No + * need to rate-limit; it's CAP_SYS_ADMIN only. */ + if (port->flags & UPF_SPD_MASK) { + printk(KERN_NOTICE "%s sets custom speed on %s%d. This is deprecated.\n", + current->comm, state->info->tty->driver->name, + state->port->line); + } + uart_change_speed(state, NULL); + } + } else + retval = uart_startup(state, 1); + exit: + up(&state->sem); + return retval; +} + + +/* + * uart_get_lsr_info - get line status register info. + * Note: uart_ioctl protects us against hangups. + */ +static int uart_get_lsr_info(struct uart_state *state, unsigned int *value) +{ + struct uart_port *port = state->port; + unsigned int result; + + result = port->ops->tx_empty(port); + + /* + * If we're about to load something into the transmit + * register, we'll pretend the transmitter isn't empty to + * avoid a race condition (depending on when the transmit + * interrupt happens). + */ + if (port->x_char || + ((uart_circ_chars_pending(&state->info->xmit) > 0) && + !state->info->tty->stopped && !state->info->tty->hw_stopped)) + result &= ~TIOCSER_TEMT; + + return put_user(result, value); +} + +static int uart_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; + int result = -EIO; + + down(&state->sem); + if ((!file || !tty_hung_up_p(file)) && + !(tty->flags & (1 << TTY_IO_ERROR))) { + result = port->mctrl; + result |= port->ops->get_mctrl(port); + } + up(&state->sem); + + return result; +} + +static int +uart_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; + int ret = -EIO; + + down(&state->sem); + if ((!file || !tty_hung_up_p(file)) && + !(tty->flags & (1 << TTY_IO_ERROR))) { + uart_update_mctrl(port, set, clear); + ret = 0; + } + up(&state->sem); + return ret; +} + +static void uart_break_ctl(struct tty_struct *tty, int break_state) +{ + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; + + BUG_ON(!kernel_locked()); + + down(&state->sem); + + if (port->type != PORT_UNKNOWN) + port->ops->break_ctl(port, break_state); + + up(&state->sem); +} + +static int uart_do_autoconfig(struct uart_state *state) +{ + struct uart_port *port = state->port; + int flags, ret; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + /* + * Take the per-port semaphore. This prevents count from + * changing, and hence any extra opens of the port while + * we're auto-configuring. + */ + if (down_interruptible(&state->sem)) + return -ERESTARTSYS; + + ret = -EBUSY; + if (uart_users(state) == 1) { + uart_shutdown(state); + + /* + * If we already have a port type configured, + * we must release its resources. + */ + if (port->type != PORT_UNKNOWN) + port->ops->release_port(port); + + flags = UART_CONFIG_TYPE; + if (port->flags & UPF_AUTO_IRQ) + flags |= UART_CONFIG_IRQ; + + /* + * This will claim the ports resources if + * a port is found. + */ + port->ops->config_port(port, flags); + + ret = uart_startup(state, 1); + } + up(&state->sem); + return ret; +} + +/* + * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change + * - mask passed in arg for lines of interest + * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) + * Caller should use TIOCGICOUNT to see which one it was + */ +static int +uart_wait_modem_status(struct uart_state *state, unsigned long arg) +{ + struct uart_port *port = state->port; + DECLARE_WAITQUEUE(wait, current); + struct uart_icount cprev, cnow; + int ret; + + /* + * note the counters on entry + */ + spin_lock_irq(&port->lock); + memcpy(&cprev, &port->icount, sizeof(struct uart_icount)); + + /* + * Force modem status interrupts on + */ + port->ops->enable_ms(port); + spin_unlock_irq(&port->lock); + + add_wait_queue(&state->info->delta_msr_wait, &wait); + for (;;) { + spin_lock_irq(&port->lock); + memcpy(&cnow, &port->icount, sizeof(struct uart_icount)); + spin_unlock_irq(&port->lock); + + set_current_state(TASK_INTERRUPTIBLE); + + if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts))) { + ret = 0; + break; + } + + schedule(); + + /* see if a signal did it */ + if (signal_pending(current)) { + ret = -ERESTARTSYS; + break; + } + + cprev = cnow; + } + + current->state = TASK_RUNNING; + remove_wait_queue(&state->info->delta_msr_wait, &wait); + + return ret; +} + +/* + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. + */ +static int +uart_get_count(struct uart_state *state, struct serial_icounter_struct *icnt) +{ + struct serial_icounter_struct icount; + struct uart_icount cnow; + struct uart_port *port = state->port; + + spin_lock_irq(&port->lock); + memcpy(&cnow, &port->icount, sizeof(struct uart_icount)); + spin_unlock_irq(&port->lock); + + icount.cts = cnow.cts; + icount.dsr = cnow.dsr; + icount.rng = cnow.rng; + icount.dcd = cnow.dcd; + icount.rx = cnow.rx; + icount.tx = cnow.tx; + icount.frame = cnow.frame; + icount.overrun = cnow.overrun; + icount.parity = cnow.parity; + icount.brk = cnow.brk; + icount.buf_overrun = cnow.buf_overrun; + + return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0; +} + +/* + * Called via sys_ioctl under the BKL. We can use spin_lock_irq() here. + */ +static int +uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + struct uart_state *state = tty->driver_data; + int ret = -ENOIOCTLCMD; + + BUG_ON(!kernel_locked()); + + /* + * These ioctls don't rely on the hardware to be present. + */ + switch (cmd) { + case TIOCGSERIAL: + ret = uart_get_info(state, (struct serial_struct *)arg); + break; + + case TIOCSSERIAL: + ret = uart_set_info(state, (struct serial_struct *)arg); + break; + + case TIOCSERCONFIG: + ret = uart_do_autoconfig(state); + break; + + case TIOCSERGWILD: /* obsolete */ + case TIOCSERSWILD: /* obsolete */ + ret = 0; + break; + } + + if (ret != -ENOIOCTLCMD) + goto out; + + if (tty->flags & (1 << TTY_IO_ERROR)) { + ret = -EIO; + goto out; + } + + /* + * The following should only be used when hardware is present. + */ + switch (cmd) { + case TIOCMIWAIT: + ret = uart_wait_modem_status(state, arg); + break; + + case TIOCGICOUNT: + ret = uart_get_count(state, (struct serial_icounter_struct *)arg); + break; + } + + if (ret != -ENOIOCTLCMD) + goto out; + + down(&state->sem); + + if (tty_hung_up_p(filp)) { + ret = -EIO; + goto out_up; + } + + /* + * All these rely on hardware being present and need to be + * protected against the tty being hung up. + */ + switch (cmd) { + case TIOCSERGETLSR: /* Get line status register */ + ret = uart_get_lsr_info(state, (unsigned int *)arg); + break; + + default: { + struct uart_port *port = state->port; + if (port->ops->ioctl) + ret = port->ops->ioctl(port, cmd, arg); + break; + } + } + out_up: + up(&state->sem); + out: + return ret; +} + +static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios) +{ + struct uart_state *state = tty->driver_data; + unsigned long flags; + unsigned int cflag = tty->termios->c_cflag; + + BUG_ON(!kernel_locked()); + + /* + * These are the bits that are used to setup various + * flags in the low level driver. + */ +#define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) + + if ((cflag ^ old_termios->c_cflag) == 0 && + RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0) + return; + + uart_change_speed(state, old_termios); + + /* Handle transition to B0 status */ + if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) + uart_clear_mctrl(state->port, TIOCM_RTS | TIOCM_DTR); + + /* Handle transition away from B0 status */ + if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { + unsigned int mask = TIOCM_DTR; + if (!(cflag & CRTSCTS) || + !test_bit(TTY_THROTTLED, &tty->flags)) + mask |= TIOCM_RTS; + uart_set_mctrl(state->port, mask); + } + + /* Handle turning off CRTSCTS */ + if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) { + spin_lock_irqsave(&state->port->lock, flags); + tty->hw_stopped = 0; + __uart_start(tty); + spin_unlock_irqrestore(&state->port->lock, flags); + } + +#if 0 + /* + * No need to wake up processes in open wait, since they + * sample the CLOCAL flag once, and don't recheck it. + * XXX It's not clear whether the current behavior is correct + * or not. Hence, this may change..... + */ + if (!(old_termios->c_cflag & CLOCAL) && + (tty->termios->c_cflag & CLOCAL)) + wake_up_interruptible(&state->info->open_wait); +#endif +} + +/* + * In 2.4.5, calls to this will be serialized via the BKL in + * linux/drivers/char/tty_io.c:tty_release() + * linux/drivers/char/tty_io.c:do_tty_handup() + */ +static void uart_close(struct tty_struct *tty, struct file *filp) +{ + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; + + BUG_ON(!kernel_locked()); + DPRINTK("uart_close(%d) called\n", port->line); + + down(&state->sem); + + if (tty_hung_up_p(filp)) + goto done; + + if ((tty->count == 1) && (state->count != 1)) { + /* + * Uh, oh. tty->count is 1, which means that the tty + * structure will be freed. state->count should always + * be one in these conditions. If it's greater than + * one, we've got real problems, since it means the + * serial port won't be shutdown. + */ + printk("uart_close: bad serial port count; tty->count is 1, " + "state->count is %d\n", state->count); + state->count = 1; + } + if (--state->count < 0) { + printk("rs_close: bad serial port count for %s: %d\n", + tty->name, state->count); + state->count = 0; + } + if (state->count) + goto done; + + /* + * Now we wait for the transmit buffer to clear; and we notify + * the line discipline to only process XON/XOFF characters by + * setting tty->closing. + */ + tty->closing = 1; + + if (state->closing_wait != USF_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, state->closing_wait); + + /* + * At this point, we stop accepting input. To do this, we + * disable the receive line status interrupts. + */ + if (state->info->flags & UIF_INITIALIZED) { + unsigned long flags; + spin_lock_irqsave(&port->lock, flags); + port->ops->stop_rx(port); + spin_unlock_irqrestore(&port->lock, flags); + /* + * Before we drop DTR, make sure the UART transmitter + * has completely drained; this is especially + * important if there is a transmit FIFO! + */ + uart_wait_until_sent(tty, port->timeout); + } + + uart_shutdown(state); + uart_flush_buffer(tty); + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + tty->closing = 0; + state->info->tty = NULL; + + if (state->info->blocked_open) { + if (state->close_delay) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(state->close_delay); + set_current_state(TASK_RUNNING); + } + } else if (!uart_console(port)) { + uart_change_pm(state, 3); + } + + /* + * Wake up anyone trying to open this port. + */ + state->info->flags &= ~UIF_NORMAL_ACTIVE; + wake_up_interruptible(&state->info->open_wait); + + done: + up(&state->sem); +} + +static void uart_wait_until_sent(struct tty_struct *tty, int timeout) +{ + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; + unsigned long char_time, expire; + + BUG_ON(!kernel_locked()); + + if (port->type == PORT_UNKNOWN || port->fifosize == 0) + return; + + /* + * Set the check interval to be 1/5 of the estimated time to + * send a single character, and make it at least 1. The check + * interval should also be less than the timeout. + * + * Note: we have to use pretty tight timings here to satisfy + * the NIST-PCTS. + */ + char_time = (port->timeout - HZ/50) / port->fifosize; + char_time = char_time / 5; + if (char_time == 0) + char_time = 1; + if (timeout && timeout < char_time) + char_time = timeout; + + /* + * If the transmitter hasn't cleared in twice the approximate + * amount of time to send the entire FIFO, it probably won't + * ever clear. This assumes the UART isn't doing flow + * control, which is currently the case. Hence, if it ever + * takes longer than port->timeout, this is probably due to a + * UART bug of some kind. So, we clamp the timeout parameter at + * 2*port->timeout. + */ + if (timeout == 0 || timeout > 2 * port->timeout) + timeout = 2 * port->timeout; + + expire = jiffies + timeout; + + DPRINTK("uart_wait_until_sent(%d), jiffies=%lu, expire=%lu...\n", + port->line, jiffies, expire); + + /* + * Check whether the transmitter is empty every 'char_time'. + * 'timeout' / 'expire' give us the maximum amount of time + * we wait. + */ + while (!port->ops->tx_empty(port)) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(char_time); + if (signal_pending(current)) + break; + if (time_after(jiffies, expire)) + break; + } + set_current_state(TASK_RUNNING); /* might not be needed */ +} + +/* + * This is called with the BKL held in + * linux/drivers/char/tty_io.c:do_tty_hangup() + * We're called from the eventd thread, so we can sleep for + * a _short_ time only. + */ +static void uart_hangup(struct tty_struct *tty) +{ + struct uart_state *state = tty->driver_data; + + BUG_ON(!kernel_locked()); + DPRINTK("uart_hangup(%d)\n", state->port->line); + + down(&state->sem); + if (state->info && state->info->flags & UIF_NORMAL_ACTIVE) { + uart_flush_buffer(tty); + uart_shutdown(state); + state->count = 0; + state->info->flags &= ~UIF_NORMAL_ACTIVE; + state->info->tty = NULL; + wake_up_interruptible(&state->info->open_wait); + wake_up_interruptible(&state->info->delta_msr_wait); + } + up(&state->sem); +} + +/* + * Copy across the serial console cflag setting into the termios settings + * for the initial open of the port. This allows continuity between the + * kernel settings, and the settings init adopts when it opens the port + * for the first time. + */ +static void uart_update_termios(struct uart_state *state) +{ + struct tty_struct *tty = state->info->tty; + struct uart_port *port = state->port; + + if (uart_console(port) && port->cons->cflag) { + tty->termios->c_cflag = port->cons->cflag; + port->cons->cflag = 0; + } + + /* + * If the device failed to grab its irq resources, + * or some other error occurred, don't try to talk + * to the port hardware. + */ + if (!(tty->flags & (1 << TTY_IO_ERROR))) { + /* + * Make termios settings take effect. + */ + uart_change_speed(state, NULL); + + /* + * And finally enable the RTS and DTR signals. + */ + if (tty->termios->c_cflag & CBAUD) + uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS); + } +} + +/* + * Block the open until the port is ready. We must be called with + * the per-port semaphore held. + */ +static int +uart_block_til_ready(struct file *filp, struct uart_state *state) +{ + DECLARE_WAITQUEUE(wait, current); + struct uart_info *info = state->info; + struct uart_port *port = state->port; + + info->blocked_open++; + state->count--; + + add_wait_queue(&info->open_wait, &wait); + while (1) { + set_current_state(TASK_INTERRUPTIBLE); + + /* + * If we have been hung up, tell userspace/restart open. + */ + if (tty_hung_up_p(filp) || info->tty == NULL) + break; + + /* + * If the port has been closed, tell userspace/restart open. + */ + if (!(info->flags & UIF_INITIALIZED)) + break; + + /* + * If non-blocking mode is set, or CLOCAL mode is set, + * we don't want to wait for the modem status lines to + * indicate that the port is ready. + * + * Also, if the port is not enabled/configured, we want + * to allow the open to succeed here. Note that we will + * have set TTY_IO_ERROR for a non-existant port. + */ + if ((filp->f_flags & O_NONBLOCK) || + (info->tty->termios->c_cflag & CLOCAL) || + (info->tty->flags & (1 << TTY_IO_ERROR))) { + break; + } + + /* + * Set DTR to allow modem to know we're waiting. Do + * not set RTS here - we want to make sure we catch + * the data from the modem. + */ + if (info->tty->termios->c_cflag & CBAUD) + uart_set_mctrl(port, TIOCM_DTR); + + /* + * and wait for the carrier to indicate that the + * modem is ready for us. + */ + if (port->ops->get_mctrl(port) & TIOCM_CAR) + break; + + up(&state->sem); + schedule(); + down(&state->sem); + + if (signal_pending(current)) + break; + } + set_current_state(TASK_RUNNING); + remove_wait_queue(&info->open_wait, &wait); + + state->count++; + info->blocked_open--; + + if (signal_pending(current)) + return -ERESTARTSYS; + + if (!info->tty || tty_hung_up_p(filp)) + return -EAGAIN; + + return 0; +} + +static struct uart_state *uart_get(struct uart_driver *drv, int line) +{ + struct uart_state *state; + + down(&port_sem); + state = drv->state + line; + if (down_interruptible(&state->sem)) { + state = ERR_PTR(-ERESTARTSYS); + goto out; + } + + state->count++; + if (!state->port) { + state->count--; + up(&state->sem); + state = ERR_PTR(-ENXIO); + goto out; + } + + if (!state->info) { + state->info = kmalloc(sizeof(struct uart_info), GFP_KERNEL); + if (state->info) { + memset(state->info, 0, sizeof(struct uart_info)); + init_waitqueue_head(&state->info->open_wait); + init_waitqueue_head(&state->info->delta_msr_wait); + + /* + * Link the info into the other structures. + */ + state->port->info = state->info; + + tasklet_init(&state->info->tlet, uart_tasklet_action, + (unsigned long)state); + } else { + state->count--; + up(&state->sem); + state = ERR_PTR(-ENOMEM); + } + } + + out: + up(&port_sem); + return state; +} + +/* + * In 2.4.5, calls to uart_open are serialised by the BKL in + * linux/fs/devices.c:chrdev_open() + * Note that if this fails, then uart_close() _will_ be called. + * + * In time, we want to scrap the "opening nonpresent ports" + * behaviour and implement an alternative way for setserial + * to set base addresses/ports/types. This will allow us to + * get rid of a certain amount of extra tests. + */ +static int uart_open(struct tty_struct *tty, struct file *filp) +{ + struct uart_driver *drv = (struct uart_driver *)tty->driver->driver_state; + struct uart_state *state; + int retval, line = tty->index; + + BUG_ON(!kernel_locked()); + DPRINTK("uart_open(%d) called\n", line); + + /* + * tty->driver->num won't change, so we won't fail here with + * tty->driver_data set to something non-NULL (and therefore + * we won't get caught by uart_close()). + */ + retval = -ENODEV; + if (line >= tty->driver->num) + goto fail; + + /* + * We take the semaphore inside uart_get to guarantee that we won't + * be re-entered while allocating the info structure, or while we + * request any IRQs that the driver may need. This also has the nice + * side-effect that it delays the action of uart_hangup, so we can + * guarantee that info->tty will always contain something reasonable. + */ + state = uart_get(drv, line); + if (IS_ERR(state)) { + retval = PTR_ERR(state); + goto fail; + } + + /* + * Once we set tty->driver_data here, we are guaranteed that + * uart_close() will decrement the driver module use count. + * Any failures from here onwards should not touch the count. + */ + tty->driver_data = state; + tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0; + tty->alt_speed = 0; + state->info->tty = tty; + + /* + * If the port is in the middle of closing, bail out now. + */ + if (tty_hung_up_p(filp)) { + retval = -EAGAIN; + state->count--; + up(&state->sem); + goto fail; + } + + /* + * Make sure the device is in D0 state. + */ + if (state->count == 1) + uart_change_pm(state, 0); + + /* + * Start up the serial port. + */ + retval = uart_startup(state, 0); + + /* + * If we succeeded, wait until the port is ready. + */ + if (retval == 0) + retval = uart_block_til_ready(filp, state); + up(&state->sem); + + /* + * If this is the first open to succeed, adjust things to suit. + */ + if (retval == 0 && !(state->info->flags & UIF_NORMAL_ACTIVE)) { + state->info->flags |= UIF_NORMAL_ACTIVE; + + uart_update_termios(state); + } + + fail: + return retval; +} + +static const char *uart_type(struct uart_port *port) +{ + const char *str = NULL; + + if (port->ops->type) + str = port->ops->type(port); + + if (!str) + str = "unknown"; + + return str; +} + +#ifdef CONFIG_PROC_FS + +static int uart_line_info(char *buf, struct uart_driver *drv, int i) +{ + struct uart_state *state = drv->state + i; + struct uart_port *port = state->port; + char stat_buf[32]; + unsigned int status; + int ret; + + if (!port) + return 0; + + ret = sprintf(buf, "%d: uart:%s port:%08X irq:%d", + port->line, uart_type(port), + port->iobase, port->irq); + + if (port->type == PORT_UNKNOWN) { + strcat(buf, "\n"); + return ret + 1; + } + + if(capable(CAP_SYS_ADMIN)) + { + status = port->ops->get_mctrl(port); + + ret += sprintf(buf + ret, " tx:%d rx:%d", + port->icount.tx, port->icount.rx); + if (port->icount.frame) + ret += sprintf(buf + ret, " fe:%d", + port->icount.frame); + if (port->icount.parity) + ret += sprintf(buf + ret, " pe:%d", + port->icount.parity); + if (port->icount.brk) + ret += sprintf(buf + ret, " brk:%d", + port->icount.brk); + if (port->icount.overrun) + ret += sprintf(buf + ret, " oe:%d", + port->icount.overrun); + +#define INFOBIT(bit,str) \ + if (port->mctrl & (bit)) \ + strncat(stat_buf, (str), sizeof(stat_buf) - \ + strlen(stat_buf) - 2) +#define STATBIT(bit,str) \ + if (status & (bit)) \ + strncat(stat_buf, (str), sizeof(stat_buf) - \ + strlen(stat_buf) - 2) + + stat_buf[0] = '\0'; + stat_buf[1] = '\0'; + INFOBIT(TIOCM_RTS, "|RTS"); + STATBIT(TIOCM_CTS, "|CTS"); + INFOBIT(TIOCM_DTR, "|DTR"); + STATBIT(TIOCM_DSR, "|DSR"); + STATBIT(TIOCM_CAR, "|CD"); + STATBIT(TIOCM_RNG, "|RI"); + if (stat_buf[0]) + stat_buf[0] = ' '; + strcat(stat_buf, "\n"); + + ret += sprintf(buf + ret, stat_buf); + } +#undef STATBIT +#undef INFOBIT + return ret; +} + +static int uart_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + struct tty_driver *ttydrv = data; + struct uart_driver *drv = ttydrv->driver_state; + int i, len = 0, l; + off_t begin = 0; + + len += sprintf(page, "serinfo:1.0 driver%s%s revision:%s\n", + "", "", ""); + for (i = 0; i < drv->nr && len < PAGE_SIZE - 96; i++) { + l = uart_line_info(page + len, drv, i); + len += l; + if (len + begin > off + count) + goto done; + if (len + begin < off) { + begin += len; + len = 0; + } + } + *eof = 1; + done: + if (off >= len + begin) + return 0; + *start = page + (off - begin); + return (count < begin + len - off) ? count : (begin + len - off); +} +#endif + +#ifdef CONFIG_SERIAL_CORE_CONSOLE +/* + * Check whether an invalid uart number has been specified, and + * if so, search for the first available port that does have + * console support. + */ +struct uart_port * __init +uart_get_console(struct uart_port *ports, int nr, struct console *co) +{ + int idx = co->index; + + if (idx < 0 || idx >= nr || (ports[idx].iobase == 0 && + ports[idx].membase == NULL)) + for (idx = 0; idx < nr; idx++) + if (ports[idx].iobase != 0 || + ports[idx].membase != NULL) + break; + + co->index = idx; + + return ports + idx; +} + +/** + * uart_parse_options - Parse serial port baud/parity/bits/flow contro. + * @options: pointer to option string + * @baud: pointer to an 'int' variable for the baud rate. + * @parity: pointer to an 'int' variable for the parity. + * @bits: pointer to an 'int' variable for the number of data bits. + * @flow: pointer to an 'int' variable for the flow control character. + * + * uart_parse_options decodes a string containing the serial console + * options. The format of the string is , + * eg: 115200n8r + */ +void __init +uart_parse_options(char *options, int *baud, int *parity, int *bits, int *flow) +{ + char *s = options; + + *baud = simple_strtoul(s, NULL, 10); + while (*s >= '0' && *s <= '9') + s++; + if (*s) + *parity = *s++; + if (*s) + *bits = *s++ - '0'; + if (*s) + *flow = *s; +} + +struct baud_rates { + unsigned int rate; + unsigned int cflag; +}; + +static struct baud_rates baud_rates[] = { + { 921600, B921600 }, + { 460800, B460800 }, + { 230400, B230400 }, + { 115200, B115200 }, + { 57600, B57600 }, + { 38400, B38400 }, + { 19200, B19200 }, + { 9600, B9600 }, + { 4800, B4800 }, + { 2400, B2400 }, + { 1200, B1200 }, + { 0, B38400 } +}; + +/** + * uart_set_options - setup the serial console parameters + * @port: pointer to the serial ports uart_port structure + * @co: console pointer + * @baud: baud rate + * @parity: parity character - 'n' (none), 'o' (odd), 'e' (even) + * @bits: number of data bits + * @flow: flow control character - 'r' (rts) + */ +int __init +uart_set_options(struct uart_port *port, struct console *co, + int baud, int parity, int bits, int flow) +{ + struct termios termios; + int i; + + memset(&termios, 0, sizeof(struct termios)); + + termios.c_cflag = CREAD | HUPCL | CLOCAL; + + /* + * Construct a cflag setting. + */ + for (i = 0; baud_rates[i].rate; i++) + if (baud_rates[i].rate <= baud) + break; + + termios.c_cflag |= baud_rates[i].cflag; + + if (bits == 7) + termios.c_cflag |= CS7; + else + termios.c_cflag |= CS8; + + switch (parity) { + case 'o': case 'O': + termios.c_cflag |= PARODD; + /*fall through*/ + case 'e': case 'E': + termios.c_cflag |= PARENB; + break; + } + + if (flow == 'r') + termios.c_cflag |= CRTSCTS; + + port->ops->set_termios(port, &termios, NULL); + co->cflag = termios.c_cflag; + + return 0; +} +#endif /* CONFIG_SERIAL_CORE_CONSOLE */ + +static void uart_change_pm(struct uart_state *state, int pm_state) +{ + struct uart_port *port = state->port; + if (port->ops->pm) + port->ops->pm(port, pm_state, state->pm_state); + state->pm_state = pm_state; +} + +int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) +{ + struct uart_state *state = drv->state + port->line; + + down(&state->sem); + + if (state->info && state->info->flags & UIF_INITIALIZED) { + struct uart_ops *ops = port->ops; + + spin_lock_irq(&port->lock); + ops->stop_tx(port, 0); + ops->set_mctrl(port, 0); + ops->stop_rx(port); + spin_unlock_irq(&port->lock); + + /* + * Wait for the transmitter to empty. + */ + while (!ops->tx_empty(port)) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(10*HZ/1000); + } + set_current_state(TASK_RUNNING); + + ops->shutdown(port); + } + + /* + * Disable the console device before suspending. + */ + if (uart_console(port)) + port->cons->flags &= ~CON_ENABLED; + + uart_change_pm(state, 3); + + up(&state->sem); + + return 0; +} + +int uart_resume_port(struct uart_driver *drv, struct uart_port *port) +{ + struct uart_state *state = drv->state + port->line; + + down(&state->sem); + + uart_change_pm(state, 0); + + /* + * Re-enable the console device after suspending. + */ + if (uart_console(port)) { + uart_change_speed(state, NULL); + port->cons->flags |= CON_ENABLED; + } + + if (state->info && state->info->flags & UIF_INITIALIZED) { + struct uart_ops *ops = port->ops; + + ops->set_mctrl(port, 0); + ops->startup(port); + uart_change_speed(state, NULL); + spin_lock_irq(&port->lock); + ops->set_mctrl(port, port->mctrl); + ops->start_tx(port, 0); + spin_unlock_irq(&port->lock); + } + + up(&state->sem); + + return 0; +} + +static inline void +uart_report_port(struct uart_driver *drv, struct uart_port *port) +{ + printk("%s%d", drv->dev_name, port->line); + printk(" at "); + switch (port->iotype) { + case UPIO_PORT: + printk("I/O 0x%x", port->iobase); + break; + case UPIO_HUB6: + printk("I/O 0x%x offset 0x%x", port->iobase, port->hub6); + break; + case UPIO_MEM: + printk("MMIO 0x%lx", port->mapbase); + break; + } + printk(" (irq = %d) is a %s\n", port->irq, uart_type(port)); +} + +static void +uart_configure_port(struct uart_driver *drv, struct uart_state *state, + struct uart_port *port) +{ + unsigned int flags; + + /* + * If there isn't a port here, don't do anything further. + */ + if (!port->iobase && !port->mapbase && !port->membase) + return; + + /* + * Now do the auto configuration stuff. Note that config_port + * is expected to claim the resources and map the port for us. + */ + flags = UART_CONFIG_TYPE; + if (port->flags & UPF_AUTO_IRQ) + flags |= UART_CONFIG_IRQ; + if (port->flags & UPF_BOOT_AUTOCONF) { + port->type = PORT_UNKNOWN; + port->ops->config_port(port, flags); + } + + if (port->type != PORT_UNKNOWN) { + unsigned long flags; + + uart_report_port(drv, port); + + /* + * Ensure that the modem control lines are de-activated. + * We probably don't need a spinlock around this, but + */ + spin_lock_irqsave(&port->lock, flags); + port->ops->set_mctrl(port, 0); + spin_unlock_irqrestore(&port->lock, flags); + + /* + * Power down all ports by default, except the + * console if we have one. + */ + if (!uart_console(port)) + uart_change_pm(state, 3); + } +} + +/* + * This reverses the effects of uart_configure_port, hanging up the + * port before removal. + */ +static void +uart_unconfigure_port(struct uart_driver *drv, struct uart_state *state) +{ + struct uart_port *port = state->port; + struct uart_info *info = state->info; + + if (info && info->tty) + tty_vhangup(info->tty); + + down(&state->sem); + + state->info = NULL; + + /* + * Free the port IO and memory resources, if any. + */ + if (port->type != PORT_UNKNOWN) + port->ops->release_port(port); + + /* + * Indicate that there isn't a port here anymore. + */ + port->type = PORT_UNKNOWN; + + /* + * Kill the tasklet, and free resources. + */ + if (info) { + tasklet_kill(&info->tlet); + kfree(info); + } + + up(&state->sem); +} + +static struct tty_operations uart_ops = { + .open = uart_open, + .close = uart_close, + .write = uart_write, + .put_char = uart_put_char, + .flush_chars = uart_flush_chars, + .write_room = uart_write_room, + .chars_in_buffer= uart_chars_in_buffer, + .flush_buffer = uart_flush_buffer, + .ioctl = uart_ioctl, + .throttle = uart_throttle, + .unthrottle = uart_unthrottle, + .send_xchar = uart_send_xchar, + .set_termios = uart_set_termios, + .stop = uart_stop, + .start = uart_start, + .hangup = uart_hangup, + .break_ctl = uart_break_ctl, + .wait_until_sent= uart_wait_until_sent, +#ifdef CONFIG_PROC_FS + .read_proc = uart_read_proc, +#endif + .tiocmget = uart_tiocmget, + .tiocmset = uart_tiocmset, +}; + +/** + * uart_register_driver - register a driver with the uart core layer + * @drv: low level driver structure + * + * Register a uart driver with the core driver. We in turn register + * with the tty layer, and initialise the core driver per-port state. + * + * We have a proc file in /proc/tty/driver which is named after the + * normal driver. + * + * drv->port should be NULL, and the per-port structures should be + * registered using uart_add_one_port after this call has succeeded. + */ +int uart_register_driver(struct uart_driver *drv) +{ + struct tty_driver *normal = NULL; + int i, retval; + + BUG_ON(drv->state); + + /* + * Maybe we should be using a slab cache for this, especially if + * we have a large number of ports to handle. + */ + drv->state = kmalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL); + retval = -ENOMEM; + if (!drv->state) + goto out; + + memset(drv->state, 0, sizeof(struct uart_state) * drv->nr); + + normal = alloc_tty_driver(drv->nr); + if (!normal) + goto out; + + drv->tty_driver = normal; + + normal->owner = drv->owner; + normal->driver_name = drv->driver_name; + normal->devfs_name = drv->devfs_name; + normal->name = drv->dev_name; + normal->major = drv->major; + normal->minor_start = drv->minor; + normal->type = TTY_DRIVER_TYPE_SERIAL; + normal->subtype = SERIAL_TYPE_NORMAL; + normal->init_termios = tty_std_termios; + normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; + normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; + normal->driver_state = drv; + tty_set_operations(normal, &uart_ops); + + /* + * Initialise the UART state(s). + */ + for (i = 0; i < drv->nr; i++) { + struct uart_state *state = drv->state + i; + + state->close_delay = 5 * HZ / 10; + state->closing_wait = 30 * HZ; + + init_MUTEX(&state->sem); + } + + retval = tty_register_driver(normal); + out: + if (retval < 0) { + put_tty_driver(normal); + kfree(drv->state); + } + return retval; +} + +/** + * uart_unregister_driver - remove a driver from the uart core layer + * @drv: low level driver structure + * + * Remove all references to a driver from the core driver. The low + * level driver must have removed all its ports via the + * uart_remove_one_port() if it registered them with uart_add_one_port(). + * (ie, drv->port == NULL) + */ +void uart_unregister_driver(struct uart_driver *drv) +{ + struct tty_driver *p = drv->tty_driver; + tty_unregister_driver(p); + put_tty_driver(p); + kfree(drv->state); + drv->tty_driver = NULL; +} + +struct tty_driver *uart_console_device(struct console *co, int *index) +{ + struct uart_driver *p = co->data; + *index = co->index; + return p->tty_driver; +} + +/** + * uart_add_one_port - attach a driver-defined port structure + * @drv: pointer to the uart low level driver structure for this port + * @port: uart port structure to use for this port. + * + * This allows the driver to register its own uart_port structure + * with the core driver. The main purpose is to allow the low + * level uart drivers to expand uart_port, rather than having yet + * more levels of structures. + */ +int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) +{ + struct uart_state *state; + int ret = 0; + + BUG_ON(in_interrupt()); + + if (port->line >= drv->nr) + return -EINVAL; + + state = drv->state + port->line; + + down(&port_sem); + if (state->port) { + ret = -EINVAL; + goto out; + } + + state->port = port; + + spin_lock_init(&port->lock); + port->cons = drv->cons; + port->info = state->info; + + uart_configure_port(drv, state, port); + + /* + * Register the port whether it's detected or not. This allows + * setserial to be used to alter this ports parameters. + */ + tty_register_device(drv->tty_driver, port->line, NULL); + + out: + up(&port_sem); + + return ret; +} + +/** + * uart_remove_one_port - detach a driver defined port structure + * @drv: pointer to the uart low level driver structure for this port + * @port: uart port structure for this port + * + * This unhooks (and hangs up) the specified port structure from the + * core driver. No further calls will be made to the low-level code + * for this port. + */ +int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port) +{ + struct uart_state *state = drv->state + port->line; + + BUG_ON(in_interrupt()); + + if (state->port != port) + printk(KERN_ALERT "Removing wrong port: %p != %p\n", + state->port, port); + + down(&port_sem); + + /* + * Remove the devices from devfs + */ + tty_unregister_device(drv->tty_driver, port->line); + + uart_unconfigure_port(drv, state); + state->port = NULL; + up(&port_sem); + + return 0; +} + +/* + * Are the two ports equivalent? + */ +static int uart_match_port(struct uart_port *port1, struct uart_port *port2) +{ + if (port1->iotype != port2->iotype) + return 0; + + switch (port1->iotype) { + case UPIO_PORT: + return (port1->iobase == port2->iobase); + case UPIO_HUB6: + return (port1->iobase == port2->iobase) && + (port1->hub6 == port2->hub6); + case UPIO_MEM: + return (port1->membase == port2->membase); + } + return 0; +} + +/* + * Try to find an unused uart_state slot for a port. + */ +static struct uart_state * +uart_find_match_or_unused(struct uart_driver *drv, struct uart_port *port) +{ + int i; + + /* + * First, find a port entry which matches. Note: if we do + * find a matching entry, and it has a non-zero use count, + * then we can't register the port. + */ + for (i = 0; i < drv->nr; i++) + if (uart_match_port(drv->state[i].port, port)) + return &drv->state[i]; + + /* + * We didn't find a matching entry, so look for the first + * free entry. We look for one which hasn't been previously + * used (indicated by zero iobase). + */ + for (i = 0; i < drv->nr; i++) + if (drv->state[i].port->type == PORT_UNKNOWN && + drv->state[i].port->iobase == 0 && + drv->state[i].count == 0) + return &drv->state[i]; + + /* + * That also failed. Last resort is to find any currently + * entry which doesn't have a real port associated with it. + */ + for (i = 0; i < drv->nr; i++) + if (drv->state[i].port->type == PORT_UNKNOWN && + drv->state[i].count == 0) + return &drv->state[i]; + + return NULL; +} + +/** + * uart_register_port: register uart settings with a port + * @drv: pointer to the uart low level driver structure for this port + * @port: uart port structure describing the port + * + * Register UART settings with the specified low level driver. Detect + * the type of the port if UPF_BOOT_AUTOCONF is set, and detect the + * IRQ if UPF_AUTO_IRQ is set. + * + * We try to pick the same port for the same IO base address, so that + * when a modem is plugged in, unplugged and plugged back in, it gets + * allocated the same port. + * + * Returns negative error, or positive line number. + */ +int uart_register_port(struct uart_driver *drv, struct uart_port *port) +{ + struct uart_state *state; + int ret; + + down(&port_sem); + + state = uart_find_match_or_unused(drv, port); + + if (state) { + /* + * Ok, we've found a line that we can use. + * + * If we find a port that matches this one, and it appears + * to be in-use (even if it doesn't have a type) we shouldn't + * alter it underneath itself - the port may be open and + * trying to do useful work. + */ + if (uart_users(state) != 0) { + ret = -EBUSY; + goto out; + } + + /* + * If the port is already initialised, don't touch it. + */ + if (state->port->type == PORT_UNKNOWN) { + state->port->iobase = port->iobase; + state->port->membase = port->membase; + state->port->irq = port->irq; + state->port->uartclk = port->uartclk; + state->port->fifosize = port->fifosize; + state->port->regshift = port->regshift; + state->port->iotype = port->iotype; + state->port->flags = port->flags; + state->port->line = state - drv->state; + state->port->mapbase = port->mapbase; + + uart_configure_port(drv, state, state->port); + } + + ret = state->port->line; + } else + ret = -ENOSPC; + out: + up(&port_sem); + return ret; +} + +/** + * uart_unregister_port - de-allocate a port + * @drv: pointer to the uart low level driver structure for this port + * @line: line index previously returned from uart_register_port() + * + * Hang up the specified line associated with the low level driver, + * and mark the port as unused. + */ +void uart_unregister_port(struct uart_driver *drv, int line) +{ + struct uart_state *state; + + if (line < 0 || line >= drv->nr) { + printk(KERN_ERR "Attempt to unregister "); + printk("%s%d", drv->dev_name, line); + printk("\n"); + return; + } + + state = drv->state + line; + + down(&port_sem); + uart_unconfigure_port(drv, state); + up(&port_sem); +} + +EXPORT_SYMBOL(uart_write_wakeup); +EXPORT_SYMBOL(uart_register_driver); +EXPORT_SYMBOL(uart_unregister_driver); +EXPORT_SYMBOL(uart_suspend_port); +EXPORT_SYMBOL(uart_resume_port); +EXPORT_SYMBOL(uart_register_port); +EXPORT_SYMBOL(uart_unregister_port); +EXPORT_SYMBOL(uart_add_one_port); +EXPORT_SYMBOL(uart_remove_one_port); + +MODULE_DESCRIPTION("Serial driver core"); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/serial/serial_cs.c Thu Sep 11 23:03:12 2003 @@ -0,0 +1,712 @@ +/*====================================================================== + + A driver for PCMCIA serial devices + + serial_cs.c 1.134 2002/05/04 05:48:53 + + The contents of this file are subject to the Mozilla Public + License Version 1.1 (the "License"); you may not use this file + except in compliance with the License. You may obtain a copy of + the License at http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS + IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + implied. See the License for the specific language governing + rights and limitations under the License. + + The initial developer of the original code is David A. Hinds + . Portions created by David A. Hinds + are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + + Alternatively, the contents of this file may be used under the + terms of the GNU General Public License version 2 (the "GPL"), in which + case the provisions of the GPL are applicable instead of the + above. If you wish to allow the use of your version of this file + only under the terms of the GPL and not to allow others to use + your version of this file under the MPL, indicate your decision + by deleting the provisions above and replace them with the notice + and other provisions required by the GPL. If you do not delete + the provisions above, a recipient may use your version of this + file under either the MPL or the GPL. + +======================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +MODULE_PARM(pc_debug, "i"); +#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) +static char *version = "serial_cs.c 1.134 2002/05/04 05:48:53 (David Hinds)"; +#else +#define DEBUG(n, args...) +#endif + +/*====================================================================*/ + +/* Parameters that can be set with 'insmod' */ + +/* Bit map of interrupts to choose from */ +static u_int irq_mask = 0xdeb8; +static int irq_list[4] = { -1 }; + +/* Enable the speaker? */ +static int do_sound = 1; +/* Skip strict UART tests? */ +static int buggy_uart; + +MODULE_PARM(irq_mask, "i"); +MODULE_PARM(irq_list, "1-4i"); +MODULE_PARM(do_sound, "i"); +MODULE_PARM(buggy_uart, "i"); + +/*====================================================================*/ + +/* Table of multi-port card ID's */ + +struct multi_id { + u_short manfid; + u_short prodid; + int multi; /* 1 = multifunction, > 1 = # ports */ +}; + +static struct multi_id multi_id[] = { + { MANFID_OMEGA, PRODID_OMEGA_QSP_100, 4 }, + { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232, 2 }, + { MANFID_QUATECH, PRODID_QUATECH_DUAL_RS232_D1, 2 }, + { MANFID_QUATECH, PRODID_QUATECH_QUAD_RS232, 4 }, + { MANFID_SOCKET, PRODID_SOCKET_DUAL_RS232, 2 }, + { MANFID_INTEL, PRODID_INTEL_DUAL_RS232, 2 }, + { MANFID_NATINST, PRODID_NATINST_QUAD_RS232, 4 } +}; +#define MULTI_COUNT (sizeof(multi_id)/sizeof(struct multi_id)) + +struct serial_info { + dev_link_t link; + int ndev; + int multi; + int slave; + int manfid; + dev_node_t node[4]; + int line[4]; +}; + +static void serial_config(dev_link_t * link); +static int serial_event(event_t event, int priority, + event_callback_args_t * args); + +static dev_info_t dev_info = "serial_cs"; + +static dev_link_t *serial_attach(void); +static void serial_detach(dev_link_t *); + +static dev_link_t *dev_list = NULL; + +/*====================================================================== + + After a card is removed, serial_remove() will unregister + the serial device(s), and release the PCMCIA configuration. + +======================================================================*/ + +static void serial_remove(dev_link_t *link) +{ + struct serial_info *info = link->priv; + int i; + + link->state &= ~DEV_PRESENT; + + DEBUG(0, "serial_release(0x%p)\n", link); + + /* + * Recheck to see if the device is still configured. + */ + if (info->link.state & DEV_CONFIG) { + for (i = 0; i < info->ndev; i++) + unregister_serial(info->line[i]); + + info->link.dev = NULL; + + if (!info->slave) { + CardServices(ReleaseConfiguration, info->link.handle); + CardServices(ReleaseIO, info->link.handle, &info->link.io); + CardServices(ReleaseIRQ, info->link.handle, &info->link.irq); + } + + info->link.state &= ~DEV_CONFIG; + } +} + +/*====================================================================== + + serial_attach() creates an "instance" of the driver, allocating + local data structures for one device. The device is registered + with Card Services. + +======================================================================*/ + +static dev_link_t *serial_attach(void) +{ + struct serial_info *info; + client_reg_t client_reg; + dev_link_t *link; + int i, ret; + + DEBUG(0, "serial_attach()\n"); + + /* Create new serial device */ + info = kmalloc(sizeof (*info), GFP_KERNEL); + if (!info) + return NULL; + memset(info, 0, sizeof (*info)); + link = &info->link; + link->priv = info; + + link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + link->io.NumPorts1 = 8; + link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; + if (irq_list[0] == -1) + link->irq.IRQInfo2 = irq_mask; + else + for (i = 0; i < 4; i++) + link->irq.IRQInfo2 |= 1 << irq_list[i]; + link->conf.Attributes = CONF_ENABLE_IRQ; + if (do_sound) { + link->conf.Attributes |= CONF_ENABLE_SPKR; + link->conf.Status = CCSR_AUDIO_ENA; + } + link->conf.IntType = INT_MEMORY_AND_IO; + + /* Register with Card Services */ + link->next = dev_list; + dev_list = link; + client_reg.dev_info = &dev_info; + client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; + client_reg.EventMask = + CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | + CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | + CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; + client_reg.event_handler = &serial_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + ret = CardServices(RegisterClient, &link->handle, &client_reg); + if (ret != CS_SUCCESS) { + cs_error(link->handle, RegisterClient, ret); + serial_detach(link); + return NULL; + } + + return link; +} + +/*====================================================================== + + This deletes a driver "instance". The device is de-registered + with Card Services. If it has been released, all local data + structures are freed. Otherwise, the structures will be freed + when the device is released. + +======================================================================*/ + +static void serial_detach(dev_link_t * link) +{ + struct serial_info *info = link->priv; + dev_link_t **linkp; + int ret; + + DEBUG(0, "serial_detach(0x%p)\n", link); + + /* Locate device structure */ + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) + break; + if (*linkp == NULL) + return; + + /* + * Ensure any outstanding scheduled tasks are completed. + */ + flush_scheduled_work(); + + /* + * Ensure that the ports have been released. + */ + serial_remove(link); + + if (link->handle) { + ret = CardServices(DeregisterClient, link->handle); + if (ret != CS_SUCCESS) + cs_error(link->handle, DeregisterClient, ret); + } + + /* Unlink device structure, free bits */ + *linkp = link->next; + kfree(info); +} + +/*====================================================================*/ + +static int setup_serial(struct serial_info * info, ioaddr_t port, int irq) +{ + struct serial_struct serial; + int line; + + memset(&serial, 0, sizeof (serial)); + serial.port = port; + serial.irq = irq; + serial.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ; + if (buggy_uart) + serial.flags |= UPF_BUGGY_UART; + line = register_serial(&serial); + if (line < 0) { + printk(KERN_NOTICE "serial_cs: register_serial() at 0x%04lx," + " irq %d failed\n", (u_long) serial.port, serial.irq); + return -EINVAL; + } + + info->line[info->ndev] = line; + sprintf(info->node[info->ndev].dev_name, "ttyS%d", line); + info->node[info->ndev].major = TTY_MAJOR; + info->node[info->ndev].minor = 0x40 + line; + if (info->ndev > 0) + info->node[info->ndev - 1].next = &info->node[info->ndev]; + info->ndev++; + + return 0; +} + +/*====================================================================*/ + +static int +get_tuple(int fn, client_handle_t handle, tuple_t * tuple, cisparse_t * parse) +{ + int i; + i = CardServices(fn, handle, tuple); + if (i != CS_SUCCESS) + return CS_NO_MORE_ITEMS; + i = CardServices(GetTupleData, handle, tuple); + if (i != CS_SUCCESS) + return i; + return CardServices(ParseTuple, handle, tuple, parse); +} + +#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c) +#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c) + +/*====================================================================*/ + +static int simple_config(dev_link_t * link) +{ + static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; + client_handle_t handle = link->handle; + struct serial_info *info = link->priv; + tuple_t tuple; + u_char buf[256]; + cisparse_t parse; + cistpl_cftable_entry_t *cf = &parse.cftable_entry; + config_info_t config; + int i, j, try; + + /* If the card is already configured, look up the port and irq */ + i = CardServices(GetConfigurationInfo, handle, &config); + if ((i == CS_SUCCESS) && (config.Attributes & CONF_VALID_CLIENT)) { + ioaddr_t port = 0; + if ((config.BasePort2 != 0) && (config.NumPorts2 == 8)) { + port = config.BasePort2; + info->slave = 1; + } else if ((info->manfid == MANFID_OSITECH) && + (config.NumPorts1 == 0x40)) { + port = config.BasePort1 + 0x28; + info->slave = 1; + } + if (info->slave) + return setup_serial(info, port, config.AssignedIRQ); + } + link->conf.Vcc = config.Vcc; + + /* First pass: look for a config entry that looks normal. */ + tuple.TupleData = (cisdata_t *) buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; + tuple.Attributes = 0; + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + /* Two tries: without IO aliases, then with aliases */ + for (try = 0; try < 2; try++) { + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + if (i != CS_SUCCESS) + goto next_entry; + if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM)) + link->conf.Vpp1 = link->conf.Vpp2 = + cf->vpp1.param[CISTPL_POWER_VNOM] / 10000; + if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && + (cf->io.win[0].base != 0)) { + link->conf.ConfigIndex = cf->index; + link->io.BasePort1 = cf->io.win[0].base; + link->io.IOAddrLines = (try == 0) ? + 16 : cf->io.flags & CISTPL_IO_LINES_MASK; + i = + CardServices(RequestIO, link->handle, + &link->io); + if (i == CS_SUCCESS) + goto found_port; + } + next_entry: + i = next_tuple(handle, &tuple, &parse); + } + } + + /* Second pass: try to find an entry that isn't picky about + its base address, then try to grab any standard serial port + address, and finally try to get any free port. */ + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && + ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) { + link->conf.ConfigIndex = cf->index; + for (j = 0; j < 5; j++) { + link->io.BasePort1 = base[j]; + link->io.IOAddrLines = base[j] ? 16 : 3; + i = CardServices(RequestIO, link->handle, + &link->io); + if (i == CS_SUCCESS) + goto found_port; + } + } + i = next_tuple(handle, &tuple, &parse); + } + + found_port: + if (i != CS_SUCCESS) { + printk(KERN_NOTICE + "serial_cs: no usable port range found, giving up\n"); + cs_error(link->handle, RequestIO, i); + return -1; + } + + i = CardServices(RequestIRQ, link->handle, &link->irq); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestIRQ, i); + link->irq.AssignedIRQ = 0; + } + if (info->multi && (info->manfid == MANFID_3COM)) + link->conf.ConfigIndex &= ~(0x08); + i = CardServices(RequestConfiguration, link->handle, &link->conf); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestConfiguration, i); + return -1; + } + + return setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ); +} + +static int multi_config(dev_link_t * link) +{ + client_handle_t handle = link->handle; + struct serial_info *info = link->priv; + tuple_t tuple; + u_char buf[256]; + cisparse_t parse; + cistpl_cftable_entry_t *cf = &parse.cftable_entry; + config_info_t config; + int i, base2 = 0; + + i = CardServices(GetConfigurationInfo, handle, &config); + if (i != CS_SUCCESS) { + cs_error(handle, GetConfigurationInfo, i); + return -1; + } + link->conf.Vcc = config.Vcc; + + tuple.TupleData = (cisdata_t *) buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; + tuple.Attributes = 0; + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + + /* First, look for a generic full-sized window */ + link->io.NumPorts1 = info->multi * 8; + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + /* The quad port cards have bad CIS's, so just look for a + window larger than 8 ports and assume it will be right */ + if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && + (cf->io.win[0].len > 8)) { + link->conf.ConfigIndex = cf->index; + link->io.BasePort1 = cf->io.win[0].base; + link->io.IOAddrLines = + cf->io.flags & CISTPL_IO_LINES_MASK; + i = CardServices(RequestIO, link->handle, &link->io); + base2 = link->io.BasePort1 + 8; + if (i == CS_SUCCESS) + break; + } + i = next_tuple(handle, &tuple, &parse); + } + + /* If that didn't work, look for two windows */ + if (i != CS_SUCCESS) { + link->io.NumPorts1 = link->io.NumPorts2 = 8; + info->multi = 2; + i = first_tuple(handle, &tuple, &parse); + while (i != CS_NO_MORE_ITEMS) { + if ((i == CS_SUCCESS) && (cf->io.nwin == 2)) { + link->conf.ConfigIndex = cf->index; + link->io.BasePort1 = cf->io.win[0].base; + link->io.BasePort2 = cf->io.win[1].base; + link->io.IOAddrLines = + cf->io.flags & CISTPL_IO_LINES_MASK; + i = + CardServices(RequestIO, link->handle, + &link->io); + base2 = link->io.BasePort2; + if (i == CS_SUCCESS) + break; + } + i = next_tuple(handle, &tuple, &parse); + } + } + + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestIO, i); + return -1; + } + + i = CardServices(RequestIRQ, link->handle, &link->irq); + if (i != CS_SUCCESS) { + printk(KERN_NOTICE + "serial_cs: no usable port range found, giving up\n"); + cs_error(link->handle, RequestIRQ, i); + link->irq.AssignedIRQ = 0; + } + /* Socket Dual IO: this enables irq's for second port */ + if (info->multi && (info->manfid == MANFID_SOCKET)) { + link->conf.Present |= PRESENT_EXT_STATUS; + link->conf.ExtStatus = ESR_REQ_ATTN_ENA; + } + i = CardServices(RequestConfiguration, link->handle, &link->conf); + if (i != CS_SUCCESS) { + cs_error(link->handle, RequestConfiguration, i); + return -1; + } + + /* The Oxford Semiconductor OXCF950 cards are in fact single-port: + 8 registers are for the UART, the others are extra registers */ + if (info->manfid == MANFID_OXSEMI) { + if (cf->index == 1 || cf->index == 3) { + setup_serial(info, base2, link->irq.AssignedIRQ); + outb(12, link->io.BasePort1 + 1); + } else { + setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ); + outb(12, base2 + 1); + } + return 0; + } + + setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ); + /* The Nokia cards are not really multiport cards */ + if (info->manfid == MANFID_NOKIA) + return 0; + for (i = 0; i < info->multi - 1; i++) + setup_serial(info, base2 + (8 * i), link->irq.AssignedIRQ); + + return 0; +} + +/*====================================================================== + + serial_config() is scheduled to run after a CARD_INSERTION event + is received, to configure the PCMCIA socket, and to make the + serial device available to the system. + +======================================================================*/ + +#define CS_CHECK(fn, args...) \ +while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed + +void serial_config(dev_link_t * link) +{ + client_handle_t handle = link->handle; + struct serial_info *info = link->priv; + tuple_t tuple; + u_short buf[128]; + cisparse_t parse; + cistpl_cftable_entry_t *cf = &parse.cftable_entry; + int i, last_ret, last_fn; + + DEBUG(0, "serial_config(0x%p)\n", link); + + tuple.TupleData = (cisdata_t *) buf; + tuple.TupleOffset = 0; + tuple.TupleDataMax = 255; + tuple.Attributes = 0; + /* Get configuration register information */ + tuple.DesiredTuple = CISTPL_CONFIG; + last_ret = first_tuple(handle, &tuple, &parse); + if (last_ret != CS_SUCCESS) { + last_fn = ParseTuple; + goto cs_failed; + } + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + /* Configure card */ + link->state |= DEV_CONFIG; + + /* Is this a compliant multifunction card? */ + tuple.DesiredTuple = CISTPL_LONGLINK_MFC; + tuple.Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; + info->multi = (first_tuple(handle, &tuple, &parse) == CS_SUCCESS); + + /* Is this a multiport card? */ + tuple.DesiredTuple = CISTPL_MANFID; + if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) { + info->manfid = le16_to_cpu(buf[0]); + for (i = 0; i < MULTI_COUNT; i++) + if ((info->manfid == multi_id[i].manfid) && + (le16_to_cpu(buf[1]) == multi_id[i].prodid)) + break; + if (i < MULTI_COUNT) + info->multi = multi_id[i].multi; + } + + /* Another check for dual-serial cards: look for either serial or + multifunction cards that ask for appropriate IO port ranges */ + tuple.DesiredTuple = CISTPL_FUNCID; + if ((info->multi == 0) && + ((first_tuple(handle, &tuple, &parse) != CS_SUCCESS) || + (parse.funcid.func == CISTPL_FUNCID_MULTI) || + (parse.funcid.func == CISTPL_FUNCID_SERIAL))) { + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) { + if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) + info->multi = cf->io.win[0].len >> 3; + if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && + (cf->io.win[1].len == 8)) + info->multi = 2; + } + } + + if (info->multi > 1) + multi_config(link); + else + simple_config(link); + + if (info->ndev == 0) + goto failed; + + if (info->manfid == MANFID_IBM) { + conf_reg_t reg = { 0, CS_READ, 0x800, 0 }; + CS_CHECK(AccessConfigurationRegister, link->handle, ®); + reg.Action = CS_WRITE; + reg.Value = reg.Value | 1; + CS_CHECK(AccessConfigurationRegister, link->handle, ®); + } + + link->dev = &info->node[0]; + link->state &= ~DEV_CONFIG_PENDING; + return; + + cs_failed: + cs_error(link->handle, last_fn, last_ret); + failed: + serial_remove(link); + link->state &= ~DEV_CONFIG_PENDING; +} + +/*====================================================================== + + The card status event handler. Mostly, this schedules other + stuff to run after an event is received. A CARD_REMOVAL event + also sets some flags to discourage the serial drivers from + talking to the ports. + +======================================================================*/ + +static int +serial_event(event_t event, int priority, event_callback_args_t * args) +{ + dev_link_t *link = args->client_data; + struct serial_info *info = link->priv; + + DEBUG(1, "serial_event(0x%06x)\n", event); + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + serial_remove(link); + break; + + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + serial_config(link); + break; + + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + if ((link->state & DEV_CONFIG) && !info->slave) + CardServices(ReleaseConfiguration, link->handle); + break; + + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (DEV_OK(link) && !info->slave) + CardServices(RequestConfiguration, link->handle, + &link->conf); + break; + } + return 0; +} + +static struct pcmcia_driver serial_cs_driver = { + .owner = THIS_MODULE, + .drv = { + .name = "serial_cs", + }, + .attach = serial_attach, + .detach = serial_detach, +}; + +static int __init init_serial_cs(void) +{ + return pcmcia_register_driver(&serial_cs_driver); +} + +static void __exit exit_serial_cs(void) +{ + pcmcia_unregister_driver(&serial_cs_driver); + + /* XXX: this really needs to move into generic code.. */ + while (dev_list != NULL) + serial_detach(dev_list); +} + +module_init(init_serial_cs); +module_exit(exit_serial_cs); + +MODULE_LICENSE("GPL"); diff -Nru a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c --- a/drivers/video/i810/i810_main.c Thu Sep 11 23:03:12 2003 +++ b/drivers/video/i810/i810_main.c Thu Sep 11 23:03:12 2003 @@ -57,7 +57,7 @@ #include "i810_main.h" /* PCI */ -static const char *i810_pci_list[] __initdata = { +static const char *i810_pci_list[] __devinitdata = { "Intel(R) 810 Framebuffer Device" , "Intel(R) 810-DC100 Framebuffer Device" , "Intel(R) 810E Framebuffer Device" , @@ -66,7 +66,7 @@ "Intel(R) 815 (Internal Graphics with AGP) Framebuffer Device" }; -static struct pci_device_id i810fb_pci_tbl[] __initdata = { +static struct pci_device_id i810fb_pci_tbl[] = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3, @@ -1456,7 +1456,7 @@ return 0; } -static struct fb_ops i810fb_ops __initdata = { +static struct fb_ops i810fb_ops __devinitdata = { .owner = THIS_MODULE, .fb_open = i810fb_open, .fb_release = i810fb_release, @@ -1538,7 +1538,7 @@ * AGP resource allocation * ***********************************************************************/ -static void __init i810_fix_pointers(struct i810fb_par *par) +static void __devinit i810_fix_pointers(struct i810fb_par *par) { par->fb.physical = par->aperture.physical+(par->fb.offset << 12); par->fb.virtual = par->aperture.virtual+(par->fb.offset << 12); @@ -1550,7 +1550,7 @@ (par->cursor_heap.offset << 12); } -static void __init i810_fix_offsets(struct i810fb_par *par) +static void __devinit i810_fix_offsets(struct i810fb_par *par) { if (vram + 1 > par->aperture.size >> 20) vram = (par->aperture.size >> 20) - 1; @@ -1570,7 +1570,7 @@ par->cursor_heap.size = 4096; } -static int __init i810_alloc_agp_mem(struct fb_info *info) +static int __devinit i810_alloc_agp_mem(struct fb_info *info) { struct i810fb_par *par = (struct i810fb_par *) info->par; int size; @@ -1635,7 +1635,7 @@ * Sets the the user monitor's horizontal and vertical * frequency limits */ -static void __init i810_init_monspecs(struct fb_info *info) +static void __devinit i810_init_monspecs(struct fb_info *info) { if (!hsync1) hsync1 = HFMIN; @@ -1663,7 +1663,7 @@ * @par: pointer to i810fb_par structure * @info: pointer to current fb_info structure */ -static void __init i810_init_defaults(struct i810fb_par *par, +static void __devinit i810_init_defaults(struct i810fb_par *par, struct fb_info *info) { if (voffset) @@ -1707,7 +1707,7 @@ * i810_init_device - initialize device * @par: pointer to i810fb_par structure */ -static void __init i810_init_device(struct i810fb_par *par) +static void __devinit i810_init_device(struct i810fb_par *par) { u8 reg, *mmio = par->mmio_start_virtual; @@ -1726,7 +1726,7 @@ par->mem_freq = (reg) ? 133 : 100; } -static int __init +static int __devinit i810_allocate_pci_resource(struct i810fb_par *par, const struct pci_device_id *entry) { @@ -1831,7 +1831,7 @@ return 0; } -static int __init i810fb_init_pci (struct pci_dev *dev, +static int __devinit i810fb_init_pci (struct pci_dev *dev, const struct pci_device_id *entry) { struct fb_info *info; diff -Nru a/drivers/video/i810/i810_main.h b/drivers/video/i810/i810_main.h --- a/drivers/video/i810/i810_main.h Thu Sep 11 23:03:13 2003 +++ b/drivers/video/i810/i810_main.h Thu Sep 11 23:03:13 2003 @@ -14,7 +14,7 @@ #ifndef __I810_MAIN_H__ #define __I810_MAIN_H__ -static int __init i810fb_init_pci (struct pci_dev *dev, +static int __devinit i810fb_init_pci (struct pci_dev *dev, const struct pci_device_id *entry); static void __exit i810fb_remove_pci(struct pci_dev *dev); static int i810fb_resume(struct pci_dev *dev); @@ -95,7 +95,7 @@ #ifdef CONFIG_MTRR #define KERNEL_HAS_MTRR 1 -static inline void __init set_mtrr(struct i810fb_par *par) +static inline void __devinit set_mtrr(struct i810fb_par *par) { par->mtrr_reg = mtrr_add((u32) par->aperture.physical, par->aperture.size, MTRR_TYPE_WRCOMB, 1); diff -Nru a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c --- a/drivers/video/riva/fbdev.c Thu Sep 11 23:03:13 2003 +++ b/drivers/video/riva/fbdev.c Thu Sep 11 23:03:13 2003 @@ -1576,7 +1576,7 @@ .fb_sync = rivafb_sync, }; -static int __init riva_set_fbinfo(struct fb_info *info) +static int __devinit riva_set_fbinfo(struct fb_info *info) { struct riva_par *par = (struct riva_par *) info->par; unsigned int cmap_len; @@ -1726,7 +1726,7 @@ * * ------------------------------------------------------------------------- */ -static int __init rivafb_probe(struct pci_dev *pd, +static int __devinit rivafb_probe(struct pci_dev *pd, const struct pci_device_id *ent) { struct riva_chip_info *rci = &riva_chip_info[ent->driver_data]; diff -Nru a/fs/Kconfig b/fs/Kconfig --- a/fs/Kconfig Thu Sep 11 23:03:12 2003 +++ b/fs/Kconfig Thu Sep 11 23:03:12 2003 @@ -1505,7 +1505,7 @@ cifs module since smbfs is currently more stable and provides support for older servers. The intent of this module is to provide the most advanced network file system function for CIFS compliant servers, - including support for dfs (heirarchical name space), secure per-user + including support for dfs (hierarchical name space), secure per-user session establishment, safe distributed caching (oplock), optional packet signing, Unicode and other internationalization improvements, and optional Winbind (nsswitch) integration. This module is in an early diff -Nru a/fs/afs/Makefile b/fs/afs/Makefile --- a/fs/afs/Makefile Thu Sep 11 23:03:13 2003 +++ b/fs/afs/Makefile Thu Sep 11 23:03:13 2003 @@ -2,6 +2,8 @@ # Makefile for Red Hat Linux AFS client. # +#CFLAGS += -finstrument-functions + kafs-objs := \ callback.o \ cell.o \ diff -Nru a/fs/afs/cache-layout.h b/fs/afs/cache-layout.h --- a/fs/afs/cache-layout.h Thu Sep 11 23:03:13 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,224 +0,0 @@ -/* cache-layout.h: AFS cache layout - * - * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * - * The cache is stored on a block device and is laid out as: - * - * 0 +------------------------------------------------ - * | - * | SuperBlock - * | - * 1 +------------------------------------------------ - * | - * | file-meta-data File: Data block #0 - * | - file-meta-data file (volix #0 file #0) : Meta-data block - * | - contains direct pointers to first 64 file data blocks - * | - Cached cell catalogue file (volix #0 file #1) file: Meta-data block - * | - Cached volume location catalogue file (volix #0 file #2): Meta-data block - * | - Vnode catalogue hash bucket #n file: Meta-data block - * | - * 2 +------------------------------------------------ - * | - * | Bitmap Block Allocation Bitmap - * | - 1 bit per block in the bitmap block - * | - bit 0 of dword 0 refers to the bitmap block 0 - * | - set if the bitmap block is full - * | - 32768 bits per block, requiring 4 blocks for a 16Tb cache - * | - bitmap bitmap blocks are cleared initially - * | - not present if <4 bitmap blocks - * | - * +------------------------------------------------ - * | - * | File Block Allocation Bitmap - * | - 1 bit per block in the cache - * | - bit 0 of dword 0 refers to the first block of the data cache - * | - set if block is allocated - * | - 32768 bits per block, requiring 131072 blocks for a 16Tb cache - * | - bitmap blocks are cleared lazily (sb->bix_bitmap_unready) - * | - * +------------------------------------------------ - * | - * | Data Cache - * | - * End +------------------------------------------------ - * - * Blocks are indexed by an unsigned 32-bit word, meaning that the cache can hold up to 2^32 pages, - * or 16Tb in total. - * - * Credentials will be cached in memory, since they are subject to change without notice, and are - * difficult to derive manually, being constructed from the following information: - * - per vnode user ID and mode mask - * - parent directory ACL - * - directory ACL (dirs only) - * - group lists from ptserver - */ - -#ifndef _LINUX_AFS_CACHE_LAYOUT_H -#define _LINUX_AFS_CACHE_LAYOUT_H - -#include "types.h" - -typedef u32 afsc_blockix_t; -typedef u32 afsc_cellix_t; - -/* Cached volume index - * - afsc_volix_t/4 is the index into the volume cache - * - afsc_volix_t%4 is 0 for R/W, 1 for R/O and 2 for Bak (3 is not used) - * - afsc_volix_t==0-3 refers to a "virtual" volume that stores meta-data about the cache - */ -typedef struct { - u32 index; -} afsc_volix_t; - -#define AFSC_VNCAT_HASH_NBUCKETS 128 - -/* special meta file IDs (all cell 0 vol 0) */ -enum afsc_meta_fids { - AFSC_META_FID_METADATA = 0, - AFSC_META_FID_CELL_CATALOGUE = 1, - AFSC_META_FID_VLDB_CATALOGUE = 2, - AFSC_META_FID_VNODE_CATALOGUE0 = 3, - AFSC_META_FID__COUNT = AFSC_VNCAT_HASH_NBUCKETS + 3 -}; - -/*****************************************************************************/ -/* - * cache superblock block layout - * - the blockdev is prepared for initialisation by 'echo "kafsuninit" >/dev/hdaXX' before mounting - * - when initialised, the magic number is changed to "kafs-cache" - */ -struct afsc_super_block -{ - char magic[10]; /* magic number */ -#define AFSC_SUPER_MAGIC "kafs-cache" -#define AFSC_SUPER_MAGIC_NEEDS_INIT "kafsuninit" -#define AFSC_SUPER_MAGIC_SIZE 10 - - unsigned short endian; /* 0x1234 stored CPU-normal order */ -#define AFSC_SUPER_ENDIAN 0x1234 - - unsigned version; /* format version */ -#define AFSC_SUPER_VERSION 1 - - /* layout */ - unsigned bsize; /* cache block size */ - afsc_blockix_t bix_bitmap_fullmap; /* block ix of bitmap full bitmap */ - afsc_blockix_t bix_bitmap; /* block ix of alloc bitmap */ - afsc_blockix_t bix_bitmap_unready; /* block ix of unready area of bitmap */ - afsc_blockix_t bix_cache; /* block ix of data cache */ - afsc_blockix_t bix_end; /* block ix of end of cache */ -}; - -/*****************************************************************************/ -/* - * vnode (inode) metadata cache record - * - padded out to 512 bytes and stored eight to a page - * - only the data version is necessary - * - disconnected operation is not supported - * - afs_iget() contacts the server to get the meta-data _anyway_ when an inode is first brought - * into memory - * - at least 64 direct block pointers will be available (a directory is max 256Kb) - * - any block pointer which is 0 indicates an uncached page - */ -struct afsc_vnode_meta -{ - /* file ID */ - afsc_volix_t volume_ix; /* volume catalogue index */ - unsigned vnode; /* vnode number */ - unsigned unique; /* FID unique */ - unsigned size; /* size of file */ - time_t mtime; /* last modification time */ - - /* file status */ - afs_dataversion_t version; /* current data version */ - - /* file contents */ - afsc_blockix_t dbl_indirect; /* double indirect block index */ - afsc_blockix_t indirect; /* single indirect block 0 index */ - afsc_blockix_t direct[0]; /* direct block index (#AFSC_VNODE_META_DIRECT) */ -}; - -#define AFSC_VNODE_META_RECSIZE 512 /* record size */ - -#define AFSC_VNODE_META_DIRECT \ - ((AFSC_VNODE_META_RECSIZE-sizeof(struct afsc_vnode_meta))/sizeof(afsc_blockix_t)) - -#define AFSC_VNODE_META_PER_PAGE (PAGE_SIZE / AFSC_VNODE_META_RECSIZE) - -/*****************************************************************************/ -/* - * entry in the cached cell catalogue - */ -struct afsc_cell_record -{ - char name[64]; /* cell name (padded with NULs) */ - struct in_addr servers[16]; /* cached cell servers */ -}; - -/*****************************************************************************/ -/* - * entry in the cached volume location catalogue - * - indexed by afsc_volix_t/4 - */ -struct afsc_vldb_record -{ - char name[64]; /* volume name (padded with NULs) */ - afs_volid_t vid[3]; /* volume IDs for R/W, R/O and Bak volumes */ - unsigned char vidmask; /* voltype mask for vid[] */ - unsigned char _pad[1]; - unsigned short nservers; /* number of entries used in servers[] */ - struct in_addr servers[8]; /* fileserver addresses */ - unsigned char srvtmask[8]; /* voltype masks for servers[] */ -#define AFSC_VOL_STM_RW 0x01 /* server holds a R/W version of the volume */ -#define AFSC_VOL_STM_RO 0x02 /* server holds a R/O version of the volume */ -#define AFSC_VOL_STM_BAK 0x04 /* server holds a backup version of the volume */ - - afsc_cellix_t cell_ix; /* cell catalogue index (MAX_UINT if unused) */ - time_t ctime; /* time at which cached */ -}; - -/*****************************************************************************/ -/* - * vnode catalogue entry - * - must be 2^x size so that do_generic_file_read doesn't present them split across pages - */ -struct afsc_vnode_catalogue -{ - afsc_volix_t volume_ix; /* volume catalogue index */ - afs_vnodeid_t vnode; /* vnode ID */ - u32 meta_ix; /* metadata file index */ - u32 atime; /* last time entry accessed */ -} __attribute__((packed)); - -#define AFSC_VNODE_CATALOGUE_PER_BLOCK ((size_t)(PAGE_SIZE/sizeof(struct afsc_vnode_catalogue))) - -/*****************************************************************************/ -/* - * vnode data "page directory" block - * - first 1024 pages don't map through here - * - PAGE_SIZE in size - */ -struct afsc_indirect_block -{ - afsc_blockix_t pt_bix[1024]; /* "page table" block indices */ -}; - -/*****************************************************************************/ -/* - * vnode data "page table" block - * - PAGE_SIZE in size - */ -struct afsc_dbl_indirect_block -{ - afsc_blockix_t page_bix[1024]; /* "page" block indices */ -}; - - -#endif /* _LINUX_AFS_CACHE_LAYOUT_H */ diff -Nru a/fs/afs/cache.h b/fs/afs/cache.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/fs/afs/cache.h Thu Sep 11 23:03:14 2003 @@ -0,0 +1,27 @@ +/* cache.h: AFS local cache management interface + * + * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#ifndef _LINUX_AFS_CACHE_H +#define _LINUX_AFS_CACHE_H + +#undef AFS_CACHING_SUPPORT + +#include +#ifdef AFS_CACHING_SUPPORT +#include +#endif +#include "types.h" + +#ifdef __KERNEL__ + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_AFS_CACHE_H */ diff -Nru a/fs/afs/callback.c b/fs/afs/callback.c --- a/fs/afs/callback.c Thu Sep 11 23:03:12 2003 +++ b/fs/afs/callback.c Thu Sep 11 23:03:12 2003 @@ -68,7 +68,7 @@ spin_unlock(&vnode->lock); iput(inode); - if (release) afs_put_server(server); + afs_put_server(server); spin_lock(&server->cb_lock); } diff -Nru a/fs/afs/cell.c b/fs/afs/cell.c --- a/fs/afs/cell.c Thu Sep 11 23:03:11 2003 +++ b/fs/afs/cell.c Thu Sep 11 23:03:11 2003 @@ -36,6 +36,19 @@ MODULE_PARM(rootcell,"s"); MODULE_PARM_DESC(rootcell,"root AFS cell name and VL server IP addr list"); +#ifdef AFS_CACHING_SUPPORT +static cachefs_match_val_t afs_cell_cache_match(void *target, const void *entry); +static void afs_cell_cache_update(void *source, void *entry); + +struct cachefs_index_def afs_cache_cell_index_def = { + .name = "cell_ix", + .data_size = sizeof(afs_cell_t), + .keys[0] = { CACHEFS_INDEX_KEYS_ASCIIZ, 64 }, + .match = afs_cell_cache_match, + .update = afs_cell_cache_update, +}; +#endif + /*****************************************************************************/ /* * create a cell record @@ -65,7 +78,6 @@ atomic_set(&cell->usage,0); INIT_LIST_HEAD(&cell->link); - INIT_LIST_HEAD(&cell->caches); rwlock_init(&cell->sv_lock); INIT_LIST_HEAD(&cell->sv_list); @@ -96,7 +108,7 @@ cell->vl_addrs[cell->vl_naddrs++].s_addr = htonl((a<<24)|(b<<16)|(c<<8)|d); - if (cell->vl_naddrs>=16) + if (cell->vl_naddrs >= AFS_CELL_MAX_ADDRS) break; } while(vllist=next, vllist); @@ -106,6 +118,14 @@ if (ret<0) goto error; +#ifdef AFS_CACHING_SUPPORT + /* put it up for caching */ + cachefs_acquire_cookie(afs_cache_netfs.primary_index, + &afs_vlocation_cache_index_def, + cell, + &cell->cache); +#endif + /* add to the cell lists */ write_lock(&afs_cells_lock); list_add_tail(&cell->link,&afs_cells); @@ -166,36 +186,45 @@ /* * lookup a cell record */ -int afs_cell_lookup(const char *name, afs_cell_t **_cell) +int afs_cell_lookup(const char *name, unsigned namesz, struct afs_cell **_cell) { struct list_head *_p; afs_cell_t *cell; + int ret; - _enter("\"%s\",",name?name:"*thiscell*"); + _enter("\"%*.*s\",", namesz, namesz, name ? name : ""); - cell = afs_cell_root; + *_cell = NULL; if (name) { /* if the cell was named, look for it in the cell record list */ + ret = -ENOENT; cell = NULL; read_lock(&afs_cells_lock); list_for_each(_p,&afs_cells) { - cell = list_entry(_p,afs_cell_t,link); - if (strcmp(cell->name,name)==0) + cell = list_entry(_p, struct afs_cell, link); + if (strncmp(cell->name, name, namesz) == 0) { + afs_get_cell(cell); break; + } cell = NULL; } read_unlock(&afs_cells_lock); - } - if (cell) + if (cell) + ret = 0; + } + else { + cell = afs_cell_root; afs_get_cell(cell); + ret = 0; + } *_cell = cell; - _leave(" = %d (%p)",cell?0:-ENOENT,cell); - return cell ? 0 : -ENOENT; + _leave(" = %d (%p)", ret, cell); + return ret; } /* end afs_cell_lookup() */ @@ -211,8 +240,8 @@ cell = *_cell; if (cell && !list_empty(&cell->link)) - atomic_inc(&cell->usage); - else + afs_get_cell(cell); + else cell = NULL; write_unlock(&afs_cells_lock); @@ -226,6 +255,9 @@ */ void afs_put_cell(afs_cell_t *cell) { + if (!cell) + return; + _enter("%p{%d,%s}",cell,atomic_read(&cell->usage),cell->name); /* sanity check */ @@ -278,6 +310,10 @@ list_del_init(&cell->proc_link); up_write(&afs_proc_cells_sem); +#ifdef AFS_CACHING_SUPPORT + cachefs_relinquish_cookie(cell->cache,0); +#endif + up_write(&afs_cells_sem); if (!list_empty(&cell->sv_list)) BUG(); @@ -377,8 +413,7 @@ _enter(""); - if (afs_cell_root) - afs_put_cell(afs_cell_root); + afs_put_cell(afs_cell_root); while (!list_empty(&afs_cells)) { cell = NULL; @@ -450,3 +485,46 @@ _leave(""); } /* end afs_cell_purge() */ + +/*****************************************************************************/ +/* + * match a cell record obtained from the cache + */ +#ifdef AFS_CACHING_SUPPORT +static cachefs_match_val_t afs_cell_cache_match(void *target, const void *entry) +{ + const struct afs_cache_cell *ccell = entry; + struct afs_cell *cell = target; + + _enter("{%s},{%s}", ccell->name, cell->name); + + if (strncmp(ccell->name, cell->name, sizeof(ccell->name)) == 0) { + _leave(" = SUCCESS"); + return CACHEFS_MATCH_SUCCESS; + } + + _leave(" = FAILED"); + return CACHEFS_MATCH_FAILED; +} /* end afs_cell_cache_match() */ +#endif + +/*****************************************************************************/ +/* + * update a cell record in the cache + */ +#ifdef AFS_CACHING_SUPPORT +static void afs_cell_cache_update(void *source, void *entry) +{ + struct afs_cache_cell *ccell = entry; + struct afs_cell *cell = source; + + _enter("%p,%p", source, entry); + + strncpy(ccell->name, cell->name, sizeof(ccell->name)); + + memcpy(ccell->vl_servers, + cell->vl_addrs, + min(sizeof(ccell->vl_servers), sizeof(cell->vl_addrs))); + +} /* end afs_cell_cache_update() */ +#endif diff -Nru a/fs/afs/cell.h b/fs/afs/cell.h --- a/fs/afs/cell.h Thu Sep 11 23:03:13 2003 +++ b/fs/afs/cell.h Thu Sep 11 23:03:13 2003 @@ -13,11 +13,24 @@ #define _LINUX_AFS_CELL_H #include "types.h" +#include "cache.h" + +#define AFS_CELL_MAX_ADDRS 15 extern volatile int afs_cells_being_purged; /* T when cells are being purged by rmmod */ /*****************************************************************************/ /* + * entry in the cached cell catalogue + */ +struct afs_cache_cell +{ + char name[64]; /* cell name (padded with NULs) */ + struct in_addr vl_servers[15]; /* cached cell VL servers */ +}; + +/*****************************************************************************/ +/* * AFS cell record */ struct afs_cell @@ -26,7 +39,9 @@ struct list_head link; /* main cell list link */ struct list_head proc_link; /* /proc cell list link */ struct proc_dir_entry *proc_dir; /* /proc dir for this cell */ - struct list_head caches; /* list of caches currently backing this cell */ +#ifdef AFS_CACHING_SUPPORT + struct cachefs_cookie *cache; /* caching cookie */ +#endif /* server record management */ rwlock_t sv_lock; /* active server list lock */ @@ -41,22 +56,22 @@ spinlock_t vl_gylock; /* graveyard lock */ unsigned short vl_naddrs; /* number of VL servers in addr list */ unsigned short vl_curr_svix; /* current server index */ - struct in_addr vl_addrs[16]; /* cell VL server addresses */ + struct in_addr vl_addrs[AFS_CELL_MAX_ADDRS]; /* cell VL server addresses */ char name[0]; /* cell name - must go last */ }; extern int afs_cell_init(void); -extern int afs_cell_create(const char *name, char *vllist, afs_cell_t **_cell); +extern int afs_cell_create(const char *name, char *vllist, struct afs_cell **_cell); -extern int afs_cell_lookup(const char *name, afs_cell_t **_cell); +extern int afs_cell_lookup(const char *name, unsigned nmsize, struct afs_cell **_cell); #define afs_get_cell(C) do { atomic_inc(&(C)->usage); } while(0) -extern afs_cell_t *afs_get_cell_maybe(afs_cell_t **_cell); +extern struct afs_cell *afs_get_cell_maybe(struct afs_cell **_cell); -extern void afs_put_cell(afs_cell_t *cell); +extern void afs_put_cell(struct afs_cell *cell); extern void afs_cell_purge(void); diff -Nru a/fs/afs/cmservice.c b/fs/afs/cmservice.c --- a/fs/afs/cmservice.c Thu Sep 11 23:03:12 2003 +++ b/fs/afs/cmservice.c Thu Sep 11 23:03:12 2003 @@ -119,6 +119,7 @@ int die; printk("kAFS: Started kafscmd %d\n",current->pid); + daemonize("kafscmd"); complete(&kafscmd_alive); @@ -293,15 +294,20 @@ down_write(&afscm_sem); if (!afscm_usage) { - ret = kernel_thread(kafscmd,NULL,0); - if (ret<0) + ret = kernel_thread(kafscmd, NULL, 0); + if (ret < 0) goto out; wait_for_completion(&kafscmd_alive); - ret = rxrpc_add_service(afs_transport,&AFSCM_service); + ret = rxrpc_add_service(afs_transport, &AFSCM_service); if (ret<0) goto kill; + +#ifdef AFS_AUTOMOUNT_SUPPORT + afs_kafstimod_add_timer(&afs_mntpt_expiry_timer, + afs_mntpt_expiry_timeout * HZ); +#endif } afscm_usage++; @@ -330,17 +336,20 @@ down_write(&afscm_sem); - if (afscm_usage==0) BUG(); + if (afscm_usage == 0) BUG(); afscm_usage--; - if (afscm_usage==0) { + if (afscm_usage == 0) { /* don't want more incoming calls */ - rxrpc_del_service(afs_transport,&AFSCM_service); + rxrpc_del_service(afs_transport, &AFSCM_service); /* abort any calls I've still got open (the afscm_error() will dequeue them) */ spin_lock(&afscm_calls_lock); while (!list_empty(&afscm_calls)) { - call = list_entry(afscm_calls.next,struct rxrpc_call,app_link); + call = list_entry(afscm_calls.next, + struct rxrpc_call, + app_link); + list_del_init(&call->app_link); rxrpc_get_call(call); spin_unlock(&afscm_calls_lock); @@ -348,7 +357,8 @@ rxrpc_call_abort(call,-ESRCH); /* abort, dequeue and put */ _debug("nuking active call %08x.%d", - ntohl(call->conn->conn_id),ntohl(call->call_id)); + ntohl(call->conn->conn_id), + ntohl(call->call_id)); rxrpc_put_call(call); rxrpc_put_call(call); @@ -376,6 +386,10 @@ spin_lock(&kafscmd_attention_lock); } spin_unlock(&kafscmd_attention_lock); + +#ifdef AFS_AUTOMOUNT_SUPPORT + afs_kafstimod_del_timer(&afs_mntpt_expiry_timer); +#endif } up_write(&afscm_sem); @@ -490,7 +504,7 @@ if (ret<0) rxrpc_call_abort(call,ret); - if (server) afs_put_server(server); + afs_put_server(server); _leave(" = %d",ret); @@ -556,7 +570,7 @@ if (ret<0) rxrpc_call_abort(call,ret); - if (server) afs_put_server(server); + afs_put_server(server); _leave(" = %d",ret); @@ -622,7 +636,7 @@ if (ret<0) rxrpc_call_abort(call,ret); - if (server) afs_put_server(server); + afs_put_server(server); _leave(" = %d",ret); diff -Nru a/fs/afs/dir.c b/fs/afs/dir.c --- a/fs/afs/dir.c Thu Sep 11 23:03:12 2003 +++ b/fs/afs/dir.c Thu Sep 11 23:03:12 2003 @@ -23,10 +23,11 @@ #include "super.h" #include "internal.h" -static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *); +static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry, + struct nameidata *nd); static int afs_dir_open(struct inode *inode, struct file *file); static int afs_dir_readdir(struct file *file, void *dirent, filldir_t filldir); -static int afs_d_revalidate(struct dentry *dentry, struct nameidata *); +static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd); static int afs_d_delete(struct dentry *dentry); static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen, loff_t fpos, ino_t ino, unsigned dtype); @@ -70,7 +71,7 @@ u8 name[16]; u8 overflow[4]; /* if any char of the name (inc NUL) reaches here, consume * the next dirent too */ - } parts; + } u; u8 extended_name[32]; } afs_dirent_t; @@ -256,7 +257,7 @@ /* got a valid entry */ dire = &block->dirents[offset]; - nlen = strnlen(dire->parts.name,sizeof(*block) - offset*sizeof(afs_dirent_t)); + nlen = strnlen(dire->u.name,sizeof(*block) - offset*sizeof(afs_dirent_t)); _debug("ENT[%Zu.%u]: %s %Zu \"%s\"\n", blkoff/sizeof(afs_dir_block_t),offset, @@ -288,11 +289,11 @@ /* found the next entry */ ret = filldir(cookie, - dire->parts.name, + dire->u.name, nlen, blkoff + offset * sizeof(afs_dirent_t), - ntohl(dire->parts.vnode), - filldir==afs_dir_lookup_filldir ? dire->parts.unique : DT_UNKNOWN); + ntohl(dire->u.vnode), + filldir==afs_dir_lookup_filldir ? dire->u.unique : DT_UNKNOWN); if (ret<0) { _leave(" = 0 [full]"); return 0; @@ -414,7 +415,8 @@ /* * look up an entry in a directory */ -static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) +static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry, + struct nameidata *nd) { struct afs_dir_lookup_cookie cookie; struct afs_super_info *as; @@ -423,11 +425,11 @@ unsigned fpos; int ret; - _enter("{%lu},{%s}",dir->i_ino,dentry->d_name.name); + _enter("{%lu},%p{%s}",dir->i_ino,dentry,dentry->d_name.name); /* insanity checks first */ - if (sizeof(afs_dir_block_t) != 2048) BUG(); - if (sizeof(afs_dirent_t) != 32) BUG(); + BUG_ON(sizeof(afs_dir_block_t) != 2048); + BUG_ON(sizeof(afs_dirent_t) != 32); if (dentry->d_name.len > 255) { _leave(" = -ENAMETOOLONG"); @@ -495,9 +497,11 @@ unsigned fpos; int ret; - _enter("%s,%p",dentry->d_name.name,nd); + _enter("{sb=%p n=%s},",dentry->d_sb,dentry->d_name.name); + + /* lock down the parent dentry so we can peer at it */ + parent = dget_parent(dentry->d_parent); - parent = dget_parent(dentry); dir = parent->d_inode; inode = dentry->d_inode; diff -Nru a/fs/afs/file.c b/fs/afs/file.c --- a/fs/afs/file.c Thu Sep 11 23:03:13 2003 +++ b/fs/afs/file.c Thu Sep 11 23:03:13 2003 @@ -16,6 +16,7 @@ #include #include #include +#include #include "volume.h" #include "vnode.h" #include @@ -27,6 +28,8 @@ #endif static int afs_file_readpage(struct file *file, struct page *page); +static int afs_file_invalidatepage(struct page *page, unsigned long offset); +static int afs_file_releasepage(struct page *page, int gfp_flags); static ssize_t afs_file_write(struct file *file, const char *buf, size_t size, loff_t *off); @@ -37,7 +40,7 @@ struct file_operations afs_file_file_operations = { .read = generic_file_read, .write = afs_file_write, - .mmap = generic_file_readonly_mmap, + .mmap = generic_file_mmap, #if 0 .open = afs_file_open, .release = afs_file_release, @@ -47,6 +50,10 @@ struct address_space_operations afs_fs_aops = { .readpage = afs_file_readpage, + .sync_page = block_sync_page, + .set_page_dirty = __set_page_dirty_nobuffers, + .releasepage = afs_file_releasepage, + .invalidatepage = afs_file_invalidatepage, }; /*****************************************************************************/ @@ -66,11 +73,48 @@ /*****************************************************************************/ /* + * deal with notification that a page was read from the cache + */ +#ifdef AFS_CACHING_SUPPORT +static void afs_file_readpage_read_complete(void *cookie_data, struct page *page, void *data, + int error) +{ + _enter("%p,%p,%p,%d",cookie_data,page,data,error); + + if (error) + SetPageError(page); + else + SetPageUptodate(page); + unlock_page(page); + +} /* end afs_file_readpage_read_complete() */ +#endif + +/*****************************************************************************/ +/* + * deal with notification that a page was written to the cache + */ +#ifdef AFS_CACHING_SUPPORT +static void afs_file_readpage_write_complete(void *cookie_data, struct page *page, void *data, + int error) +{ + _enter("%p,%p,%p,%d",cookie_data,page,data,error); + + unlock_page(page); + +} /* end afs_file_readpage_write_complete() */ +#endif + +/*****************************************************************************/ +/* * AFS read page from file (or symlink) */ static int afs_file_readpage(struct file *file, struct page *page) { struct afs_rxfs_fetch_descriptor desc; +#ifdef AFS_CACHING_SUPPORT + struct cachefs_page *pageio; +#endif struct inode *inode; afs_vnode_t *vnode; int ret; @@ -88,28 +132,73 @@ if (vnode->flags & AFS_VNODE_DELETED) goto error; - /* work out how much to get and from where */ - desc.fid = vnode->fid; - desc.offset = page->index << PAGE_CACHE_SHIFT; - desc.size = min((size_t)(inode->i_size - desc.offset),(size_t)PAGE_SIZE); - desc.buffer = kmap(page); - - clear_page(desc.buffer); - - /* read the contents of the file from the server into the page */ - ret = afs_vnode_fetch_data(vnode,&desc); - kunmap(page); - if (ret<0) { - if (ret==-ENOENT) { - _debug("got NOENT from server - marking file deleted and stale"); - vnode->flags |= AFS_VNODE_DELETED; - ret = -ESTALE; - } +#ifdef AFS_CACHING_SUPPORT + ret = cachefs_page_get_private(page,&pageio,GFP_NOIO); + if (ret<0) goto error; - } - SetPageUptodate(page); - unlock_page(page); + /* is it cached? */ + ret = cachefs_read_or_alloc_page(vnode->cache, + page, + afs_file_readpage_read_complete, + NULL, + GFP_KERNEL); +#else + ret = -ENOBUFS; +#endif + + switch (ret) { + /* read BIO submitted and wb-journal entry found */ + case 1: + BUG(); // TODO - handle wb-journal match + + /* read BIO submitted (page in cache) */ + case 0: + break; + + /* no page available in cache */ + case -ENOBUFS: + case -ENODATA: + default: + desc.fid = vnode->fid; + desc.offset = page->index << PAGE_CACHE_SHIFT; + desc.size = min((size_t)(inode->i_size - desc.offset),(size_t)PAGE_SIZE); + desc.buffer = kmap(page); + + clear_page(desc.buffer); + + /* read the contents of the file from the server into the page */ + ret = afs_vnode_fetch_data(vnode,&desc); + kunmap(page); + if (ret<0) { + if (ret==-ENOENT) { + _debug("got NOENT from server - marking file deleted and stale"); + vnode->flags |= AFS_VNODE_DELETED; + ret = -ESTALE; + } + +#ifdef AFS_CACHING_SUPPORT + cachefs_uncache_page(vnode->cache,page); +#endif + goto error; + } + + SetPageUptodate(page); + +#ifdef AFS_CACHING_SUPPORT + if (cachefs_write_page(vnode->cache, + page, + afs_file_readpage_write_complete, + NULL, + GFP_KERNEL) != 0 + ) { + cachefs_uncache_page(vnode->cache,page); + unlock_page(page); + } +#else + unlock_page(page); +#endif + } _leave(" = 0"); return 0; @@ -122,3 +211,83 @@ return ret; } /* end afs_file_readpage() */ + +/*****************************************************************************/ +/* + * get a page cookie for the specified page + */ +#ifdef AFS_CACHING_SUPPORT +int afs_cache_get_page_cookie(struct page *page, struct cachefs_page **_page_cookie) +{ + int ret; + + _enter(""); + ret = cachefs_page_get_private(page,_page_cookie,GFP_NOIO); + + _leave(" = %d",ret); + return ret; +} /* end afs_cache_get_page_cookie() */ +#endif + +/*****************************************************************************/ +/* + * invalidate part or all of a page + */ +static int afs_file_invalidatepage(struct page *page, unsigned long offset) +{ + int ret = 1; + + _enter("{%lu},%lu",page->index,offset); + + BUG_ON(!PageLocked(page)); + if (PagePrivate(page)) { +#ifdef AFS_CACHING_SUPPORT + struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); + cachefs_uncache_page(vnode->cache,page); +#endif + + /* + * We release buffers only if the entire page is being invalidated. + * The get_block cached value has been unconditionally invalidated, + * so real IO is not possible anymore. + */ + if (offset == 0) { + BUG_ON(!PageLocked(page)); + + ret = 0; + if (!PageWriteback(page)) + ret = page->mapping->a_ops->releasepage(page, 0); + } + } + + _leave(" = %d",ret); + return ret; +} /* end afs_file_invalidatepage() */ + +/*****************************************************************************/ +/* + * release a page and cleanup its private data + */ +static int afs_file_releasepage(struct page *page, int gfp_flags) +{ + struct cachefs_page *pageio; + + _enter("{%lu},%x",page->index,gfp_flags); + + if (PagePrivate(page)) { +#ifdef AFS_CACHING_SUPPORT + struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); + cachefs_uncache_page(vnode->cache,page); +#endif + + pageio = (struct cachefs_page *) page->private; + page->private = 0; + ClearPagePrivate(page); + + if (pageio) + kfree(pageio); + } + + _leave(" = 0"); + return 0; +} /* end afs_file_releasepage() */ diff -Nru a/fs/afs/inode.c b/fs/afs/inode.c --- a/fs/afs/inode.c Thu Sep 11 23:03:12 2003 +++ b/fs/afs/inode.c Thu Sep 11 23:03:12 2003 @@ -69,17 +69,16 @@ inode->i_uid = vnode->status.owner; inode->i_gid = 0; inode->i_size = vnode->status.size; - inode->i_atime.tv_sec = inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = vnode->status.mtime_server; - inode->i_atime.tv_nsec = - inode->i_mtime.tv_nsec = - inode->i_ctime.tv_nsec = 0; + inode->i_ctime.tv_sec = vnode->status.mtime_server; + inode->i_ctime.tv_nsec = 0; + inode->i_atime = inode->i_mtime = inode->i_ctime; inode->i_blksize = PAGE_CACHE_SIZE; inode->i_blocks = 0; inode->i_version = vnode->fid.unique; inode->i_mapping->a_ops = &afs_fs_aops; /* check to see whether a symbolic link is really a mountpoint */ - if (vnode->status.type==AFS_FTYPE_SYMLINK) { + if (vnode->status.type == AFS_FTYPE_SYMLINK) { afs_mntpt_check_symlink(vnode); if (vnode->flags & AFS_VNODE_MOUNTPOINT) { @@ -105,7 +104,7 @@ ret = afs_vnode_fetch_status(vnode); - if (ret==0) + if (ret == 0) ret = afs_inode_map_status(vnode); return ret; @@ -120,8 +119,8 @@ { struct afs_iget_data *data = opaque; - /* only match inodes with the same version number */ - return inode->i_ino==data->fid.vnode && inode->i_version==data->fid.unique; + return inode->i_ino == data->fid.vnode && + inode->i_version == data->fid.unique; } /* end afs_iget5_test() */ /*****************************************************************************/ @@ -145,20 +144,22 @@ /* * inode retrieval */ -inline int afs_iget(struct super_block *sb, afs_fid_t *fid, struct inode **_inode) +inline int afs_iget(struct super_block *sb, afs_fid_t *fid, + struct inode **_inode) { - struct afs_iget_data data = { .fid = *fid }; + struct afs_iget_data data = { fid: *fid }; struct afs_super_info *as; + struct afs_vnode *vnode; struct inode *inode; - afs_vnode_t *vnode; int ret; - _enter(",{%u,%u,%u},,",fid->vid,fid->vnode,fid->unique); + _enter(",{%u,%u,%u},,", fid->vid, fid->vnode, fid->unique); as = sb->s_fs_info; data.volume = as->volume; - inode = iget5_locked(sb,fid->vnode,afs_iget5_test,afs_iget5_set,&data); + inode = iget5_locked(sb, fid->vnode, afs_iget5_test, afs_iget5_set, + &data); if (!inode) { _leave(" = -ENOMEM"); return -ENOMEM; @@ -173,10 +174,19 @@ *_inode = inode; else iput(inode); - _leave(" = %d",ret); + _leave(" = %d", ret); return ret; } +#ifdef AFS_CACHING_SUPPORT + /* set up caching before reading the status, as fetch-status reads the + * first page of symlinks to see if they're really mntpts */ + cachefs_acquire_cookie(vnode->volume->cache, + NULL, + vnode, + &vnode->cache); +#endif + /* okay... it's a new inode */ vnode->flags |= AFS_VNODE_CHANGED; ret = afs_inode_fetch_status(inode); @@ -187,11 +197,11 @@ unlock_new_inode(inode); *_inode = inode; - _leave(" = 0 [CB { v=%u x=%lu t=%u nix=%u }]", + _leave(" = 0 [CB { v=%u x=%lu t=%u } c=%p]", vnode->cb_version, vnode->cb_timeout.timo_jif, vnode->cb_type, - vnode->nix + vnode->cache ); return 0; @@ -201,7 +211,7 @@ unlock_new_inode(inode); iput(inode); - _leave(" = %d [bad]",ret); + _leave(" = %d [bad]", ret); return ret; } /* end afs_iget() */ @@ -209,7 +219,8 @@ /* * read the attributes of an inode */ -int afs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) +int afs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry, + struct kstat *stat) { struct inode *inode; afs_vnode_t *vnode; @@ -217,23 +228,25 @@ inode = dentry->d_inode; - _enter("{ ino=%lu v=%lu }",inode->i_ino,inode->i_version); + _enter("{ ino=%lu v=%lu }", inode->i_ino, inode->i_version); vnode = AFS_FS_I(inode); ret = afs_inode_fetch_status(inode); - if (ret==-ENOENT) { - _leave(" = %d [%d %p]",ret,atomic_read(&dentry->d_count),dentry->d_inode); + if (ret == -ENOENT) { + _leave(" = %d [%d %p]", + ret, atomic_read(&dentry->d_count), dentry->d_inode); return ret; } - else if (ret<0) { + else if (ret < 0) { make_bad_inode(inode); - _leave(" = %d",ret); + _leave(" = %d", ret); return ret; } - /* transfer attributes from the inode structure to the stat structure */ - generic_fillattr(inode,stat); + /* transfer attributes from the inode structure to the stat + * structure */ + generic_fillattr(inode, stat); _leave(" = 0 CB { v=%u x=%u t=%u }", vnode->cb_version, @@ -261,9 +274,14 @@ vnode->cb_type ); - if (inode->i_ino!=vnode->fid.vnode) BUG(); + BUG_ON(inode->i_ino != vnode->fid.vnode); afs_vnode_give_up_callback(vnode); + +#ifdef AFS_CACHING_SUPPORT + cachefs_relinquish_cookie(vnode->cache, 0); + vnode->cache = NULL; +#endif _leave(""); } /* end afs_clear_inode() */ diff -Nru a/fs/afs/internal.h b/fs/afs/internal.h --- a/fs/afs/internal.h Thu Sep 11 23:03:12 2003 +++ b/fs/afs/internal.h Thu Sep 11 23:03:12 2003 @@ -26,7 +26,7 @@ #define kproto(FMT, a...) printk("### "FMT"\n" , ## a) #define knet(FMT, a...) printk(FMT"\n" , ## a) -#if 0 +#ifdef __KDEBUG #define _enter(FMT, a...) kenter(FMT , ## a) #define _leave(FMT, a...) kleave(FMT , ## a) #define _debug(FMT, a...) kdebug(FMT , ## a) @@ -56,6 +56,9 @@ */ extern struct rw_semaphore afs_proc_cells_sem; extern struct list_head afs_proc_cells; +#ifdef AFS_CACHING_SUPPORT +extern struct cachefs_index_def afs_cache_cell_index_def; +#endif /* * dir.c @@ -70,6 +73,10 @@ extern struct inode_operations afs_file_inode_operations; extern struct file_operations afs_file_file_operations; +#ifdef AFS_CACHING_SUPPORT +extern int afs_cache_get_page_cookie(struct page *page, struct cachefs_page **_page_cookie); +#endif + /* * inode.c */ @@ -78,10 +85,22 @@ extern void afs_clear_inode(struct inode *inode); /* + * main.c + */ +#ifdef AFS_CACHING_SUPPORT +extern struct cachefs_netfs afs_cache_netfs; +#endif + +/* * mntpt.c */ extern struct inode_operations afs_mntpt_inode_operations; extern struct file_operations afs_mntpt_file_operations; +#ifdef AFS_AUTOMOUNT_SUPPORT +extern struct afs_timer afs_mntpt_expiry_timer; +extern struct afs_timer_ops afs_mntpt_expiry_timer_ops; +extern unsigned long afs_mntpt_expiry_timeout; +#endif extern int afs_mntpt_check_symlink(afs_vnode_t *vnode); diff -Nru a/fs/afs/kafsasyncd.c b/fs/afs/kafsasyncd.c --- a/fs/afs/kafsasyncd.c Thu Sep 11 23:03:14 2003 +++ b/fs/afs/kafsasyncd.c Thu Sep 11 23:03:14 2003 @@ -153,8 +153,7 @@ spin_lock(&kafsasyncd_async_lock); /* fold the busy and attention queues together */ - list_splice(&kafsasyncd_async_busyq,&kafsasyncd_async_attnq); - list_del_init(&kafsasyncd_async_busyq); + list_splice_init(&kafsasyncd_async_busyq,&kafsasyncd_async_attnq); /* dequeue kafsasyncd from all their wait queues */ list_for_each(_p,&kafsasyncd_async_attnq) { @@ -197,6 +196,7 @@ spin_lock(&kafsasyncd_async_lock); init_waitqueue_entry(&op->waiter,kafsasyncd_task); + add_wait_queue(&op->call->waitq,&op->waiter); list_del(&op->link); list_add_tail(&op->link,&kafsasyncd_async_busyq); @@ -238,7 +238,10 @@ spin_lock(&kafsasyncd_async_lock); - list_del_init(&op->link); + if (!list_empty(&op->link)) { + list_del_init(&op->link); + remove_wait_queue(&op->call->waitq,&op->waiter); + } spin_unlock(&kafsasyncd_async_lock); diff -Nru a/fs/afs/kafstimod.c b/fs/afs/kafstimod.c --- a/fs/afs/kafstimod.c Thu Sep 11 23:03:13 2003 +++ b/fs/afs/kafstimod.c Thu Sep 11 23:03:13 2003 @@ -82,7 +82,7 @@ for (;;) { unsigned long jif; - unsigned long timeout; + signed long timeout; /* deal with the server being asked to die */ if (kafstimod_die) { @@ -98,18 +98,18 @@ spin_lock(&kafstimod_lock); if (list_empty(&kafstimod_list)) { timeout = MAX_SCHEDULE_TIMEOUT; - } else { - unsigned long tmo; - - timer = list_entry(kafstimod_list.next, - afs_timer_t, link); - tmo = timer->timo_jif; + } + else { + timer = list_entry(kafstimod_list.next,afs_timer_t,link); + timeout = timer->timo_jif; jif = jiffies; - if (time_before_eq(tmo,jif)) + if (time_before_eq((unsigned long)timeout,jif)) goto immediate; - timeout = (long)tmo - (long)jiffies; + else { + timeout = (long)timeout - (long)jiffies; + } } spin_unlock(&kafstimod_lock); @@ -170,7 +170,7 @@ wake_up(&kafstimod_sleepq); _leave(""); -} /* end afs_kafstimod_queue_vlocation() */ +} /* end afs_kafstimod_add_timer() */ /*****************************************************************************/ /* diff -Nru a/fs/afs/main.c b/fs/afs/main.c --- a/fs/afs/main.c Thu Sep 11 23:03:11 2003 +++ b/fs/afs/main.c Thu Sep 11 23:03:11 2003 @@ -17,6 +17,7 @@ #include #include #include +#include "cache.h" #include "cell.h" #include "server.h" #include "fsclient.h" @@ -47,6 +48,18 @@ struct list_head afs_cb_hash_tbl[AFS_CB_HASH_COUNT]; spinlock_t afs_cb_hash_lock = SPIN_LOCK_UNLOCKED; +#ifdef AFS_CACHING_SUPPORT +static struct cachefs_netfs_operations afs_cache_ops = { + .get_page_cookie = afs_cache_get_page_cookie, +}; + +struct cachefs_netfs afs_cache_netfs = { + .name = "afs", + .version = 0, + .ops = &afs_cache_ops, +}; +#endif + /*****************************************************************************/ /* * initialise the AFS client FS module @@ -64,34 +77,41 @@ /* register the /proc stuff */ ret = afs_proc_init(); - if (ret<0) + if (ret < 0) return ret; +#ifdef AFS_CACHING_SUPPORT + /* we want to be able to cache */ + ret = cachefs_register_netfs(&afs_cache_netfs,&afs_cache_cell_index_def); + if (ret < 0) + goto error; +#endif + /* initialise the cell DB */ ret = afs_cell_init(); - if (ret<0) - goto error; + if (ret < 0) + goto error_cache; /* start the timeout daemon */ ret = afs_kafstimod_start(); - if (ret<0) - goto error; + if (ret < 0) + goto error_cache; /* start the async operation daemon */ ret = afs_kafsasyncd_start(); - if (ret<0) + if (ret < 0) goto error_kafstimod; /* create the RxRPC transport */ ret = rxrpc_create_transport(7001,&afs_transport); - if (ret<0) + if (ret < 0) goto error_kafsasyncd; afs_transport->peer_ops = &afs_peer_ops; /* register the filesystems */ ret = afs_fs_init(); - if (ret<0) + if (ret < 0) goto error_transport; return ret; @@ -102,7 +122,11 @@ afs_kafsasyncd_stop(); error_kafstimod: afs_kafstimod_stop(); + error_cache: +#ifdef AFS_CACHING_SUPPORT + cachefs_unregister_netfs(&afs_cache_netfs); error: +#endif afs_cell_purge(); afs_proc_cleanup(); printk(KERN_ERR "kAFS: failed to register: %d\n",ret); @@ -122,6 +146,9 @@ afs_kafstimod_stop(); afs_kafsasyncd_stop(); afs_cell_purge(); +#ifdef AFS_CACHING_SUPPORT + cachefs_unregister_netfs(&afs_cache_netfs); +#endif afs_proc_cleanup(); } /* end afs_exit() */ @@ -142,7 +169,7 @@ /* determine which server the peer resides in (if any) */ ret = afs_server_find_by_peer(peer,&server); - if (ret<0) + if (ret < 0) return ret; /* none that we recognise, so abort */ _debug("Server %p{u=%d}\n",server,atomic_read(&server->usage)); @@ -191,3 +218,48 @@ _leave(""); } /* end afs_discarding_peer() */ + +/*****************************************************************************/ +/* + * clear the dead space between task_struct and kernel stack + * - called by supplying -finstrument-functions to gcc + */ +#if 0 +void __cyg_profile_func_enter (void *this_fn, void *call_site) +__attribute__((no_instrument_function)); + +void __cyg_profile_func_enter (void *this_fn, void *call_site) +{ + asm volatile(" movl %%esp,%%edi \n" + " andl %0,%%edi \n" + " addl %1,%%edi \n" + " movl %%esp,%%ecx \n" + " subl %%edi,%%ecx \n" + " shrl $2,%%ecx \n" + " movl $0xedededed,%%eax \n" + " rep stosl \n" + : + : "i"(~(THREAD_SIZE-1)), "i"(sizeof(struct thread_info)) + : "eax", "ecx", "edi", "memory", "cc" + ); +} + +void __cyg_profile_func_exit(void *this_fn, void *call_site) +__attribute__((no_instrument_function)); + +void __cyg_profile_func_exit(void *this_fn, void *call_site) +{ + asm volatile(" movl %%esp,%%edi \n" + " andl %0,%%edi \n" + " addl %1,%%edi \n" + " movl %%esp,%%ecx \n" + " subl %%edi,%%ecx \n" + " shrl $2,%%ecx \n" + " movl $0xdadadada,%%eax \n" + " rep stosl \n" + : + : "i"(~(THREAD_SIZE-1)), "i"(sizeof(struct thread_info)) + : "eax", "ecx", "edi", "memory", "cc" + ); +} +#endif diff -Nru a/fs/afs/mntpt.c b/fs/afs/mntpt.c --- a/fs/afs/mntpt.c Thu Sep 11 23:03:11 2003 +++ b/fs/afs/mntpt.c Thu Sep 11 23:03:11 2003 @@ -16,24 +16,52 @@ #include #include #include +#include +#include +#include +#include "super.h" +#include "cell.h" #include "volume.h" #include "vnode.h" #include "internal.h" -static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *); +static struct dentry *afs_mntpt_lookup(struct inode *dir, + struct dentry *dentry, + struct nameidata *nd); static int afs_mntpt_open(struct inode *inode, struct file *file); +#ifdef AFS_AUTOMOUNT_SUPPORT +static int afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd); +#endif + struct file_operations afs_mntpt_file_operations = { .open = afs_mntpt_open, }; struct inode_operations afs_mntpt_inode_operations = { .lookup = afs_mntpt_lookup, +#ifdef AFS_AUTOMOUNT_SUPPORT + .follow_link = afs_mntpt_follow_link, +#endif .readlink = page_readlink, .getattr = afs_inode_getattr, }; +#ifdef AFS_AUTOMOUNT_SUPPORT +static LIST_HEAD(afs_vfsmounts); + +static void afs_mntpt_expiry_timed_out(struct afs_timer *timer); + +struct afs_timer_ops afs_mntpt_expiry_timer_ops = { + .timed_out = afs_mntpt_expiry_timed_out, +}; + +struct afs_timer afs_mntpt_expiry_timer; + +unsigned long afs_mntpt_expiry_timeout = 20; +#endif + /*****************************************************************************/ /* * check a symbolic link to see whether it actually encodes a mountpoint @@ -93,8 +121,17 @@ /* * no valid lookup procedure on this sort of dir */ -static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) +static struct dentry *afs_mntpt_lookup(struct inode *dir, + struct dentry *dentry, + struct nameidata *nd) { + kenter("%p,%p{%p{%s},%s}", + dir, + dentry, + dentry->d_parent, + dentry->d_parent ? dentry->d_parent->d_name.name : (const unsigned char*)"", + dentry->d_name.name); + return ERR_PTR(-EREMOTE); } /* end afs_mntpt_lookup() */ @@ -104,5 +141,146 @@ */ static int afs_mntpt_open(struct inode *inode, struct file *file) { + kenter("%p,%p{%p{%s},%s}", + inode, file, + file->f_dentry->d_parent, + file->f_dentry->d_parent ? file->f_dentry->d_parent->d_name.name : (const unsigned char*)"", + file->f_dentry->d_name.name); + return -EREMOTE; } /* end afs_mntpt_open() */ + +#ifdef AFS_AUTOMOUNT_SUPPORT +/*****************************************************************************/ +/* + * create a vfsmount to be automounted + */ +static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt) +{ + struct afs_super_info *super; + struct vfsmount *mnt; + struct page *page = NULL; + size_t size; + char *buf, *devname = NULL, *options = NULL; + int ret; + + kenter("{%s}", mntpt->d_name.name); + + BUG_ON(!mntpt->d_inode); + + ret = -EINVAL; + size = mntpt->d_inode->i_size; + if (size > PAGE_SIZE - 1) + goto error; + + ret = -ENOMEM; + devname = (char *) get_zeroed_page(GFP_KERNEL); + if (!devname) + goto error; + + options = (char *) get_zeroed_page(GFP_KERNEL); + if (!options) + goto error; + + /* read the contents of the AFS special symlink */ + page = read_cache_page(mntpt->d_inode->i_mapping, + 0, + (filler_t*)mntpt->d_inode->i_mapping->a_ops->readpage, + NULL); + if (IS_ERR(page)) { + ret = PTR_ERR(page); + goto error; + } + + ret = -EIO; + wait_on_page_locked(page); + if (!PageUptodate(page) || PageError(page)) + goto error; + + buf = kmap(page); + memcpy(devname, buf, size); + kunmap(page); + page_cache_release(page); + page = NULL; + + /* work out what options we want */ + super = AFS_FS_S(mntpt->d_sb); + memcpy(options, "cell=", 5); + strcpy(options + 5, super->volume->cell->name); + if (super->volume->type == AFSVL_RWVOL) + strcat(options,",rwpath"); + + /* try and do the mount */ + kdebug("--- attempting mount %s -o %s ---", devname, options); + mnt = do_kern_mount("afs", 0, devname, options); + kdebug("--- mount result %p ---", mnt); + + free_page((unsigned long)devname); + free_page((unsigned long)options); + kleave(" = %p",mnt); + return mnt; + + error: + if (page) + page_cache_release(page); + if (devname) + free_page((unsigned long)devname); + if (options) + free_page((unsigned long)options); + kleave(" = %d",ret); + return ERR_PTR(ret); +} /* end afs_mntpt_do_automount() */ + +/*****************************************************************************/ +/* + * follow a link from a mountpoint directory, thus causing it to be mounted + */ +static int afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd) +{ + struct nameidata newnd; + struct vfsmount *newmnt; + int err; + + kenter("%p{%s},{%s:%p{%s}}", + dentry, + dentry->d_name.name, + nd->mnt->mnt_devname, + dentry, + nd->dentry->d_name.name); + + newmnt = afs_mntpt_do_automount(dentry); + if (IS_ERR(newmnt)) + return PTR_ERR(newmnt); + + struct_cpy(&newnd,nd); + newnd.dentry = dentry; + err = do_add_mount(newmnt, &newnd, 0, &afs_vfsmounts); + + if (!err) { + path_release(nd); + mntget(newmnt); + nd->mnt = newmnt; + dget(newmnt->mnt_root); + nd->dentry = newmnt->mnt_root; + } + + kleave(" = %d", err); + return err; +} /* end afs_mntpt_follow_link() */ + +/*****************************************************************************/ +/* + * handle mountpoint expiry timer going off + */ +static void afs_mntpt_expiry_timed_out(struct afs_timer *timer) +{ + kenter(""); + + mark_mounts_for_expiry(&afs_vfsmounts); + + afs_kafstimod_add_timer(&afs_mntpt_expiry_timer, + afs_mntpt_expiry_timeout * HZ); + + kleave(""); +} /* end afs_mntpt_expiry_timed_out() */ +#endif diff -Nru a/fs/afs/mount.h b/fs/afs/mount.h --- a/fs/afs/mount.h Thu Sep 11 23:03:11 2003 +++ b/fs/afs/mount.h Thu Sep 11 23:03:11 2003 @@ -17,7 +17,7 @@ const char *cell; /* name of cell containing volume */ const char *cache; /* name of cache block device */ size_t nservers; /* number of server addresses listed */ - u_int32_t servers[10]; /* IP addresses of servers in this cell */ + uint32_t servers[10]; /* IP addresses of servers in this cell */ }; #endif /* _LINUX_AFS_MOUNT_H */ diff -Nru a/fs/afs/server.c b/fs/afs/server.c --- a/fs/afs/server.c Thu Sep 11 23:03:11 2003 +++ b/fs/afs/server.c Thu Sep 11 23:03:11 2003 @@ -148,6 +148,9 @@ { afs_cell_t *cell; + if (!server) + return; + _enter("%p",server); cell = server->cell; diff -Nru a/fs/afs/super.c b/fs/afs/super.c --- a/fs/afs/super.c Thu Sep 11 23:03:12 2003 +++ b/fs/afs/super.c Thu Sep 11 23:03:12 2003 @@ -29,15 +29,22 @@ #define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */ +struct afs_mount_params { + int rwpath; + struct afs_cell *default_cell; + struct afs_volume *volume; +}; + static inline char *strdup(const char *s) { - char *ns = kmalloc(strlen(s)+1,GFP_KERNEL); + char *ns = kmalloc(strlen(s) + 1, GFP_KERNEL); if (ns) - strcpy(ns,s); + strcpy(ns, s); return ns; } -static void afs_i_init_once(void *foo, kmem_cache_t *cachep, unsigned long flags); +static void afs_i_init_once(void *foo, kmem_cache_t *cachep, + unsigned long flags); static struct super_block *afs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, @@ -66,6 +73,7 @@ }; static kmem_cache_t *afs_inode_cachep; +static atomic_t afs_count_active_inodes; /*****************************************************************************/ /* @@ -75,16 +83,22 @@ { int ret; - kenter(""); + _enter(""); + +#ifdef AFS_AUTOMOUNT_SUPPORT + afs_timer_init(&afs_mntpt_expiry_timer, &afs_mntpt_expiry_timer_ops); +#endif /* create ourselves an inode cache */ + atomic_set(&afs_count_active_inodes, 0); + ret = -ENOMEM; afs_inode_cachep = kmem_cache_create("afs_inode_cache", - sizeof(afs_vnode_t), - 0, - SLAB_HWCACHE_ALIGN|SLAB_RECLAIM_ACCOUNT, - afs_i_init_once, - NULL); + sizeof(afs_vnode_t), + 0, + SLAB_HWCACHE_ALIGN, + afs_i_init_once, + NULL); if (!afs_inode_cachep) { printk(KERN_NOTICE "kAFS: Failed to allocate inode cache\n"); return ret; @@ -92,9 +106,9 @@ /* now export our filesystem to lesser mortals */ ret = register_filesystem(&afs_fs_type); - if (ret<0) { + if (ret < 0) { kmem_cache_destroy(afs_inode_cachep); - kleave(" = %d",ret); + kleave(" = %d", ret); return ret; } @@ -108,11 +122,16 @@ */ void __exit afs_fs_exit(void) { - /* destroy our private inode cache */ - kmem_cache_destroy(afs_inode_cachep); - unregister_filesystem(&afs_fs_type); + if (atomic_read(&afs_count_active_inodes) != 0) { + printk("kAFS: %d active inode objects still present\n", + atomic_read(&afs_count_active_inodes)); + BUG(); + } + + kmem_cache_destroy(afs_inode_cachep); + } /* end afs_fs_exit() */ /*****************************************************************************/ @@ -122,7 +141,7 @@ static int want_arg(char **_value, const char *option) { if (!_value || !*_value || !**_value) { - printk(KERN_NOTICE "kAFS: %s: argument missing\n",option); + printk(KERN_NOTICE "kAFS: %s: argument missing\n", option); return 0; } return 1; @@ -130,27 +149,13 @@ /*****************************************************************************/ /* - * check that there is a value - */ -#if 0 -static int want_value(char **_value, const char *option) -{ - if (!_value || !*_value || !**_value) { - printk(KERN_NOTICE "kAFS: %s: argument incomplete\n",option); - return 0; - } - return 1; -} /* end want_value() */ -#endif - -/*****************************************************************************/ -/* * check that there's no subsequent value */ static int want_no_value(char *const *_value, const char *option) { if (*_value && **_value) { - printk(KERN_NOTICE "kAFS: %s: Invalid argument: %s\n",option,*_value); + printk(KERN_NOTICE "kAFS: %s: Invalid argument: %s\n", + option, *_value); return 0; } return 1; @@ -158,150 +163,55 @@ /*****************************************************************************/ /* - * extract a number from an option string value - */ -#if 0 -static int want_number(char **_value, const char *option, unsigned long *number, - unsigned long limit) -{ - char *value = *_value; - - if (!want_value(_value,option)) - return 0; - - *number = simple_strtoul(value,_value,0); - - if (value==*_value) { - printk(KERN_NOTICE "kAFS: %s: Invalid number: %s\n",option,value); - return 0; - } - - if (*number>limit) { - printk(KERN_NOTICE "kAFS: %s: numeric value %lu > %lu\n",option,*number,limit); - return 0; - } - - return 1; -} /* end want_number() */ -#endif - -/*****************************************************************************/ -/* - * extract a separator from an option string value - */ -#if 0 -static int want_sep(char **_value, const char *option, char sep) -{ - if (!want_value(_value,option)) - return 0; - - if (*(*_value)++ != sep) { - printk(KERN_NOTICE "kAFS: %s: '%c' expected: %s\n",option,sep,*_value-1); - return 0; - } - - return 1; -} /* end want_number() */ -#endif - -/*****************************************************************************/ -/* - * extract an IP address from an option string value - */ -#if 0 -static int want_ipaddr(char **_value, const char *option, struct in_addr *addr) -{ - unsigned long number[4]; - - if (!want_value(_value,option)) - return 0; - - if (!want_number(_value,option,&number[0],255) || - !want_sep(_value,option,'.') || - !want_number(_value,option,&number[1],255) || - !want_sep(_value,option,'.') || - !want_number(_value,option,&number[2],255) || - !want_sep(_value,option,'.') || - !want_number(_value,option,&number[3],255)) - return 0; - - ((u8*)addr)[0] = number[0]; - ((u8*)addr)[1] = number[1]; - ((u8*)addr)[2] = number[2]; - ((u8*)addr)[3] = number[3]; - - return 1; -} /* end want_numeric() */ -#endif - -/*****************************************************************************/ -/* * parse the mount options * - this function has been shamelessly adapted from the ext3 fs which shamelessly adapted it from * the msdos fs */ -static int afs_super_parse_options(struct afs_super_info *as, char *options, const char ** devname) +static int afs_super_parse_options(struct afs_mount_params *params, + char *options, + const char **devname) { char *key, *value; int ret; - _enter("%s",options); + _enter("%s", options); + + options[PAGE_SIZE - 1] = 0; ret = 0; - while ((key = strsep(&options,","))) + while ((key = strsep(&options, ","))) { - value = strchr(key,'='); + value = strchr(key, '='); if (value) *value++ = 0; - printk("kAFS: KEY: %s, VAL:%s\n",key,value?:"-"); + printk("kAFS: KEY: %s, VAL:%s\n", key, value ?: "-"); - if (strcmp(key,"rwpath")==0) { - if (!want_no_value(&value,"rwpath")) return -EINVAL; - as->rwparent = 1; + if (strcmp(key, "rwpath") == 0) { + if (!want_no_value(&value, "rwpath")) + return -EINVAL; + params->rwpath = 1; continue; } - else if (strcmp(key,"vol")==0) { - if (!want_arg(&value,"vol")) return -EINVAL; + else if (strcmp(key, "vol") == 0) { + if (!want_arg(&value, "vol")) + return -EINVAL; *devname = value; continue; } - -#if 0 - if (strcmp(key,"servers")==0) { - if (!want_arg(&value,"servers")) return -EINVAL; - - _debug("servers=%s",value); - - for (;;) { - struct in_addr addr; - - if (!want_ipaddr(&value,"servers",&addr)) - return -EINVAL; - - ret = afs_create_server(as->cell,&addr,&as->server); - if (ret<0) { - printk("kAFS: unable to create server: %d\n",ret); - return ret; - } - - if (!*value) - break; - - if (as->server) { - printk(KERN_NOTICE - "kAFS: only one server can be specified\n"); - return -EINVAL; - } - - if (!want_sep(&value,"servers",':')) - return -EINVAL; - } + else if (strcmp(key, "cell") == 0) { + if (!want_arg(&value, "cell")) + return -EINVAL; + afs_put_cell(params->default_cell); + ret = afs_cell_lookup(value, + strlen(value), + ¶ms->default_cell); + if (ret < 0) + return -EINVAL; continue; } -#endif - printk("kAFS: Unknown mount option: '%s'\n",key); + printk("kAFS: Unknown mount option: '%s'\n", key); ret = -EINVAL; goto error; } @@ -309,67 +219,48 @@ ret = 0; error: - _leave(" = %d",ret); - + _leave(" = %d", ret); return ret; } /* end afs_super_parse_options() */ -struct fill_super_options { - const char *dev_name; - void *options; -}; +/*****************************************************************************/ +/* + * check a superblock to see if it's the one we're looking for + */ +static int afs_test_super(struct super_block *sb, void *data) +{ + struct afs_mount_params *params = data; + struct afs_super_info *as = sb->s_fs_info; + + return as->volume == params->volume; +} /* end afs_test_super() */ /*****************************************************************************/ /* * fill in the superblock */ -static int afs_fill_super(struct super_block *sb, void *_data, int silent) +static int afs_fill_super(struct super_block *sb, void *data, int silent) { + struct afs_mount_params *params = data; struct afs_super_info *as = NULL; struct dentry *root = NULL; struct inode *inode = NULL; afs_fid_t fid; - struct fill_super_options *data = _data; - const char *devname; - char *options; int ret; - _enter(""); - - if (!data) { - _leave(" = -EINVAL"); - return -EINVAL; - } - devname = data->dev_name; - options = data->options; - if (options) - options[PAGE_SIZE-1] = 0; + kenter(""); /* allocate a superblock info record */ - as = kmalloc(sizeof(struct afs_super_info),GFP_KERNEL); + as = kmalloc(sizeof(struct afs_super_info), GFP_KERNEL); if (!as) { _leave(" = -ENOMEM"); return -ENOMEM; } - memset(as,0,sizeof(struct afs_super_info)); + memset(as, 0, sizeof(struct afs_super_info)); - /* parse the options */ - if (options) { - ret = afs_super_parse_options(as,options,&devname); - if (ret<0) - goto error; - if (!devname) { - printk("kAFS: no volume name specified\n"); - ret = -EINVAL; - goto error; - } - } - - /* parse the device name */ - ret = afs_volume_lookup(devname,as->rwparent,&as->volume); - if (ret<0) - goto error; + afs_get_volume(params->volume); + as->volume = params->volume; /* fill in the superblock */ sb->s_blocksize = PAGE_CACHE_SIZE; @@ -382,8 +273,8 @@ fid.vid = as->volume->vid; fid.vnode = 1; fid.unique = 1; - ret = afs_iget(sb,&fid,&inode); - if (ret<0) + ret = afs_iget(sb, &fid, &inode); + if (ret < 0) goto error; ret = -ENOMEM; @@ -393,19 +284,18 @@ sb->s_root = root; - _leave(" = 0"); + kleave(" = 0"); return 0; error: - if (root) dput(root); - if (inode) iput(inode); - if (as) { - if (as->volume) afs_put_volume(as->volume); - kfree(as); - } + dput(root); + iput(inode); + afs_put_volume(as->volume); + kfree(as); + sb->s_fs_info = NULL; - _leave(" = %d",ret); + kleave(" = %d", ret); return ret; } /* end afs_fill_super() */ @@ -414,32 +304,72 @@ * get an AFS superblock * - TODO: don't use get_sb_nodev(), but rather call sget() directly */ -static struct super_block * -afs_get_sb(struct file_system_type *fs_type, int flags, - const char *dev_name, void *options) +static struct super_block *afs_get_sb(struct file_system_type *fs_type, + int flags, + const char *dev_name, + void *options) { + struct afs_mount_params params; struct super_block *sb; - struct fill_super_options data = { dev_name, options }; int ret; - _enter(",,%s,%p",dev_name,options); + _enter(",,%s,%p", dev_name, options); + + memset(¶ms, 0, sizeof(params)); /* start the cache manager */ ret = afscm_start(); - if (ret<0) { - _leave(" = %d",ret); + if (ret < 0) { + _leave(" = %d", ret); return ERR_PTR(ret); } + /* parse the options */ + if (options) { + ret = afs_super_parse_options(¶ms, options, &dev_name); + if (ret < 0) + goto error; + if (!dev_name) { + printk("kAFS: no volume name specified\n"); + ret = -EINVAL; + goto error; + } + } + + /* parse the device name */ + ret = afs_volume_lookup(dev_name, + params.default_cell, + params.rwpath, + ¶ms.volume); + if (ret < 0) + goto error; + /* allocate a deviceless superblock */ - sb = get_sb_nodev(fs_type, flags, &data, afs_fill_super); - if (IS_ERR(sb)) { - afscm_stop(); - return sb; + sb = sget(fs_type, afs_test_super, set_anon_super, ¶ms); + if (IS_ERR(sb)) + goto error; + + sb->s_flags = flags; + + ret = afs_fill_super(sb, ¶ms, flags & MS_VERBOSE ? 1 : 0); + if (ret < 0) { + up_write(&sb->s_umount); + deactivate_super(sb); + goto error; } + sb->s_flags |= MS_ACTIVE; - _leave(""); + afs_put_volume(params.volume); + afs_put_cell(params.default_cell); + _leave(" = %p", sb); return sb; + + error: + afs_put_volume(params.volume); + afs_put_cell(params.default_cell); + afscm_stop(); + _leave(" = %d", ret); + return ERR_PTR(ret); } /* end afs_get_sb() */ /*****************************************************************************/ @@ -452,11 +382,7 @@ _enter(""); - if (as) { - if (as->volume) afs_put_volume(as->volume); - } - - /* stop the cache manager */ + afs_put_volume(as->volume); afscm_stop(); _leave(""); @@ -466,18 +392,21 @@ /* * initialise an inode cache slab element prior to any use */ -static void afs_i_init_once(void *_vnode, kmem_cache_t *cachep, unsigned long flags) +static void afs_i_init_once(void *_vnode, kmem_cache_t *cachep, + unsigned long flags) { afs_vnode_t *vnode = (afs_vnode_t *) _vnode; - if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) { - memset(vnode,0,sizeof(*vnode)); + if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == + SLAB_CTOR_CONSTRUCTOR) { + memset(vnode, 0, sizeof(*vnode)); inode_init_once(&vnode->vfs_inode); init_waitqueue_head(&vnode->update_waitq); spin_lock_init(&vnode->lock); INIT_LIST_HEAD(&vnode->cb_link); INIT_LIST_HEAD(&vnode->cb_hash_link); - afs_timer_init(&vnode->cb_timeout,&afs_vnode_cb_timed_out_ops); + afs_timer_init(&vnode->cb_timeout, + &afs_vnode_cb_timed_out_ops); } } /* end afs_i_init_once() */ @@ -490,16 +419,19 @@ { afs_vnode_t *vnode; - vnode = (afs_vnode_t *) kmem_cache_alloc(afs_inode_cachep,SLAB_KERNEL); + vnode = (afs_vnode_t *) + kmem_cache_alloc(afs_inode_cachep, SLAB_KERNEL); if (!vnode) return NULL; - memset(&vnode->fid,0,sizeof(vnode->fid)); - memset(&vnode->status,0,sizeof(vnode->status)); + atomic_inc(&afs_count_active_inodes); + + memset(&vnode->fid, 0, sizeof(vnode->fid)); + memset(&vnode->status, 0, sizeof(vnode->status)); - vnode->volume = NULL; - vnode->update_cnt = 0; - vnode->flags = 0; + vnode->volume = NULL; + vnode->update_cnt = 0; + vnode->flags = 0; return &vnode->vfs_inode; } /* end afs_alloc_inode() */ @@ -510,6 +442,10 @@ */ static void afs_destroy_inode(struct inode *inode) { - _enter("{%lu}",inode->i_ino); + _enter("{%lu}", inode->i_ino); + kmem_cache_free(afs_inode_cachep, AFS_FS_I(inode)); + + atomic_dec(&afs_count_active_inodes); + } /* end afs_destroy_inode() */ diff -Nru a/fs/afs/super.h b/fs/afs/super.h --- a/fs/afs/super.h Thu Sep 11 23:03:14 2003 +++ b/fs/afs/super.h Thu Sep 11 23:03:14 2003 @@ -29,7 +29,7 @@ */ struct afs_super_info { - afs_volume_t *volume; /* volume record */ + struct afs_volume *volume; /* volume record */ char rwparent; /* T if parent is R/W AFS volume */ }; diff -Nru a/fs/afs/types.h b/fs/afs/types.h --- a/fs/afs/types.h Thu Sep 11 23:03:12 2003 +++ b/fs/afs/types.h Thu Sep 11 23:03:12 2003 @@ -33,26 +33,13 @@ typedef struct afs_volume afs_volume_t; typedef struct afs_volume_info afs_volume_info_t; -typedef struct afsc_cache afsc_cache_t; -typedef struct afsc_cache_cell afsc_cache_cell_t; -typedef struct afsc_cache_vldb afsc_cache_vldb_t; -typedef struct afsc_cell_record afsc_cell_record_t; -typedef struct afsc_inode afsc_inode_t; -typedef struct afsc_io afsc_io_t; -typedef struct afsc_io_subop afsc_io_subop_t; -typedef struct afsc_io_queue afsc_io_queue_t; -typedef struct afsc_super_block afsc_super_block_t; -typedef struct afsc_vldb_record afsc_vldb_record_t; -typedef struct afsc_vnode_catalogue afsc_vnode_catalogue_t; -typedef struct afsc_vnode_meta afsc_vnode_meta_t; - typedef struct afsvl_dbentry afsvl_dbentry_t; typedef enum { AFSVL_RWVOL, /* read/write volume */ AFSVL_ROVOL, /* read-only volume */ AFSVL_BACKVOL, /* backup volume */ -} afs_voltype_t; +} __attribute__((packed)) afs_voltype_t; extern const char *afs_voltypes[]; diff -Nru a/fs/afs/vlclient.c b/fs/afs/vlclient.c --- a/fs/afs/vlclient.c Thu Sep 11 23:03:11 2003 +++ b/fs/afs/vlclient.c Thu Sep 11 23:03:11 2003 @@ -176,8 +176,8 @@ /* * look up a volume location database entry by name */ -int afs_rxvl_get_entry_by_name(afs_server_t *server, const char *volname, - afsc_vldb_record_t *entry) +int afs_rxvl_get_entry_by_name(afs_server_t *server, const char *volname, unsigned volnamesz, + struct afs_cache_vlocation *entry) { DECLARE_WAITQUEUE(myself,current); @@ -189,29 +189,29 @@ int ret, loop; u32 *bp, param[2], zero; - _enter(",%s,",volname); + _enter(",%*.*s,%u,", volnamesz, volnamesz, volname, volnamesz); - memset(entry,0,sizeof(*entry)); + memset(entry, 0, sizeof(*entry)); /* get hold of the vlserver connection */ - ret = afs_server_get_vlconn(server,&conn); + ret = afs_server_get_vlconn(server, &conn); if (ret<0) goto out; /* create a call through that connection */ - ret = rxrpc_create_call(conn,NULL,NULL,afs_rxvl_aemap,&call); - if (ret<0) { - printk("kAFS: Unable to create call: %d\n",ret); + ret = rxrpc_create_call(conn, NULL, NULL, afs_rxvl_aemap, &call); + if (ret < 0) { + printk("kAFS: Unable to create call: %d\n", ret); goto out_put_conn; } call->app_opcode = VLGETENTRYBYNAME; /* we want to get event notifications from the call */ - add_wait_queue(&call->waitq,&myself); + add_wait_queue(&call->waitq, &myself); /* marshall the parameters */ - piov[1].iov_len = strlen(volname); - piov[1].iov_base = (char*)volname; + piov[1].iov_len = volnamesz; + piov[1].iov_base = (char*) volname; zero = 0; piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3; @@ -224,16 +224,16 @@ piov[0].iov_base = param; /* send the parameters to the server */ - ret = rxrpc_call_write_data(call,3,piov,RXRPC_LAST_PACKET,GFP_NOFS,0,&sent); + ret = rxrpc_call_write_data(call, 3, piov, RXRPC_LAST_PACKET, GFP_NOFS, 0, &sent); if (ret<0) goto abort; /* wait for the reply to completely arrive */ - bp = rxrpc_call_alloc_scratch(call,384); + bp = rxrpc_call_alloc_scratch(call, 384); - ret = rxrpc_call_read_data(call,bp,384,RXRPC_CALL_READ_BLOCK|RXRPC_CALL_READ_ALL); - if (ret<0) { - if (ret==-ECONNABORTED) { + ret = rxrpc_call_read_data(call, bp, 384, RXRPC_CALL_READ_BLOCK|RXRPC_CALL_READ_ALL); + if (ret < 0) { + if (ret == -ECONNABORTED) { ret = call->app_errno; goto out_unwait; } @@ -255,9 +255,9 @@ for (loop=0; loop<8; loop++) { tmp = ntohl(*bp++); - if (tmp & AFS_VLSF_RWVOL ) entry->srvtmask[loop] |= AFSC_VOL_STM_RW; - if (tmp & AFS_VLSF_ROVOL ) entry->srvtmask[loop] |= AFSC_VOL_STM_RO; - if (tmp & AFS_VLSF_BACKVOL) entry->srvtmask[loop] |= AFSC_VOL_STM_BAK; + if (tmp & AFS_VLSF_RWVOL ) entry->srvtmask[loop] |= AFS_VOL_VTM_RW; + if (tmp & AFS_VLSF_ROVOL ) entry->srvtmask[loop] |= AFS_VOL_VTM_RO; + if (tmp & AFS_VLSF_BACKVOL) entry->srvtmask[loop] |= AFS_VOL_VTM_BAK; } entry->vid[0] = ntohl(*bp++); @@ -267,26 +267,26 @@ bp++; /* clone ID */ tmp = ntohl(*bp++); /* flags */ - if (tmp & AFS_VLF_RWEXISTS ) entry->vidmask |= AFSC_VOL_STM_RW; - if (tmp & AFS_VLF_ROEXISTS ) entry->vidmask |= AFSC_VOL_STM_RO; - if (tmp & AFS_VLF_BACKEXISTS) entry->vidmask |= AFSC_VOL_STM_BAK; + if (tmp & AFS_VLF_RWEXISTS ) entry->vidmask |= AFS_VOL_VTM_RW; + if (tmp & AFS_VLF_ROEXISTS ) entry->vidmask |= AFS_VOL_VTM_RO; + if (tmp & AFS_VLF_BACKEXISTS) entry->vidmask |= AFS_VOL_VTM_BAK; ret = -ENOMEDIUM; if (!entry->vidmask) goto abort; /* success */ - entry->ctime = get_seconds(); + entry->rtime = get_seconds(); ret = 0; out_unwait: set_current_state(TASK_RUNNING); - remove_wait_queue(&call->waitq,&myself); + remove_wait_queue(&call->waitq, &myself); rxrpc_put_call(call); out_put_conn: rxrpc_put_connection(conn); out: - _leave(" = %d",ret); + _leave(" = %d", ret); return ret; abort: @@ -303,7 +303,7 @@ int afs_rxvl_get_entry_by_id(afs_server_t *server, afs_volid_t volid, afs_voltype_t voltype, - afsc_vldb_record_t *entry) + struct afs_cache_vlocation *entry) { DECLARE_WAITQUEUE(myself,current); @@ -375,9 +375,9 @@ for (loop=0; loop<8; loop++) { tmp = ntohl(*bp++); - if (tmp & AFS_VLSF_RWVOL ) entry->srvtmask[loop] |= AFSC_VOL_STM_RW; - if (tmp & AFS_VLSF_ROVOL ) entry->srvtmask[loop] |= AFSC_VOL_STM_RO; - if (tmp & AFS_VLSF_BACKVOL) entry->srvtmask[loop] |= AFSC_VOL_STM_BAK; + if (tmp & AFS_VLSF_RWVOL ) entry->srvtmask[loop] |= AFS_VOL_VTM_RW; + if (tmp & AFS_VLSF_ROVOL ) entry->srvtmask[loop] |= AFS_VOL_VTM_RO; + if (tmp & AFS_VLSF_BACKVOL) entry->srvtmask[loop] |= AFS_VOL_VTM_BAK; } entry->vid[0] = ntohl(*bp++); @@ -387,9 +387,9 @@ bp++; /* clone ID */ tmp = ntohl(*bp++); /* flags */ - if (tmp & AFS_VLF_RWEXISTS ) entry->vidmask |= AFSC_VOL_STM_RW; - if (tmp & AFS_VLF_ROEXISTS ) entry->vidmask |= AFSC_VOL_STM_RO; - if (tmp & AFS_VLF_BACKEXISTS) entry->vidmask |= AFSC_VOL_STM_BAK; + if (tmp & AFS_VLF_RWEXISTS ) entry->vidmask |= AFS_VOL_VTM_RW; + if (tmp & AFS_VLF_ROEXISTS ) entry->vidmask |= AFS_VOL_VTM_RO; + if (tmp & AFS_VLF_BACKEXISTS) entry->vidmask |= AFS_VOL_VTM_BAK; ret = -ENOMEDIUM; if (!entry->vidmask) @@ -401,13 +401,13 @@ entry->servers[1].s_addr = htonl(0xac101243); entry->servers[2].s_addr = htonl(0xac10125b /*0xac10125b*/); - entry->srvtmask[0] = AFSC_VOL_STM_RO; - entry->srvtmask[1] = AFSC_VOL_STM_RO; - entry->srvtmask[2] = AFSC_VOL_STM_RO | AFSC_VOL_STM_RW; + entry->srvtmask[0] = AFS_VOL_VTM_RO; + entry->srvtmask[1] = AFS_VOL_VTM_RO; + entry->srvtmask[2] = AFS_VOL_VTM_RO | AFS_VOL_VTM_RW; #endif /* success */ - entry->ctime = get_seconds(); + entry->rtime = get_seconds(); ret = 0; out_unwait: @@ -520,7 +520,7 @@ * attend to the asynchronous get VLDB entry by ID */ int afs_rxvl_get_entry_by_id_async2(afs_async_op_t *op, - afsc_vldb_record_t *entry) + struct afs_cache_vlocation *entry) { unsigned *bp, tmp; int loop, ret; @@ -550,9 +550,9 @@ for (loop=0; loop<8; loop++) { tmp = ntohl(*bp++); - if (tmp & AFS_VLSF_RWVOL ) entry->srvtmask[loop] |= AFSC_VOL_STM_RW; - if (tmp & AFS_VLSF_ROVOL ) entry->srvtmask[loop] |= AFSC_VOL_STM_RO; - if (tmp & AFS_VLSF_BACKVOL) entry->srvtmask[loop] |= AFSC_VOL_STM_BAK; + if (tmp & AFS_VLSF_RWVOL ) entry->srvtmask[loop] |= AFS_VOL_VTM_RW; + if (tmp & AFS_VLSF_ROVOL ) entry->srvtmask[loop] |= AFS_VOL_VTM_RO; + if (tmp & AFS_VLSF_BACKVOL) entry->srvtmask[loop] |= AFS_VOL_VTM_BAK; } entry->vid[0] = ntohl(*bp++); @@ -562,9 +562,9 @@ bp++; /* clone ID */ tmp = ntohl(*bp++); /* flags */ - if (tmp & AFS_VLF_RWEXISTS ) entry->vidmask |= AFSC_VOL_STM_RW; - if (tmp & AFS_VLF_ROEXISTS ) entry->vidmask |= AFSC_VOL_STM_RO; - if (tmp & AFS_VLF_BACKEXISTS) entry->vidmask |= AFSC_VOL_STM_BAK; + if (tmp & AFS_VLF_RWEXISTS ) entry->vidmask |= AFS_VOL_VTM_RW; + if (tmp & AFS_VLF_ROEXISTS ) entry->vidmask |= AFS_VOL_VTM_RO; + if (tmp & AFS_VLF_BACKEXISTS) entry->vidmask |= AFS_VOL_VTM_BAK; ret = -ENOMEDIUM; if (!entry->vidmask) { @@ -578,13 +578,13 @@ entry->servers[1].s_addr = htonl(0xac101243); entry->servers[2].s_addr = htonl(0xac10125b /*0xac10125b*/); - entry->srvtmask[0] = AFSC_VOL_STM_RO; - entry->srvtmask[1] = AFSC_VOL_STM_RO; - entry->srvtmask[2] = AFSC_VOL_STM_RO | AFSC_VOL_STM_RW; + entry->srvtmask[0] = AFS_VOL_VTM_RO; + entry->srvtmask[1] = AFS_VOL_VTM_RO; + entry->srvtmask[2] = AFS_VOL_VTM_RO | AFS_VOL_VTM_RW; #endif /* success */ - entry->ctime = get_seconds(); + entry->rtime = get_seconds(); ret = 0; goto done; } @@ -626,7 +626,8 @@ case RXRPC_CSTATE_CLNT_GOT_REPLY: if (call->app_read_count==0) break; - printk("kAFS: Reply bigger than expected {cst=%u asyn=%d mark=%Zu rdy=%Zu pr=%u%s}", + printk("kAFS: Reply bigger than expected" + " {cst=%u asyn=%d mark=%Zu rdy=%Zu pr=%u%s}", call->app_call_state, call->app_async_read, call->app_mark, diff -Nru a/fs/afs/vlclient.h b/fs/afs/vlclient.h --- a/fs/afs/vlclient.h Thu Sep 11 23:03:11 2003 +++ b/fs/afs/vlclient.h Thu Sep 11 23:03:11 2003 @@ -46,7 +46,7 @@ }; /* maps to "struct vldbentry" in vvl-spec.pdf */ -struct afsvl_dbentry { +struct afs_vldbentry { char name[65]; /* name of volume (including NUL char) */ afs_voltype_t type; /* volume type */ unsigned num_servers; /* num servers that hold instances of this vol */ @@ -77,19 +77,20 @@ /* look up a volume location database entry by name */ extern int afs_rxvl_get_entry_by_name(afs_server_t *server, const char *volname, - afsc_vldb_record_t *entry); + unsigned volnamesz, + struct afs_cache_vlocation *entry); /* look up a volume location database entry by ID */ extern int afs_rxvl_get_entry_by_id(afs_server_t *server, afs_volid_t volid, afs_voltype_t voltype, - afsc_vldb_record_t *entry); + struct afs_cache_vlocation *entry); extern int afs_rxvl_get_entry_by_id_async(afs_async_op_t *op, afs_volid_t volid, afs_voltype_t voltype); extern int afs_rxvl_get_entry_by_id_async2(afs_async_op_t *op, - afsc_vldb_record_t *entry); + struct afs_cache_vlocation *entry); #endif /* _LINUX_AFS_VLCLIENT_H */ diff -Nru a/fs/afs/vlocation.c b/fs/afs/vlocation.c --- a/fs/afs/vlocation.c Thu Sep 11 23:03:12 2003 +++ b/fs/afs/vlocation.c Thu Sep 11 23:03:12 2003 @@ -56,6 +56,19 @@ static afs_vlocation_t *afs_vlocation_update; /* VL currently being updated */ static spinlock_t afs_vlocation_update_lock = SPIN_LOCK_UNLOCKED; /* lock guarding update queue */ +#ifdef AFS_CACHING_SUPPORT +static cachefs_match_val_t afs_vlocation_cache_match(void *target, const void *entry); +static void afs_vlocation_cache_update(void *source, void *entry); + +struct cachefs_index_def afs_vlocation_cache_index_def = { + .name = "vldb", + .data_size = sizeof(struct afs_cache_vlocation), + .keys[0] = { CACHEFS_INDEX_KEYS_ASCIIZ, 64 }, + .match = afs_vlocation_cache_match, + .update = afs_vlocation_cache_update, +}; +#endif + /*****************************************************************************/ /* * iterate through the VL servers in a cell until one of them admits knowing about the volume in @@ -64,21 +77,23 @@ */ static int afs_vlocation_access_vl_by_name(afs_vlocation_t *vlocation, const char *name, - afsc_vldb_record_t *vldb) + unsigned namesz, + struct afs_cache_vlocation *vldb) { afs_server_t *server = NULL; afs_cell_t *cell = vlocation->cell; int count, ret; - _enter("%s,%s,",cell->name,name); + _enter("%s,%*.*s,%u", cell->name, namesz, namesz, name, namesz); ret = -ENOMEDIUM; for (count=cell->vl_naddrs; count>0; count--) { _debug("CellServ[%hu]: %08x", - cell->vl_curr_svix,cell->vl_addrs[cell->vl_curr_svix].s_addr); + cell->vl_curr_svix, + cell->vl_addrs[cell->vl_curr_svix].s_addr); /* try and create a server */ - ret = afs_server_lookup(cell,&cell->vl_addrs[cell->vl_curr_svix],&server); + ret = afs_server_lookup(cell, &cell->vl_addrs[cell->vl_curr_svix], &server); switch (ret) { case 0: break; @@ -90,7 +105,7 @@ } /* attempt to access the VL server */ - ret = afs_rxvl_get_entry_by_name(server,name,vldb); + ret = afs_rxvl_get_entry_by_name(server, name, namesz, vldb); switch (ret) { case 0: afs_put_server(server); @@ -107,7 +122,7 @@ } up_write(&server->sem); afs_put_server(server); - if (ret==-ENOMEM || ret==-ENONET) + if (ret == -ENOMEM || ret == -ENONET) goto out; goto rotate; case -ENOMEDIUM: @@ -140,21 +155,22 @@ static int afs_vlocation_access_vl_by_id(afs_vlocation_t *vlocation, afs_volid_t volid, afs_voltype_t voltype, - afsc_vldb_record_t *vldb) + struct afs_cache_vlocation *vldb) { afs_server_t *server = NULL; afs_cell_t *cell = vlocation->cell; int count, ret; - _enter("%s,%x,%d,",cell->name,volid,voltype); + _enter("%s,%x,%d,", cell->name, volid, voltype); ret = -ENOMEDIUM; for (count=cell->vl_naddrs; count>0; count--) { _debug("CellServ[%hu]: %08x", - cell->vl_curr_svix,cell->vl_addrs[cell->vl_curr_svix].s_addr); + cell->vl_curr_svix, + cell->vl_addrs[cell->vl_curr_svix].s_addr); /* try and create a server */ - ret = afs_server_lookup(cell,&cell->vl_addrs[cell->vl_curr_svix],&server); + ret = afs_server_lookup(cell, &cell->vl_addrs[cell->vl_curr_svix], &server); switch (ret) { case 0: break; @@ -166,7 +182,7 @@ } /* attempt to access the VL server */ - ret = afs_rxvl_get_entry_by_id(server,volid,voltype,vldb); + ret = afs_rxvl_get_entry_by_id(server, volid, voltype, vldb); switch (ret) { case 0: afs_put_server(server); @@ -183,7 +199,7 @@ } up_write(&server->sem); afs_put_server(server); - if (ret==-ENOMEM || ret==-ENONET) + if (ret == -ENOMEM || ret == -ENONET) goto out; goto rotate; case -ENOMEDIUM: @@ -216,74 +232,83 @@ * - lookup in the local cache if not able to find on the VL server * - insert/update in the local cache if did get a VL response */ -int afs_vlocation_lookup(afs_cell_t *cell, const char *name, afs_vlocation_t **_vlocation) +int afs_vlocation_lookup(afs_cell_t *cell, const char *name, unsigned namesz, + afs_vlocation_t **_vlocation) { - afsc_vldb_record_t vldb; + struct afs_cache_vlocation vldb; struct list_head *_p; afs_vlocation_t *vlocation; afs_voltype_t voltype; afs_volid_t vid; int active = 0, ret; - _enter(",%s,%s,",cell->name,name); + _enter("{%s},%*.*s,%u,", cell->name, namesz, namesz, name, namesz); - if (strlen(name)>sizeof(vlocation->vldb.name)) { + if (namesz > sizeof(vlocation->vldb.name)) { _leave(" = -ENAMETOOLONG"); return -ENAMETOOLONG; } /* search the cell's active list first */ - list_for_each(_p,&cell->vl_list) { - vlocation = list_entry(_p,afs_vlocation_t,link); - if (strncmp(vlocation->vldb.name,name,sizeof(vlocation->vldb.name))==0) + list_for_each(_p, &cell->vl_list) { + vlocation = list_entry(_p, afs_vlocation_t, link); + if (namesz < sizeof(vlocation->vldb.name) && + vlocation->vldb.name[namesz] != '\0') + continue; + + if (memcmp(vlocation->vldb.name, name, namesz) == 0) goto found_in_memory; } /* search the cell's graveyard list second */ spin_lock(&cell->vl_gylock); - list_for_each(_p,&cell->vl_graveyard) { - vlocation = list_entry(_p,afs_vlocation_t,link); - if (strncmp(vlocation->vldb.name,name,sizeof(vlocation->vldb.name))==0) + list_for_each(_p, &cell->vl_graveyard) { + vlocation = list_entry(_p, afs_vlocation_t, link); + if (namesz < sizeof(vlocation->vldb.name) && + vlocation->vldb.name[namesz] != '\0') + continue; + + if (memcmp(vlocation->vldb.name, name, namesz) == 0) goto found_in_graveyard; } spin_unlock(&cell->vl_gylock); /* not in the cell's in-memory lists - create a new record */ - vlocation = kmalloc(sizeof(afs_vlocation_t),GFP_KERNEL); + vlocation = kmalloc(sizeof(afs_vlocation_t), GFP_KERNEL); if (!vlocation) return -ENOMEM; - memset(vlocation,0,sizeof(afs_vlocation_t)); - atomic_set(&vlocation->usage,1); + memset(vlocation, 0, sizeof(afs_vlocation_t)); + atomic_set(&vlocation->usage, 1); INIT_LIST_HEAD(&vlocation->link); rwlock_init(&vlocation->lock); - strncpy(vlocation->vldb.name,name,sizeof(vlocation->vldb.name)); + memcpy(vlocation->vldb.name, name, namesz); - afs_timer_init(&vlocation->timeout,&afs_vlocation_timer_ops); - afs_timer_init(&vlocation->upd_timer,&afs_vlocation_update_timer_ops); - afs_async_op_init(&vlocation->upd_op,&afs_vlocation_update_op_ops); - - INIT_LIST_HEAD(&vlocation->caches); + afs_timer_init(&vlocation->timeout, &afs_vlocation_timer_ops); + afs_timer_init(&vlocation->upd_timer, &afs_vlocation_update_timer_ops); + afs_async_op_init(&vlocation->upd_op, &afs_vlocation_update_op_ops); afs_get_cell(cell); vlocation->cell = cell; - list_add_tail(&vlocation->link,&cell->vl_list); + list_add_tail(&vlocation->link, &cell->vl_list); -#if 0 - /* search local cache if wasn't in memory */ - ret = afsc_lookup_vlocation(vlocation); - switch (ret) { - default: goto error; /* disk error */ - case 0: goto found_in_cache; /* pulled from local cache into memory */ - case -ENOENT: break; /* not in local cache */ - } +#ifdef AFS_CACHING_SUPPORT + /* we want to store it in the cache, plus it might already be encached */ + cachefs_acquire_cookie(cell->cache, + &afs_volume_cache_index_def, + vlocation, + &vlocation->cache); + + if (vlocation->valid) + goto found_in_cache; #endif /* try to look up an unknown volume in the cell VL databases by name */ - ret = afs_vlocation_access_vl_by_name(vlocation,name,&vldb); + ret = afs_vlocation_access_vl_by_name(vlocation, name, namesz, &vldb); if (ret<0) { - printk("kAFS: failed to locate '%s' in cell '%s'\n",name,cell->name); + printk("kAFS: failed to locate '%*.*s' in cell '%s'\n", + namesz, namesz, name, cell->name); goto error; } @@ -294,7 +319,7 @@ _debug("found in graveyard"); atomic_inc(&vlocation->usage); list_del(&vlocation->link); - list_add_tail(&vlocation->link,&cell->vl_list); + list_add_tail(&vlocation->link, &cell->vl_list); spin_unlock(&cell->vl_gylock); afs_kafstimod_del_timer(&vlocation->timeout); @@ -308,30 +333,32 @@ active: active = 1; -/* found_in_cache: */ +#ifdef AFS_CACHING_SUPPORT + found_in_cache: +#endif /* try to look up a cached volume in the cell VL databases by ID */ _debug("found in cache"); _debug("Locally Cached: %s %02x { %08x(%x) %08x(%x) %08x(%x) }", vlocation->vldb.name, vlocation->vldb.vidmask, - ntohl(vlocation->vldb.servers[0].s_addr),vlocation->vldb.srvtmask[0], - ntohl(vlocation->vldb.servers[1].s_addr),vlocation->vldb.srvtmask[1], - ntohl(vlocation->vldb.servers[2].s_addr),vlocation->vldb.srvtmask[2] + ntohl(vlocation->vldb.servers[0].s_addr), vlocation->vldb.srvtmask[0], + ntohl(vlocation->vldb.servers[1].s_addr), vlocation->vldb.srvtmask[1], + ntohl(vlocation->vldb.servers[2].s_addr), vlocation->vldb.srvtmask[2] ); _debug("Vids: %08x %08x %08x", - vlocation->vldb.vid[0],vlocation->vldb.vid[1],vlocation->vldb.vid[2]); + vlocation->vldb.vid[0], vlocation->vldb.vid[1], vlocation->vldb.vid[2]); - if (vlocation->vldb.vidmask & AFSC_VOL_STM_RW) { + if (vlocation->vldb.vidmask & AFS_VOL_VTM_RW) { vid = vlocation->vldb.vid[0]; voltype = AFSVL_RWVOL; } - else if (vlocation->vldb.vidmask & AFSC_VOL_STM_RO) { + else if (vlocation->vldb.vidmask & AFS_VOL_VTM_RO) { vid = vlocation->vldb.vid[1]; voltype = AFSVL_ROVOL; } - else if (vlocation->vldb.vidmask & AFSC_VOL_STM_BAK) { + else if (vlocation->vldb.vidmask & AFS_VOL_VTM_BAK) { vid = vlocation->vldb.vid[2]; voltype = AFSVL_BACKVOL; } @@ -341,41 +368,44 @@ voltype = 0; } - ret = afs_vlocation_access_vl_by_id(vlocation,vid,voltype,&vldb); + ret = afs_vlocation_access_vl_by_id(vlocation, vid, voltype, &vldb); switch (ret) { /* net error */ default: - printk("kAFS: failed to volume '%s' (%x) up in '%s': %d\n", - name,vid,cell->name,ret); + printk("kAFS: failed to volume '%*.*s' (%x) up in '%s': %d\n", + namesz, namesz, name, vid, cell->name, ret); goto error; /* pulled from local cache into memory */ - case 0: + case 0: goto found_on_vlserver; /* uh oh... looks like the volume got deleted */ case -ENOMEDIUM: - printk("kAFS: volume '%s' (%x) does not exist '%s'\n",name,vid,cell->name); + printk("kAFS: volume '%*.*s' (%x) does not exist '%s'\n", + namesz, namesz, name, vid, cell->name); /* TODO: make existing record unavailable */ goto error; } found_on_vlserver: - _debug("Done VL Lookup: %s %02x { %08x(%x) %08x(%x) %08x(%x) }", - name, + _debug("Done VL Lookup: %*.*s %02x { %08x(%x) %08x(%x) %08x(%x) }", + namesz, namesz, name, vldb.vidmask, - ntohl(vldb.servers[0].s_addr),vldb.srvtmask[0], - ntohl(vldb.servers[1].s_addr),vldb.srvtmask[1], - ntohl(vldb.servers[2].s_addr),vldb.srvtmask[2] + ntohl(vldb.servers[0].s_addr), vldb.srvtmask[0], + ntohl(vldb.servers[1].s_addr), vldb.srvtmask[1], + ntohl(vldb.servers[2].s_addr), vldb.srvtmask[2] ); - _debug("Vids: %08x %08x %08x",vldb.vid[0],vldb.vid[1],vldb.vid[2]); + _debug("Vids: %08x %08x %08x", vldb.vid[0], vldb.vid[1], vldb.vid[2]); - if (strncmp(vldb.name,name,sizeof(vlocation->vldb.name))!=0) - printk("kAFS: name of volume '%s' changed to '%s' on server\n",name,vldb.name); + if ((namesz < sizeof(vlocation->vldb.name) && vlocation->vldb.name[namesz] != '\0') || + memcmp(vldb.name, name, namesz) != 0) + printk("kAFS: name of volume '%*.*s' changed to '%s' on server\n", + namesz, namesz, name, vldb.name); - memcpy(&vlocation->vldb,&vldb,sizeof(vlocation->vldb)); + memcpy(&vlocation->vldb, &vldb, sizeof(vlocation->vldb)); #if 0 /* add volume entry to local cache */ @@ -384,7 +414,7 @@ goto error; #endif - afs_kafstimod_add_timer(&vlocation->upd_timer,10*HZ); + afs_kafstimod_add_timer(&vlocation->upd_timer, 10*HZ); *_vlocation = vlocation; _leave(" = 0 (%p)",vlocation); @@ -397,10 +427,10 @@ } else { list_del(&vlocation->link); - afs_put_cell(vlocation->cell); -#if 0 - afs_put_cache(vlocation->cache); +#ifdef AFS_CACHING_SUPPORT + cachefs_relinquish_cookie(vlocation->cache, 0); #endif + afs_put_cell(vlocation->cell); kfree(vlocation); } } @@ -414,12 +444,17 @@ * finish using a volume location record * - caller must have cell->vol_sem write-locked */ -void __afs_put_vlocation(afs_vlocation_t *vlocation) +void __afs_put_vlocation(struct afs_vlocation *vlocation) { - afs_cell_t *cell = vlocation->cell; + struct afs_cell *cell; + + if (!vlocation) + return; _enter("%s",vlocation->vldb.name); + cell = vlocation->cell; + /* sanity check */ if (atomic_read(&vlocation->usage)<=0) BUG(); @@ -453,11 +488,13 @@ */ void afs_put_vlocation(afs_vlocation_t *vlocation) { - afs_cell_t *cell = vlocation->cell; + if (vlocation) { + struct afs_cell *cell = vlocation->cell; - down_write(&cell->vl_sem); - __afs_put_vlocation(vlocation); - up_write(&cell->vl_sem); + down_write(&cell->vl_sem); + __afs_put_vlocation(vlocation); + up_write(&cell->vl_sem); + } } /* end afs_put_vlocation() */ /*****************************************************************************/ @@ -489,10 +526,10 @@ } /* we can now destroy it properly */ - afs_put_cell(cell); -#if 0 - afs_put_cache(vlocation->cache); +#ifdef AFS_CACHING_SUPPORT + cachefs_relinquish_cookie(vlocation->cache,0); #endif + afs_put_cell(cell); kfree(vlocation); @@ -513,15 +550,15 @@ vlocation->vldb.name,vlocation->upd_first_svix,vlocation->upd_curr_svix); /* try to look up a cached volume in the cell VL databases by ID */ - if (vlocation->vldb.vidmask & AFSC_VOL_STM_RW) { + if (vlocation->vldb.vidmask & AFS_VOL_VTM_RW) { vid = vlocation->vldb.vid[0]; voltype = AFSVL_RWVOL; } - else if (vlocation->vldb.vidmask & AFSC_VOL_STM_RO) { + else if (vlocation->vldb.vidmask & AFS_VOL_VTM_RO) { vid = vlocation->vldb.vid[1]; voltype = AFSVL_ROVOL; } - else if (vlocation->vldb.vidmask & AFSC_VOL_STM_BAK) { + else if (vlocation->vldb.vidmask & AFS_VOL_VTM_BAK) { vid = vlocation->vldb.vid[2]; voltype = AFSVL_BACKVOL; } @@ -571,10 +608,8 @@ printk("kAFS: Abandoning VL update '%s': %d\n",vlocation->vldb.name,ret); /* discard the server record */ - if (vlocation->upd_op.server) { - afs_put_server(vlocation->upd_op.server); - vlocation->upd_op.server = NULL; - } + afs_put_server(vlocation->upd_op.server); + vlocation->upd_op.server = NULL; spin_lock(&afs_vlocation_update_lock); afs_vlocation_update = NULL; @@ -669,7 +704,7 @@ */ static void afs_vlocation_update_attend(afs_async_op_t *op) { - afsc_vldb_record_t vldb; + struct afs_cache_vlocation vldb; afs_vlocation_t *vlocation = list_entry(op,afs_vlocation_t,upd_op); unsigned tmp; int ret; @@ -762,11 +797,9 @@ try_next: vlocation->upd_busy_cnt = 0; - if (vlocation->upd_op.server) { - /* discard the server record */ - afs_put_server(vlocation->upd_op.server); - vlocation->upd_op.server = NULL; - } + /* discard the server record */ + afs_put_server(vlocation->upd_op.server); + vlocation->upd_op.server = NULL; tmp = vlocation->cell->vl_naddrs; if (tmp==0) @@ -822,3 +855,68 @@ _leave(""); } /* end afs_vlocation_update_discard() */ + +/*****************************************************************************/ +/* + * match a VLDB record stored in the cache + * - may also load target from entry + */ +#ifdef AFS_CACHING_SUPPORT +static cachefs_match_val_t afs_vlocation_cache_match(void *target, + const void *entry) +{ + const struct afs_cache_vlocation *vldb = entry; + struct afs_vlocation *vlocation = target; + + _enter("{%s},{%s}", vlocation->vldb.name, vldb->name); + + if (strncmp(vlocation->vldb.name, + vldb->name, + sizeof(vldb->name)) == 0) { + if (!vlocation->valid || + vlocation->vldb.rtime == vldb->rtime) { + struct_cpy(&vlocation->vldb, vldb); + vlocation->valid = 1; + _leave(" = SUCCESS [c->m]"); + return CACHEFS_MATCH_SUCCESS; + } + /* need to update cache if cached info differs */ + else if (memcmp(&vlocation->vldb, vldb, sizeof(*vldb)) != 0) { + /* delete if VIDs for this name differ */ + if (memcmp(&vlocation->vldb.vid, + &vldb->vid, + sizeof(vldb->vid)) != 0) { + _leave(" = DELETE"); + return CACHEFS_MATCH_SUCCESS_DELETE; + } + + _leave(" = UPDATE"); + return CACHEFS_MATCH_SUCCESS_UPDATE; + } + else { + _leave(" = SUCCESS"); + return CACHEFS_MATCH_SUCCESS; + } + } + + _leave(" = FAILED"); + return CACHEFS_MATCH_FAILED; +} /* end afs_vlocation_cache_match() */ +#endif + +/*****************************************************************************/ +/* + * update a VLDB record stored in the cache + */ +#ifdef AFS_CACHING_SUPPORT +static void afs_vlocation_cache_update(void *source, void *entry) +{ + struct afs_cache_vlocation *vldb = entry; + struct afs_vlocation *vlocation = source; + + _enter(""); + + struct_cpy(vldb,&vlocation->vldb); + +} /* end afs_vlocation_cache_update() */ +#endif diff -Nru a/fs/afs/vnode.c b/fs/afs/vnode.c --- a/fs/afs/vnode.c Thu Sep 11 23:03:12 2003 +++ b/fs/afs/vnode.c Thu Sep 11 23:03:12 2003 @@ -29,6 +29,19 @@ .timed_out = afs_vnode_cb_timed_out, }; +#ifdef AFS_CACHING_SUPPORT +static cachefs_match_val_t afs_vnode_cache_match(void *target, const void *entry); +static void afs_vnode_cache_update(void *source, void *entry); + +struct cachefs_index_def afs_vnode_cache_index_def = { + .name = "vnode", + .data_size = sizeof(struct afs_cache_vnode), + .keys[0] = { CACHEFS_INDEX_KEYS_BIN, 4 }, + .match = afs_vnode_cache_match, + .update = afs_vnode_cache_update, +}; +#endif + /*****************************************************************************/ /* * handle a callback timing out @@ -61,8 +74,7 @@ spin_unlock(&vnode->lock); - if (oldserver) - afs_put_server(oldserver); + afs_put_server(oldserver); _leave(""); } /* end afs_vnode_cb_timed_out() */ @@ -126,8 +138,7 @@ wake_up_all(&vnode->update_waitq); - if (oldserver) - afs_put_server(oldserver); + afs_put_server(oldserver); _leave(""); @@ -272,7 +283,7 @@ /*****************************************************************************/ /* * break any outstanding callback on a vnode - * - only relevant to server that issued it + * - only relevent to server that issued it */ int afs_vnode_give_up_callback(afs_vnode_t *vnode) { @@ -314,3 +325,56 @@ _leave(" = %d",ret); return ret; } /* end afs_vnode_give_up_callback() */ + +/*****************************************************************************/ +/* + * match a vnode record stored in the cache + */ +#ifdef AFS_CACHING_SUPPORT +static cachefs_match_val_t afs_vnode_cache_match(void *target, const void *entry) +{ + const struct afs_cache_vnode *cvnode = entry; + struct afs_vnode *vnode = target; + + _enter("{%x,%x,%Lx},{%x,%x,%Lx}", + vnode->fid.vnode, + vnode->fid.unique, + vnode->status.version, + cvnode->vnode_id, + cvnode->vnode_unique, + cvnode->data_version); + + if (vnode->fid.vnode != cvnode->vnode_id) { + _leave(" = FAILED"); + return CACHEFS_MATCH_FAILED; + } + + if (vnode->fid.unique != cvnode->vnode_unique || + vnode->status.version != cvnode->data_version) { + _leave(" = DELETE"); + return CACHEFS_MATCH_SUCCESS_DELETE; + } + + _leave(" = SUCCESS"); + return CACHEFS_MATCH_SUCCESS; +} /* end afs_vnode_cache_match() */ +#endif + +/*****************************************************************************/ +/* + * update a vnode record stored in the cache + */ +#ifdef AFS_CACHING_SUPPORT +static void afs_vnode_cache_update(void *source, void *entry) +{ + struct afs_cache_vnode *cvnode = entry; + struct afs_vnode *vnode = source; + + _enter(""); + + cvnode->vnode_id = vnode->fid.vnode; + cvnode->vnode_unique = vnode->fid.unique; + cvnode->data_version = vnode->status.version; + +} /* end afs_vnode_cache_update() */ +#endif diff -Nru a/fs/afs/vnode.h b/fs/afs/vnode.h --- a/fs/afs/vnode.h Thu Sep 11 23:03:11 2003 +++ b/fs/afs/vnode.h Thu Sep 11 23:03:11 2003 @@ -15,6 +15,7 @@ #include #include "server.h" #include "kafstimod.h" +#include "cache.h" #ifdef __KERNEL__ @@ -22,16 +23,33 @@ /*****************************************************************************/ /* + * vnode catalogue entry + */ +struct afs_cache_vnode +{ + afs_vnodeid_t vnode_id; /* vnode ID */ + unsigned vnode_unique; /* vnode ID uniquifier */ + afs_dataversion_t data_version; /* data version */ +}; + +#ifdef AFS_CACHING_SUPPORT +extern struct cachefs_index_def afs_vnode_cache_index_def; +#endif + +/*****************************************************************************/ +/* * AFS inode private data */ struct afs_vnode { struct inode vfs_inode; /* the VFS's inode record */ - afs_volume_t *volume; /* volume on which vnode resides */ - afs_fid_t fid; /* the file identifier for this inode */ - afs_file_status_t status; /* AFS status info for this file */ - unsigned nix; /* vnode index in cache */ + struct afs_volume *volume; /* volume on which vnode resides */ + struct afs_fid fid; /* the file identifier for this inode */ + struct afs_file_status status; /* AFS status info for this file */ +#ifdef AFS_CACHING_SUPPORT + struct cachefs_cookie *cache; /* caching cookie */ +#endif wait_queue_head_t update_waitq; /* status fetch waitqueue */ unsigned update_cnt; /* number of outstanding ops that will update the @@ -43,10 +61,10 @@ #define AFS_VNODE_MOUNTPOINT 0x00000004 /* set if vnode is a mountpoint symlink */ /* outstanding callback notification on this file */ - afs_server_t *cb_server; /* server that made the current promise */ + struct afs_server *cb_server; /* server that made the current promise */ struct list_head cb_link; /* link in server's promises list */ struct list_head cb_hash_link; /* link in master callback hash */ - afs_timer_t cb_timeout; /* timeout on promise */ + struct afs_timer cb_timeout; /* timeout on promise */ unsigned cb_version; /* callback version */ unsigned cb_expiry; /* callback expiry time */ afs_callback_type_t cb_type; /* type of callback */ diff -Nru a/fs/afs/volume.c b/fs/afs/volume.c --- a/fs/afs/volume.c Thu Sep 11 23:03:11 2003 +++ b/fs/afs/volume.c Thu Sep 11 23:03:11 2003 @@ -16,7 +16,9 @@ #include #include #include "volume.h" +#include "vnode.h" #include "cell.h" +#include "cache.h" #include "cmservice.h" #include "fsclient.h" #include "vlclient.h" @@ -24,6 +26,20 @@ const char *afs_voltypes[] = { "R/W", "R/O", "BAK" }; +#ifdef AFS_CACHING_SUPPORT +static cachefs_match_val_t afs_volume_cache_match(void *target, const void *entry); +static void afs_volume_cache_update(void *source, void *entry); + +struct cachefs_index_def afs_volume_cache_index_def = { + .name = "volume", + .data_size = sizeof(struct afs_cache_vhash), + .keys[0] = { CACHEFS_INDEX_KEYS_BIN, 1 }, + .keys[1] = { CACHEFS_INDEX_KEYS_BIN, 1 }, + .match = afs_volume_cache_match, + .update = afs_volume_cache_update, +}; +#endif + /*****************************************************************************/ /* * lookup a volume by name @@ -43,19 +59,19 @@ * - Rule 2: If parent volume is R/O, then mount R/O volume by preference, R/W if not available * - Rule 3: If parent volume is R/W, then only mount R/W volume unless explicitly told otherwise */ -int afs_volume_lookup(const char *name, int rwparent, afs_volume_t **_volume) +int afs_volume_lookup(const char *name, struct afs_cell *cell, int rwpath, + afs_volume_t **_volume) { - afs_vlocation_t *vlocation = NULL; + struct afs_vlocation *vlocation = NULL; + struct afs_volume *volume = NULL; afs_voltype_t type; - afs_volume_t *volume = NULL; - afs_cell_t *cell = NULL; - char *cellname, *volname, *suffix; + const char *cellname, *volname, *suffix; char srvtmask; - int force, ret, loop; + int force, ret, loop, cellnamesz, volnamesz; - _enter(",%s,",name); + _enter("%s,,%d,", name, rwpath); - if (!name || (name[0]!='%' && name[0]!='#') || !name[1]) { + if (!name || (name[0] != '%' && name[0] != '#') || !name[1]) { printk("kAFS: unparsable volume name\n"); return -EINVAL; } @@ -64,24 +80,22 @@ force = 0; type = AFSVL_ROVOL; - if (rwparent || name[0]=='%') { + if (rwpath || name[0] == '%') { type = AFSVL_RWVOL; force = 1; } - suffix = strrchr(name,'.'); + suffix = strrchr(name, '.'); if (suffix) { - if (strcmp(suffix,".readonly")==0) { + if (strcmp(suffix, ".readonly") == 0) { type = AFSVL_ROVOL; force = 1; } - else if (strcmp(suffix,".backup")==0) { + else if (strcmp(suffix, ".backup") == 0) { type = AFSVL_BACKVOL; force = 1; } - else if (suffix[1]==0) { - *suffix = 0; - suffix = NULL; + else if (suffix[1] == 0) { } else { suffix = NULL; @@ -90,38 +104,45 @@ /* split the cell and volume names */ name++; - volname = strchr(name,':'); + volname = strchr(name, ':'); if (volname) { - *volname++ = 0; cellname = name; + cellnamesz = volname - name; } else { volname = name; cellname = NULL; + cellnamesz = 0; } - _debug("CELL:%s VOLUME:%s SUFFIX:%s TYPE:%d%s", - cellname,volname,suffix?:"-",type,force?" FORCE":""); + volnamesz = suffix ? suffix - volname : strlen(volname); - /* lookup the cell record */ - ret = afs_cell_lookup(cellname,&cell); - if (ret<0) - printk("kAFS: unable to lookup cell '%s'\n",cellname?:""); + _debug("CELL:%*.*s [%p] VOLUME:%*.*s SUFFIX:%s TYPE:%d%s", + cellnamesz, cellnamesz, cellname ?: "", cell, + volnamesz, volnamesz, volname, suffix ?: "-", + type, + force ? " FORCE" : ""); - if (cellname) volname[-1] = ':'; - if (ret<0) - goto error; + /* lookup the cell record */ + if (cellname || !cell) { + ret = afs_cell_lookup(cellname, cellnamesz, &cell); + if (ret<0) { + printk("kAFS: unable to lookup cell '%s'\n", cellname ?: ""); + goto error; + } + } + else { + afs_get_cell(cell); + } /* lookup the volume location record */ - if (suffix) *suffix = 0; - ret = afs_vlocation_lookup(cell,volname,&vlocation); - if (suffix) *suffix = '.'; - if (ret<0) + ret = afs_vlocation_lookup(cell, volname, volnamesz, &vlocation); + if (ret < 0) goto error; /* make the final decision on the type we want */ ret = -ENOMEDIUM; - if (force && !(vlocation->vldb.vidmask & (1<vldb.vidmask & (1 << type))) goto error; srvtmask = 0; @@ -129,13 +150,13 @@ srvtmask |= vlocation->vldb.srvtmask[loop]; if (force) { - if (!(srvtmask & (1 <usage,1); - volume->type = type; - volume->type_force = force; - volume->cell = cell; - volume->vid = vlocation->vldb.vid[type]; + memset(volume, 0, sizeof(afs_volume_t)); + atomic_set(&volume->usage, 1); + volume->type = type; + volume->type_force = force; + volume->cell = cell; + volume->vid = vlocation->vldb.vid[type]; init_rwsem(&volume->server_sem); @@ -183,15 +204,20 @@ } /* attach the cache and volume location */ -#if 0 - afs_get_cache(cache); volume->cache = cache; +#ifdef AFS_CACHING_SUPPORT + cachefs_acquire_cookie(vlocation->cache, + &afs_vnode_cache_index_def, + volume, + &volume->cache); #endif - afs_get_vlocation(vlocation); volume->vlocation = vlocation; + + afs_get_vlocation(vlocation); + volume->vlocation = vlocation; vlocation->vols[type] = volume; success: - _debug("kAFS selected %s volume %08x",afs_voltypes[volume->type],volume->vid); + _debug("kAFS selected %s volume %08x", afs_voltypes[volume->type], volume->vid); *_volume = volume; ret = 0; @@ -199,18 +225,17 @@ error_up: up_write(&cell->vl_sem); error: - if (vlocation) afs_put_vlocation(vlocation); - if (cell) afs_put_cell(cell); + afs_put_vlocation(vlocation); + afs_put_cell(cell); - _leave(" = %d (%p)",ret,volume); + _leave(" = %d (%p)", ret, volume); return ret; error_discard: up_write(&cell->vl_sem); for (loop=volume->nservers-1; loop>=0; loop--) - if (volume->servers[loop]) - afs_put_server(volume->servers[loop]); + afs_put_server(volume->servers[loop]); kfree(volume); goto error; @@ -225,6 +250,9 @@ afs_vlocation_t *vlocation; int loop; + if (!volume) + return; + _enter("%p",volume); vlocation = volume->vlocation; @@ -246,16 +274,14 @@ up_write(&vlocation->cell->vl_sem); - afs_put_vlocation(vlocation); - /* finish cleaning up the volume */ -#if 0 - if (volume->cache) afs_put_cache(volume->cache); +#ifdef AFS_CACHING_SUPPORT + cachefs_relinquish_cookie(volume->cache,0); #endif + afs_put_vlocation(vlocation); for (loop=volume->nservers-1; loop>=0; loop--) - if (volume->servers[loop]) - afs_put_server(volume->servers[loop]); + afs_put_server(volume->servers[loop]); kfree(volume); @@ -428,3 +454,42 @@ return 0; } /* end afs_volume_release_fileserver() */ + +/*****************************************************************************/ +/* + * match a volume hash record stored in the cache + */ +#ifdef AFS_CACHING_SUPPORT +static cachefs_match_val_t afs_volume_cache_match(void *target, const void *entry) +{ + const struct afs_cache_vhash *vhash = entry; + struct afs_volume *volume = target; + + _enter("{%u},{%u}", volume->type, vhash->vtype); + + if (volume->type == vhash->vtype) { + _leave(" = SUCCESS"); + return CACHEFS_MATCH_SUCCESS; + } + + _leave(" = FAILED"); + return CACHEFS_MATCH_FAILED; +} /* end afs_volume_cache_match() */ +#endif + +/*****************************************************************************/ +/* + * update a volume hash record stored in the cache + */ +#ifdef AFS_CACHING_SUPPORT +static void afs_volume_cache_update(void *source, void *entry) +{ + struct afs_cache_vhash *vhash = entry; + struct afs_volume *volume = source; + + _enter(""); + + vhash->vtype = volume->type; + +} /* end afs_volume_cache_update() */ +#endif diff -Nru a/fs/afs/volume.h b/fs/afs/volume.h --- a/fs/afs/volume.h Thu Sep 11 23:03:13 2003 +++ b/fs/afs/volume.h Thu Sep 11 23:03:13 2003 @@ -16,7 +16,7 @@ #include "fsclient.h" #include "kafstimod.h" #include "kafsasyncd.h" -#include "cache-layout.h" +#include "cache.h" #define __packed __attribute__((packed)) @@ -30,21 +30,60 @@ /*****************************************************************************/ /* + * entry in the cached volume location catalogue + */ +struct afs_cache_vlocation +{ + uint8_t name[64]; /* volume name (lowercase, padded with NULs) */ + uint8_t nservers; /* number of entries used in servers[] */ + uint8_t vidmask; /* voltype mask for vid[] */ + uint8_t srvtmask[8]; /* voltype masks for servers[] */ +#define AFS_VOL_VTM_RW 0x01 /* R/W version of the volume is available (on this server) */ +#define AFS_VOL_VTM_RO 0x02 /* R/O version of the volume is available (on this server) */ +#define AFS_VOL_VTM_BAK 0x04 /* backup version of the volume is available (on this server) */ + + afs_volid_t vid[3]; /* volume IDs for R/W, R/O and Bak volumes */ + struct in_addr servers[8]; /* fileserver addresses */ + time_t rtime; /* last retrieval time */ +}; + +#ifdef AFS_CACHING_SUPPORT +extern struct cachefs_index_def afs_vlocation_cache_index_def; +#endif + +/*****************************************************************************/ +/* + * volume -> vnode hash table entry + */ +struct afs_cache_vhash +{ + afs_voltype_t vtype; /* which volume variation */ + uint8_t hash_bucket; /* which hash bucket this represents */ +} __attribute__((packed)); + +#ifdef AFS_CACHING_SUPPORT +extern struct cachefs_index_def afs_volume_cache_index_def; +#endif + +/*****************************************************************************/ +/* * AFS volume location record */ struct afs_vlocation { atomic_t usage; struct list_head link; /* link in cell volume location list */ - afs_timer_t timeout; /* decaching timer */ - afs_cell_t *cell; /* cell to which volume belongs */ - struct list_head caches; /* backing caches */ - afsc_vldb_record_t vldb; /* volume information DB record */ + struct afs_timer timeout; /* decaching timer */ + struct afs_cell *cell; /* cell to which volume belongs */ +#ifdef AFS_CACHING_SUPPORT + struct cachefs_cookie *cache; /* caching cookie */ +#endif + struct afs_cache_vlocation vldb; /* volume information DB record */ struct afs_volume *vols[3]; /* volume access record pointer (index by type) */ rwlock_t lock; /* access lock */ unsigned long read_jif; /* time at which last read from vlserver */ - afs_timer_t upd_timer; /* update timer */ - afs_async_op_t upd_op; /* update operation */ + struct afs_timer upd_timer; /* update timer */ + struct afs_async_op upd_op; /* update operation */ afs_vlocation_upd_t upd_state; /* update state */ unsigned short upd_first_svix; /* first server index during update */ unsigned short upd_curr_svix; /* current server index during update */ @@ -53,13 +92,16 @@ unsigned short valid; /* T if valid */ }; -extern int afs_vlocation_lookup(afs_cell_t *cell, const char *name, afs_vlocation_t **_vlocation); +extern int afs_vlocation_lookup(struct afs_cell *cell, + const char *name, + unsigned namesz, + struct afs_vlocation **_vlocation); #define afs_get_vlocation(V) do { atomic_inc(&(V)->usage); } while(0) -extern void __afs_put_vlocation(afs_vlocation_t *vlocation); -extern void afs_put_vlocation(afs_vlocation_t *vlocation); -extern void afs_vlocation_do_timeout(afs_vlocation_t *vlocation); +extern void __afs_put_vlocation(struct afs_vlocation *vlocation); +extern void afs_put_vlocation(struct afs_vlocation *vlocation); +extern void afs_vlocation_do_timeout(struct afs_vlocation *vlocation); /*****************************************************************************/ /* @@ -68,25 +110,34 @@ struct afs_volume { atomic_t usage; - afs_cell_t *cell; /* cell to which belongs (unrefd ptr) */ - afs_vlocation_t *vlocation; /* volume location */ + struct afs_cell *cell; /* cell to which belongs (unrefd ptr) */ + struct afs_vlocation *vlocation; /* volume location */ +#ifdef AFS_CACHING_SUPPORT + struct cachefs_cookie *cache; /* caching cookie */ +#endif afs_volid_t vid; /* volume ID */ afs_voltype_t __packed type; /* type of volume */ char type_force; /* force volume type (suppress R/O -> R/W) */ unsigned short nservers; /* number of server slots filled */ unsigned short rjservers; /* number of servers discarded due to -ENOMEDIUM */ - afs_server_t *servers[8]; /* servers on which volume resides (ordered) */ + struct afs_server *servers[8]; /* servers on which volume resides (ordered) */ struct rw_semaphore server_sem; /* lock for accessing current server */ }; -extern int afs_volume_lookup(const char *name, int ro, afs_volume_t **_volume); +extern int afs_volume_lookup(const char *name, + struct afs_cell *cell, + int rwpath, + struct afs_volume **_volume); #define afs_get_volume(V) do { atomic_inc(&(V)->usage); } while(0) -extern void afs_put_volume(afs_volume_t *volume); +extern void afs_put_volume(struct afs_volume *volume); -extern int afs_volume_pick_fileserver(afs_volume_t *volume, afs_server_t **_server); +extern int afs_volume_pick_fileserver(struct afs_volume *volume, + struct afs_server **_server); -extern int afs_volume_release_fileserver(afs_volume_t *volume, afs_server_t *server, int result); +extern int afs_volume_release_fileserver(struct afs_volume *volume, + struct afs_server *server, + int result); #endif /* _LINUX_AFS_VOLUME_H */ diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c --- a/fs/binfmt_elf.c Thu Sep 11 23:03:12 2003 +++ b/fs/binfmt_elf.c Thu Sep 11 23:03:12 2003 @@ -1023,6 +1023,7 @@ elf->e_ident[EI_CLASS] = ELF_CLASS; elf->e_ident[EI_DATA] = ELF_DATA; elf->e_ident[EI_VERSION] = EV_CURRENT; + elf->e_ident[EI_OSABI] = ELF_OSABI; memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD); elf->e_type = ET_CORE; diff -Nru a/fs/dcache.c b/fs/dcache.c --- a/fs/dcache.c Thu Sep 11 23:03:11 2003 +++ b/fs/dcache.c Thu Sep 11 23:03:11 2003 @@ -82,7 +82,7 @@ /* * Release the dentry's inode, using the filesystem * d_iput() operation if defined. - * Called with dcache_lock held, drops it. + * Called with dcache_lock and per dentry lock held, drops both. */ static inline void dentry_iput(struct dentry * dentry) { @@ -90,13 +90,16 @@ if (inode) { dentry->d_inode = NULL; list_del_init(&dentry->d_alias); + spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); if (dentry->d_op && dentry->d_op->d_iput) dentry->d_op->d_iput(dentry, inode); else iput(inode); - } else + } else { + spin_unlock(&dentry->d_lock); spin_unlock(&dcache_lock); + } } /* @@ -177,9 +180,8 @@ dentry_stat.nr_unused--; } list_del(&dentry->d_child); - spin_unlock(&dentry->d_lock); dentry_stat.nr_dentry--; /* For d_free, below */ - /* drops the lock, at that point nobody can reach this dentry */ + /*drops the locks, at that point nobody can reach this dentry */ dentry_iput(dentry); parent = dentry->d_parent; d_free(dentry); @@ -341,7 +343,6 @@ __d_drop(dentry); list_del(&dentry->d_child); - spin_unlock(&dentry->d_lock); dentry_stat.nr_dentry--; /* For d_free, below */ dentry_iput(dentry); parent = dentry->d_parent; @@ -1116,7 +1117,6 @@ spin_lock(&dcache_lock); spin_lock(&dentry->d_lock); if (atomic_read(&dentry->d_count) == 1) { - spin_unlock(&dentry->d_lock); dentry_iput(dentry); return; } diff -Nru a/fs/eventpoll.c b/fs/eventpoll.c --- a/fs/eventpoll.c Thu Sep 11 23:03:12 2003 +++ b/fs/eventpoll.c Thu Sep 11 23:03:12 2003 @@ -288,8 +288,10 @@ static int ep_alloc_pages(char **pages, int numpages); static int ep_free_pages(char **pages, int numpages); static int ep_file_init(struct file *file, unsigned int hashbits); -static unsigned int ep_hash_index(struct eventpoll *ep, struct file *file, int fd); -static struct list_head *ep_hash_entry(struct eventpoll *ep, unsigned int index); +static unsigned int ep_hash_index(struct eventpoll *ep, struct file *file, + int fd); +static struct list_head *ep_hash_entry(struct eventpoll *ep, + unsigned int index); static int ep_init(struct eventpoll *ep, unsigned int hashbits); static void ep_free(struct eventpoll *ep); static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd); @@ -299,7 +301,8 @@ poll_table *pt); static int ep_insert(struct eventpoll *ep, struct epoll_event *event, struct file *tfile, int fd); -static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_event *event); +static int ep_modify(struct eventpoll *ep, struct epitem *epi, + struct epoll_event *event); static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi); static int ep_unlink(struct eventpoll *ep, struct epitem *epi); static int ep_remove(struct eventpoll *ep, struct epitem *epi); @@ -309,11 +312,12 @@ static int ep_collect_ready_items(struct eventpoll *ep, struct list_head *txlist, int maxevents); static int ep_send_events(struct eventpoll *ep, struct list_head *txlist, - struct epoll_event *events); + struct epoll_event __user *events); static void ep_reinject_items(struct eventpoll *ep, struct list_head *txlist); static int ep_events_transfer(struct eventpoll *ep, - struct epoll_event *events, int maxevents); -static int ep_poll(struct eventpoll *ep, struct epoll_event *events, + struct epoll_event __user *events, + int maxevents); +static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, int maxevents, long timeout); static int eventpollfs_delete_dentry(struct dentry *dentry); static struct inode *ep_eventpoll_inode(void); @@ -532,11 +536,13 @@ /* - * The following function implement the controller interface for the eventpoll - * file that enable the insertion/removal/change of file descriptors inside - * the interest set. It rapresents the kernel part of the user space epoll_ctl(2). + * The following function implements the controller interface for + * the eventpoll file that enables the insertion/removal/change of + * file descriptors inside the interest set. It represents + * the kernel part of the user space epoll_ctl(2). */ -asmlinkage long sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) +asmlinkage long +sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event) { int error; struct file *file, *tfile; @@ -637,8 +643,8 @@ * Implement the event wait interface for the eventpoll file. It is the kernel * part of the user space epoll_wait(2). */ -asmlinkage long sys_epoll_wait(int epfd, struct epoll_event *events, int maxevents, - int timeout) +asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events, + int maxevents, int timeout) { int error; struct file *file; @@ -662,7 +668,7 @@ goto eexit_1; /* - * We have to check that the file structure underneath the file descriptor + * We have to check that the file structure underneath the fd * the user passed to us _is_ an eventpoll file. */ error = -EINVAL; @@ -1409,7 +1415,7 @@ * because of the way poll() is traditionally implemented in Linux. */ static int ep_send_events(struct eventpoll *ep, struct list_head *txlist, - struct epoll_event *events) + struct epoll_event __user *events) { int eventcnt = 0, eventbuf = 0; unsigned int revents; @@ -1521,7 +1527,8 @@ /* * Perform the transfer of events to user space. */ -static int ep_events_transfer(struct eventpoll *ep, struct epoll_event *events, int maxevents) +static int ep_events_transfer(struct eventpoll *ep, + struct epoll_event __user *events, int maxevents) { int eventcnt = 0; struct list_head txlist; @@ -1549,8 +1556,8 @@ } -static int ep_poll(struct eventpoll *ep, struct epoll_event *events, int maxevents, - long timeout) +static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, + int maxevents, long timeout) { int res, eavail; unsigned long flags; diff -Nru a/fs/exec.c b/fs/exec.c --- a/fs/exec.c Thu Sep 11 23:03:12 2003 +++ b/fs/exec.c Thu Sep 11 23:03:12 2003 @@ -56,7 +56,7 @@ int core_uses_pid; char core_pattern[65] = "core"; -/* The maximal length of core_pattern is also specified in sysctl.c */ +/* The maximal length of core_pattern is also specified in sysctl.c */ static struct linux_binfmt *formats; static rwlock_t binfmt_lock = RW_LOCK_UNLOCKED; @@ -190,7 +190,7 @@ * memory to free pages in kernel mem. These are in a format ready * to be put directly into the top of new user memory. */ -int copy_strings(int argc,char __user * __user * argv, struct linux_binprm *bprm) +int copy_strings(int argc,char __user * __user * argv, struct linux_binprm *bprm) { struct page *kmapped_page = NULL; char *kaddr = NULL; @@ -213,7 +213,7 @@ } bprm->p -= len; - /* XXX: add architecture specific overflow check here. */ + /* XXX: add architecture specific overflow check here. */ pos = bprm->p; while (len > 0) { @@ -275,10 +275,10 @@ { int r; mm_segment_t oldfs = get_fs(); - set_fs(KERNEL_DS); + set_fs(KERNEL_DS); r = copy_strings(argc, (char __user * __user *)argv, bprm); set_fs(oldfs); - return r; + return r; } #ifdef CONFIG_MMU @@ -374,7 +374,13 @@ /* Adjust bprm->p to point to the end of the strings. */ bprm->p = PAGE_SIZE * i - offset; - stack_base = STACK_TOP - current->rlim[RLIMIT_STACK].rlim_max; + + /* Limit stack size to 1GB */ + stack_base = current->rlim[RLIMIT_STACK].rlim_max; + if (stack_base > (1 << 30)) + stack_base = 1 << 30; + stack_base = PAGE_ALIGN(STACK_TOP - stack_base); + mm->arg_start = stack_base; arg_size = i << PAGE_SHIFT; @@ -421,7 +427,7 @@ mpnt->vm_private_data = (void *) 0; insert_vm_struct(mm, mpnt); mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; - } + } for (i = 0 ; i < MAX_ARG_PAGES ; i++) { struct page *page = bprm->page[i]; @@ -803,7 +809,7 @@ /* An exec changes our domain. We are no longer part of the thread group */ - + current->self_exec_id++; flush_signal_handlers(current, 0); @@ -887,7 +893,7 @@ * */ -void compute_creds(struct linux_binprm *bprm) +void compute_creds(struct linux_binprm *bprm) { task_lock(current); if (bprm->e_uid != current->uid || bprm->e_gid != current->gid) { @@ -1052,7 +1058,7 @@ return retval; bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); - memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); + memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); bprm.file = file; bprm.filename = filename; @@ -1083,21 +1089,21 @@ goto out; retval = prepare_binprm(&bprm); - if (retval < 0) - goto out; + if (retval < 0) + goto out; retval = copy_strings_kernel(1, &bprm.filename, &bprm); - if (retval < 0) - goto out; + if (retval < 0) + goto out; bprm.exec = bprm.p; retval = copy_strings(bprm.envc, envp, &bprm); - if (retval < 0) - goto out; + if (retval < 0) + goto out; retval = copy_strings(bprm.argc, argv, &bprm); - if (retval < 0) - goto out; + if (retval < 0) + goto out; retval = search_binary_handler(&bprm,regs); if (retval >= 0) { diff -Nru a/fs/ext2/symlink.c b/fs/ext2/symlink.c --- a/fs/ext2/symlink.c Thu Sep 11 23:03:11 2003 +++ b/fs/ext2/symlink.c Thu Sep 11 23:03:11 2003 @@ -20,7 +20,8 @@ #include "ext2.h" #include "xattr.h" -static int ext2_readlink(struct dentry *dentry, char *buffer, int buflen) +static int +ext2_readlink(struct dentry *dentry, char __user *buffer, int buflen) { struct ext2_inode_info *ei = EXT2_I(dentry->d_inode); return vfs_readlink(dentry, buffer, buflen, (char *)ei->i_data); diff -Nru a/fs/ext3/super.c b/fs/ext3/super.c --- a/fs/ext3/super.c Thu Sep 11 23:03:13 2003 +++ b/fs/ext3/super.c Thu Sep 11 23:03:13 2003 @@ -34,10 +34,6 @@ #include "xattr.h" #include "acl.h" -#ifdef CONFIG_JBD_DEBUG -static int ext3_ro_after; /* Make fs read-only after this many jiffies */ -#endif - static int ext3_load_journal(struct super_block *, struct ext3_super_block *); static int ext3_create_journal(struct super_block *, struct ext3_super_block *, int); @@ -50,64 +46,6 @@ struct ext3_super_block * es); static int ext3_sync_fs(struct super_block *sb, int wait); -#ifdef CONFIG_JBD_DEBUG -int journal_no_write[2]; - -/* - * Debug code for turning filesystems "read-only" after a specified - * amount of time. This is for crash/recovery testing. - */ - -static void make_rdonly(struct block_device *bdev, int *no_write) -{ - char b[BDEVNAME_SIZE]; - - if (bdev) { - printk(KERN_WARNING "Turning device %s read-only\n", - bdevname(bdev, b)); - *no_write = 0xdead0000 + bdev->bd_dev; - } -} - -static void turn_fs_readonly(unsigned long arg) -{ - struct super_block *sb = (struct super_block *)arg; - - make_rdonly(sb->s_bdev, &journal_no_write[0]); - make_rdonly(EXT3_SB(sb)->s_journal->j_dev, &journal_no_write[1]); - wake_up(&EXT3_SB(sb)->ro_wait_queue); -} - -static void setup_ro_after(struct super_block *sb) -{ - struct ext3_sb_info *sbi = EXT3_SB(sb); - init_timer(&sbi->turn_ro_timer); - if (ext3_ro_after) { - printk(KERN_DEBUG "fs will go read-only in %d jiffies\n", - ext3_ro_after); - init_waitqueue_head(&sbi->ro_wait_queue); - journal_no_write[0] = 0; - journal_no_write[1] = 0; - sbi->turn_ro_timer.function = turn_fs_readonly; - sbi->turn_ro_timer.data = (unsigned long)sb; - sbi->turn_ro_timer.expires = jiffies + ext3_ro_after; - ext3_ro_after = 0; - add_timer(&sbi->turn_ro_timer); - } -} - -static void clear_ro_after(struct super_block *sb) -{ - del_timer_sync(&EXT3_SB(sb)->turn_ro_timer); - journal_no_write[0] = 0; - journal_no_write[1] = 0; - ext3_ro_after = 0; -} -#else -#define setup_ro_after(sb) do {} while (0) -#define clear_ro_after(sb) do {} while (0) -#endif - /* * Wrappers for journal_start/end. * @@ -481,7 +419,6 @@ invalidate_bdev(sbi->journal_bdev, 0); ext3_blkdev_remove(sbi); } - clear_ro_after(sb); sb->s_fs_info = NULL; kfree(sbi); return; @@ -741,14 +678,6 @@ set_opt (sbi->s_mount_opt, OLDALLOC); else if (!strcmp (this_char, "orlov")) clear_opt (sbi->s_mount_opt, OLDALLOC); -#ifdef CONFIG_JBD_DEBUG - else if (!strcmp (this_char, "ro-after")) { - unsigned long v; - if (want_numeric(value, "ro-after", &v)) - return 0; - ext3_ro_after = v; - } -#endif /* Silently ignore the quota options */ else if (!strcmp (this_char, "grpquota") || !strcmp (this_char, "noquota") @@ -892,7 +821,6 @@ ext3_check_inodes_bitmap (sb); } #endif - setup_ro_after(sb); return res; } @@ -1092,9 +1020,6 @@ int i; int needs_recovery; -#ifdef CONFIG_JBD_DEBUG - ext3_ro_after = 0; -#endif sbi = kmalloc(sizeof(*sbi), GFP_KERNEL); if (!sbi) return -ENOMEM; @@ -1103,7 +1028,6 @@ sbi->s_mount_opt = 0; sbi->s_resuid = EXT3_DEF_RESUID; sbi->s_resgid = EXT3_DEF_RESGID; - setup_ro_after(sb); blocksize = sb_min_blocksize(sb, EXT3_MIN_BLOCK_SIZE); if (!blocksize) { @@ -1868,8 +1792,6 @@ struct ext3_sb_info *sbi = EXT3_SB(sb); unsigned long tmp; - clear_ro_after(sb); - /* * Allow the "check" option to be passed as a remount option. */ @@ -1929,7 +1851,6 @@ sb->s_flags &= ~MS_RDONLY; } } - setup_ro_after(sb); return 0; } diff -Nru a/fs/fat/file.c b/fs/fat/file.c --- a/fs/fat/file.c Thu Sep 11 23:03:11 2003 +++ b/fs/fat/file.c Thu Sep 11 23:03:11 2003 @@ -11,8 +11,8 @@ #include #include -static ssize_t fat_file_write(struct file *filp, const char *buf, size_t count, - loff_t *ppos); +static ssize_t fat_file_write(struct file *filp, const char __user *buf, + size_t count, loff_t *ppos); struct file_operations fat_file_operations = { .llseek = generic_file_llseek, @@ -66,8 +66,8 @@ return 0; } -static ssize_t fat_file_write(struct file *filp, const char *buf, size_t count, - loff_t *ppos) +static ssize_t fat_file_write(struct file *filp, const char __user *buf, + size_t count, loff_t *ppos) { struct inode *inode = filp->f_dentry->d_inode; int retval; diff -Nru a/fs/intermezzo/inode.c b/fs/intermezzo/inode.c --- a/fs/intermezzo/inode.c Thu Sep 11 23:03:11 2003 +++ b/fs/intermezzo/inode.c Thu Sep 11 23:03:11 2003 @@ -167,7 +167,6 @@ exit: CDEBUG(D_MALLOC, "after umount: kmem %ld, vmem %ld\n", presto_kmemory, presto_vmemory); - MOD_DEC_USE_COUNT; return ; } diff -Nru a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c --- a/fs/jffs/inode-v23.c Thu Sep 11 23:03:13 2003 +++ b/fs/jffs/inode-v23.c Thu Sep 11 23:03:13 2003 @@ -1734,7 +1734,7 @@ the device should be read from the flash memory and then added to the inode's i_rdev member. */ u16 val; - jffs_read_data(f, (char *)val, 0, 2); + jffs_read_data(f, (char *)&val, 0, 2); init_special_inode(inode, inode->i_mode, old_decode_dev(val)); } diff -Nru a/fs/proc/generic.c b/fs/proc/generic.c --- a/fs/proc/generic.c Thu Sep 11 23:03:14 2003 +++ b/fs/proc/generic.c Thu Sep 11 23:03:14 2003 @@ -18,13 +18,13 @@ #include #include -static ssize_t proc_file_read(struct file * file, char * buf, +static ssize_t proc_file_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos); -static ssize_t proc_file_write(struct file * file, const char * buffer, +static ssize_t proc_file_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos); static loff_t proc_file_lseek(struct file *, loff_t, int); -int proc_match(int len, const char *name,struct proc_dir_entry * de) +int proc_match(int len, const char *name, struct proc_dir_entry *de) { if (de->namelen != len) return 0; @@ -45,7 +45,8 @@ #define PROC_BLOCK_SIZE (PAGE_SIZE - 1024) static ssize_t -proc_file_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos) +proc_file_read(struct file *file, char __user *buf, size_t nbytes, + loff_t *ppos) { struct inode * inode = file->f_dentry->d_inode; char *page; @@ -59,8 +60,7 @@ if (!(page = (char*) __get_free_page(GFP_KERNEL))) return -ENOMEM; - while ((nbytes > 0) && !eof) - { + while ((nbytes > 0) && !eof) { count = MIN(PROC_BLOCK_SIZE, nbytes); start = NULL; @@ -184,7 +184,7 @@ } static ssize_t -proc_file_write(struct file * file, const char * buffer, +proc_file_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { struct inode *inode = file->f_dentry->d_inode; @@ -201,7 +201,7 @@ static loff_t -proc_file_lseek(struct file * file, loff_t offset, int orig) +proc_file_lseek(struct file *file, loff_t offset, int orig) { lock_kernel(); @@ -299,15 +299,16 @@ return i; } -static int proc_readlink(struct dentry *dentry, char *buffer, int buflen) +static int +proc_readlink(struct dentry *dentry, char __user *buffer, int buflen) { - char *s=PDE(dentry->d_inode)->data; + char *s = PDE(dentry->d_inode)->data; return vfs_readlink(dentry, buffer, buflen, s); } static int proc_follow_link(struct dentry *dentry, struct nameidata *nd) { - char *s=PDE(dentry->d_inode)->data; + char *s = PDE(dentry->d_inode)->data; return vfs_follow_link(nd, s); } diff -Nru a/fs/proc/kcore.c b/fs/proc/kcore.c --- a/fs/proc/kcore.c Thu Sep 11 23:03:12 2003 +++ b/fs/proc/kcore.c Thu Sep 11 23:03:12 2003 @@ -27,7 +27,7 @@ return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; } -static ssize_t read_kcore(struct file *, char *, size_t, loff_t *); +static ssize_t read_kcore(struct file *, char __user *, size_t, loff_t *); struct file_operations proc_kcore_operations = { .read = read_kcore, @@ -175,6 +175,7 @@ elf->e_ident[EI_CLASS] = ELF_CLASS; elf->e_ident[EI_DATA] = ELF_DATA; elf->e_ident[EI_VERSION]= EV_CURRENT; + elf->e_ident[EI_OSABI] = ELF_OSABI; memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD); elf->e_type = ET_CORE; elf->e_machine = ELF_ARCH; @@ -267,7 +268,8 @@ /* * read from the ELF header and then kernel memory */ -static ssize_t read_kcore(struct file *file, char *buffer, size_t buflen, loff_t *fpos) +static ssize_t +read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos) { ssize_t acc = 0; size_t size, tsz; diff -Nru a/fs/proc/kmsg.c b/fs/proc/kmsg.c --- a/fs/proc/kmsg.c Thu Sep 11 23:03:14 2003 +++ b/fs/proc/kmsg.c Thu Sep 11 23:03:14 2003 @@ -17,7 +17,7 @@ extern wait_queue_head_t log_wait; -extern int do_syslog(int type, char * bug, int count); +extern int do_syslog(int type, char __user *bug, int count); static int kmsg_open(struct inode * inode, struct file * file) { @@ -30,13 +30,13 @@ return 0; } -static ssize_t kmsg_read(struct file * file, char * buf, +static ssize_t kmsg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - return do_syslog(2,buf,count); + return do_syslog(2, buf, count); } -static unsigned int kmsg_poll(struct file *file, poll_table * wait) +static unsigned int kmsg_poll(struct file *file, poll_table *wait) { poll_wait(file, &log_wait, wait); if (do_syslog(9, 0, 0)) diff -Nru a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c --- a/fs/proc/proc_misc.c Thu Sep 11 23:03:11 2003 +++ b/fs/proc/proc_misc.c Thu Sep 11 23:03:11 2003 @@ -343,7 +343,7 @@ #endif extern struct seq_operations slabinfo_op; -extern ssize_t slabinfo_write(struct file *, const char *, size_t, loff_t *); +extern ssize_t slabinfo_write(struct file *, const char __user *, size_t, loff_t *); static int slabinfo_open(struct inode *inode, struct file *file) { return seq_open(file, &slabinfo_op); @@ -548,8 +548,8 @@ * buffer. Use of the program readprofile is recommended in order to * get meaningful info out of these data. */ -static ssize_t read_profile(struct file *file, char *buf, - size_t count, loff_t *ppos) +static ssize_t +read_profile(struct file *file, char __user *buf, size_t count, loff_t *ppos) { unsigned long p = *ppos; ssize_t read; @@ -580,13 +580,13 @@ * Writing a 'profiling multiplier' value into it also re-sets the profiling * interrupt frequency, on architectures that support this. */ -static ssize_t write_profile(struct file * file, const char * buf, +static ssize_t write_profile(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { #ifdef CONFIG_SMP extern int setup_profiling_timer (unsigned int multiplier); - if (count==sizeof(int)) { + if (count == sizeof(int)) { unsigned int multiplier; if (copy_from_user(&multiplier, buf, sizeof(int))) @@ -610,8 +610,8 @@ /* * writing 'C' to /proc/sysrq-trigger is like sysrq-C */ -static ssize_t write_sysrq_trigger(struct file *file, const char *buf, - size_t count, loff_t *ppos) +static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) { if (count) { char c; diff -Nru a/fs/reiserfs/file.c b/fs/reiserfs/file.c --- a/fs/reiserfs/file.c Thu Sep 11 23:03:11 2003 +++ b/fs/reiserfs/file.c Thu Sep 11 23:03:11 2003 @@ -485,6 +485,11 @@ /* Now the final thing, if we have grew the file, we must update it's size*/ if ( pos + write_bytes > inode->i_size) { inode->i_size = pos + write_bytes; // Set new size + /* If the file have grown so much that tail packing is no longer possible, reset + "need to pack" flag */ + if ( (have_large_tails (inode->i_sb) && inode->i_size > i_block_size (inode)*4) || + (have_small_tails (inode->i_sb) && inode->i_size > i_block_size(inode)) ) + REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask ; } /* Amount of on-disk blocks used by file have changed, update it */ @@ -999,8 +1004,40 @@ struct page * prepared_pages[REISERFS_WRITE_PAGES_AT_A_TIME]; /* To simplify coding at this time, we store locked pages in array for now */ - if ( count <= PAGE_CACHE_SIZE || file->f_flags & O_DIRECT) + if ( count <= PAGE_CACHE_SIZE ) return generic_file_write(file, buf, count, ppos); + + if ( file->f_flags & O_DIRECT) { // Direct IO needs some special threating. + int result, after_file_end = 0; + if ( (*ppos + count >= inode->i_size) || (file->f_flags & O_APPEND) ) { + /* If we are appending a file, we need to put this savelink in here. + If we will crash while doing direct io, finish_unfinished will + cut the garbage from the file end. */ + struct reiserfs_transaction_handle th; + reiserfs_write_lock(inode->i_sb); + journal_begin(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT ); + reiserfs_update_inode_transaction(inode); + add_save_link (&th, inode, 1 /* Truncate */); + journal_end(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT ); + reiserfs_write_unlock(inode->i_sb); + after_file_end = 1; + } + result = generic_file_write(file, buf, count, ppos); + + if ( after_file_end ) { /* Now update i_size and remove the savelink */ + struct reiserfs_transaction_handle th; + reiserfs_write_lock(inode->i_sb); + journal_begin(&th, inode->i_sb, 1); + reiserfs_update_inode_transaction(inode); + reiserfs_update_sd(&th, inode); + journal_end(&th, inode->i_sb, 1); + remove_save_link (inode, 1/* truncate */); + reiserfs_write_unlock(inode->i_sb); + } + + return result; + } + if ( unlikely((ssize_t) count < 0 )) return -EINVAL; diff -Nru a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c --- a/fs/reiserfs/inode.c Thu Sep 11 23:03:12 2003 +++ b/fs/reiserfs/inode.c Thu Sep 11 23:03:12 2003 @@ -306,7 +306,7 @@ ** read old data off disk. Set the up to date bit on the buffer instead ** and jump to the end */ - if (PageUptodate(bh_result->b_page)) { + if (!bh_result->b_page || PageUptodate(bh_result->b_page)) { set_buffer_uptodate(bh_result); goto finished ; } @@ -420,6 +420,45 @@ return reiserfs_get_block(inode, block, bh_result, GET_BLOCK_NO_HOLE) ; } +/* This is special helper for reiserfs_get_block in case we are executing + direct_IO request. */ +static int reiserfs_get_blocks_direct_io(struct inode *inode, + sector_t iblock, + unsigned long max_blocks, + struct buffer_head *bh_result, + int create) +{ + int ret ; + + bh_result->b_page = NULL; + + /* We set the b_size before reiserfs_get_block call since it is + referenced in convert_tail_for_hole() that may be called from + reiserfs_get_block() */ + bh_result->b_size = (1 << inode->i_blkbits); + + ret = reiserfs_get_block(inode, iblock, bh_result, create) ; + + /* don't allow direct io onto tail pages */ + if (ret == 0 && buffer_mapped(bh_result) && bh_result->b_blocknr == 0) { + /* make sure future calls to the direct io funcs for this offset + ** in the file fail by unmapping the buffer + */ + reiserfs_unmap_buffer(bh_result); + ret = -EINVAL ; + } + /* Possible unpacked tail. Flush the data before pages have + disappeared */ + if (REISERFS_I(inode)->i_flags & i_pack_on_close_mask) { + lock_kernel(); + reiserfs_commit_for_inode(inode); + REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask; + unlock_kernel(); + } + return ret ; +} + + /* ** helper function for when reiserfs_get_block is called for a hole ** but the file tail is still in a direct item @@ -448,7 +487,10 @@ tail_end = (tail_start | (bh_result->b_size - 1)) + 1 ; index = tail_offset >> PAGE_CACHE_SHIFT ; - if (index != hole_page->index) { + /* hole_page can be zero in case of direct_io, we are sure + that we cannot get here if we write with O_DIRECT into + tail page */ + if (!hole_page || index != hole_page->index) { tail_page = grab_cache_page(inode->i_mapping, index) ; retval = -ENOMEM; if (!tail_page) { @@ -554,7 +596,12 @@ return ret; } - REISERFS_I(inode)->i_flags |= i_pack_on_close_mask ; + /* If file is of such a size, that it might have a tail and tails are enabled + ** we should mark it as possibly needing tail packing on close + */ + if ( (have_large_tails (inode->i_sb) && inode->i_size < i_block_size (inode)*4) || + (have_small_tails (inode->i_sb) && inode->i_size < i_block_size(inode)) ) + REISERFS_I(inode)->i_flags |= i_pack_on_close_mask ; windex = push_journal_writer("reiserfs_get_block") ; @@ -745,21 +792,26 @@ */ set_buffer_uptodate (unbh); - /* we've converted the tail, so we must - ** flush unbh before the transaction commits - */ - add_to_flushlist(inode, unbh) ; - - /* mark it dirty now to prevent commit_write from adding - ** this buffer to the inode's dirty buffer list + /* unbh->b_page == NULL in case of DIRECT_IO request, this means + buffer will disappear shortly, so it should not be added to */ + if ( unbh->b_page ) { + /* we've converted the tail, so we must + ** flush unbh before the transaction commits + */ + add_to_flushlist(inode, unbh) ; + + /* mark it dirty now to prevent commit_write from adding + ** this buffer to the inode's dirty buffer list + */ /* * AKPM: changed __mark_buffer_dirty to mark_buffer_dirty(). * It's still atomic, but it sets the page dirty too, * which makes it eligible for writeback at any time by the * VM (which was also the case with __mark_buffer_dirty()) */ - mark_buffer_dirty(unbh) ; + mark_buffer_dirty(unbh) ; + } //inode->i_blocks += inode->i_sb->s_blocksize / 512; //mark_tail_converted (inode); @@ -2204,6 +2256,13 @@ if (pos > inode->i_size) { struct reiserfs_transaction_handle th ; reiserfs_write_lock(inode->i_sb); + /* If the file have grown beyond the border where it + can have a tail, unmark it as needing a tail + packing */ + if ( (have_large_tails (inode->i_sb) && inode->i_size > i_block_size (inode)*4) || + (have_small_tails (inode->i_sb) && inode->i_size > i_block_size(inode)) ) + REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask ; + journal_begin(&th, inode->i_sb, 1) ; reiserfs_update_inode_transaction(inode) ; inode->i_size = pos ; @@ -2310,6 +2369,19 @@ return ret ; } +/* We thank Mingming Cao for helping us understand in great detail what + to do in this section of the code. */ +static int reiserfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, + loff_t offset, unsigned long nr_segs) +{ + struct file *file = iocb->ki_filp; + struct inode *inode = file->f_dentry->d_inode->i_mapping->host; + + return blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, + offset, nr_segs, reiserfs_get_blocks_direct_io, NULL); +} + + struct address_space_operations reiserfs_address_space_operations = { .writepage = reiserfs_writepage, .readpage = reiserfs_readpage, @@ -2318,5 +2390,6 @@ .sync_page = block_sync_page, .prepare_write = reiserfs_prepare_write, .commit_write = reiserfs_commit_write, - .bmap = reiserfs_aop_bmap + .bmap = reiserfs_aop_bmap, + .direct_IO = reiserfs_direct_IO } ; diff -Nru a/fs/reiserfs/tail_conversion.c b/fs/reiserfs/tail_conversion.c --- a/fs/reiserfs/tail_conversion.c Thu Sep 11 23:03:14 2003 +++ b/fs/reiserfs/tail_conversion.c Thu Sep 11 23:03:14 2003 @@ -104,8 +104,10 @@ /* we only send the unbh pointer if the buffer is not up to date. ** this avoids overwriting good data from writepage() with old data ** from the disk or buffer cache + ** Special case: unbh->b_page will be NULL if we are coming through + ** DIRECT_IO handler here. */ - if (buffer_uptodate(unbh) || PageUptodate(unbh->b_page)) { + if (!unbh->b_page || buffer_uptodate(unbh) || PageUptodate(unbh->b_page)) { up_to_date_bh = NULL ; } else { up_to_date_bh = unbh ; diff -Nru a/fs/ufs/namei.c b/fs/ufs/namei.c --- a/fs/ufs/namei.c Thu Sep 11 23:03:14 2003 +++ b/fs/ufs/namei.c Thu Sep 11 23:03:14 2003 @@ -112,11 +112,13 @@ static int ufs_mknod (struct inode * dir, struct dentry *dentry, int mode, dev_t rdev) { - struct inode * inode; + struct inode *inode; + int err; + if (!old_valid_dev(rdev)) return -EINVAL; inode = ufs_new_inode(dir, mode); - int err = PTR_ERR(inode); + err = PTR_ERR(inode); if (!IS_ERR(inode)) { init_special_inode(inode, mode, rdev); /* NOTE: that'll go when we get wide dev_t */ diff -Nru a/fs/xattr.c b/fs/xattr.c --- a/fs/xattr.c Thu Sep 11 23:03:12 2003 +++ b/fs/xattr.c Thu Sep 11 23:03:12 2003 @@ -53,7 +53,8 @@ * Extended attribute SET operations */ static long -setxattr(struct dentry *d, char *name, void *value, size_t size, int flags) +setxattr(struct dentry *d, char __user *name, void __user *value, + size_t size, int flags) { int error; void *kvalue; @@ -94,7 +95,8 @@ } asmlinkage long -sys_setxattr(char *path, char *name, void *value, size_t size, int flags) +sys_setxattr(char __user *path, char __user *name, void __user *value, + size_t size, int flags) { struct nameidata nd; int error; @@ -108,7 +110,8 @@ } asmlinkage long -sys_lsetxattr(char *path, char *name, void *value, size_t size, int flags) +sys_lsetxattr(char __user *path, char __user *name, void __user *value, + size_t size, int flags) { struct nameidata nd; int error; @@ -122,7 +125,8 @@ } asmlinkage long -sys_fsetxattr(int fd, char *name, void *value, size_t size, int flags) +sys_fsetxattr(int fd, char __user *name, void __user *value, + size_t size, int flags) { struct file *f; int error = -EBADF; @@ -139,7 +143,7 @@ * Extended attribute GET operations */ static ssize_t -getxattr(struct dentry *d, char *name, void *value, size_t size) +getxattr(struct dentry *d, char __user *name, void __user *value, size_t size) { ssize_t error; void *kvalue; @@ -172,7 +176,8 @@ } asmlinkage ssize_t -sys_getxattr(char *path, char *name, void *value, size_t size) +sys_getxattr(char __user *path, char __user *name, void __user *value, + size_t size) { struct nameidata nd; ssize_t error; @@ -186,7 +191,8 @@ } asmlinkage ssize_t -sys_lgetxattr(char *path, char *name, void *value, size_t size) +sys_lgetxattr(char __user *path, char __user *name, void __user *value, + size_t size) { struct nameidata nd; ssize_t error; @@ -200,7 +206,7 @@ } asmlinkage ssize_t -sys_fgetxattr(int fd, char *name, void *value, size_t size) +sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size) { struct file *f; ssize_t error = -EBADF; @@ -217,7 +223,7 @@ * Extended attribute LIST operations */ static ssize_t -listxattr(struct dentry *d, char *list, size_t size) +listxattr(struct dentry *d, char __user *list, size_t size) { ssize_t error; char *klist; @@ -243,7 +249,7 @@ } asmlinkage ssize_t -sys_listxattr(char *path, char *list, size_t size) +sys_listxattr(char __user *path, char __user *list, size_t size) { struct nameidata nd; ssize_t error; @@ -257,7 +263,7 @@ } asmlinkage ssize_t -sys_llistxattr(char *path, char *list, size_t size) +sys_llistxattr(char __user *path, char __user *list, size_t size) { struct nameidata nd; ssize_t error; @@ -271,7 +277,7 @@ } asmlinkage ssize_t -sys_flistxattr(int fd, char *list, size_t size) +sys_flistxattr(int fd, char __user *list, size_t size) { struct file *f; ssize_t error = -EBADF; @@ -288,7 +294,7 @@ * Extended attribute REMOVE operations */ static long -removexattr(struct dentry *d, char *name) +removexattr(struct dentry *d, char __user *name) { int error; char kname[XATTR_NAME_MAX + 1]; @@ -313,7 +319,7 @@ } asmlinkage long -sys_removexattr(char *path, char *name) +sys_removexattr(char __user *path, char __user *name) { struct nameidata nd; int error; @@ -327,7 +333,7 @@ } asmlinkage long -sys_lremovexattr(char *path, char *name) +sys_lremovexattr(char __user *path, char __user *name) { struct nameidata nd; int error; @@ -341,7 +347,7 @@ } asmlinkage long -sys_fremovexattr(int fd, char *name) +sys_fremovexattr(int fd, char __user *name) { struct file *f; int error = -EBADF; diff -Nru a/include/asm-arm/hardware/sa1111.h b/include/asm-arm/hardware/sa1111.h --- a/include/asm-arm/hardware/sa1111.h Thu Sep 11 23:03:14 2003 +++ b/include/asm-arm/hardware/sa1111.h Thu Sep 11 23:03:14 2003 @@ -543,7 +543,7 @@ #define SA1111_DEV(_d) container_of((_d), struct sa1111_dev, dev) #define sa1111_get_drvdata(d) dev_get_drvdata(&(d)->dev) -#define sa1111_set_drvdata(d,p) dev_get_drvdata(&(d)->dev, p) +#define sa1111_set_drvdata(d,p) dev_set_drvdata(&(d)->dev, p) struct sa1111_driver { struct device_driver drv; @@ -557,11 +557,6 @@ #define SA1111_DRV(_d) container_of((_d), struct sa1111_driver, drv) #define SA1111_DRIVER_NAME(_sadev) ((_sadev)->dev.driver->name) - -/* - * Probe for a SA1111 chip. - */ -extern int sa1111_init(unsigned long phys, unsigned int irq); /* * These frob the SKPCR register. diff -Nru a/include/asm-generic/cpumask_up.h b/include/asm-generic/cpumask_up.h --- a/include/asm-generic/cpumask_up.h Thu Sep 11 23:03:11 2003 +++ b/include/asm-generic/cpumask_up.h Thu Sep 11 23:03:11 2003 @@ -6,7 +6,7 @@ #define cpu_set(cpu, map) do { (void)(cpu); cpus_coerce(map) = 1UL; } while (0) #define cpu_clear(cpu, map) do { (void)(cpu); cpus_coerce(map) = 0UL; } while (0) #define cpu_isset(cpu, map) ((void)(cpu), cpus_coerce(map) != 0UL) -#define cpu_test_and_set(cpu, map) ((void)(cpu), test_and_set_bit(0, (map).mask)) +#define cpu_test_and_set(cpu, map) ((void)(cpu), test_and_set_bit(0, &(map))) #define cpus_and(dst, src1, src2) \ do { \ diff -Nru a/include/asm-i386/cpufeature.h b/include/asm-i386/cpufeature.h --- a/include/asm-i386/cpufeature.h Thu Sep 11 23:03:13 2003 +++ b/include/asm-i386/cpufeature.h Thu Sep 11 23:03:13 2003 @@ -71,6 +71,8 @@ /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ #define X86_FEATURE_EST (4*32+ 7) /* Enhanced SpeedStep */ +#define X86_FEATURE_MWAIT (4*32+ 3) /* Monitor/Mwait support */ + /* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ #define X86_FEATURE_XSTORE (5*32+ 2) /* on-CPU RNG present (xstore insn) */ diff -Nru a/include/asm-i386/ist.h b/include/asm-i386/ist.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-i386/ist.h Thu Sep 11 23:03:14 2003 @@ -0,0 +1,32 @@ +#ifndef _ASM_IST_H +#define _ASM_IST_H + +/* + * Include file for the interface to IST BIOS + * Copyright 2002 Andy Grover + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + + +#ifdef __KERNEL__ + +struct ist_info { + unsigned long signature; + unsigned long command; + unsigned long event; + unsigned long perf_level; +}; + +extern struct ist_info ist_info; + +#endif /* __KERNEL__ */ +#endif /* _ASM_IST_H */ diff -Nru a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h --- a/include/asm-i386/mmzone.h Thu Sep 11 23:03:12 2003 +++ b/include/asm-i386/mmzone.h Thu Sep 11 23:03:12 2003 @@ -119,7 +119,7 @@ #ifdef CONFIG_X86_NUMAQ #include -#elif CONFIG_NUMA /* summit or generic arch */ +#elif CONFIG_ACPI_SRAT #include #elif CONFIG_X86_PC #define get_memcfg_numa get_memcfg_numa_flat diff -Nru a/include/asm-i386/numnodes.h b/include/asm-i386/numnodes.h --- a/include/asm-i386/numnodes.h Thu Sep 11 23:03:11 2003 +++ b/include/asm-i386/numnodes.h Thu Sep 11 23:03:11 2003 @@ -5,7 +5,7 @@ #ifdef CONFIG_X86_NUMAQ #include -#elif CONFIG_NUMA +#elif CONFIG_ACPI_SRAT #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 Sep 11 23:03:11 2003 +++ b/include/asm-i386/processor.h Thu Sep 11 23:03:11 2003 @@ -272,6 +272,22 @@ #define pc98 0 #endif +static inline void __monitor(const void *eax, unsigned long ecx, + unsigned long edx) +{ + /* "monitor %eax,%ecx,%edx;" */ + asm volatile( + ".byte 0x0f,0x01,0xc8;" + : :"a" (eax), "c" (ecx), "d"(edx)); +} + +static inline void __mwait(unsigned long eax, unsigned long ecx) +{ + /* "mwait %eax,%ecx;" */ + asm volatile( + ".byte 0x0f,0x01,0xc9;" + : :"a" (eax), "c" (ecx)); +} /* from system description table in BIOS. Mostly for MCA use, but others may find it useful. */ @@ -600,5 +616,7 @@ "r" (x)); } #define spin_lock_prefetch(x) prefetchw(x) + +extern void select_idle_routine(const struct cpuinfo_x86 *c); #endif /* __ASM_I386_PROCESSOR_H */ diff -Nru a/include/asm-i386/setup.h b/include/asm-i386/setup.h --- a/include/asm-i386/setup.h Thu Sep 11 23:03:13 2003 +++ b/include/asm-i386/setup.h Thu Sep 11 23:03:13 2003 @@ -26,6 +26,7 @@ #define E820_MAP_NR (*(char*) (PARAM+E820NR)) #define E820_MAP ((struct e820entry *) (PARAM+E820MAP)) #define APM_BIOS_INFO (*(struct apm_bios_info *) (PARAM+0x40)) +#define IST_INFO (*(struct ist_info *) (PARAM+0x60)) #define DRIVE_INFO (*(struct drive_info_struct *) (PARAM+0x80)) #define SYS_DESC_TABLE (*(struct sys_desc_table_struct*)(PARAM+0xa0)) #define MOUNT_ROOT_RDONLY (*(unsigned short *) (PARAM+0x1F2)) diff -Nru a/include/asm-i386/srat.h b/include/asm-i386/srat.h --- a/include/asm-i386/srat.h Thu Sep 11 23:03:12 2003 +++ b/include/asm-i386/srat.h Thu Sep 11 23:03:12 2003 @@ -27,6 +27,10 @@ #ifndef _ASM_SRAT_H_ #define _ASM_SRAT_H_ +#ifndef CONFIG_ACPI_SRAT +#error CONFIG_ACPI_SRAT not defined, and srat.h header has been included +#endif + #define MAX_NUMNODES 8 extern void get_memcfg_from_srat(void); extern unsigned long *get_zholes_size(int); diff -Nru a/include/asm-i386/timer.h b/include/asm-i386/timer.h --- a/include/asm-i386/timer.h Thu Sep 11 23:03:11 2003 +++ b/include/asm-i386/timer.h Thu Sep 11 23:03:11 2003 @@ -38,8 +38,10 @@ extern struct timer_opts timer_cyclone; #endif +extern unsigned long calibrate_tsc(void); #ifdef CONFIG_HPET_TIMER extern struct timer_opts timer_hpet; +extern unsigned long calibrate_tsc_hpet(unsigned long *tsc_hpet_quotient_ptr); #endif #endif diff -Nru a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h --- a/include/asm-ia64/acpi.h Thu Sep 11 23:03:13 2003 +++ b/include/asm-ia64/acpi.h Thu Sep 11 23:03:13 2003 @@ -54,47 +54,35 @@ #define ACPI_ENABLE_IRQS() local_irq_enable() #define ACPI_FLUSH_CPU_CACHE() -#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \ - do { \ - __asm__ volatile ("1: ld4 r29=[%1]\n" \ - ";;\n" \ - "mov ar.ccv=r29\n" \ - "mov r2=r29\n" \ - "shr.u r30=r29,1\n" \ - "and r29=-4,r29\n" \ - ";;\n" \ - "add r29=2,r29\n" \ - "and r30=1,r30\n" \ - ";;\n" \ - "add r29=r29,r30\n" \ - ";;\n" \ - "cmpxchg4.acq r30=[%1],r29,ar.ccv\n" \ - ";;\n" \ - "cmp.eq p6,p7=r2,r30\n" \ - "(p7) br.dpnt.few 1b\n" \ - "cmp.gt p8,p9=3,r29\n" \ - ";;\n" \ - "(p8) mov %0=-1\n" \ - "(p9) mov %0=r0\n" \ - :"=r"(Acq):"r"(GLptr):"r2","r29","r30","memory"); \ - } while (0) +static inline int +ia64_acpi_acquire_global_lock (unsigned int *lock) +{ + unsigned int old, new, val; + do { + old = *lock; + new = (((old & ~0x3) + 2) + ((old >> 1) & 0x1)); + val = ia64_cmpxchg4_acq(lock, new, old); + } while (unlikely (val != old)); + return (new < 3) ? -1 : 0; +} -#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \ - do { \ - __asm__ volatile ("1: ld4 r29=[%1]\n" \ - ";;\n" \ - "mov ar.ccv=r29\n" \ - "mov r2=r29\n" \ - "and r29=-4,r29\n" \ - ";;\n" \ - "cmpxchg4.acq r30=[%1],r29,ar.ccv\n" \ - ";;\n" \ - "cmp.eq p6,p7=r2,r30\n" \ - "(p7) br.dpnt.few 1b\n" \ - "and %0=1,r2\n" \ - ";;\n" \ - :"=r"(Acq):"r"(GLptr):"r2","r29","r30","memory"); \ - } while (0) +static inline int +ia64_acpi_release_global_lock (unsigned int *lock) +{ + unsigned int old, new, val; + do { + old = *lock; + new = old & ~0x3; + val = ia64_cmpxchg4_acq(lock, new, old); + } while (unlikely (val != old)); + return old & 0x1; +} + +#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \ + ((Acq) = ia64_acpi_acquire_global_lock((unsigned int *) GLptr)) + +#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \ + ((Acq) = ia64_acpi_release_global_lock((unsigned int *) GLptr)) const char *acpi_get_sysname (void); int acpi_request_vector (u32 int_type); diff -Nru a/include/asm-ia64/hw_irq.h b/include/asm-ia64/hw_irq.h --- a/include/asm-ia64/hw_irq.h Thu Sep 11 23:03:12 2003 +++ b/include/asm-ia64/hw_irq.h Thu Sep 11 23:03:12 2003 @@ -9,6 +9,7 @@ #include #include #include +#include #include #include diff -Nru a/include/asm-ia64/intel_intrin.h b/include/asm-ia64/intel_intrin.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-ia64/intel_intrin.h Thu Sep 11 23:03:14 2003 @@ -0,0 +1,254 @@ +#ifndef _ASM_IA64_INTEL_INTRIN_H +#define _ASM_IA64_INTEL_INTRIN_H +/* + * Intel Compiler Intrinsics + * + * Copyright (C) 2002,2003 Jun Nakajima + * Copyright (C) 2002,2003 Suresh Siddha + * + */ +#include + +void __lfetch(int lfhint, void *y); +void __lfetch_excl(int lfhint, void *y); +void __lfetch_fault(int lfhint, void *y); +void __lfetch_fault_excl(int lfhint, void *y); + +/* In the following, whichFloatReg should be an integer from 0-127 */ +void __ldfs(const int whichFloatReg, void *src); +void __ldfd(const int whichFloatReg, void *src); +void __ldfe(const int whichFloatReg, void *src); +void __ldf8(const int whichFloatReg, void *src); +void __ldf_fill(const int whichFloatReg, void *src); +void __stfs(void *dst, const int whichFloatReg); +void __stfd(void *dst, const int whichFloatReg); +void __stfe(void *dst, const int whichFloatReg); +void __stf8(void *dst, const int whichFloatReg); +void __stf_spill(void *dst, const int whichFloatReg); + +void __st1_rel(void *dst, const __s8 value); +void __st2_rel(void *dst, const __s16 value); +void __st4_rel(void *dst, const __s32 value); +void __st8_rel(void *dst, const __s64 value); +__u8 __ld1_acq(void *src); +__u16 __ld2_acq(void *src); +__u32 __ld4_acq(void *src); +__u64 __ld8_acq(void *src); + +__u64 __fetchadd4_acq(__u32 *addend, const int increment); +__u64 __fetchadd4_rel(__u32 *addend, const int increment); +__u64 __fetchadd8_acq(__u64 *addend, const int increment); +__u64 __fetchadd8_rel(__u64 *addend, const int increment); + +__u64 __getf_exp(double d); + +/* OS Related Itanium(R) Intrinsics */ + +/* The names to use for whichReg and whichIndReg below come from + the include file asm/ia64regs.h */ + +__u64 __getIndReg(const int whichIndReg, __s64 index); +__u64 __getReg(const int whichReg); + +void __setIndReg(const int whichIndReg, __s64 index, __u64 value); +void __setReg(const int whichReg, __u64 value); + +void __mf(void); +void __mfa(void); +void __synci(void); +void __itcd(__s64 pa); +void __itci(__s64 pa); +void __itrd(__s64 whichTransReg, __s64 pa); +void __itri(__s64 whichTransReg, __s64 pa); +void __ptce(__s64 va); +void __ptcl(__s64 va, __s64 pagesz); +void __ptcg(__s64 va, __s64 pagesz); +void __ptcga(__s64 va, __s64 pagesz); +void __ptri(__s64 va, __s64 pagesz); +void __ptrd(__s64 va, __s64 pagesz); +void __invala (void); +void __invala_gr(const int whichGeneralReg /* 0-127 */ ); +void __invala_fr(const int whichFloatReg /* 0-127 */ ); +void __nop(const int); +void __fc(__u64 *addr); +void __sum(int mask); +void __rum(int mask); +void __ssm(int mask); +void __rsm(int mask); +__u64 __thash(__s64); +__u64 __ttag(__s64); +__s64 __tpa(__s64); + +/* Intrinsics for implementing get/put_user macros */ +void __st_user(const char *tableName, __u64 addr, char size, char relocType, __u64 val); +void __ld_user(const char *tableName, __u64 addr, char size, char relocType); + +/* This intrinsic does not generate code, it creates a barrier across which + * the compiler will not schedule data access instructions. + */ +void __memory_barrier(void); + +void __isrlz(void); +void __dsrlz(void); + +__u64 _m64_mux1(__u64 a, const int n); +__u64 __thash(__u64); + +/* Lock and Atomic Operation Related Intrinsics */ +__u64 _InterlockedExchange8(volatile __u8 *trgt, __u8 value); +__u64 _InterlockedExchange16(volatile __u16 *trgt, __u16 value); +__s64 _InterlockedExchange(volatile __u32 *trgt, __u32 value); +__s64 _InterlockedExchange64(volatile __u64 *trgt, __u64 value); + +__u64 _InterlockedCompareExchange8_rel(volatile __u8 *dest, __u64 xchg, __u64 comp); +__u64 _InterlockedCompareExchange8_acq(volatile __u8 *dest, __u64 xchg, __u64 comp); +__u64 _InterlockedCompareExchange16_rel(volatile __u16 *dest, __u64 xchg, __u64 comp); +__u64 _InterlockedCompareExchange16_acq(volatile __u16 *dest, __u64 xchg, __u64 comp); +__u64 _InterlockedCompareExchange_rel(volatile __u32 *dest, __u64 xchg, __u64 comp); +__u64 _InterlockedCompareExchange_acq(volatile __u32 *dest, __u64 xchg, __u64 comp); +__u64 _InterlockedCompareExchange64_rel(volatile __u64 *dest, __u64 xchg, __u64 comp); +__u64 _InterlockedCompareExchange64_acq(volatile __u64 *dest, __u64 xchg, __u64 comp); + +__s64 _m64_dep_mi(const int v, __s64 s, const int p, const int len); +__s64 _m64_shrp(__s64 a, __s64 b, const int count); +__s64 _m64_popcnt(__s64 a); + +#define ia64_barrier() __memory_barrier() + +#define ia64_stop() /* Nothing: As of now stop bit is generated for each + * intrinsic + */ + +#define ia64_getreg __getReg +#define ia64_setreg __setReg + +#define ia64_hint(x) + +#define ia64_mux1_brcst 0 +#define ia64_mux1_mix 8 +#define ia64_mux1_shuf 9 +#define ia64_mux1_alt 10 +#define ia64_mux1_rev 11 + +#define ia64_mux1 _m64_mux1 +#define ia64_popcnt _m64_popcnt +#define ia64_getf_exp __getf_exp +#define ia64_shrp _m64_shrp + +#define ia64_tpa __tpa +#define ia64_invala __invala +#define ia64_invala_gr __invala_gr +#define ia64_invala_fr __invala_fr +#define ia64_nop __nop +#define ia64_sum __sum +#define ia64_ssm __ssm +#define ia64_rum __rum +#define ia64_rsm __rsm +#define ia64_fc __fc + +#define ia64_ldfs __ldfs +#define ia64_ldfd __ldfd +#define ia64_ldfe __ldfe +#define ia64_ldf8 __ldf8 +#define ia64_ldf_fill __ldf_fill + +#define ia64_stfs __stfs +#define ia64_stfd __stfd +#define ia64_stfe __stfe +#define ia64_stf8 __stf8 +#define ia64_stf_spill __stf_spill + +#define ia64_mf __mf +#define ia64_mfa __mfa + +#define ia64_fetchadd4_acq __fetchadd4_acq +#define ia64_fetchadd4_rel __fetchadd4_rel +#define ia64_fetchadd8_acq __fetchadd8_acq +#define ia64_fetchadd8_rel __fetchadd8_rel + +#define ia64_xchg1 _InterlockedExchange8 +#define ia64_xchg2 _InterlockedExchange16 +#define ia64_xchg4 _InterlockedExchange +#define ia64_xchg8 _InterlockedExchange64 + +#define ia64_cmpxchg1_rel _InterlockedCompareExchange8_rel +#define ia64_cmpxchg1_acq _InterlockedCompareExchange8_acq +#define ia64_cmpxchg2_rel _InterlockedCompareExchange16_rel +#define ia64_cmpxchg2_acq _InterlockedCompareExchange16_acq +#define ia64_cmpxchg4_rel _InterlockedCompareExchange_rel +#define ia64_cmpxchg4_acq _InterlockedCompareExchange_acq +#define ia64_cmpxchg8_rel _InterlockedCompareExchange64_rel +#define ia64_cmpxchg8_acq _InterlockedCompareExchange64_acq + +#define __ia64_set_dbr(index, val) \ + __setIndReg(_IA64_REG_INDR_DBR, index, val) +#define ia64_set_ibr(index, val) \ + __setIndReg(_IA64_REG_INDR_IBR, index, val) +#define ia64_set_pkr(index, val) \ + __setIndReg(_IA64_REG_INDR_PKR, index, val) +#define ia64_set_pmc(index, val) \ + __setIndReg(_IA64_REG_INDR_PMC, index, val) +#define ia64_set_pmd(index, val) \ + __setIndReg(_IA64_REG_INDR_PMD, index, val) +#define ia64_set_rr(index, val) \ + __setIndReg(_IA64_REG_INDR_RR, index, val) + +#define ia64_get_cpuid(index) __getIndReg(_IA64_REG_INDR_CPUID, index) +#define __ia64_get_dbr(index) __getIndReg(_IA64_REG_INDR_DBR, index) +#define ia64_get_ibr(index) __getIndReg(_IA64_REG_INDR_IBR, index) +#define ia64_get_pkr(index) __getIndReg(_IA64_REG_INDR_PKR, index) +#define ia64_get_pmc(index) __getIndReg(_IA64_REG_INDR_PMC, index) +#define ia64_get_pmd(index) __getIndReg(_IA64_REG_INDR_PMD, index) +#define ia64_get_rr(index) __getIndReg(_IA64_REG_INDR_RR, index) + +#define ia64_srlz_d __dsrlz +#define ia64_srlz_i __isrlz + +#define ia64_st1_rel __st1_rel +#define ia64_st2_rel __st2_rel +#define ia64_st4_rel __st4_rel +#define ia64_st8_rel __st8_rel + +#define ia64_ld1_acq __ld1_acq +#define ia64_ld2_acq __ld2_acq +#define ia64_ld4_acq __ld4_acq +#define ia64_ld8_acq __ld8_acq + +#define ia64_sync_i __synci +#define ia64_thash __thash +#define ia64_ttag __ttag +#define ia64_itcd __itcd +#define ia64_itci __itci +#define ia64_itrd __itrd +#define ia64_itri __itri +#define ia64_ptce __ptce +#define ia64_ptcl __ptcl +#define ia64_ptcg __ptcg +#define ia64_ptcga __ptcga +#define ia64_ptri __ptri +#define ia64_ptrd __ptrd +#define ia64_dep_mi _m64_dep_mi + +/* Values for lfhint in __lfetch and __lfetch_fault */ + +#define ia64_lfhint_none 0 +#define ia64_lfhint_nt1 1 +#define ia64_lfhint_nt2 2 +#define ia64_lfhint_nta 3 + +#define ia64_lfetch __lfetch +#define ia64_lfetch_excl __lfetch_excl +#define ia64_lfetch_fault __lfetch_fault +#define ia64_lfetch_fault_excl __lfetch_fault_excl + +#define ia64_intrin_local_irq_restore(x) \ +do { \ + if ((x) != 0) { \ + ia64_ssm(IA64_PSR_I); \ + ia64_srlz_d(); \ + } else { \ + ia64_rsm(IA64_PSR_I); \ + } \ +} while (0) + +#endif /* _ASM_IA64_INTEL_INTRIN_H */ diff -Nru a/include/asm-ia64/ptrace.h b/include/asm-ia64/ptrace.h --- a/include/asm-ia64/ptrace.h Thu Sep 11 23:03:13 2003 +++ b/include/asm-ia64/ptrace.h Thu Sep 11 23:03:13 2003 @@ -223,6 +223,12 @@ }; #ifdef __KERNEL__ +/* + * We use the ia64_psr(regs)->ri to determine which of the three + * instructions in bundle (16 bytes) took the sample. Generate + * the canonical representation by adding to instruction pointer. + */ +# define instruction_pointer(regs) ((regs)->cr_iip + ia64_psr(regs)->ri) /* given a pointer to a task_struct, return the user's pt_regs */ # define ia64_task_regs(t) (((struct pt_regs *) ((char *) (t) + IA64_STK_OFFSET)) - 1) # define ia64_psr(regs) ((struct ia64_psr *) &(regs)->cr_ipsr) diff -Nru a/include/asm-ia64/signal.h b/include/asm-ia64/signal.h --- a/include/asm-ia64/signal.h Thu Sep 11 23:03:11 2003 +++ b/include/asm-ia64/signal.h Thu Sep 11 23:03:11 2003 @@ -2,7 +2,7 @@ #define _ASM_IA64_SIGNAL_H /* - * Copyright (C) 1998-2001 Hewlett-Packard Co + * Copyright (C) 1998-2001, 2003 Hewlett-Packard Co * David Mosberger-Tang * * Unfortunately, this file is being included by bits/signal.h in @@ -96,7 +96,16 @@ * ar.rsc.loadrs is 14 bits, we can assume that they'll never take up * more than 16KB of space. */ -#define MINSIGSTKSZ 131027 /* min. stack size for sigaltstack() */ +#if 1 + /* + * This is a stupid typo: the value was _meant_ to be 131072 (0x20000), but I typed it + * in wrong. ;-( To preserve backwards compatibility, we leave the kernel at the + * incorrect value and fix libc only. + */ +# define MINSIGSTKSZ 131027 /* min. stack size for sigaltstack() */ +#else +# define MINSIGSTKSZ 131072 /* min. stack size for sigaltstack() */ +#endif #define SIGSTKSZ 262144 /* default stack size for sigaltstack() */ #ifdef __KERNEL__ diff -Nru a/include/asm-ia64/sn/hcl.h b/include/asm-ia64/sn/hcl.h --- a/include/asm-ia64/sn/hcl.h Thu Sep 11 23:03:12 2003 +++ b/include/asm-ia64/sn/hcl.h Thu Sep 11 23:03:12 2003 @@ -10,6 +10,7 @@ #define _ASM_IA64_SN_HCL_H #include +#include extern vertex_hdl_t hwgraph_root; extern vertex_hdl_t linux_busnum; diff -Nru a/include/asm-ia64/sn/ioc3.h b/include/asm-ia64/sn/ioc3.h --- a/include/asm-ia64/sn/ioc3.h Thu Sep 11 23:03:12 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,705 +0,0 @@ -/* - * Copyright (c) 2002-2003 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/NoticeExplan - */ - -/* $Id: ioc3.h,v 1.2 2000/11/16 19:49:17 pfg Exp $ - * - * Copyright (C) 1999 Ralf Baechle - * This file is part of the Linux driver for the SGI IOC3. - */ -#ifndef _ASM_IA64_SN_IOC3_H -#define _ASM_IA64_SN_IOC3_H - -#include - -/* SUPERIO uart register map */ -typedef volatile struct ioc3_uartregs { - union { - volatile u8 rbr; /* read only, DLAB == 0 */ - volatile u8 thr; /* write only, DLAB == 0 */ - volatile u8 dll; /* DLAB == 1 */ - } u1; - union { - volatile u8 ier; /* DLAB == 0 */ - volatile u8 dlm; /* DLAB == 1 */ - } u2; - union { - volatile u8 iir; /* read only */ - volatile u8 fcr; /* write only */ - } u3; - volatile u8 iu_lcr; - volatile u8 iu_mcr; - volatile u8 iu_lsr; - volatile u8 iu_msr; - volatile u8 iu_scr; -} ioc3_uregs_t; - -#define iu_rbr u1.rbr -#define iu_thr u1.thr -#define iu_dll u1.dll -#define iu_ier u2.ier -#define iu_dlm u2.dlm -#define iu_iir u3.iir -#define iu_fcr u3.fcr - -struct ioc3_sioregs { - volatile u8 fill[0x141]; /* starts at 0x141 */ - - volatile u8 uartc; - volatile u8 kbdcg; - - volatile u8 fill0[0x150 - 0x142 - 1]; - - volatile u8 pp_data; - volatile u8 pp_dsr; - volatile u8 pp_dcr; - - volatile u8 fill1[0x158 - 0x152 - 1]; - - volatile u8 pp_fifa; - volatile u8 pp_cfgb; - volatile u8 pp_ecr; - - volatile u8 fill2[0x168 - 0x15a - 1]; - - volatile u8 rtcad; - volatile u8 rtcdat; - - volatile u8 fill3[0x170 - 0x169 - 1]; - - struct ioc3_uartregs uartb; /* 0x20170 */ - struct ioc3_uartregs uarta; /* 0x20178 */ -}; - -/* Register layout of IOC3 in configuration space. */ -struct ioc3 { - volatile u32 pad0[7]; /* 0x00000 */ - volatile u32 sio_ir; /* 0x0001c */ - volatile u32 sio_ies; /* 0x00020 */ - volatile u32 sio_iec; /* 0x00024 */ - volatile u32 sio_cr; /* 0x00028 */ - volatile u32 int_out; /* 0x0002c */ - volatile u32 mcr; /* 0x00030 */ - - /* General Purpose I/O registers */ - volatile u32 gpcr_s; /* 0x00034 */ - volatile u32 gpcr_c; /* 0x00038 */ - volatile u32 gpdr; /* 0x0003c */ - volatile u32 gppr_0; /* 0x00040 */ - volatile u32 gppr_1; /* 0x00044 */ - volatile u32 gppr_2; /* 0x00048 */ - volatile u32 gppr_3; /* 0x0004c */ - volatile u32 gppr_4; /* 0x00050 */ - volatile u32 gppr_5; /* 0x00054 */ - volatile u32 gppr_6; /* 0x00058 */ - volatile u32 gppr_7; /* 0x0005c */ - volatile u32 gppr_8; /* 0x00060 */ - volatile u32 gppr_9; /* 0x00064 */ - volatile u32 gppr_10; /* 0x00068 */ - volatile u32 gppr_11; /* 0x0006c */ - volatile u32 gppr_12; /* 0x00070 */ - volatile u32 gppr_13; /* 0x00074 */ - volatile u32 gppr_14; /* 0x00078 */ - volatile u32 gppr_15; /* 0x0007c */ - - /* Parallel Port Registers */ - volatile u32 ppbr_h_a; /* 0x00080 */ - volatile u32 ppbr_l_a; /* 0x00084 */ - volatile u32 ppcr_a; /* 0x00088 */ - volatile u32 ppcr; /* 0x0008c */ - volatile u32 ppbr_h_b; /* 0x00090 */ - volatile u32 ppbr_l_b; /* 0x00094 */ - volatile u32 ppcr_b; /* 0x00098 */ - - /* Keyboard and Mouse Registers */ - volatile u32 km_csr; /* 0x0009c */ - volatile u32 k_rd; /* 0x000a0 */ - volatile u32 m_rd; /* 0x000a4 */ - volatile u32 k_wd; /* 0x000a8 */ - volatile u32 m_wd; /* 0x000ac */ - - /* Serial Port Registers */ - volatile u32 sbbr_h; /* 0x000b0 */ - volatile u32 sbbr_l; /* 0x000b4 */ - volatile u32 sscr_a; /* 0x000b8 */ - volatile u32 stpir_a; /* 0x000bc */ - volatile u32 stcir_a; /* 0x000c0 */ - volatile u32 srpir_a; /* 0x000c4 */ - volatile u32 srcir_a; /* 0x000c8 */ - volatile u32 srtr_a; /* 0x000cc */ - volatile u32 shadow_a; /* 0x000d0 */ - volatile u32 sscr_b; /* 0x000d4 */ - volatile u32 stpir_b; /* 0x000d8 */ - volatile u32 stcir_b; /* 0x000dc */ - volatile u32 srpir_b; /* 0x000e0 */ - volatile u32 srcir_b; /* 0x000e4 */ - volatile u32 srtr_b; /* 0x000e8 */ - volatile u32 shadow_b; /* 0x000ec */ - - /* Ethernet Registers */ - volatile u32 emcr; /* 0x000f0 */ - volatile u32 eisr; /* 0x000f4 */ - volatile u32 eier; /* 0x000f8 */ - volatile u32 ercsr; /* 0x000fc */ - volatile u32 erbr_h; /* 0x00100 */ - volatile u32 erbr_l; /* 0x00104 */ - volatile u32 erbar; /* 0x00108 */ - volatile u32 ercir; /* 0x0010c */ - volatile u32 erpir; /* 0x00110 */ - volatile u32 ertr; /* 0x00114 */ - volatile u32 etcsr; /* 0x00118 */ - volatile u32 ersr; /* 0x0011c */ - volatile u32 etcdc; /* 0x00120 */ - volatile u32 ebir; /* 0x00124 */ - volatile u32 etbr_h; /* 0x00128 */ - volatile u32 etbr_l; /* 0x0012c */ - volatile u32 etcir; /* 0x00130 */ - volatile u32 etpir; /* 0x00134 */ - volatile u32 emar_h; /* 0x00138 */ - volatile u32 emar_l; /* 0x0013c */ - volatile u32 ehar_h; /* 0x00140 */ - volatile u32 ehar_l; /* 0x00144 */ - volatile u32 micr; /* 0x00148 */ - volatile u32 midr_r; /* 0x0014c */ - volatile u32 midr_w; /* 0x00150 */ - volatile u32 pad1[(0x20000 - 0x00154) / 4]; - - /* SuperIO Registers XXX */ - struct ioc3_sioregs sregs; /* 0x20000 */ - volatile u32 pad2[(0x40000 - 0x20180) / 4]; - - /* SSRAM Diagnostic Access */ - volatile u32 ssram[(0x80000 - 0x40000) / 4]; - - /* Bytebus device offsets - 0x80000 - Access to the generic devices selected with DEV0 - 0x9FFFF bytebus DEV_SEL_0 - 0xA0000 - Access to the generic devices selected with DEV1 - 0xBFFFF bytebus DEV_SEL_1 - 0xC0000 - Access to the generic devices selected with DEV2 - 0xDFFFF bytebus DEV_SEL_2 - 0xE0000 - Access to the generic devices selected with DEV3 - 0xFFFFF bytebus DEV_SEL_3 */ -}; - -/* - * Ethernet RX Buffer - */ -struct ioc3_erxbuf { - u32 w0; /* first word (valid,bcnt,cksum) */ - u32 err; /* second word various errors */ - /* next comes n bytes of padding */ - /* then the received ethernet frame itself */ -}; - -#define ERXBUF_IPCKSUM_MASK 0x0000ffff -#define ERXBUF_BYTECNT_MASK 0x07ff0000 -#define ERXBUF_BYTECNT_SHIFT 16 -#define ERXBUF_V 0x80000000 - -#define ERXBUF_CRCERR 0x00000001 /* aka RSV15 */ -#define ERXBUF_FRAMERR 0x00000002 /* aka RSV14 */ -#define ERXBUF_CODERR 0x00000004 /* aka RSV13 */ -#define ERXBUF_INVPREAMB 0x00000008 /* aka RSV18 */ -#define ERXBUF_LOLEN 0x00007000 /* aka RSV2_0 */ -#define ERXBUF_HILEN 0x03ff0000 /* aka RSV12_3 */ -#define ERXBUF_MULTICAST 0x04000000 /* aka RSV16 */ -#define ERXBUF_BROADCAST 0x08000000 /* aka RSV17 */ -#define ERXBUF_LONGEVENT 0x10000000 /* aka RSV19 */ -#define ERXBUF_BADPKT 0x20000000 /* aka RSV20 */ -#define ERXBUF_GOODPKT 0x40000000 /* aka RSV21 */ -#define ERXBUF_CARRIER 0x80000000 /* aka RSV22 */ - -/* - * Ethernet TX Descriptor - */ -#define ETXD_DATALEN 104 -struct ioc3_etxd { - u32 cmd; /* command field */ - u32 bufcnt; /* buffer counts field */ - u64 p1; /* buffer pointer 1 */ - u64 p2; /* buffer pointer 2 */ - u8 data[ETXD_DATALEN]; /* opt. tx data */ -}; - -#define ETXD_BYTECNT_MASK 0x000007ff /* total byte count */ -#define ETXD_INTWHENDONE 0x00001000 /* intr when done */ -#define ETXD_D0V 0x00010000 /* data 0 valid */ -#define ETXD_B1V 0x00020000 /* buf 1 valid */ -#define ETXD_B2V 0x00040000 /* buf 2 valid */ -#define ETXD_DOCHECKSUM 0x00080000 /* insert ip cksum */ -#define ETXD_CHKOFF_MASK 0x07f00000 /* cksum byte offset */ -#define ETXD_CHKOFF_SHIFT 20 - -#define ETXD_D0CNT_MASK 0x0000007f -#define ETXD_B1CNT_MASK 0x0007ff00 -#define ETXD_B1CNT_SHIFT 8 -#define ETXD_B2CNT_MASK 0x7ff00000 -#define ETXD_B2CNT_SHIFT 20 - -/* - * Bytebus device space - */ -#define IOC3_BYTEBUS_DEV0 0x80000L -#define IOC3_BYTEBUS_DEV1 0xa0000L -#define IOC3_BYTEBUS_DEV2 0xc0000L -#define IOC3_BYTEBUS_DEV3 0xe0000L - -/* ------------------------------------------------------------------------- */ - -/* Superio Registers (PIO Access) */ -#define IOC3_SIO_BASE 0x20000 -#define IOC3_SIO_UARTC (IOC3_SIO_BASE+0x141) /* UART Config */ -#define IOC3_SIO_KBDCG (IOC3_SIO_BASE+0x142) /* KBD Config */ -#define IOC3_SIO_PP_BASE (IOC3_SIO_BASE+PP_BASE) /* Parallel Port */ -#define IOC3_SIO_RTC_BASE (IOC3_SIO_BASE+0x168) /* Real Time Clock */ -#define IOC3_SIO_UB_BASE (IOC3_SIO_BASE+UARTB_BASE) /* UART B */ -#define IOC3_SIO_UA_BASE (IOC3_SIO_BASE+UARTA_BASE) /* UART A */ - -/* SSRAM Diagnostic Access */ -#define IOC3_SSRAM IOC3_RAM_OFF /* base of SSRAM diagnostic access */ -#define IOC3_SSRAM_LEN 0x40000 /* 256kb (address space size, may not be fully populated) */ -#define IOC3_SSRAM_DM 0x0000ffff /* data mask */ -#define IOC3_SSRAM_PM 0x00010000 /* parity mask */ - -/* bitmasks for PCI_SCR */ -#define PCI_SCR_PAR_RESP_EN 0x00000040 /* enb PCI parity checking */ -#define PCI_SCR_SERR_EN 0x00000100 /* enable the SERR# driver */ -#define PCI_SCR_DROP_MODE_EN 0x00008000 /* drop pios on parity err */ -#define PCI_SCR_RX_SERR (0x1 << 16) -#define PCI_SCR_DROP_MODE (0x1 << 17) -#define PCI_SCR_SIG_PAR_ERR (0x1 << 24) -#define PCI_SCR_SIG_TAR_ABRT (0x1 << 27) -#define PCI_SCR_RX_TAR_ABRT (0x1 << 28) -#define PCI_SCR_SIG_MST_ABRT (0x1 << 29) -#define PCI_SCR_SIG_SERR (0x1 << 30) -#define PCI_SCR_PAR_ERR (0x1 << 31) - -/* bitmasks for IOC3_KM_CSR */ -#define KM_CSR_K_WRT_PEND 0x00000001 /* kbd port xmitting or resetting */ -#define KM_CSR_M_WRT_PEND 0x00000002 /* mouse port xmitting or resetting */ -#define KM_CSR_K_LCB 0x00000004 /* Line Cntrl Bit for last KBD write */ -#define KM_CSR_M_LCB 0x00000008 /* same for mouse */ -#define KM_CSR_K_DATA 0x00000010 /* state of kbd data line */ -#define KM_CSR_K_CLK 0x00000020 /* state of kbd clock line */ -#define KM_CSR_K_PULL_DATA 0x00000040 /* pull kbd data line low */ -#define KM_CSR_K_PULL_CLK 0x00000080 /* pull kbd clock line low */ -#define KM_CSR_M_DATA 0x00000100 /* state of ms data line */ -#define KM_CSR_M_CLK 0x00000200 /* state of ms clock line */ -#define KM_CSR_M_PULL_DATA 0x00000400 /* pull ms data line low */ -#define KM_CSR_M_PULL_CLK 0x00000800 /* pull ms clock line low */ -#define KM_CSR_EMM_MODE 0x00001000 /* emulation mode */ -#define KM_CSR_SIM_MODE 0x00002000 /* clock X8 */ -#define KM_CSR_K_SM_IDLE 0x00004000 /* Keyboard is idle */ -#define KM_CSR_M_SM_IDLE 0x00008000 /* Mouse is idle */ -#define KM_CSR_K_TO 0x00010000 /* Keyboard trying to send/receive */ -#define KM_CSR_M_TO 0x00020000 /* Mouse trying to send/receive */ -#define KM_CSR_K_TO_EN 0x00040000 /* KM_CSR_K_TO + KM_CSR_K_TO_EN = cause - SIO_IR to assert */ -#define KM_CSR_M_TO_EN 0x00080000 /* KM_CSR_M_TO + KM_CSR_M_TO_EN = cause - SIO_IR to assert */ -#define KM_CSR_K_CLAMP_ONE 0x00100000 /* Pull K_CLK low after rec. one char */ -#define KM_CSR_M_CLAMP_ONE 0x00200000 /* Pull M_CLK low after rec. one char */ -#define KM_CSR_K_CLAMP_THREE 0x00400000 /* Pull K_CLK low after rec. three chars */ -#define KM_CSR_M_CLAMP_THREE 0x00800000 /* Pull M_CLK low after rec. three char */ - -/* bitmasks for IOC3_K_RD and IOC3_M_RD */ -#define KM_RD_DATA_2 0x000000ff /* 3rd char recvd since last read */ -#define KM_RD_DATA_2_SHIFT 0 -#define KM_RD_DATA_1 0x0000ff00 /* 2nd char recvd since last read */ -#define KM_RD_DATA_1_SHIFT 8 -#define KM_RD_DATA_0 0x00ff0000 /* 1st char recvd since last read */ -#define KM_RD_DATA_0_SHIFT 16 -#define KM_RD_FRAME_ERR_2 0x01000000 /* framing or parity error in byte 2 */ -#define KM_RD_FRAME_ERR_1 0x02000000 /* same for byte 1 */ -#define KM_RD_FRAME_ERR_0 0x04000000 /* same for byte 0 */ - -#define KM_RD_KBD_MSE 0x08000000 /* 0 if from kbd, 1 if from mouse */ -#define KM_RD_OFLO 0x10000000 /* 4th char recvd before this read */ -#define KM_RD_VALID_2 0x20000000 /* DATA_2 valid */ -#define KM_RD_VALID_1 0x40000000 /* DATA_1 valid */ -#define KM_RD_VALID_0 0x80000000 /* DATA_0 valid */ -#define KM_RD_VALID_ALL (KM_RD_VALID_0|KM_RD_VALID_1|KM_RD_VALID_2) - -/* bitmasks for IOC3_K_WD & IOC3_M_WD */ -#define KM_WD_WRT_DATA 0x000000ff /* write to keyboard/mouse port */ -#define KM_WD_WRT_DATA_SHIFT 0 - -/* bitmasks for serial RX status byte */ -#define RXSB_OVERRUN 0x01 /* char(s) lost */ -#define RXSB_PAR_ERR 0x02 /* parity error */ -#define RXSB_FRAME_ERR 0x04 /* framing error */ -#define RXSB_BREAK 0x08 /* break character */ -#define RXSB_CTS 0x10 /* state of CTS */ -#define RXSB_DCD 0x20 /* state of DCD */ -#define RXSB_MODEM_VALID 0x40 /* DCD, CTS and OVERRUN are valid */ -#define RXSB_DATA_VALID 0x80 /* data byte, FRAME_ERR PAR_ERR & BREAK valid */ - -/* bitmasks for serial TX control byte */ -#define TXCB_INT_WHEN_DONE 0x20 /* interrupt after this byte is sent */ -#define TXCB_INVALID 0x00 /* byte is invalid */ -#define TXCB_VALID 0x40 /* byte is valid */ -#define TXCB_MCR 0x80 /* data<7:0> to modem control register */ -#define TXCB_DELAY 0xc0 /* delay data<7:0> mSec */ - -/* bitmasks for IOC3_SBBR_L */ -#define SBBR_L_SIZE 0x00000001 /* 0 == 1KB rings, 1 == 4KB rings */ -#define SBBR_L_BASE 0xfffff000 /* lower serial ring base addr */ - -/* bitmasks for IOC3_SSCR_ */ -#define SSCR_RX_THRESHOLD 0x000001ff /* hiwater mark */ -#define SSCR_TX_TIMER_BUSY 0x00010000 /* TX timer in progress */ -#define SSCR_HFC_EN 0x00020000 /* hardware flow control enabled */ -#define SSCR_RX_RING_DCD 0x00040000 /* post RX record on delta-DCD */ -#define SSCR_RX_RING_CTS 0x00080000 /* post RX record on delta-CTS */ -#define SSCR_HIGH_SPD 0x00100000 /* 4X speed */ -#define SSCR_DIAG 0x00200000 /* bypass clock divider for sim */ -#define SSCR_RX_DRAIN 0x08000000 /* drain RX buffer to memory */ -#define SSCR_DMA_EN 0x10000000 /* enable ring buffer DMA */ -#define SSCR_DMA_PAUSE 0x20000000 /* pause DMA */ -#define SSCR_PAUSE_STATE 0x40000000 /* sets when PAUSE takes effect */ -#define SSCR_RESET 0x80000000 /* reset DMA channels */ - -/* all producer/comsumer pointers are the same bitfield */ -#define PROD_CONS_PTR_4K 0x00000ff8 /* for 4K buffers */ -#define PROD_CONS_PTR_1K 0x000003f8 /* for 1K buffers */ -#define PROD_CONS_PTR_OFF 3 - -/* bitmasks for IOC3_SRCIR_ */ -#define SRCIR_ARM 0x80000000 /* arm RX timer */ - -/* bitmasks for IOC3_SRPIR_ */ -#define SRPIR_BYTE_CNT 0x07000000 /* bytes in packer */ -#define SRPIR_BYTE_CNT_SHIFT 24 - -/* bitmasks for IOC3_STCIR_ */ -#define STCIR_BYTE_CNT 0x0f000000 /* bytes in unpacker */ -#define STCIR_BYTE_CNT_SHIFT 24 - -/* bitmasks for IOC3_SHADOW_ */ -#define SHADOW_DR 0x00000001 /* data ready */ -#define SHADOW_OE 0x00000002 /* overrun error */ -#define SHADOW_PE 0x00000004 /* parity error */ -#define SHADOW_FE 0x00000008 /* framing error */ -#define SHADOW_BI 0x00000010 /* break interrupt */ -#define SHADOW_THRE 0x00000020 /* transmit holding register empty */ -#define SHADOW_TEMT 0x00000040 /* transmit shift register empty */ -#define SHADOW_RFCE 0x00000080 /* char in RX fifo has an error */ -#define SHADOW_DCTS 0x00010000 /* delta clear to send */ -#define SHADOW_DDCD 0x00080000 /* delta data carrier detect */ -#define SHADOW_CTS 0x00100000 /* clear to send */ -#define SHADOW_DCD 0x00800000 /* data carrier detect */ -#define SHADOW_DTR 0x01000000 /* data terminal ready */ -#define SHADOW_RTS 0x02000000 /* request to send */ -#define SHADOW_OUT1 0x04000000 /* 16550 OUT1 bit */ -#define SHADOW_OUT2 0x08000000 /* 16550 OUT2 bit */ -#define SHADOW_LOOP 0x10000000 /* loopback enabled */ - -/* bitmasks for IOC3_SRTR_ */ -#define SRTR_CNT 0x00000fff /* reload value for RX timer */ -#define SRTR_CNT_VAL 0x0fff0000 /* current value of RX timer */ -#define SRTR_CNT_VAL_SHIFT 16 -#define SRTR_HZ 16000 /* SRTR clock frequency */ - -/* bitmasks for IOC3_SIO_IR, IOC3_SIO_IEC and IOC3_SIO_IES */ -#define SIO_IR_SA_TX_MT 0x00000001 /* Serial port A TX empty */ -#define SIO_IR_SA_RX_FULL 0x00000002 /* port A RX buf full */ -#define SIO_IR_SA_RX_HIGH 0x00000004 /* port A RX hiwat */ -#define SIO_IR_SA_RX_TIMER 0x00000008 /* port A RX timeout */ -#define SIO_IR_SA_DELTA_DCD 0x00000010 /* port A delta DCD */ -#define SIO_IR_SA_DELTA_CTS 0x00000020 /* port A delta CTS */ -#define SIO_IR_SA_INT 0x00000040 /* port A pass-thru intr */ -#define SIO_IR_SA_TX_EXPLICIT 0x00000080 /* port A explicit TX thru */ -#define SIO_IR_SA_MEMERR 0x00000100 /* port A PCI error */ -#define SIO_IR_SB_TX_MT 0x00000200 /* */ -#define SIO_IR_SB_RX_FULL 0x00000400 /* */ -#define SIO_IR_SB_RX_HIGH 0x00000800 /* */ -#define SIO_IR_SB_RX_TIMER 0x00001000 /* */ -#define SIO_IR_SB_DELTA_DCD 0x00002000 /* */ -#define SIO_IR_SB_DELTA_CTS 0x00004000 /* */ -#define SIO_IR_SB_INT 0x00008000 /* */ -#define SIO_IR_SB_TX_EXPLICIT 0x00010000 /* */ -#define SIO_IR_SB_MEMERR 0x00020000 /* */ -#define SIO_IR_PP_INT 0x00040000 /* P port pass-thru intr */ -#define SIO_IR_PP_INTA 0x00080000 /* PP context A thru */ -#define SIO_IR_PP_INTB 0x00100000 /* PP context B thru */ -#define SIO_IR_PP_MEMERR 0x00200000 /* PP PCI error */ -#define SIO_IR_KBD_INT 0x00400000 /* kbd/mouse intr */ -#define SIO_IR_RT_INT 0x08000000 /* RT output pulse */ -#define SIO_IR_GEN_INT1 0x10000000 /* RT input pulse */ -#define SIO_IR_GEN_INT_SHIFT 28 - -/* per device interrupt masks */ -#define SIO_IR_SA (SIO_IR_SA_TX_MT | SIO_IR_SA_RX_FULL | \ - SIO_IR_SA_RX_HIGH | SIO_IR_SA_RX_TIMER | \ - SIO_IR_SA_DELTA_DCD | SIO_IR_SA_DELTA_CTS | \ - SIO_IR_SA_INT | SIO_IR_SA_TX_EXPLICIT | \ - SIO_IR_SA_MEMERR) -#define SIO_IR_SB (SIO_IR_SB_TX_MT | SIO_IR_SB_RX_FULL | \ - SIO_IR_SB_RX_HIGH | SIO_IR_SB_RX_TIMER | \ - SIO_IR_SB_DELTA_DCD | SIO_IR_SB_DELTA_CTS | \ - SIO_IR_SB_INT | SIO_IR_SB_TX_EXPLICIT | \ - SIO_IR_SB_MEMERR) -#define SIO_IR_PP (SIO_IR_PP_INT | SIO_IR_PP_INTA | \ - SIO_IR_PP_INTB | SIO_IR_PP_MEMERR) -#define SIO_IR_RT (SIO_IR_RT_INT | SIO_IR_GEN_INT1) - -/* macro to load pending interrupts */ -#define IOC3_PENDING_INTRS(mem) (PCI_INW(&((mem)->sio_ir)) & \ - PCI_INW(&((mem)->sio_ies_ro))) - -/* bitmasks for SIO_CR */ -#define SIO_CR_SIO_RESET 0x00000001 /* reset the SIO */ -#define SIO_CR_SER_A_BASE 0x000000fe /* DMA poll addr port A */ -#define SIO_CR_SER_A_BASE_SHIFT 1 -#define SIO_CR_SER_B_BASE 0x00007f00 /* DMA poll addr port B */ -#define SIO_CR_SER_B_BASE_SHIFT 8 -#define SIO_SR_CMD_PULSE 0x00078000 /* byte bus strobe length */ -#define SIO_CR_CMD_PULSE_SHIFT 15 -#define SIO_CR_ARB_DIAG 0x00380000 /* cur !enet PCI requet (ro) */ -#define SIO_CR_ARB_DIAG_TXA 0x00000000 -#define SIO_CR_ARB_DIAG_RXA 0x00080000 -#define SIO_CR_ARB_DIAG_TXB 0x00100000 -#define SIO_CR_ARB_DIAG_RXB 0x00180000 -#define SIO_CR_ARB_DIAG_PP 0x00200000 -#define SIO_CR_ARB_DIAG_IDLE 0x00400000 /* 0 -> active request (ro) */ - -/* bitmasks for INT_OUT */ -#define INT_OUT_COUNT 0x0000ffff /* pulse interval timer */ -#define INT_OUT_MODE 0x00070000 /* mode mask */ -#define INT_OUT_MODE_0 0x00000000 /* set output to 0 */ -#define INT_OUT_MODE_1 0x00040000 /* set output to 1 */ -#define INT_OUT_MODE_1PULSE 0x00050000 /* send 1 pulse */ -#define INT_OUT_MODE_PULSES 0x00060000 /* send 1 pulse every interval */ -#define INT_OUT_MODE_SQW 0x00070000 /* toggle output every interval */ -#define INT_OUT_DIAG 0x40000000 /* diag mode */ -#define INT_OUT_INT_OUT 0x80000000 /* current state of INT_OUT */ - -/* time constants for INT_OUT */ -#define INT_OUT_NS_PER_TICK (30 * 260) /* 30 ns PCI clock, divisor=260 */ -#define INT_OUT_TICKS_PER_PULSE 3 /* outgoing pulse lasts 3 ticks */ -#define INT_OUT_US_TO_COUNT(x) /* convert uS to a count value */ \ - (((x) * 10 + INT_OUT_NS_PER_TICK / 200) * \ - 100 / INT_OUT_NS_PER_TICK - 1) -#define INT_OUT_COUNT_TO_US(x) /* convert count value to uS */ \ - (((x) + 1) * INT_OUT_NS_PER_TICK / 1000) -#define INT_OUT_MIN_TICKS 3 /* min period is width of pulse in "ticks" */ -#define INT_OUT_MAX_TICKS INT_OUT_COUNT /* largest possible count */ - -/* bitmasks for GPCR */ -#define GPCR_DIR 0x000000ff /* tristate pin input or output */ -#define GPCR_DIR_PIN(x) (1<<(x)) /* access one of the DIR bits */ -#define GPCR_EDGE 0x000f0000 /* extint edge or level sensitive */ -#define GPCR_EDGE_PIN(x) (1<<((x)+15)) /* access one of the EDGE bits */ - -/* values for GPCR */ -#define GPCR_INT_OUT_EN 0x00100000 /* enable INT_OUT to pin 0 */ -#define GPCR_MLAN_EN 0x00200000 /* enable MCR to pin 8 */ -#define GPCR_DIR_SERA_XCVR 0x00000080 /* Port A Transceiver select enable */ -#define GPCR_DIR_SERB_XCVR 0x00000040 /* Port B Transceiver select enable */ -#define GPCR_DIR_PHY_RST 0x00000020 /* ethernet PHY reset enable */ - -/* defs for some of the generic I/O pins */ -#define GPCR_PHY_RESET 0x20 /* pin is output to PHY reset */ -#define GPCR_UARTB_MODESEL 0x40 /* pin is output to port B mode sel */ -#define GPCR_UARTA_MODESEL 0x80 /* pin is output to port A mode sel */ - -#define GPPR_PHY_RESET_PIN 5 /* GIO pin controlling phy reset */ -#define GPPR_UARTB_MODESEL_PIN 6 /* GIO pin controlling uart b mode select */ -#define GPPR_UARTA_MODESEL_PIN 7 /* GIO pin controlling uart a mode select */ - -#define EMCR_DUPLEX 0x00000001 -#define EMCR_PROMISC 0x00000002 -#define EMCR_PADEN 0x00000004 -#define EMCR_RXOFF_MASK 0x000001f8 -#define EMCR_RXOFF_SHIFT 3 -#define EMCR_RAMPAR 0x00000200 -#define EMCR_BADPAR 0x00000800 -#define EMCR_BUFSIZ 0x00001000 -#define EMCR_TXDMAEN 0x00002000 -#define EMCR_TXEN 0x00004000 -#define EMCR_RXDMAEN 0x00008000 -#define EMCR_RXEN 0x00010000 -#define EMCR_LOOPBACK 0x00020000 -#define EMCR_ARB_DIAG 0x001c0000 -#define EMCR_ARB_DIAG_IDLE 0x00200000 -#define EMCR_RST 0x80000000 - -#define EISR_RXTIMERINT 0x00000001 -#define EISR_RXTHRESHINT 0x00000002 -#define EISR_RXOFLO 0x00000004 -#define EISR_RXBUFOFLO 0x00000008 -#define EISR_RXMEMERR 0x00000010 -#define EISR_RXPARERR 0x00000020 -#define EISR_TXEMPTY 0x00010000 -#define EISR_TXRTRY 0x00020000 -#define EISR_TXEXDEF 0x00040000 -#define EISR_TXLCOL 0x00080000 -#define EISR_TXGIANT 0x00100000 -#define EISR_TXBUFUFLO 0x00200000 -#define EISR_TXEXPLICIT 0x00400000 -#define EISR_TXCOLLWRAP 0x00800000 -#define EISR_TXDEFERWRAP 0x01000000 -#define EISR_TXMEMERR 0x02000000 -#define EISR_TXPARERR 0x04000000 - -#define ERCSR_THRESH_MASK 0x000001ff /* enet RX threshold */ -#define ERCSR_RX_TMR 0x40000000 /* simulation only */ -#define ERCSR_DIAG_OFLO 0x80000000 /* simulation only */ - -#define ERBR_ALIGNMENT 4096 -#define ERBR_L_RXRINGBASE_MASK 0xfffff000 - -#define ERBAR_BARRIER_BIT 0x0100 -#define ERBAR_RXBARR_MASK 0xffff0000 -#define ERBAR_RXBARR_SHIFT 16 - -#define ERCIR_RXCONSUME_MASK 0x00000fff - -#define ERPIR_RXPRODUCE_MASK 0x00000fff -#define ERPIR_ARM 0x80000000 - -#define ERTR_CNT_MASK 0x000007ff - -#define ETCSR_IPGT_MASK 0x0000007f -#define ETCSR_IPGR1_MASK 0x00007f00 -#define ETCSR_IPGR1_SHIFT 8 -#define ETCSR_IPGR2_MASK 0x007f0000 -#define ETCSR_IPGR2_SHIFT 16 -#define ETCSR_NOTXCLK 0x80000000 - -#define ETCDC_COLLCNT_MASK 0x0000ffff -#define ETCDC_DEFERCNT_MASK 0xffff0000 -#define ETCDC_DEFERCNT_SHIFT 16 - -#define ETBR_ALIGNMENT (64*1024) -#define ETBR_L_RINGSZ_MASK 0x00000001 -#define ETBR_L_RINGSZ128 0 -#define ETBR_L_RINGSZ512 1 -#define ETBR_L_TXRINGBASE_MASK 0xffffc000 - -#define ETCIR_TXCONSUME_MASK 0x0000ffff -#define ETCIR_IDLE 0x80000000 - -#define ETPIR_TXPRODUCE_MASK 0x0000ffff - -#define EBIR_TXBUFPROD_MASK 0x0000001f -#define EBIR_TXBUFCONS_MASK 0x00001f00 -#define EBIR_TXBUFCONS_SHIFT 8 -#define EBIR_RXBUFPROD_MASK 0x007fc000 -#define EBIR_RXBUFPROD_SHIFT 14 -#define EBIR_RXBUFCONS_MASK 0xff800000 -#define EBIR_RXBUFCONS_SHIFT 23 - -#define MICR_REGADDR_MASK 0x0000001f -#define MICR_PHYADDR_MASK 0x000003e0 -#define MICR_PHYADDR_SHIFT 5 -#define MICR_READTRIG 0x00000400 -#define MICR_BUSY 0x00000800 - -#define MIDR_DATA_MASK 0x0000ffff - -#define ERXBUF_IPCKSUM_MASK 0x0000ffff -#define ERXBUF_BYTECNT_MASK 0x07ff0000 -#define ERXBUF_BYTECNT_SHIFT 16 -#define ERXBUF_V 0x80000000 - -#define ERXBUF_CRCERR 0x00000001 /* aka RSV15 */ -#define ERXBUF_FRAMERR 0x00000002 /* aka RSV14 */ -#define ERXBUF_CODERR 0x00000004 /* aka RSV13 */ -#define ERXBUF_INVPREAMB 0x00000008 /* aka RSV18 */ -#define ERXBUF_LOLEN 0x00007000 /* aka RSV2_0 */ -#define ERXBUF_HILEN 0x03ff0000 /* aka RSV12_3 */ -#define ERXBUF_MULTICAST 0x04000000 /* aka RSV16 */ -#define ERXBUF_BROADCAST 0x08000000 /* aka RSV17 */ -#define ERXBUF_LONGEVENT 0x10000000 /* aka RSV19 */ -#define ERXBUF_BADPKT 0x20000000 /* aka RSV20 */ -#define ERXBUF_GOODPKT 0x40000000 /* aka RSV21 */ -#define ERXBUF_CARRIER 0x80000000 /* aka RSV22 */ - -#define ETXD_BYTECNT_MASK 0x000007ff /* total byte count */ -#define ETXD_INTWHENDONE 0x00001000 /* intr when done */ -#define ETXD_D0V 0x00010000 /* data 0 valid */ -#define ETXD_B1V 0x00020000 /* buf 1 valid */ -#define ETXD_B2V 0x00040000 /* buf 2 valid */ -#define ETXD_DOCHECKSUM 0x00080000 /* insert ip cksum */ -#define ETXD_CHKOFF_MASK 0x07f00000 /* cksum byte offset */ -#define ETXD_CHKOFF_SHIFT 20 - -#define ETXD_D0CNT_MASK 0x0000007f -#define ETXD_B1CNT_MASK 0x0007ff00 -#define ETXD_B1CNT_SHIFT 8 -#define ETXD_B2CNT_MASK 0x7ff00000 -#define ETXD_B2CNT_SHIFT 20 - -typedef enum ioc3_subdevs_e { - ioc3_subdev_ether, - ioc3_subdev_generic, - ioc3_subdev_nic, - ioc3_subdev_kbms, - ioc3_subdev_ttya, - ioc3_subdev_ttyb, - ioc3_subdev_ecpp, - ioc3_subdev_rt, - ioc3_nsubdevs -} ioc3_subdev_t; - -/* subdevice disable bits, - * from the standard INFO_LBL_SUBDEVS - */ -#define IOC3_SDB_ETHER (1< -#include - -#define RTC_BASE_ADDR (unsigned char *)(nvram_base) - -/* Defines for the SGS-Thomson M48T35 clock */ -#define RTC_SGS_WRITE_ENABLE 0x80 -#define RTC_SGS_READ_PROTECT 0x40 -#define RTC_SGS_YEAR_ADDR (RTC_BASE_ADDR + 0x7fffL) -#define RTC_SGS_MONTH_ADDR (RTC_BASE_ADDR + 0x7ffeL) -#define RTC_SGS_DATE_ADDR (RTC_BASE_ADDR + 0x7ffdL) -#define RTC_SGS_DAY_ADDR (RTC_BASE_ADDR + 0x7ffcL) -#define RTC_SGS_HOUR_ADDR (RTC_BASE_ADDR + 0x7ffbL) -#define RTC_SGS_MIN_ADDR (RTC_BASE_ADDR + 0x7ffaL) -#define RTC_SGS_SEC_ADDR (RTC_BASE_ADDR + 0x7ff9L) -#define RTC_SGS_CONTROL_ADDR (RTC_BASE_ADDR + 0x7ff8L) - -/* Defines for the Dallas DS1386 */ -#define RTC_DAL_UPDATE_ENABLE 0x80 -#define RTC_DAL_UPDATE_DISABLE 0x00 -#define RTC_DAL_YEAR_ADDR (RTC_BASE_ADDR + 0xaL) -#define RTC_DAL_MONTH_ADDR (RTC_BASE_ADDR + 0x9L) -#define RTC_DAL_DATE_ADDR (RTC_BASE_ADDR + 0x8L) -#define RTC_DAL_DAY_ADDR (RTC_BASE_ADDR + 0x6L) -#define RTC_DAL_HOUR_ADDR (RTC_BASE_ADDR + 0x4L) -#define RTC_DAL_MIN_ADDR (RTC_BASE_ADDR + 0x2L) -#define RTC_DAL_SEC_ADDR (RTC_BASE_ADDR + 0x1L) -#define RTC_DAL_CONTROL_ADDR (RTC_BASE_ADDR + 0xbL) -#define RTC_DAL_USER_ADDR (RTC_BASE_ADDR + 0xeL) - -/* Defines for the Dallas DS1742 */ -#define RTC_DS1742_WRITE_ENABLE 0x80 -#define RTC_DS1742_READ_ENABLE 0x40 -#define RTC_DS1742_UPDATE_DISABLE 0x00 -#define RTC_DS1742_YEAR_ADDR (RTC_BASE_ADDR + 0x7ffL) -#define RTC_DS1742_MONTH_ADDR (RTC_BASE_ADDR + 0x7feL) -#define RTC_DS1742_DATE_ADDR (RTC_BASE_ADDR + 0x7fdL) -#define RTC_DS1742_DAY_ADDR (RTC_BASE_ADDR + 0x7fcL) -#define RTC_DS1742_HOUR_ADDR (RTC_BASE_ADDR + 0x7fbL) -#define RTC_DS1742_MIN_ADDR (RTC_BASE_ADDR + 0x7faL) -#define RTC_DS1742_SEC_ADDR (RTC_BASE_ADDR + 0x7f9L) -#define RTC_DS1742_CONTROL_ADDR (RTC_BASE_ADDR + 0x7f8L) -#define RTC_DS1742_USER_ADDR (RTC_BASE_ADDR + 0x0L) - -#define BCD_TO_INT(x) (((x>>4) * 10) + (x & 0xf)) -#define INT_TO_BCD(x) (((x / 10)<<4) + (x % 10)) - -#define YRREF 1970 - -#endif /* _ASM_IA64_SN_KLCLOCK_H */ diff -Nru a/include/asm-ia64/sn/nodepda.h b/include/asm-ia64/sn/nodepda.h --- a/include/asm-ia64/sn/nodepda.h Thu Sep 11 23:03:11 2003 +++ b/include/asm-ia64/sn/nodepda.h Thu Sep 11 23:03:11 2003 @@ -87,7 +87,7 @@ char irq_flags[NR_IRQS]; struct pci_dev *device_dev[NR_IRQS]; char share_count[NR_IRQS]; - struct pci_dev *current; + struct pci_dev *curr; }; typedef struct irqpda_s irqpda_t; diff -Nru a/include/asm-ia64/sn/pci/pciio.h b/include/asm-ia64/sn/pci/pciio.h --- a/include/asm-ia64/sn/pci/pciio.h Thu Sep 11 23:03:11 2003 +++ b/include/asm-ia64/sn/pci/pciio.h Thu Sep 11 23:03:11 2003 @@ -695,5 +695,39 @@ extern int pciio_error_handler(vertex_hdl_t, int, ioerror_mode_t, ioerror_t *); extern int pciio_dma_enabled(vertex_hdl_t); +/** + * sn_pci_set_vchan - Set the requested Virtual Channel bits into the mapped DMA + * address. + * @pci_dev: pci device pointer + * @addr: mapped dma address + * @vchan: Virtual Channel to use 0 or 1. + * + * Set the Virtual Channel bit in the mapped dma address. + */ + +static inline int +sn_pci_set_vchan(struct pci_dev *pci_dev, + dma_addr_t *addr, + int vchan) +{ + if (vchan > 1) { + return -1; + } + + if (!(*addr >> 32)) /* Using a mask here would be cleaner */ + return 0; /* but this generates better code */ + + if (vchan == 1) { + /* Set Bit 57 */ + *addr |= (1UL << 57); + } + else { + /* Clear Bit 57 */ + *addr &= ~(1UL << 57); + } + + return 0; +} + #endif /* C or C++ */ #endif /* _ASM_SN_PCI_PCIIO_H */ diff -Nru a/include/asm-ia64/sn/sn2/intr.h b/include/asm-ia64/sn/sn2/intr.h --- a/include/asm-ia64/sn/sn2/intr.h Thu Sep 11 23:03:13 2003 +++ b/include/asm-ia64/sn/sn2/intr.h Thu Sep 11 23:03:13 2003 @@ -17,10 +17,11 @@ #define SGI_II_ERROR (0x31) #define SGI_XBOW_ERROR (0x32) #define SGI_PCIBR_ERROR (0x33) +#define SGI_ACPI_SCI_INT (0x34) #define SGI_XPC_NOTIFY (0xe7) #define IA64_SN2_FIRST_DEVICE_VECTOR (0x34) -#define IA64_SN2_LAST_DEVICE_VECTOR (0xe6) +#define IA64_SN2_LAST_DEVICE_VECTOR (0xe7) #define SN2_IRQ_RESERVED (0x1) #define SN2_IRQ_CONNECTED (0x2) diff -Nru a/include/asm-ia64/spinlock.h b/include/asm-ia64/spinlock.h --- a/include/asm-ia64/spinlock.h Thu Sep 11 23:03:11 2003 +++ b/include/asm-ia64/spinlock.h Thu Sep 11 23:03:11 2003 @@ -24,6 +24,7 @@ #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 } #define spin_lock_init(x) ((x)->lock = 0) +#ifdef ASM_SUPPORTED /* * Try to get the lock. If we fail to get the lock, make a non-standard call to * ia64_spinlock_contention(). We do not use a normal call because that would force all @@ -85,6 +86,21 @@ # endif /* CONFIG_MCKINLEY */ #endif } +#else /* !ASM_SUPPORTED */ +# define _raw_spin_lock(x) \ +do { \ + __u32 *ia64_spinlock_ptr = (__u32 *) (x); \ + __u64 ia64_spinlock_val; \ + ia64_spinlock_val = ia64_cmpxchg4_acq(ia64_spinlock_ptr, 1, 0); \ + if (unlikely(ia64_spinlock_val)) { \ + do { \ + while (*ia64_spinlock_ptr) \ + ia64_barrier(); \ + ia64_spinlock_val = ia64_cmpxchg4_acq(ia64_spinlock_ptr, 1, 0); \ + } while (ia64_spinlock_val); \ + } \ +} while (0) +#endif /* !ASM_SUPPORTED */ #define spin_is_locked(x) ((x)->lock != 0) #define _raw_spin_unlock(x) do { barrier(); ((spinlock_t *) x)->lock = 0; } while (0) @@ -117,22 +133,19 @@ ia64_fetchadd(-1, (int *) __read_lock_ptr, rel); \ } while (0) +#ifdef ASM_SUPPORTED #define _raw_write_lock(rw) \ do { \ __asm__ __volatile__ ( \ "mov ar.ccv = r0\n" \ - "dep r29 = -1, r0, 31, 1\n" \ - ";;\n" \ + "dep r29 = -1, r0, 31, 1;;\n" \ "1:\n" \ - "ld4 r2 = [%0]\n" \ - ";;\n" \ + "ld4 r2 = [%0];;\n" \ "cmp4.eq p0,p7 = r0,r2\n" \ "(p7) br.cond.spnt.few 1b \n" \ - "cmpxchg4.acq r2 = [%0], r29, ar.ccv\n" \ - ";;\n" \ + "cmpxchg4.acq r2 = [%0], r29, ar.ccv;;\n" \ "cmp4.eq p0,p7 = r0, r2\n" \ - "(p7) br.cond.spnt.few 1b\n" \ - ";;\n" \ + "(p7) br.cond.spnt.few 1b;;\n" \ :: "r"(rw) : "ar.ccv", "p7", "r2", "r29", "memory"); \ } while(0) @@ -142,12 +155,34 @@ \ __asm__ __volatile__ ( \ "mov ar.ccv = r0\n" \ - "dep r29 = -1, r0, 31, 1\n" \ - ";;\n" \ + "dep r29 = -1, r0, 31, 1;;\n" \ "cmpxchg4.acq %0 = [%1], r29, ar.ccv\n" \ : "=r"(result) : "r"(rw) : "ar.ccv", "r29", "memory"); \ (result == 0); \ }) + +#else /* !ASM_SUPPORTED */ + +#define _raw_write_lock(l) \ +({ \ + __u64 ia64_val, ia64_set_val = ia64_dep_mi(-1, 0, 31, 1); \ + __u32 ia64_write_lock_ptr = (__u32 *) (l); \ + do { \ + while (*ia64_write_lock_ptr) \ + ia64_barrier(); \ + ia64_val = ia64_cmpxchg4_acq(ia64_write_lock_ptr, ia64_set_val, 0); \ + } while (ia64_val); \ +}) + +#define _raw_write_trylock(rw) \ +({ \ + __u64 ia64_val; \ + __u64 ia64_set_val = ia64_dep_mi(-1, 0, 31,1); \ + ia64_val = ia64_cmpxchg4_acq((__u32 *)(rw), ia64_set_val, 0); \ + (ia64_val == 0); \ +}) + +#endif /* !ASM_SUPPORTED */ #define _raw_write_unlock(x) \ ({ \ diff -Nru a/include/asm-ia64/uaccess.h b/include/asm-ia64/uaccess.h --- a/include/asm-ia64/uaccess.h Thu Sep 11 23:03:12 2003 +++ b/include/asm-ia64/uaccess.h Thu Sep 11 23:03:12 2003 @@ -33,6 +33,7 @@ #include #include +#include #include /* @@ -86,6 +87,8 @@ #define __put_user(x,ptr) __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) #define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr))) +#ifdef ASM_SUPPORTED + extern void __get_user_unknown (void); #define __get_user_nocheck(x,ptr,size) \ @@ -216,6 +219,90 @@ "\t.xdata4 \"__ex_table\", 1b-., 1f-.\n" \ "[1:]" \ : "=r"(__pu_err) : "m"(__m(addr)), "rO"(x), "0"(__pu_err)) + +#else /* !ASM_SUPPORTED */ + +#define RELOC_TYPE 2 /* ip-rel */ + +#define __put_user_xx(val, addr, size, err) \ + __st_user("__ex_table", (unsigned long) addr, size, RELOC_TYPE, (unsigned long) (val)); \ + (err) = ia64_getreg(_IA64_REG_R8); + +#define __get_user_xx(val, addr, size, err) \ + __ld_user("__ex_table", (unsigned long) addr, size, RELOC_TYPE); \ + (err) = ia64_getreg(_IA64_REG_R8); \ + (val) = ia64_getreg(_IA64_REG_R9); + +extern void __get_user_unknown (void); + +#define __get_user_nocheck(x, ptr, size) \ +({ \ + register long __gu_err = 0; \ + register long __gu_val = 0; \ + const __typeof__(*(ptr)) *__gu_addr = (ptr); \ + switch (size) { \ + case 1: case 2: case 4: case 8: \ + __get_user_xx(__gu_val, __gu_addr, size, __gu_err); \ + break; \ + default: \ + __get_user_unknown(); \ + break; \ + } \ + (x) = (__typeof__(*(ptr))) __gu_val; \ + __gu_err; \ +}) + +#define __get_user_check(x,ptr,size,segment) \ +({ \ + register long __gu_err = -EFAULT; \ + register long __gu_val = 0; \ + const __typeof__(*(ptr)) *__gu_addr = (ptr); \ + if (__access_ok((long) __gu_addr, size, segment)) { \ + switch (size) { \ + case 1: case 2: case 4: case 8: \ + __get_user_xx(__gu_val, __gu_addr, size, __gu_err); \ + break; \ + default: \ + __get_user_unknown(); break; \ + } \ + } \ + (x) = (__typeof__(*(ptr))) __gu_val; \ + __gu_err; \ +}) + +extern void __put_user_unknown (void); + +#define __put_user_nocheck(x, ptr, size) \ +({ \ + int __pu_err = 0; \ + __typeof__(*(ptr)) *__pu_addr = (ptr); \ + switch (size) { \ + case 1: case 2: case 4: case 8: \ + __put_user_xx(x, __pu_addr, size, __pu_err); \ + break; \ + default: \ + __put_user_unknown(); break; \ + } \ + __pu_err; \ +}) + +#define __put_user_check(x,ptr,size,segment) \ +({ \ + register long __pu_err = -EFAULT; \ + __typeof__(*(ptr)) *__pu_addr = (ptr); \ + if (__access_ok((long)__pu_addr,size,segment)) { \ + switch (size) { \ + case 1: case 2: case 4: case 8: \ + __put_user_xx(x,__pu_addr, size, __pu_err); \ + break; \ + default: \ + __put_user_unknown(); break; \ + } \ + } \ + __pu_err; \ +}) + +#endif /* !ASM_SUPPORTED */ /* * Complex access routines diff -Nru a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h --- a/include/asm-ia64/unistd.h Thu Sep 11 23:03:11 2003 +++ b/include/asm-ia64/unistd.h Thu Sep 11 23:03:11 2003 @@ -248,7 +248,6 @@ #define __NR_sys_clock_nanosleep 1256 #define __NR_sys_fstatfs64 1257 #define __NR_sys_statfs64 1258 -#define __NR_fadvises64_64 1259 #ifdef __KERNEL__ diff -Nru a/include/asm-parisc/atomic.h b/include/asm-parisc/atomic.h --- a/include/asm-parisc/atomic.h Thu Sep 11 23:03:12 2003 +++ b/include/asm-parisc/atomic.h Thu Sep 11 23:03:12 2003 @@ -49,27 +49,14 @@ * Cache-line alignment would conflict with, for example, linux/module.h */ -typedef struct { - volatile int counter; -} atomic_t; +typedef struct { volatile long counter; } atomic_t; -/* -** xchg/cmpxchg moved from asm/system.h - ggg -*/ - -#if 1 /* This should get optimized out since it's never called. ** Or get a link error if xchg is used "wrong". */ extern void __xchg_called_with_bad_pointer(void); -#else -static inline void __xchg_called_with_bad_pointer(void) -{ - extern void panic(const char * fmt, ...); - panic("xchg called with bad pointer"); -} -#endif + /* __xchg32/64 defined in arch/parisc/lib/bitops.c */ extern unsigned long __xchg8(char, char *); diff -Nru a/include/asm-parisc/bitops.h b/include/asm-parisc/bitops.h --- a/include/asm-parisc/bitops.h Thu Sep 11 23:03:11 2003 +++ b/include/asm-parisc/bitops.h Thu Sep 11 23:03:11 2003 @@ -203,55 +203,102 @@ return !!(*addr & mask); } -extern __inline__ unsigned long ffz(unsigned long word) -{ - unsigned long result; - - result = 0; - while (word & 1) { - result++; - word >>= 1; - } - - return result; -} - #ifdef __KERNEL__ /** - * __ffs - find first bit in word. + * __ffs - find first bit in word. returns 0 to "BITS_PER_LONG-1". * @word: The word to search * - * Undefined if no bit exists, so code should check against 0 first. + * __ffs() return is undefined if no bit is set. + * + * 32-bit fast __ffs by LaMont Jones "lamont At hp com". + * 64-bit enhancement by Grant Grundler "grundler At parisc-linux org". + * (with help from willy/jejb to get the semantics right) + * + * This algorithm avoids branches by making use of nullification. + * One side effect of "extr" instructions is it sets PSW[N] bit. + * How PSW[N] (nullify next insn) gets set is determined by the + * "condition" field (eg "<>" or "TR" below) in the extr* insn. + * Only the 1st and one of either the 2cd or 3rd insn will get executed. + * Each set of 3 insn will get executed in 2 cycles on PA8x00 vs 16 or so + * cycles for each mispredicted branch. */ -static __inline__ unsigned long __ffs(unsigned long word) + +static __inline__ unsigned long __ffs(unsigned long x) { - unsigned long result = 0; + unsigned long ret; - while (!(word & 1UL)) { - result++; - word >>= 1; - } - return result; + __asm__( +#if BITS_PER_LONG > 32 + " ldi 63,%1\n" + " extrd,u,*<> %0,63,32,%%r0\n" + " extrd,u,*TR %0,31,32,%0\n" + " addi -32,%1,%1\n" +#else + " ldi 31,%1\n" +#endif + " extru,<> %0,31,16,%%r0\n" + " extru,TR %0,15,16,%0\n" + " addi -16,%1,%1\n" + " extru,<> %0,31,8,%%r0\n" + " extru,TR %0,23,8,%0\n" + " addi -8,%1,%1\n" + " extru,<> %0,31,4,%%r0\n" + " extru,TR %0,27,4,%0\n" + " addi -4,%1,%1\n" + " extru,<> %0,31,2,%%r0\n" + " extru,TR %0,29,2,%0\n" + " addi -2,%1,%1\n" + " extru,= %0,31,1,%%r0\n" + " addi -1,%1,%1\n" + : "+r" (x), "=r" (ret) ); + return ret; } +/* Undefined if no bit is zero. */ +#define ffz(x) __ffs(~x) + /* - * ffs: find first bit set. This is defined the same way as - * the libc and compiler builtin ffs routines, therefore - * differs in spirit from the above ffz (man ffs). + * ffs: find first bit set. returns 1 to BITS_PER_LONG or 0 (if none set) + * This is defined the same way as the libc and compiler builtin + * ffs routines, therefore differs in spirit from the above ffz (man ffs). */ static __inline__ int ffs(int x) { - if (!x) - return 0; - return __ffs((unsigned long)x); + return x ? (__ffs((unsigned long)x) + 1) : 0; } /* - * fls: find last bit set. + * fls: find last (most significant) bit set. + * fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. */ -#define fls(x) generic_fls(x) +static __inline__ int fls(int x) +{ + int ret; + if (!x) + return 0; + + __asm__( + " ldi 1,%1\n" + " extru,<> %0,15,16,%%r0\n" + " zdep,TR %0,15,16,%0\n" /* xxxx0000 */ + " addi 16,%1,%1\n" + " extru,<> %0,7,8,%%r0\n" + " zdep,TR %0,23,24,%0\n" /* xx000000 */ + " addi 8,%1,%1\n" + " extru,<> %0,3,4,%%r0\n" + " zdep,TR %0,27,28,%0\n" /* x0000000 */ + " addi 4,%1,%1\n" + " extru,<> %0,1,2,%%r0\n" + " zdep,TR %0,29,30,%0\n" /* y0000000 (y&3 = 0 */ + " addi 2,%1,%1\n" + " extru,= %0,0,1,%%r0\n" + " addi 1,%1,%1\n" /* if y & 8, add 1 */ + : "+r" (x), "=r" (ret) ); + + return ret; +} /* * hweightN: returns the hamming weight (i.e. the number diff -Nru a/include/asm-parisc/byteorder.h b/include/asm-parisc/byteorder.h --- a/include/asm-parisc/byteorder.h Thu Sep 11 23:03:13 2003 +++ b/include/asm-parisc/byteorder.h Thu Sep 11 23:03:13 2003 @@ -5,6 +5,25 @@ #ifdef __GNUC__ +static __inline__ __const__ __u16 ___arch__swab16(__u16 x) +{ + __asm__("dep %0, 15, 8, %0\n\t" /* deposit 00ab -> 0bab */ + "shd %%r0, %0, 8, %0" /* shift 000000ab -> 00ba */ + : "=r" (x) + : "0" (x)); + return x; +} + +static __inline__ __const__ __u32 ___arch__swab24(__u32 x) +{ + __asm__("shd %0, %0, 8, %0\n\t" /* shift xabcxabc -> cxab */ + "dep %0, 15, 8, %0\n\t" /* deposit cxab -> cbab */ + "shd %%r0, %0, 8, %0" /* shift 0000cbab -> 0cba */ + : "=r" (x) + : "0" (x)); + return x; +} + static __inline__ __const__ __u32 ___arch__swab32(__u32 x) { unsigned int temp; @@ -39,34 +58,21 @@ return x; } #define __arch__swab64(x) ___arch__swab64(x) -#else +#define __BYTEORDER_HAS_U64__ +#elif !defined(__STRICT_ANSI__) static __inline__ __const__ __u64 ___arch__swab64(__u64 x) { - __u32 t1 = (__u32) x; - __u32 t2 = (__u32) ((x) >> 32); - ___arch__swab32(t1); - ___arch__swab32(t2); - return (((__u64) t1 << 32) + ((__u64) t2)); + __u32 t1 = ___arch__swab32((__u32) x); + __u32 t2 = ___arch__swab32((__u32) (x >> 32)); + return (((__u64) t1 << 32) | t2); } +#define __arch__swab64(x) ___arch__swab64(x) +#define __BYTEORDER_HAS_U64__ #endif - -static __inline__ __const__ __u16 ___arch__swab16(__u16 x) -{ - __asm__("dep %0, 15, 8, %0\n\t" /* deposit 00ab -> 0bab */ - "shd %r0, %0, 8, %0" /* shift 000000ab -> 00ba */ - : "=r" (x) - : "0" (x)); - return x; -} - -#define __arch__swab32(x) ___arch__swab32(x) #define __arch__swab16(x) ___arch__swab16(x) - -#if !defined(__STRICT_ANSI__) || defined(__KERNEL__) -# define __BYTEORDER_HAS_U64__ -# define __SWAB_64_THRU_32__ -#endif +#define __arch__swab24(x) ___arch__swab24(x) +#define __arch__swab32(x) ___arch__swab32(x) #endif /* __GNUC__ */ diff -Nru a/include/asm-parisc/cacheflush.h b/include/asm-parisc/cacheflush.h --- a/include/asm-parisc/cacheflush.h Thu Sep 11 23:03:14 2003 +++ b/include/asm-parisc/cacheflush.h Thu Sep 11 23:03:14 2003 @@ -78,8 +78,9 @@ #define flush_icache_range(s,e) do { flush_kernel_dcache_range_asm(s,e); flush_kernel_icache_range_asm(s,e); } while (0) -#define flush_icache_user_range(vma, page, addr, len) \ - flush_icache_page((vma), (page)) +#define flush_icache_user_range(vma, page, addr, len) do { \ + flush_user_dcache_range(addr, addr + len); \ + flush_user_icache_range(addr, addr + len); } while (0) static inline void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) diff -Nru a/include/asm-parisc/elf.h b/include/asm-parisc/elf.h --- a/include/asm-parisc/elf.h Thu Sep 11 23:03:13 2003 +++ b/include/asm-parisc/elf.h Thu Sep 11 23:03:13 2003 @@ -283,6 +283,7 @@ */ #define ELF_DATA ELFDATA2MSB #define ELF_ARCH EM_PARISC +#define ELF_OSABI ELFOSABI_LINUX /* %r23 is set by ld.so to a pointer to a function which might be registered using atexit. This provides a mean for the dynamic diff -Nru a/include/asm-parisc/hil.h b/include/asm-parisc/hil.h --- a/include/asm-parisc/hil.h Thu Sep 11 23:03:13 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,26 +0,0 @@ -#ifndef _ASM_HIL_H -#define _ASM_HIL_H - -/* - * linux/asm-parisc/hil.h - * - * (c) 1999 Matthew Wilcox - */ - -extern unsigned long hil_base; /* declared in drivers/parisc/hil.c */ -extern unsigned int hil_irq; - -#define HILBASE hil_base /* 0xf0821000 (old) or 0xf0201000 (new) */ -#define HIL_DATA 0x800 -#define HIL_CMD 0x801 - -#define HIL_IRQ hil_irq - -#define hil_busy() (gsc_readb(HILBASE + HIL_CMD) & HIL_BUSY) -#define hil_data_available() (gsc_readb(HILBASE + HIL_CMD) & HIL_DATA_RDY) -#define hil_status() (gsc_readb(HILBASE + HIL_CMD)) -#define hil_command(x) do { gsc_writeb((x), HILBASE + HIL_CMD); } while (0) -#define hil_read_data() (gsc_readb(HILBASE + HIL_DATA)) -#define hil_write_data(x) do { gsc_writeb((x), HILBASE + HIL_DATA); } while (0) - -#endif diff -Nru a/include/asm-parisc/io.h b/include/asm-parisc/io.h --- a/include/asm-parisc/io.h Thu Sep 11 23:03:11 2003 +++ b/include/asm-parisc/io.h Thu Sep 11 23:03:11 2003 @@ -291,4 +291,11 @@ #define dma_cache_wback(_start,_size) do { flush_kernel_dcache_range(_start,_size); } while (0) #define dma_cache_wback_inv(_start,_size) do { flush_kernel_dcache_range(_start,_size); } while (0) +/* PA machines have an MM I/O space from 0xf0000000-0xffffffff in 32 + * bit mode and from 0xfffffffff0000000-0xfffffffffffffff in 64 bit + * mode (essentially just sign extending. This macro takes in a 32 + * bit I/O address (still with the leading f) and outputs the correct + * value for either 32 or 64 bit mode */ +#define F_EXTEND(x) ((unsigned long)((x) | (0xffffffff00000000ULL))) + #endif diff -Nru a/include/asm-parisc/local.h b/include/asm-parisc/local.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-parisc/local.h Thu Sep 11 23:03:14 2003 @@ -0,0 +1,40 @@ +#ifndef _ARCH_PARISC_LOCAL_H +#define _ARCH_PARISC_LOCAL_H + +#include +#include + +typedef atomic_t local_t; + +#define LOCAL_INIT(i) ATOMIC_INIT(i) +#define local_read(v) atomic_read(v) +#define local_set(v,i) atomic_set(v,i) + +#define local_inc(v) atomic_inc(v) +#define local_dec(v) atomic_dec(v) +#define local_add(i, v) atomic_add(i, v) +#define local_sub(i, v) atomic_sub(i, v) + +#define __local_inc(v) ((v)->counter++) +#define __local_dec(v) ((v)->counter--) +#define __local_add(i,v) ((v)->counter+=(i)) +#define __local_sub(i,v) ((v)->counter-=(i)) + +/* Use these for per-cpu local_t variables: on some archs they are + * much more efficient than these naive implementations. Note they take + * a variable, not an address. + */ +#define cpu_local_read(v) local_read(&__get_cpu_var(v)) +#define cpu_local_set(v, i) local_set(&__get_cpu_var(v), (i)) + +#define cpu_local_inc(v) local_inc(&__get_cpu_var(v)) +#define cpu_local_dec(v) local_dec(&__get_cpu_var(v)) +#define cpu_local_add(i, v) local_add((i), &__get_cpu_var(v)) +#define cpu_local_sub(i, v) local_sub((i), &__get_cpu_var(v)) + +#define __cpu_local_inc(v) __local_inc(&__get_cpu_var(v)) +#define __cpu_local_dec(v) __local_dec(&__get_cpu_var(v)) +#define __cpu_local_add(i, v) __local_add((i), &__get_cpu_var(v)) +#define __cpu_local_sub(i, v) __local_sub((i), &__get_cpu_var(v)) + +#endif /* _ARCH_PARISC_LOCAL_H */ diff -Nru a/include/asm-parisc/sections.h b/include/asm-parisc/sections.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-parisc/sections.h Thu Sep 11 23:03:14 2003 @@ -0,0 +1,7 @@ +#ifndef _PARISC_SECTIONS_H +#define _PARISC_SECTIONS_H + +/* nothing to see, move along */ +#include + +#endif diff -Nru a/include/asm-parisc/uaccess.h b/include/asm-parisc/uaccess.h --- a/include/asm-parisc/uaccess.h Thu Sep 11 23:03:11 2003 +++ b/include/asm-parisc/uaccess.h Thu Sep 11 23:03:11 2003 @@ -28,6 +28,11 @@ * that put_user is the same as __put_user, etc. */ +extern int __get_kernel_bad(void); +extern int __get_user_bad(void); +extern int __put_kernel_bad(void); +extern int __put_user_bad(void); + #define access_ok(type,addr,size) (1) #define verify_area(type,addr,size) (0) @@ -35,8 +40,8 @@ #define get_user __get_user #if BITS_PER_LONG == 32 -#define LDD_KERNEL(ptr) BUG() -#define LDD_USER(ptr) BUG() +#define LDD_KERNEL(ptr) __get_kernel_bad(); +#define LDD_USER(ptr) __get_user_bad(); #define STD_KERNEL(x, ptr) __put_kernel_asm64((u32)x,ptr) #define STD_USER(x, ptr) __put_user_asm64((u32)x,ptr) #else @@ -72,7 +77,7 @@ case 2: __get_kernel_asm("ldh",ptr); break; \ case 4: __get_kernel_asm("ldw",ptr); break; \ case 8: LDD_KERNEL(ptr); break; \ - default: BUG(); break; \ + default: __get_kernel_bad(); break; \ } \ } \ else { \ @@ -81,7 +86,7 @@ case 2: __get_user_asm("ldh",ptr); break; \ case 4: __get_user_asm("ldw",ptr); break; \ case 8: LDD_USER(ptr); break; \ - default: BUG(); break; \ + default: __get_user_bad(); break; \ } \ } \ \ @@ -141,7 +146,7 @@ case 2: __put_kernel_asm("sth",x,ptr); break; \ case 4: __put_kernel_asm("stw",x,ptr); break; \ case 8: STD_KERNEL(x,ptr); break; \ - default: BUG(); break; \ + default: __put_kernel_bad(); break; \ } \ } \ else { \ @@ -150,7 +155,7 @@ case 2: __put_user_asm("sth",x,ptr); break; \ case 4: __put_user_asm("stw",x,ptr); break; \ case 8: STD_USER(x,ptr); break; \ - default: BUG(); break; \ + default: __put_user_bad(); break; \ } \ } \ \ diff -Nru a/include/asm-ppc/bitops.h b/include/asm-ppc/bitops.h --- a/include/asm-ppc/bitops.h Thu Sep 11 23:03:12 2003 +++ b/include/asm-ppc/bitops.h Thu Sep 11 23:03:12 2003 @@ -276,7 +276,7 @@ * Find the first bit set in a 140-bit bitmap. * The first 100 bits are unlikely to be set. */ -static inline int sched_find_first_bit(unsigned long *b) +static inline int sched_find_first_bit(const unsigned long *b) { if (unlikely(b[0])) return __ffs(b[0]); @@ -295,7 +295,7 @@ * @offset: The bitnumber to start searching at * @size: The maximum size to search */ -static __inline__ unsigned long find_next_bit(unsigned long *addr, +static __inline__ unsigned long find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset) { unsigned int *p = ((unsigned int *) addr) + (offset >> 5); @@ -352,7 +352,7 @@ #define find_first_zero_bit(addr, size) \ find_next_zero_bit((addr), (size), 0) -static __inline__ unsigned long find_next_zero_bit(unsigned long * addr, +static __inline__ unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, unsigned long offset) { unsigned int * p = ((unsigned int *) addr) + (offset >> 5); @@ -411,7 +411,7 @@ #define ext2_find_first_zero_bit(addr, size) \ ext2_find_next_zero_bit((addr), (size), 0) -static __inline__ unsigned long ext2_find_next_zero_bit(void *addr, +static __inline__ unsigned long ext2_find_next_zero_bit(const void *addr, unsigned long size, unsigned long offset) { unsigned int *p = ((unsigned int *) addr) + (offset >> 5); diff -Nru a/include/asm-ppc/highmem.h b/include/asm-ppc/highmem.h --- a/include/asm-ppc/highmem.h Thu Sep 11 23:03:14 2003 +++ b/include/asm-ppc/highmem.h Thu Sep 11 23:03:14 2003 @@ -26,6 +26,7 @@ #include #include #include +#include /* undef for production */ #define HIGHMEM_DEBUG 1 @@ -41,8 +42,8 @@ * easily, subsequent pte tables have to be allocated in one physical * chunk of RAM. */ -#define PKMAP_BASE CONFIG_HIGHMEM_START -#define LAST_PKMAP 1024 +#define PKMAP_BASE CONFIG_HIGHMEM_START +#define LAST_PKMAP (1 << PTE_SHIFT) #define LAST_PKMAP_MASK (LAST_PKMAP-1) #define PKMAP_NR(virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT) #define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) diff -Nru a/include/asm-ppc/ioctl.h b/include/asm-ppc/ioctl.h --- a/include/asm-ppc/ioctl.h Thu Sep 11 23:03:12 2003 +++ b/include/asm-ppc/ioctl.h Thu Sep 11 23:03:12 2003 @@ -37,11 +37,21 @@ ((nr) << _IOC_NRSHIFT) | \ ((size) << _IOC_SIZESHIFT)) +/* provoke compile error for invalid uses of size argument */ +extern int __invalid_size_argument_for_IOC; +#define _IOC_TYPECHECK(t) \ + ((sizeof(t) == sizeof(t[1]) && \ + sizeof(t) < (1 << _IOC_SIZEBITS)) ? \ + sizeof(t) : __invalid_size_argument_for_IOC) + /* used to create numbers */ #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) -#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) -#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) -#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) +#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size))) +#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) +#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) +#define _IOR_BAD(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) +#define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) +#define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) /* used to decode them.. */ #define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) diff -Nru a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h --- a/include/asm-ppc/processor.h Thu Sep 11 23:03:11 2003 +++ b/include/asm-ppc/processor.h Thu Sep 11 23:03:11 2003 @@ -848,6 +848,7 @@ /* AltiVec status */ vector128 vscr __attribute((aligned(16))); unsigned long vrsave; + int used_vr; /* set if process has used altivec */ #endif /* CONFIG_ALTIVEC */ }; diff -Nru a/include/asm-ppc/ucontext.h b/include/asm-ppc/ucontext.h --- a/include/asm-ppc/ucontext.h Thu Sep 11 23:03:13 2003 +++ b/include/asm-ppc/ucontext.h Thu Sep 11 23:03:13 2003 @@ -1,14 +1,28 @@ #ifndef _ASMPPC_UCONTEXT_H #define _ASMPPC_UCONTEXT_H -/* Copied from i386. */ +#include +#include + +struct mcontext { + elf_gregset_t mc_gregs; + elf_fpregset_t mc_fregs; + unsigned long mc_pad[2]; + elf_vrregset_t mc_vregs __attribute__((__aligned__(16))); +}; struct ucontext { - unsigned long uc_flags; - struct ucontext *uc_link; - stack_t uc_stack; - struct sigcontext uc_mcontext; - sigset_t uc_sigmask; /* mask last for extensibility */ + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + int uc_pad[7]; + struct mcontext *uc_regs; /* backward compat */ + sigset_t uc_oldsigmask; /* backward compat */ + int uc_pad2; + sigset_t uc_sigmask; + /* glibc has 1024-bit signal masks, ours are 64-bit */ + int uc_maskext[30]; + struct mcontext uc_mcontext; }; #endif /* !_ASMPPC_UCONTEXT_H */ diff -Nru a/include/asm-ppc64/hvcall.h b/include/asm-ppc64/hvcall.h --- a/include/asm-ppc64/hvcall.h Thu Sep 11 23:03:11 2003 +++ b/include/asm-ppc64/hvcall.h Thu Sep 11 23:03:11 2003 @@ -59,9 +59,6 @@ #define H_XIRR 0x74 #define H_PERFMON 0x7c -#define HSC ".long 0x44000022\n" -#define H_ENTER_r3 "li 3, 0x08\n" - /* plpar_hcall() -- Generic call interface using above opcodes * * The actual call interface is a hypervisor call instruction with diff -Nru a/include/asm-ppc64/ioctl.h b/include/asm-ppc64/ioctl.h --- a/include/asm-ppc64/ioctl.h Thu Sep 11 23:03:12 2003 +++ b/include/asm-ppc64/ioctl.h Thu Sep 11 23:03:12 2003 @@ -42,11 +42,21 @@ ((nr) << _IOC_NRSHIFT) | \ ((size) << _IOC_SIZESHIFT)) +/* provoke compile error for invalid uses of size argument */ +extern int __invalid_size_argument_for_IOC; +#define _IOC_TYPECHECK(t) \ + ((sizeof(t) == sizeof(t[1]) && \ + sizeof(t) < (1 << _IOC_SIZEBITS)) ? \ + sizeof(t) : __invalid_size_argument_for_IOC) + /* used to create numbers */ #define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) -#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) -#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) -#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) +#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size))) +#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) +#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) +#define _IOR_BAD(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) +#define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) +#define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) /* used to decode them.. */ #define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) diff -Nru a/include/asm-ppc64/local.h b/include/asm-ppc64/local.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/asm-ppc64/local.h Thu Sep 11 23:03:14 2003 @@ -0,0 +1 @@ +#include diff -Nru a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h --- a/include/asm-ppc64/mmu.h Thu Sep 11 23:03:13 2003 +++ b/include/asm-ppc64/mmu.h Thu Sep 11 23:03:13 2003 @@ -18,6 +18,12 @@ /* Default "unsigned long" context */ typedef unsigned long mm_context_t; +#ifdef CONFIG_HUGETLB_PAGE +#define CONTEXT_LOW_HPAGES (1UL<<63) +#else +#define CONTEXT_LOW_HPAGES 0 +#endif + /* * Define the size of the cache used for segment table entries. The first * entry is used as a cache pointer, therefore the actual number of entries diff -Nru a/include/asm-ppc64/mmu_context.h b/include/asm-ppc64/mmu_context.h --- a/include/asm-ppc64/mmu_context.h Thu Sep 11 23:03:12 2003 +++ b/include/asm-ppc64/mmu_context.h Thu Sep 11 23:03:12 2003 @@ -127,7 +127,8 @@ #endif mmu_context_queue.size++; - mmu_context_queue.elements[index] = mm->context; + mmu_context_queue.elements[index] = + mm->context & ~CONTEXT_LOW_HPAGES; spin_unlock_irqrestore(&mmu_context_queue.lock, flags); } @@ -188,6 +189,8 @@ get_vsid( unsigned long context, unsigned long ea ) { unsigned long ordinal, vsid; + + context &= ~CONTEXT_LOW_HPAGES; ordinal = (((ea >> 28) & 0x1fffff) * LAST_USER_CONTEXT) | context; vsid = (ordinal * VSID_RANDOMIZER) & VSID_MASK; diff -Nru a/include/asm-ppc64/mmzone.h b/include/asm-ppc64/mmzone.h --- a/include/asm-ppc64/mmzone.h Thu Sep 11 23:03:14 2003 +++ b/include/asm-ppc64/mmzone.h Thu Sep 11 23:03:14 2003 @@ -20,7 +20,7 @@ extern int numa_cpu_lookup_table[]; extern int numa_memory_lookup_table[]; -extern unsigned long numa_cpumask_lookup_table[]; +extern cpumask_t numa_cpumask_lookup_table[]; extern int nr_cpus_in_node[]; #define MAX_MEMORY (1UL << 41) diff -Nru a/include/asm-ppc64/paca.h b/include/asm-ppc64/paca.h --- a/include/asm-ppc64/paca.h Thu Sep 11 23:03:12 2003 +++ b/include/asm-ppc64/paca.h Thu Sep 11 23:03:12 2003 @@ -63,7 +63,7 @@ u16 xPacaIndex; /* Logical processor number 0x18 */ u16 active; /* Is this cpu active? 0x1a */ u32 default_decr; /* Default decrementer value 0x1c */ - u64 xHrdIntStack; /* Stack for hardware interrupts 0x20 */ + u64 unused1; u64 xKsave; /* Saved Kernel stack addr or zero 0x28 */ u64 pvr; /* Processor version register 0x30 */ u8 *exception_sp; /* 0x38 */ @@ -73,7 +73,7 @@ STAB xStab_data; /* Segment table information 0x50,0x58,0x60 */ u8 xSegments[STAB_CACHE_SIZE]; /* Cache of used stab entries 0x68,0x70 */ u8 xProcEnabled; /* 1=soft enabled 0x78 */ - u8 xHrdIntCount; /* Count of active hardware interrupts 0x79 */ + u8 unused2; u8 prof_enabled; /* 1=iSeries profiling enabled 0x7A */ u8 stab_cache_pointer; u8 resv1[4]; /* 0x7B-0x7F */ diff -Nru a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h --- a/include/asm-ppc64/page.h Thu Sep 11 23:03:11 2003 +++ b/include/asm-ppc64/page.h Thu Sep 11 23:03:11 2003 @@ -22,6 +22,39 @@ #define PAGE_MASK (~(PAGE_SIZE-1)) #define PAGE_OFFSET_MASK (PAGE_SIZE-1) +#ifdef CONFIG_HUGETLB_PAGE + +#define HPAGE_SHIFT 24 +#define HPAGE_SIZE ((1UL) << HPAGE_SHIFT) +#define HPAGE_MASK (~(HPAGE_SIZE - 1)) +#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) + +/* For 64-bit processes the hugepage range is 1T-1.5T */ +#define TASK_HPAGE_BASE (0x0000010000000000UL) +#define TASK_HPAGE_END (0x0000018000000000UL) +/* For 32-bit processes the hugepage range is 2-3G */ +#define TASK_HPAGE_BASE_32 (0x80000000UL) +#define TASK_HPAGE_END_32 (0xc0000000UL) + +#define ARCH_HAS_HUGEPAGE_ONLY_RANGE +#define is_hugepage_only_range(addr, len) \ + ( ((addr > (TASK_HPAGE_BASE-len)) && (addr < TASK_HPAGE_END)) || \ + ((current->mm->context & CONTEXT_LOW_HPAGES) && \ + (addr > (TASK_HPAGE_BASE_32-len)) && (addr < TASK_HPAGE_END_32)) ) +#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA + +#define in_hugepage_area(context, addr) \ + ((cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) && \ + ((((addr) >= TASK_HPAGE_BASE) && ((addr) < TASK_HPAGE_END)) || \ + (((context) & CONTEXT_LOW_HPAGES) && \ + (((addr) >= TASK_HPAGE_BASE_32) && ((addr) < TASK_HPAGE_END_32))))) + +#else /* !CONFIG_HUGETLB_PAGE */ + +#define in_hugepage_area(mm, addr) 0 + +#endif /* !CONFIG_HUGETLB_PAGE */ + #define SID_SHIFT 28 #define SID_MASK 0xfffffffff #define GET_ESID(x) (((x) >> SID_SHIFT) & SID_MASK) diff -Nru a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h --- a/include/asm-ppc64/pgtable.h Thu Sep 11 23:03:14 2003 +++ b/include/asm-ppc64/pgtable.h Thu Sep 11 23:03:14 2003 @@ -149,6 +149,25 @@ /* shift to put page number into pte */ #define PTE_SHIFT (16) +/* We allow 2^41 bytes of real memory, so we need 29 bits in the PMD + * to give the PTE page number. The bottom two bits are for flags. */ +#define PMD_TO_PTEPAGE_SHIFT (2) + +#ifdef CONFIG_HUGETLB_PAGE +#define _PMD_HUGEPAGE 0x00000001U +#define HUGEPTE_BATCH_SIZE (1<<(HPAGE_SHIFT-PMD_SHIFT)) + +int hash_huge_page(struct mm_struct *mm, unsigned long access, + unsigned long ea, unsigned long vsid, int local); + +#define HAVE_ARCH_UNMAPPED_AREA +#else + +#define hash_huge_page(mm,a,ea,vsid,local) -1 +#define _PMD_HUGEPAGE 0 + +#endif + #ifndef __ASSEMBLY__ /* @@ -178,12 +197,16 @@ #define pte_pfn(x) ((unsigned long)((pte_val(x) >> PTE_SHIFT))) #define pte_page(x) pfn_to_page(pte_pfn(x)) -#define pmd_set(pmdp, ptep) (pmd_val(*(pmdp)) = (__ba_to_bpn(ptep))) +#define pmd_set(pmdp, ptep) \ + (pmd_val(*(pmdp)) = (__ba_to_bpn(ptep) << PMD_TO_PTEPAGE_SHIFT)) #define pmd_none(pmd) (!pmd_val(pmd)) -#define pmd_bad(pmd) ((pmd_val(pmd)) == 0) -#define pmd_present(pmd) ((pmd_val(pmd)) != 0) +#define pmd_hugepage(pmd) (!!(pmd_val(pmd) & _PMD_HUGEPAGE)) +#define pmd_bad(pmd) (((pmd_val(pmd)) == 0) || pmd_hugepage(pmd)) +#define pmd_present(pmd) ((!pmd_hugepage(pmd)) \ + && (pmd_val(pmd) & ~_PMD_HUGEPAGE) != 0) #define pmd_clear(pmdp) (pmd_val(*(pmdp)) = 0) -#define pmd_page_kernel(pmd) (__bpn_to_ba(pmd_val(pmd))) +#define pmd_page_kernel(pmd) \ + (__bpn_to_ba(pmd_val(pmd) >> PMD_TO_PTEPAGE_SHIFT)) #define pmd_page(pmd) virt_to_page(pmd_page_kernel(pmd)) #define pgd_set(pgdp, pmdp) (pgd_val(*(pgdp)) = (__ba_to_bpn(pmdp))) #define pgd_none(pgd) (!pgd_val(pgd)) diff -Nru a/include/asm-ppc64/prom.h b/include/asm-ppc64/prom.h --- a/include/asm-ppc64/prom.h Thu Sep 11 23:03:14 2003 +++ b/include/asm-ppc64/prom.h Thu Sep 11 23:03:14 2003 @@ -183,8 +183,6 @@ extern struct device_node *find_path_device(const char *path); extern struct device_node *find_compatible_devices(const char *type, const char *compat); -extern struct device_node *find_pci_device_OFnode(unsigned char bus, - unsigned char dev_fn); extern struct device_node *find_all_nodes(void); extern int device_is_compatible(struct device_node *device, const char *); extern int machine_is_compatible(const char *compat); diff -Nru a/include/asm-ppc64/rtas.h b/include/asm-ppc64/rtas.h --- a/include/asm-ppc64/rtas.h Thu Sep 11 23:03:14 2003 +++ b/include/asm-ppc64/rtas.h Thu Sep 11 23:03:14 2003 @@ -166,6 +166,13 @@ extern void rtas_power_off(void); extern void rtas_halt(void); +/* Given an RTAS status code of 9900..9905 compute the hinted delay */ +unsigned int rtas_extended_busy_delay_time(int status); +static inline int rtas_is_extended_busy(int status) +{ + return status >= 9900 && status <= 9909; +} + /* 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/rwsem.h b/include/asm-ppc64/rwsem.h --- a/include/asm-ppc64/rwsem.h Thu Sep 11 23:03:14 2003 +++ b/include/asm-ppc64/rwsem.h Thu Sep 11 23:03:14 2003 @@ -1,5 +1,5 @@ /* - * include/asm-ppc/rwsem.h: R/W semaphores for PPC using the stuff + * include/asm-ppc64/rwsem.h: R/W semaphores for PPC using the stuff * in lib/rwsem.c. Adapted largely from include/asm-i386/rwsem.h * by Paul Mackerras . * @@ -74,9 +74,7 @@ */ static inline void __down_read(struct rw_semaphore *sem) { - if (atomic_inc_return((atomic_t *)(&sem->count)) > 0) - smp_wmb(); - else + if (unlikely(atomic_inc_return((atomic_t *)(&sem->count)) <= 0)) rwsem_down_read_failed(sem); } @@ -87,7 +85,6 @@ while ((tmp = sem->count) >= 0) { if (tmp == cmpxchg(&sem->count, tmp, tmp + RWSEM_ACTIVE_READ_BIAS)) { - smp_wmb(); return 1; } } @@ -103,9 +100,7 @@ tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS, (atomic_t *)(&sem->count)); - if (tmp == RWSEM_ACTIVE_WRITE_BIAS) - smp_wmb(); - else + if (unlikely(tmp != RWSEM_ACTIVE_WRITE_BIAS)) rwsem_down_write_failed(sem); } @@ -115,7 +110,6 @@ tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE, RWSEM_ACTIVE_WRITE_BIAS); - smp_wmb(); return tmp == RWSEM_UNLOCKED_VALUE; } @@ -126,9 +120,8 @@ { int tmp; - smp_wmb(); tmp = atomic_dec_return((atomic_t *)(&sem->count)); - if (tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0) + if (unlikely(tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0)) rwsem_wake(sem); } @@ -137,9 +130,8 @@ */ static inline void __up_write(struct rw_semaphore *sem) { - smp_wmb(); - if (atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS, - (atomic_t *)(&sem->count)) < 0) + if (unlikely(atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS, + (atomic_t *)(&sem->count)) < 0)) rwsem_wake(sem); } @@ -158,7 +150,6 @@ { int tmp; - smp_wmb(); tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count)); if (tmp < 0) rwsem_downgrade_wake(sem); @@ -169,7 +160,6 @@ */ static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem) { - smp_mb(); return atomic_add_return(delta, (atomic_t *)(&sem->count)); } diff -Nru a/include/asm-ppc64/semaphore.h b/include/asm-ppc64/semaphore.h --- a/include/asm-ppc64/semaphore.h Thu Sep 11 23:03:12 2003 +++ b/include/asm-ppc64/semaphore.h Thu Sep 11 23:03:12 2003 @@ -82,9 +82,8 @@ /* * Try to get the semaphore, take the slow path if we fail. */ - if (atomic_dec_return(&sem->count) < 0) + if (unlikely(atomic_dec_return(&sem->count) < 0)) __down(sem); - smp_wmb(); } static inline int down_interruptible(struct semaphore * sem) @@ -96,23 +95,18 @@ #endif might_sleep(); - if (atomic_dec_return(&sem->count) < 0) + if (unlikely(atomic_dec_return(&sem->count) < 0)) ret = __down_interruptible(sem); - smp_wmb(); return ret; } static inline int down_trylock(struct semaphore * sem) { - int ret; - #ifdef WAITQUEUE_DEBUG CHECK_MAGIC(sem->__magic); #endif - ret = atomic_dec_if_positive(&sem->count) < 0; - smp_wmb(); - return ret; + return atomic_dec_if_positive(&sem->count) < 0; } static inline void up(struct semaphore * sem) @@ -121,8 +115,7 @@ CHECK_MAGIC(sem->__magic); #endif - smp_wmb(); - if (atomic_inc_return(&sem->count) <= 0) + if (unlikely(atomic_inc_return(&sem->count) <= 0)) __up(sem); } diff -Nru a/include/asm-ppc64/serial.h b/include/asm-ppc64/serial.h --- a/include/asm-ppc64/serial.h Thu Sep 11 23:03:13 2003 +++ b/include/asm-ppc64/serial.h Thu Sep 11 23:03:13 2003 @@ -26,11 +26,9 @@ /* Standard COM flags (except for COM4, because of the 8514 problem) */ #ifdef CONFIG_SERIAL_DETECT_IRQ -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ) -#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ) +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ) #else -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) -#define STD_COM4_FLAGS ASYNC_BOOT_AUTOCONF +#define STD_COM_FLAGS ASYNC_BOOT_AUTOCONF #endif #ifdef CONFIG_SERIAL_MANY_PORTS @@ -60,8 +58,8 @@ /* UART CLK PORT IRQ FLAGS */ \ { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ \ { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS }, /* ttyS1 */ \ - { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS }, /* ttyS2 */ \ - { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS }, /* ttyS3 */ + { 0, BASE_BAUD, 0x890, 0xf, STD_COM_FLAGS }, /* ttyS2 */ \ + { 0, BASE_BAUD, 0x898, 0xe, STD_COM_FLAGS }, /* ttyS3 */ #ifdef CONFIG_SERIAL_MANY_PORTS diff -Nru a/include/asm-ppc64/topology.h b/include/asm-ppc64/topology.h --- a/include/asm-ppc64/topology.h Thu Sep 11 23:03:14 2003 +++ b/include/asm-ppc64/topology.h Thu Sep 11 23:03:14 2003 @@ -24,14 +24,16 @@ #define parent_node(node) (node) -static inline unsigned long node_to_cpumask(int node) +static inline cpumask_t node_to_cpumask(int node) { return numa_cpumask_lookup_table[node]; } static inline int node_to_first_cpu(int node) { - return __ffs(node_to_cpumask(node)); + cpumask_t tmp; + tmp = node_to_cpumask(node); + return first_cpu(tmp); } #define node_to_memblk(node) (node) diff -Nru a/include/asm-ppc64/uaccess.h b/include/asm-ppc64/uaccess.h --- a/include/asm-ppc64/uaccess.h Thu Sep 11 23:03:12 2003 +++ b/include/asm-ppc64/uaccess.h Thu Sep 11 23:03:12 2003 @@ -132,6 +132,7 @@ #define __put_user_size(x,ptr,size,retval,errret) \ do { \ + might_sleep(); \ retval = 0; \ switch (size) { \ case 1: __put_user_asm(x,ptr,retval,"stb",errret); break; \ @@ -185,6 +186,7 @@ #define __get_user_size(x,ptr,size,retval,errret) \ do { \ + might_sleep(); \ retval = 0; \ switch (size) { \ case 1: __get_user_asm(x,ptr,retval,"lbz",errret); break; \ @@ -220,6 +222,7 @@ static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n) { + might_sleep(); if (__builtin_constant_p(n)) { unsigned long ret; @@ -244,6 +247,7 @@ static inline unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n) { + might_sleep(); if (__builtin_constant_p(n)) { unsigned long ret; @@ -289,6 +293,7 @@ static inline unsigned long copy_in_user(void *to, const void *from, unsigned long n) { + might_sleep(); if (likely(access_ok(VERIFY_READ, from, n) && access_ok(VERIFY_WRITE, to, n))) n =__copy_tofrom_user(to, from, n); @@ -300,6 +305,7 @@ static inline unsigned long clear_user(void *addr, unsigned long size) { + might_sleep(); if (likely(access_ok(VERIFY_WRITE, addr, size))) size = __clear_user(addr, size); return size; @@ -310,6 +316,7 @@ static inline long strncpy_from_user(char *dst, const char *src, long count) { + might_sleep(); if (likely(access_ok(VERIFY_READ, src, 1))) return __strncpy_from_user(dst, src, count); return -EFAULT; @@ -329,6 +336,7 @@ */ static inline int strnlen_user(const char *str, long len) { + might_sleep(); if (likely(access_ok(VERIFY_READ, str, 1))) return __strnlen_user(str, len); return 0; diff -Nru a/include/asm-sparc/sfp-machine.h b/include/asm-sparc/sfp-machine.h --- a/include/asm-sparc/sfp-machine.h Thu Sep 11 23:03:13 2003 +++ b/include/asm-sparc/sfp-machine.h Thu Sep 11 23:03:13 2003 @@ -77,9 +77,9 @@ /* Some assembly to speed things up. */ #define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \ - __asm__ ("addcc %r7,%8,%2 - addxcc %r5,%6,%1 - addx %r3,%4,%0" \ + __asm__ ("addcc %r7,%8,%2\n\t" \ + "addxcc %r5,%6,%1\n\t" \ + "addx %r3,%4,%0\n" \ : "=r" ((USItype)(r2)), \ "=&r" ((USItype)(r1)), \ "=&r" ((USItype)(r0)) \ @@ -92,9 +92,9 @@ : "cc") #define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \ - __asm__ ("subcc %r7,%8,%2 - subxcc %r5,%6,%1 - subx %r3,%4,%0" \ + __asm__ ("subcc %r7,%8,%2\n\t" \ + "subxcc %r5,%6,%1\n\t" \ + "subx %r3,%4,%0\n" \ : "=r" ((USItype)(r2)), \ "=&r" ((USItype)(r1)), \ "=&r" ((USItype)(r0)) \ @@ -111,11 +111,11 @@ /* We need to fool gcc, as we need to pass more than 10 \ input/outputs. */ \ register USItype _t1 __asm__ ("g1"), _t2 __asm__ ("g2"); \ - __asm__ __volatile__ (" - addcc %r8,%9,%1 - addxcc %r6,%7,%0 - addxcc %r4,%5,%%g2 - addx %r2,%3,%%g1" \ + __asm__ __volatile__ ( \ + "addcc %r8,%9,%1\n\t" \ + "addxcc %r6,%7,%0\n\t" \ + "addxcc %r4,%5,%%g2\n\t" \ + "addx %r2,%3,%%g1\n\t" \ : "=&r" ((USItype)(r1)), \ "=&r" ((USItype)(r0)) \ : "%rJ" ((USItype)(x3)), \ @@ -136,11 +136,11 @@ /* We need to fool gcc, as we need to pass more than 10 \ input/outputs. */ \ register USItype _t1 __asm__ ("g1"), _t2 __asm__ ("g2"); \ - __asm__ __volatile__ (" - subcc %r8,%9,%1 - subxcc %r6,%7,%0 - subxcc %r4,%5,%%g2 - subx %r2,%3,%%g1" \ + __asm__ __volatile__ ( \ + "subcc %r8,%9,%1\n\t" \ + "subxcc %r6,%7,%0\n\t" \ + "subxcc %r4,%5,%%g2\n\t" \ + "subx %r2,%3,%%g1\n\t" \ : "=&r" ((USItype)(r1)), \ "=&r" ((USItype)(r0)) \ : "%rJ" ((USItype)(x3)), \ @@ -161,10 +161,10 @@ #define __FP_FRAC_DEC_4(x3,x2,x1,x0,y3,y2,y1,y0) __FP_FRAC_SUB_4(x3,x2,x1,x0,x3,x2,x1,x0,y3,y2,y1,y0) #define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i) \ - __asm__ ("addcc %3,%4,%3 - addxcc %2,%%g0,%2 - addxcc %1,%%g0,%1 - addx %0,%%g0,%0" \ + __asm__ ("addcc %3,%4,%3\n\t" \ + "addxcc %2,%%g0,%2\n\t" \ + "addxcc %1,%%g0,%1\n\t" \ + "addx %0,%%g0,%0\n\t" \ : "=&r" ((USItype)(x3)), \ "=&r" ((USItype)(x2)), \ "=&r" ((USItype)(x1)), \ diff -Nru a/include/asm-sparc64/vga.h b/include/asm-sparc64/vga.h --- a/include/asm-sparc64/vga.h Thu Sep 11 23:03:11 2003 +++ b/include/asm-sparc64/vga.h Thu Sep 11 23:03:11 2003 @@ -13,18 +13,16 @@ static inline void scr_writew(u16 val, u16 *addr) { - if ((long) addr < 0) - *addr = val; - else - writew(val, (unsigned long) addr); + BUG_ON((long) addr >= 0); + + *addr = val; } static inline u16 scr_readw(const u16 *addr) { - if ((long) addr < 0) - return *addr; - else - return readw((unsigned long) addr); + BUG_ON((long) addr >= 0); + + return *addr; } #define VGA_MAP_MEM(x) (x) diff -Nru a/include/linux/atmclip.h b/include/linux/atmclip.h --- a/include/linux/atmclip.h Thu Sep 11 23:03:13 2003 +++ b/include/linux/atmclip.h Thu Sep 11 23:03:13 2003 @@ -18,8 +18,4 @@ #define SIOCMKCLIP _IO('a',ATMIOC_CLIP) /* create IP interface */ -#ifdef __KERNEL__ -extern const unsigned char llc_oui[6]; -#endif - #endif diff -Nru a/include/linux/cpufreq.h b/include/linux/cpufreq.h --- a/include/linux/cpufreq.h Thu Sep 11 23:03:13 2003 +++ b/include/linux/cpufreq.h Thu Sep 11 23:03:13 2003 @@ -60,6 +60,13 @@ unsigned int transition_latency; /* in 10^(-9) s */ }; +struct cpufreq_real_policy { + unsigned int min; /* in kHz */ + unsigned int max; /* in kHz */ + unsigned int policy; /* see above */ + struct cpufreq_governor *governor; /* see below */ +}; + struct cpufreq_policy { unsigned int cpu; /* cpu nr */ struct cpufreq_cpuinfo cpuinfo;/* see above */ @@ -74,6 +81,8 @@ struct semaphore lock; /* CPU ->setpolicy or ->target may only be called once a time */ + struct cpufreq_real_policy user_policy; + struct kobject kobj; struct completion kobj_unregister; }; @@ -217,6 +226,7 @@ *********************************************************************/ int cpufreq_set_policy(struct cpufreq_policy *policy); int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu); +int cpufreq_update_policy(unsigned int cpu); /* the proc_intf.c needs this */ int cpufreq_parse_governor (char *str_governor, unsigned int *policy, struct cpufreq_governor **governor); @@ -290,7 +300,7 @@ #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE extern struct cpufreq_governor cpufreq_gov_performance; #define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_performance -#elif CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE +#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE) extern struct cpufreq_governor cpufreq_gov_userspace; #define CPUFREQ_DEFAULT_GOVERNOR &cpufreq_gov_userspace #endif diff -Nru a/include/linux/elf.h b/include/linux/elf.h --- a/include/linux/elf.h Thu Sep 11 23:03:11 2003 +++ b/include/linux/elf.h Thu Sep 11 23:03:11 2003 @@ -360,7 +360,8 @@ #define EI_CLASS 4 #define EI_DATA 5 #define EI_VERSION 6 -#define EI_PAD 7 +#define EI_OSABI 7 +#define EI_PAD 8 #define ELFMAG0 0x7f /* EI_MAG */ #define ELFMAG1 'E' @@ -381,6 +382,13 @@ #define EV_NONE 0 /* e_version, EI_VERSION */ #define EV_CURRENT 1 #define EV_NUM 2 + +#define ELFOSABI_NONE 0 +#define ELFOSABI_LINUX 3 + +#ifndef ELF_OSABI +#define ELF_OSABI ELFOSABI_NONE +#endif /* Notes used in ET_CORE */ #define NT_PRSTATUS 1 diff -Nru a/include/linux/eventpoll.h b/include/linux/eventpoll.h --- a/include/linux/eventpoll.h Thu Sep 11 23:03:12 2003 +++ b/include/linux/eventpoll.h Thu Sep 11 23:03:12 2003 @@ -48,9 +48,10 @@ /* Kernel space functions implementing the user space "epoll" API */ asmlinkage long sys_epoll_create(int size); -asmlinkage long sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); -asmlinkage long sys_epoll_wait(int epfd, struct epoll_event *events, int maxevents, - int timeout); +asmlinkage long sys_epoll_ctl(int epfd, int op, int fd, + struct epoll_event __user *event); +asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events, + int maxevents, int timeout); #ifdef CONFIG_EPOLL diff -Nru a/include/linux/if_frad.h b/include/linux/if_frad.h --- a/include/linux/if_frad.h Thu Sep 11 23:03:11 2003 +++ b/include/linux/if_frad.h Thu Sep 11 23:03:11 2003 @@ -191,9 +191,6 @@ int buffer; /* current buffer for S508 firmware */ }; -int register_frad(const char *name); -int unregister_frad(const char *name); - extern void dlci_ioctl_set(int (*hook)(unsigned int, void *)); #endif /* __KERNEL__ */ diff -Nru a/include/linux/interrupt.h b/include/linux/interrupt.h --- a/include/linux/interrupt.h Thu Sep 11 23:03:12 2003 +++ b/include/linux/interrupt.h Thu Sep 11 23:03:12 2003 @@ -3,6 +3,7 @@ #define _LINUX_INTERRUPT_H #include +#include #include #include #include diff -Nru a/include/linux/mm.h b/include/linux/mm.h --- a/include/linux/mm.h Thu Sep 11 23:03:11 2003 +++ b/include/linux/mm.h Thu Sep 11 23:03:11 2003 @@ -432,6 +432,7 @@ extern pte_t *FASTCALL(pte_alloc_kernel(struct mm_struct *mm, pmd_t *pmd, unsigned long address)); extern pte_t *FASTCALL(pte_alloc_map(struct mm_struct *mm, pmd_t *pmd, unsigned long address)); extern int install_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, struct page *page, pgprot_t prot); +extern int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, unsigned long pgoff, pgprot_t prot); extern int handle_mm_fault(struct mm_struct *mm,struct vm_area_struct *vma, unsigned long address, int write_access); extern int make_pages_present(unsigned long addr, unsigned long end); extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write); diff -Nru a/include/linux/seq_file.h b/include/linux/seq_file.h --- a/include/linux/seq_file.h Thu Sep 11 23:03:14 2003 +++ b/include/linux/seq_file.h Thu Sep 11 23:03:14 2003 @@ -65,5 +65,8 @@ 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 *); + +#define SEQ_START_TOKEN ((void *)1) + #endif #endif diff -Nru a/include/linux/serial_core.h b/include/linux/serial_core.h --- a/include/linux/serial_core.h Thu Sep 11 23:03:11 2003 +++ b/include/linux/serial_core.h Thu Sep 11 23:03:11 2003 @@ -67,6 +67,12 @@ #define PORT_PC9861 45 #define PORT_PC9801_101 46 +/* DZ */ +#define PORT_DZ 47 + +/* Parisc type numbers. */ +#define PORT_MUX 48 + /* Macintosh Zilog type numbers */ #define PORT_MAC_ZILOG 50 /* m68k : not yet implemented */ #define PORT_PMAC_ZILOG 51 @@ -319,8 +325,8 @@ /* * Power Management */ -int uart_suspend_port(struct uart_driver *reg, struct uart_port *port, u32 level); -int uart_resume_port(struct uart_driver *reg, struct uart_port *port, u32 level); +int uart_suspend_port(struct uart_driver *reg, struct uart_port *port); +int uart_resume_port(struct uart_driver *reg, struct uart_port *port); #define uart_circ_empty(circ) ((circ)->head == (circ)->tail) #define uart_circ_clear(circ) ((circ)->head = (circ)->tail = 0) diff -Nru a/include/linux/writeback.h b/include/linux/writeback.h --- a/include/linux/writeback.h Thu Sep 11 23:03:11 2003 +++ b/include/linux/writeback.h Thu Sep 11 23:03:11 2003 @@ -80,8 +80,8 @@ struct ctl_table; struct file; -int dirty_writeback_centisecs_handler(struct ctl_table *, int, struct file *, - void *, size_t *); +int dirty_writeback_centisecs_handler(struct ctl_table *, int, struct file *, + void __user *, size_t *); void page_writeback_init(void); void balance_dirty_pages(struct address_space *mapping); diff -Nru a/include/net/rose.h b/include/net/rose.h --- a/include/net/rose.h Thu Sep 11 23:03:11 2003 +++ b/include/net/rose.h Thu Sep 11 23:03:11 2003 @@ -140,9 +140,6 @@ #define rose_sk(__sk) ((rose_cb *)(__sk)->sk_protinfo) -/* Magic value indicating first entry in /proc (ie header) */ -#define ROSE_PROC_START ((void *) 1) - /* af_rose.c */ extern ax25_address rose_callsign; extern int sysctl_rose_restart_request_timeout; diff -Nru a/include/pcmcia/ss.h b/include/pcmcia/ss.h --- a/include/pcmcia/ss.h Thu Sep 11 23:03:14 2003 +++ b/include/pcmcia/ss.h Thu Sep 11 23:03:14 2003 @@ -78,7 +78,6 @@ #define SS_DMA_MODE 0x0080 #define SS_SPKR_ENA 0x0100 #define SS_OUTPUT_ENA 0x0200 -#define SS_DEBOUNCED 0x0400 /* Tell driver that the debounce delay has ended */ /* Flags for I/O port and memory windows */ #define MAP_ACTIVE 0x01 @@ -176,7 +175,6 @@ u_short functions; u_short lock_count; client_handle_t clients; - u_int real_clients; pccard_mem_map cis_mem; u_char *cis_virt; struct config_t *config; @@ -249,7 +247,7 @@ extern struct class pcmcia_socket_class; /* socket drivers are expected to use these callbacks in their .drv struct */ -extern int pcmcia_socket_dev_suspend(struct device *dev, u32 state, u32 level); -extern int pcmcia_socket_dev_resume(struct device *dev, u32 level); +extern int pcmcia_socket_dev_suspend(struct device *dev, u32 state); +extern int pcmcia_socket_dev_resume(struct device *dev); #endif /* _LINUX_SS_H */ diff -Nru a/include/rxrpc/call.h b/include/rxrpc/call.h --- a/include/rxrpc/call.h Thu Sep 11 23:03:11 2003 +++ b/include/rxrpc/call.h Thu Sep 11 23:03:11 2003 @@ -67,8 +67,8 @@ wait_queue_head_t waitq; /* wait queue for events to happen */ struct list_head link; /* general internal list link */ struct list_head call_link; /* master call list link */ - u32 chan_ix; /* connection channel index (net order) */ - u32 call_id; /* call ID on connection (net order) */ + uint32_t chan_ix; /* connection channel index (net order) */ + uint32_t call_id; /* call ID on connection (net order) */ unsigned long cjif; /* jiffies at call creation */ unsigned long flags; /* control flags */ #define RXRPC_CALL_ACKS_TIMO 0x00000001 /* ACKS timeout reached */ @@ -103,7 +103,7 @@ char ackr_dfr_perm; /* request for deferred ACKs permitted */ rxrpc_seq_t ackr_dfr_seq; /* seqno for deferred ACK */ struct rxrpc_ackpacket ackr; /* pending normal ACK packet */ - u8 ackr_array[RXRPC_CALL_ACK_WINDOW_SIZE]; /* ACK records */ + uint8_t ackr_array[RXRPC_CALL_ACK_WINDOW_SIZE]; /* ACK records */ /* presentation layer */ char app_last_rcv; /* T if received last packet from remote end */ @@ -131,14 +131,14 @@ struct list_head app_attn_link; /* application attention list linkage */ size_t app_mark; /* trigger callback when app_ready_qty>=app_mark */ char app_async_read; /* T if in async-read mode */ - u8 *app_read_buf; /* application async read buffer (app_mark size) */ - u8 *app_scr_alloc; /* application scratch allocation pointer */ + uint8_t *app_read_buf; /* application async read buffer (app_mark size) */ + uint8_t *app_scr_alloc; /* application scratch allocation pointer */ void *app_scr_ptr; /* application pointer into scratch buffer */ #define RXRPC_APP_MARK_EOF 0xFFFFFFFFU /* mark at end of input */ /* application scratch buffer */ - u8 app_scratch[0] __attribute__((aligned(sizeof(long)))); + uint8_t app_scratch[0] __attribute__((aligned(sizeof(long)))); }; #define RXRPC_CALL_SCRATCH_SIZE (PAGE_SIZE - sizeof(struct rxrpc_call)) @@ -206,7 +206,7 @@ extern int rxrpc_call_write_data(struct rxrpc_call *call, size_t sioc, struct iovec siov[], - u8 rxhdr_flags, + uint8_t rxhdr_flags, int alloc_flags, int dup_data, size_t *size_sent); diff -Nru a/include/rxrpc/connection.h b/include/rxrpc/connection.h --- a/include/rxrpc/connection.h Thu Sep 11 23:03:13 2003 +++ b/include/rxrpc/connection.h Thu Sep 11 23:03:13 2003 @@ -34,6 +34,7 @@ struct list_head link; /* link in peer's list */ struct list_head proc_link; /* link in proc list */ struct list_head err_link; /* link in ICMP error processing list */ + struct list_head id_link; /* link in ID grant list */ struct sockaddr_in addr; /* remote address */ struct rxrpc_call *channels[4]; /* channels (active calls) */ wait_queue_head_t chanwait; /* wait for channel to become available */ @@ -44,19 +45,19 @@ rxrpc_serial_t serial_counter; /* packet serial number counter */ /* the following should all be in net order */ - u32 in_epoch; /* peer's epoch */ - u32 out_epoch; /* my epoch */ - u32 conn_id; /* connection ID, appropriately shifted */ - u16 service_id; /* service ID */ - u8 security_ix; /* security ID */ - u8 in_clientflag; /* RXRPC_CLIENT_INITIATED if we are server */ - u8 out_clientflag; /* RXRPC_CLIENT_INITIATED if we are client */ + uint32_t in_epoch; /* peer's epoch */ + uint32_t out_epoch; /* my epoch */ + uint32_t conn_id; /* connection ID, appropriately shifted */ + uint16_t service_id; /* service ID */ + uint8_t security_ix; /* security ID */ + uint8_t in_clientflag; /* RXRPC_CLIENT_INITIATED if we are server */ + uint8_t out_clientflag; /* RXRPC_CLIENT_INITIATED if we are client */ }; extern int rxrpc_create_connection(struct rxrpc_transport *trans, - u16 port, - u32 addr, - unsigned short service_id, + uint16_t port, + uint32_t addr, + uint16_t service_id, void *security, struct rxrpc_connection **_conn); diff -Nru a/include/rxrpc/message.h b/include/rxrpc/message.h --- a/include/rxrpc/message.h Thu Sep 11 23:03:12 2003 +++ b/include/rxrpc/message.h Thu Sep 11 23:03:12 2003 @@ -9,8 +9,8 @@ * 2 of the License, or (at your option) any later version. */ -#ifndef _H_3AD3363A_3A9C_11D6_83D8_0002B3163499 -#define _H_3AD3363A_3A9C_11D6_83D8_0002B3163499 +#ifndef _LINUX_RXRPC_MESSAGE_H +#define _LINUX_RXRPC_MESSAGE_H #include @@ -61,7 +61,7 @@ extern int rxrpc_conn_newmsg(struct rxrpc_connection *conn, struct rxrpc_call *call, - u8 type, + uint8_t type, int count, struct iovec diov[], int alloc_flags, @@ -69,4 +69,4 @@ extern int rxrpc_conn_sendmsg(struct rxrpc_connection *conn, struct rxrpc_message *msg); -#endif /* _H_3AD3363A_3A9C_11D6_83D8_0002B3163499 */ +#endif /* _LINUX_RXRPC_MESSAGE_H */ diff -Nru a/include/rxrpc/packet.h b/include/rxrpc/packet.h --- a/include/rxrpc/packet.h Thu Sep 11 23:03:12 2003 +++ b/include/rxrpc/packet.h Thu Sep 11 23:03:12 2003 @@ -27,21 +27,21 @@ */ struct rxrpc_header { - u32 epoch; /* client boot timestamp */ + uint32_t epoch; /* client boot timestamp */ - u32 cid; /* connection and channel ID */ + uint32_t cid; /* connection and channel ID */ #define RXRPC_MAXCALLS 4 /* max active calls per conn */ #define RXRPC_CHANNELMASK (RXRPC_MAXCALLS-1) /* mask for channel ID */ #define RXRPC_CIDMASK (~RXRPC_CHANNELMASK) /* mask for connection ID */ #define RXRPC_CIDSHIFT 2 /* shift for connection ID */ - u32 callNumber; /* call ID (0 for connection-level packets) */ + uint32_t callNumber; /* call ID (0 for connection-level packets) */ #define RXRPC_PROCESS_MAXCALLS (1<<2) /* maximum number of active calls per conn (power of 2) */ - u32 seq; /* sequence number of pkt in call stream */ - u32 serial; /* serial number of pkt sent to network */ + uint32_t seq; /* sequence number of pkt in call stream */ + uint32_t serial; /* serial number of pkt sent to network */ - u8 type; /* packet type */ + uint8_t type; /* packet type */ #define RXRPC_PACKET_TYPE_DATA 1 /* data */ #define RXRPC_PACKET_TYPE_ACK 2 /* ACK */ #define RXRPC_PACKET_TYPE_BUSY 3 /* call reject */ @@ -52,7 +52,7 @@ #define RXRPC_PACKET_TYPE_DEBUG 8 /* debug info request */ #define RXRPC_N_PACKET_TYPES 9 /* number of packet types (incl type 0) */ - u8 flags; /* packet flags */ + uint8_t flags; /* packet flags */ #define RXRPC_CLIENT_INITIATED 0x01 /* signifies a packet generated by a client */ #define RXRPC_REQUEST_ACK 0x02 /* request an unconditional ACK of this packet */ #define RXRPC_LAST_PACKET 0x04 /* the last packet from this side for this call */ @@ -60,10 +60,10 @@ #define RXRPC_JUMBO_PACKET 0x20 /* [DATA] this is a jumbo packet */ #define RXRPC_SLOW_START_OK 0x20 /* [ACK] slow start supported */ - u8 userStatus; /* app-layer defined status */ - u8 securityIndex; /* security protocol ID */ - u16 _rsvd; /* reserved (used by kerberos security as cksum) */ - u16 serviceId; /* service ID */ + uint8_t userStatus; /* app-layer defined status */ + uint8_t securityIndex; /* security protocol ID */ + uint16_t _rsvd; /* reserved (used by kerberos security as cksum) */ + uint16_t serviceId; /* service ID */ } __attribute__((packed)); @@ -83,9 +83,9 @@ */ struct rxrpc_jumbo_header { - u8 flags; /* packet flags (as per rxrpc_header) */ - u8 pad; - u16 _rsvd; /* reserved (used by kerberos security as cksum) */ + uint8_t flags; /* packet flags (as per rxrpc_header) */ + uint8_t pad; + uint16_t _rsvd; /* reserved (used by kerberos security as cksum) */ }; #define RXRPC_JUMBO_DATALEN 1412 /* non-terminal jumbo packet data length */ @@ -97,13 +97,14 @@ */ struct rxrpc_ackpacket { - u16 bufferSpace; /* number of packet buffers available */ - u16 maxSkew; /* diff between serno being ACK'd and highest serial no received */ - u32 firstPacket; /* sequence no of first ACK'd packet in attached list */ - u32 previousPacket; /* sequence no of previous packet received */ - u32 serial; /* serial no of packet that prompted this ACK */ + uint16_t bufferSpace; /* number of packet buffers available */ + uint16_t maxSkew; /* diff between serno being ACK'd and highest serial no + * received */ + uint32_t firstPacket; /* sequence no of first ACK'd packet in attached list */ + uint32_t previousPacket; /* sequence no of previous packet received */ + uint32_t serial; /* serial no of packet that prompted this ACK */ - u8 reason; /* reason for ACK */ + uint8_t reason; /* reason for ACK */ #define RXRPC_ACK_REQUESTED 1 /* ACK was requested on packet */ #define RXRPC_ACK_DUPLICATE 2 /* duplicate packet received */ #define RXRPC_ACK_OUT_OF_SEQUENCE 3 /* out of sequence packet received */ @@ -114,10 +115,10 @@ #define RXRPC_ACK_DELAY 8 /* nothing happened since received packet */ #define RXRPC_ACK_IDLE 9 /* ACK due to fully received ACK window */ - u8 nAcks; /* number of ACKs */ + uint8_t nAcks; /* number of ACKs */ #define RXRPC_MAXACKS 255 - u8 acks[0]; /* list of ACK/NAKs */ + uint8_t acks[0]; /* list of ACK/NAKs */ #define RXRPC_ACK_TYPE_NACK 0 #define RXRPC_ACK_TYPE_ACK 1 diff -Nru a/include/rxrpc/peer.h b/include/rxrpc/peer.h --- a/include/rxrpc/peer.h Thu Sep 11 23:03:13 2003 +++ b/include/rxrpc/peer.h Thu Sep 11 23:03:13 2003 @@ -42,7 +42,10 @@ struct rxrpc_timer timeout; /* timeout for grave destruction */ struct list_head link; /* link in transport's peer list */ struct list_head proc_link; /* link in /proc list */ - rwlock_t conn_lock; /* lock for connections */ + rwlock_t conn_idlock; /* lock for connection IDs */ + struct list_head conn_idlist; /* list of connections granted IDs */ + uint32_t conn_idcounter; /* connection ID counter */ + rwlock_t conn_lock; /* lock for active/dead connections */ struct list_head conn_active; /* active connections to/from this peer */ struct list_head conn_graveyard; /* graveyard for inactive connections */ spinlock_t conn_gylock; /* lock for conn_graveyard */ diff -Nru a/include/rxrpc/rxrpc.h b/include/rxrpc/rxrpc.h --- a/include/rxrpc/rxrpc.h Thu Sep 11 23:03:13 2003 +++ b/include/rxrpc/rxrpc.h Thu Sep 11 23:03:13 2003 @@ -14,7 +14,7 @@ #ifdef __KERNEL__ -extern u32 rxrpc_epoch; +extern uint32_t rxrpc_epoch; extern int rxrpc_ktrace; extern int rxrpc_kdebug; diff -Nru a/include/rxrpc/transport.h b/include/rxrpc/transport.h --- a/include/rxrpc/transport.h Thu Sep 11 23:03:14 2003 +++ b/include/rxrpc/transport.h Thu Sep 11 23:03:14 2003 @@ -85,10 +85,11 @@ static inline void rxrpc_get_transport(struct rxrpc_transport *trans) { - if (atomic_read(&trans->usage)<=0) + if (atomic_read(&trans->usage) <= 0) BUG(); atomic_inc(&trans->usage); - //printk("rxrpc_get_transport(%p{u=%d})\n",trans,atomic_read(&trans->usage)); + //printk("rxrpc_get_transport(%p{u=%d})\n", + // trans, atomic_read(&trans->usage)); } extern void rxrpc_put_transport(struct rxrpc_transport *trans); @@ -98,11 +99,6 @@ extern void rxrpc_del_service(struct rxrpc_transport *trans, struct rxrpc_service *srv); - -#if 0 -extern int rxrpc_trans_add_connection(struct rxrpc_transport *trans, - struct rxrpc_connection *conn); -#endif extern void rxrpc_trans_receive_packet(struct rxrpc_transport *trans); diff -Nru a/include/rxrpc/types.h b/include/rxrpc/types.h --- a/include/rxrpc/types.h Thu Sep 11 23:03:12 2003 +++ b/include/rxrpc/types.h Thu Sep 11 23:03:12 2003 @@ -19,8 +19,8 @@ #include #include -typedef unsigned rxrpc_seq_t; /* Rx message sequence number */ -typedef unsigned rxrpc_serial_t; /* Rx message serial number */ +typedef uint32_t rxrpc_seq_t; /* Rx message sequence number */ +typedef uint32_t rxrpc_serial_t; /* Rx message serial number */ struct rxrpc_call; struct rxrpc_connection; diff -Nru a/init/Kconfig b/init/Kconfig --- a/init/Kconfig Thu Sep 11 23:03:13 2003 +++ b/init/Kconfig Thu Sep 11 23:03:13 2003 @@ -143,24 +143,24 @@ This option enables the complete Linux kernel ".config" file contents, information on compiler used to build the kernel, kernel running when this kernel was built and kernel version - from Makefile to be saved in kernel. It provides documentation + from Makefile to be saved in the kernel. It provides documentation of which kernel options are used in a running kernel or in an on-disk kernel. This information can be extracted from the kernel image file with the script scripts/extract-ikconfig and used as input to rebuild the current kernel or to build another kernel. It can also be extracted from a running kernel by reading - /proc/ikconfig/config and /proc/ikconfig/built_with, if enabled. - /proc/ikconfig/config will list the configuration that was used - to build the kernel and /proc/ikconfig/built_with will list + /proc/config.gz and /proc/config_built_with, if enabled (below). + /proc/config.gz will list the configuration that was used + to build the kernel and /proc/config_built_with will list information on the compiler and host machine that was used to build the kernel. config IKCONFIG_PROC - bool "Enable access to .config through /proc/ikconfig" + bool "Enable access to .config through /proc/config.gz" depends on IKCONFIG && PROC_FS ---help--- This option enables access to kernel configuration file and build - information through /proc/ikconfig. + information through /proc/config.gz. menuconfig EMBEDDED @@ -204,15 +204,22 @@ config MODULES bool "Enable loadable module support" help - Kernel modules are small pieces of compiled code which can be - inserted in or removed from the running kernel, using the programs - insmod and rmmod. This is described in the file - , including the fact that you have - to say "make modules" in order to compile the modules that you chose - during kernel configuration. Modules can be device drivers, file - systems, binary executable formats, and so on. If you think that you - may want to make use of modules with this kernel in the future, then - say Y here. If unsure, say Y. + Kernel modules are small pieces of compiled code which can + be inserted in the running kernel, rather than being + permanently built into the kernel. You use the "modprobe" + tool to add (and sometimes remove) them. If you say Y here, + many parts of the kernel can be built as modules (by + answering M instead of Y where indicated): this is most + useful for infrequently used options which are not required + for booting. For more information, see the man pages for + modprobe, lsmod, modinfo, insmod and rmmod. + + If you say Y here, you will need to run "make + modules_install" to put the modules under /lib/modules/ + where modprobe can find them (you may need to be root to do + this). + + If unsure, say Y. config MODULE_UNLOAD bool "Module unloading" @@ -251,21 +258,18 @@ compiled for different kernels, by adding enough information to the modules to (hopefully) spot any changes which would make them incompatible with the kernel you are running. If - you say Y here, you will need a copy of genksyms. If unsure, say N. config KMOD - bool "Kernel module loader" + bool "Automatic kernel module loading" depends on MODULES help - Normally when you have selected some drivers and/or file systems to - be created as loadable modules, you also have the responsibility to - load the corresponding modules (using the programs insmod or - modprobe) before you can use them. If you say Y here however, the - kernel will be able to load modules for itself: when a part of the - kernel needs a module, it runs modprobe with the appropriate - arguments, thereby loading the module if it is available. (This is a - replacement for kerneld.) Say Y here and read about configuring it - in . + Normally when you have selected some parts of the kernel to + be created as kernel modules, you must load them (using the + "modprobe" command) before you can use them. If you say Y + here, some parts of the kernel will be able to load modules + automatically: when a part of the kernel needs a module, it + runs modprobe with the appropriate arguments, thereby + loading the module if it is available. If unsure, say Y. endmenu diff -Nru a/init/do_mounts_rd.c b/init/do_mounts_rd.c --- a/init/do_mounts_rd.c Thu Sep 11 23:03:13 2003 +++ b/init/do_mounts_rd.c Thu Sep 11 23:03:13 2003 @@ -332,7 +332,7 @@ insize = read(crd_infd, inbuf, INBUFSIZ); if (insize == 0) { - error("RAMDISK: ran out of compressed data\n"); + error("RAMDISK: ran out of compressed data"); return -1; } @@ -369,7 +369,7 @@ static void __init error(char *x) { - printk(KERN_ERR "%s", x); + printk(KERN_ERR "%s\n", x); exit_code = 1; unzip_error = 1; } diff -Nru a/init/initramfs.c b/init/initramfs.c --- a/init/initramfs.c Thu Sep 11 23:03:11 2003 +++ b/init/initramfs.c Thu Sep 11 23:03:11 2003 @@ -248,7 +248,6 @@ next_state = Reset; return 0; } - printk(KERN_INFO "-> %s\n", collected); if (S_ISREG(mode)) { if (maybe_link() >= 0) { wfd = sys_open(collected, O_WRONLY|O_CREAT, mode); @@ -261,11 +260,13 @@ } else if (S_ISDIR(mode)) { sys_mkdir(collected, mode); sys_chown(collected, uid, gid); + sys_chmod(collected, mode); } else if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) { if (maybe_link() == 0) { sys_mknod(collected, mode, rdev); sys_chown(collected, uid, gid); + sys_chmod(collected, mode); } } else panic("populate_root: bogus mode: %o\n", mode); diff -Nru a/kernel/Makefile b/kernel/Makefile --- a/kernel/Makefile Thu Sep 11 23:03:11 2003 +++ b/kernel/Makefile Thu Sep 11 23:03:11 2003 @@ -18,6 +18,7 @@ obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o obj-$(CONFIG_COMPAT) += compat.o obj-$(CONFIG_IKCONFIG) += configs.o +obj-$(CONFIG_IKCONFIG_PROC) += configs.o ifneq ($(CONFIG_IA64),y) # According to Alan Modra , the -fno-omit-frame-pointer is @@ -28,12 +29,32 @@ CFLAGS_sched.o := $(PROFILING) -fno-omit-frame-pointer endif +# configs.o uses generated files - dependecies must be listed explicitly +$(obj)/configs.o: $(obj)/ikconfig.h + +ifdef CONFIG_IKCONFIG_PROC +$(obj)/configs.o: $(obj)/config_data.h +endif + +# ikconfig.h contains all the selected config entries - generated +# from top-level Makefile and .config. Info from ikconfig.h can +# be extracted from the kernel binary. + quiet_cmd_ikconfig = IKCFG $@ cmd_ikconfig = $(CONFIG_SHELL) $< .config $(srctree)/Makefile > $@ targets += ikconfig.h - $(obj)/ikconfig.h: scripts/mkconfigs .config Makefile FORCE $(call if_changed,ikconfig) -$(obj)/configs.o: $(obj)/ikconfig.h +# config_data.h contains the same information as ikconfig.h but gzipped. +# Info from config_data can be extracted from /proc/config* +targets += config_data.gz +$(obj)/config_data.gz: .config FORCE + $(call if_changed,gzip) + +quiet_cmd_ikconfiggz = IKCFG $@ + cmd_ikconfiggz = cat $< | scripts/bin2c kernel_config_data > $@ +targets += config_data.h +$(obj)/config_data.h: $(obj)/config_data.gz FORCE + $(call if_changed,ikconfiggz) diff -Nru a/kernel/configs.c b/kernel/configs.c --- a/kernel/configs.c Thu Sep 11 23:03:12 2003 +++ b/kernel/configs.c Thu Sep 11 23:03:12 2003 @@ -23,6 +23,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include #include #include @@ -35,129 +36,116 @@ /**************************************************/ /* the actual current config file */ +/* This one is for extraction from the kernel binary file image. */ #include "ikconfig.h" #ifdef CONFIG_IKCONFIG_PROC +/* This is the data that can be read from /proc/config.gz. */ +#include "config_data.h" + /**************************************************/ /* globals and useful constants */ -static const char IKCONFIG_NAME[] = "ikconfig"; static const char IKCONFIG_VERSION[] = "0.6"; -static int ikconfig_size; -static struct proc_dir_entry *ikconfig_dir; - static ssize_t -ikconfig_read(struct file *file, char __user *buf, - size_t len, loff_t *offset) +ikconfig_read_current(struct file *file, char __user *buf, + size_t len, loff_t * offset) { loff_t pos = *offset; ssize_t count; - - if (pos >= ikconfig_size) + + if (pos >= kernel_config_data_size) return 0; - count = min(len, (size_t)(ikconfig_size - pos)); - if(copy_to_user(buf, ikconfig_config + pos, count)) + count = min(len, (size_t)(kernel_config_data_size - pos)); + if(copy_to_user(buf, kernel_config_data + pos, count)) return -EFAULT; *offset += count; return count; } -static struct file_operations config_fops = { +static struct file_operations ikconfig_file_ops = { .owner = THIS_MODULE, - .read = ikconfig_read, + .read = ikconfig_read_current, }; + /***************************************************/ -/* built_with_show: let people read the info */ +/* build_info_show: let people read the info */ /* we have on the tools used to build this kernel */ -static int builtwith_show(struct seq_file *seq, void *v) +static int build_info_show(struct seq_file *seq, void *v) { - seq_printf(seq, + seq_printf(seq, "Kernel: %s\nCompiler: %s\nVersion_in_Makefile: %s\n", - ikconfig_built_with, LINUX_COMPILER, UTS_RELEASE); + ikconfig_build_info, LINUX_COMPILER, UTS_RELEASE); return 0; } -static int built_with_open(struct inode *inode, struct file *file) +static int build_info_open(struct inode *inode, struct file *file) { - return single_open(file, builtwith_show, PDE(inode)->data); + return single_open(file, build_info_show, PDE(inode)->data); } - -static struct file_operations builtwith_fops = { + +static struct file_operations build_info_file_ops = { .owner = THIS_MODULE, - .open = built_with_open, + .open = build_info_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, -}; +}; /***************************************************/ /* ikconfig_init: start up everything we need to */ -int __init -ikconfig_init(void) +static int __init ikconfig_init(void) { struct proc_dir_entry *entry; - printk(KERN_INFO "ikconfig %s with /proc/ikconfig\n", + printk(KERN_INFO "ikconfig %s with /proc/config*\n", IKCONFIG_VERSION); - /* create the ikconfig directory */ - ikconfig_dir = proc_mkdir(IKCONFIG_NAME, NULL); - if (ikconfig_dir == NULL) - goto leave; - ikconfig_dir->owner = THIS_MODULE; - /* create the current config file */ - entry = create_proc_entry("config", S_IFREG | S_IRUGO, ikconfig_dir); + entry = create_proc_entry("config.gz", S_IFREG | S_IRUGO, + &proc_root); if (!entry) - goto leave2; + goto leave; - entry->proc_fops = &config_fops; - entry->size = ikconfig_size = strlen(ikconfig_config); + entry->proc_fops = &ikconfig_file_ops; + entry->size = kernel_config_data_size; - /* create the "built with" file */ - entry = create_proc_entry("built_with", S_IFREG | S_IRUGO, - ikconfig_dir); + /* create the "build_info" file */ + entry = create_proc_entry("config_build_info", + S_IFREG | S_IRUGO, &proc_root); if (!entry) - goto leave3; - entry->proc_fops = &builtwith_fops; + goto leave_gz; + entry->proc_fops = &build_info_file_ops; return 0; -leave3: +leave_gz: /* remove the file from proc */ - remove_proc_entry("config", ikconfig_dir); - -leave2: - /* remove the ikconfig directory */ - remove_proc_entry(IKCONFIG_NAME, NULL); + remove_proc_entry("config.gz", &proc_root); leave: return -ENOMEM; } /***************************************************/ -/* cleanup_ikconfig: clean up our mess */ +/* ikconfig_cleanup: clean up our mess */ -static void -cleanup_ikconfig(void) +static void __exit ikconfig_cleanup(void) { /* remove the files */ - remove_proc_entry("config", ikconfig_dir); - remove_proc_entry("built_with", ikconfig_dir); - - /* remove the ikconfig directory */ - remove_proc_entry(IKCONFIG_NAME, NULL); + remove_proc_entry("config.gz", &proc_root); + remove_proc_entry("config_build_info", &proc_root); } module_init(ikconfig_init); -module_exit(cleanup_ikconfig); +module_exit(ikconfig_cleanup); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Randy Dunlap"); diff -Nru a/kernel/sched.c b/kernel/sched.c --- a/kernel/sched.c Thu Sep 11 23:03:13 2003 +++ b/kernel/sched.c Thu Sep 11 23:03:13 2003 @@ -1064,7 +1064,7 @@ */ #define CAN_MIGRATE_TASK(p,rq,this_cpu) \ - ((!idle || (jiffies - (p)->last_run > cache_decay_ticks)) && \ + ((idle || (jiffies - (p)->last_run > cache_decay_ticks)) && \ !task_running(rq, p) && \ cpu_isset(this_cpu, (p)->cpus_allowed)) diff -Nru a/kernel/softirq.c b/kernel/softirq.c --- a/kernel/softirq.c Thu Sep 11 23:03:11 2003 +++ b/kernel/softirq.c Thu Sep 11 23:03:11 2003 @@ -9,8 +9,6 @@ #include #include #include -#include -#include #include #include #include diff -Nru a/kernel/sysctl.c b/kernel/sysctl.c --- a/kernel/sysctl.c Thu Sep 11 23:03:11 2003 +++ b/kernel/sysctl.c Thu Sep 11 23:03:11 2003 @@ -643,7 +643,7 @@ .data = &dirty_writeback_centisecs, .maxlen = sizeof(dirty_writeback_centisecs), .mode = 0644, - .proc_handler = dirty_writeback_centisecs_handler, + .proc_handler = &dirty_writeback_centisecs_handler, }, { .ctl_name = VM_DIRTY_EXPIRE_CS, diff -Nru a/lib/inflate.c b/lib/inflate.c --- a/lib/inflate.c Thu Sep 11 23:03:12 2003 +++ b/lib/inflate.c Thu Sep 11 23:03:12 2003 @@ -871,7 +871,7 @@ { DEBG("dyn5b "); if (i == 1) { - error(" incomplete literal tree\n"); + error("incomplete literal tree"); huft_free(tl); } return i; /* incomplete code set */ @@ -882,7 +882,7 @@ { DEBG("dyn5d "); if (i == 1) { - error(" incomplete distance tree\n"); + error("incomplete distance tree"); #ifdef PKZIP_BUG_WORKAROUND i = 0; } @@ -1097,15 +1097,15 @@ flags = (uch)get_byte(); if ((flags & ENCRYPTED) != 0) { - error("Input is encrypted\n"); + error("Input is encrypted"); return -1; } if ((flags & CONTINUATION) != 0) { - error("Multi part input\n"); + error("Multi part input"); return -1; } if ((flags & RESERVED) != 0) { - error("Input has invalid flags\n"); + error("Input has invalid flags"); return -1; } (ulg)get_byte(); /* Get timestamp */ diff -Nru a/mm/fadvise.c b/mm/fadvise.c --- a/mm/fadvise.c Thu Sep 11 23:03:12 2003 +++ b/mm/fadvise.c Thu Sep 11 23:03:12 2003 @@ -20,7 +20,7 @@ * POSIX_FADV_WILLNEED could set PG_Referenced, and POSIX_FADV_NOREUSE could * deactivate the pages and clear PG_Referenced. */ -long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) +asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice) { struct file *file = fget(fd); struct inode *inode; @@ -80,7 +80,7 @@ return ret; } -long sys_fadvise64(int fd, loff_t offset, size_t len, int advice) +asmlinkage long sys_fadvise64(int fd, loff_t offset, size_t len, int advice) { return sys_fadvise64_64(fd, offset, len, advice); } diff -Nru a/mm/filemap.c b/mm/filemap.c --- a/mm/filemap.c Thu Sep 11 23:03:12 2003 +++ b/mm/filemap.c Thu Sep 11 23:03:12 2003 @@ -1266,6 +1266,20 @@ page_cache_release(page); return err; } + } else { + /* + * If a nonlinear mapping then store the file page offset + * in the pte. + */ + unsigned long pgidx; + pgidx = (addr - vma->vm_start) >> PAGE_SHIFT; + pgidx += vma->vm_pgoff; + pgidx >>= PAGE_CACHE_SHIFT - PAGE_SHIFT; + if (pgoff != pgidx) { + err = install_file_pte(mm, vma, addr, pgoff, prot); + if (err) + return err; + } } len -= PAGE_SIZE; diff -Nru a/mm/fremap.c b/mm/fremap.c --- a/mm/fremap.c Thu Sep 11 23:03:11 2003 +++ b/mm/fremap.c Thu Sep 11 23:03:11 2003 @@ -61,6 +61,7 @@ pte_t *pte; pgd_t *pgd; pmd_t *pmd; + pte_t pte_val; struct pte_chain *pte_chain; pte_chain = pte_chain_alloc(GFP_KERNEL); @@ -83,10 +84,11 @@ flush_icache_page(vma, page); set_pte(pte, mk_pte(page, prot)); pte_chain = page_add_rmap(page, pte, pte_chain); + pte_val = *pte; pte_unmap(pte); if (flush) flush_tlb_page(vma, addr); - update_mmu_cache(vma, addr, *pte); + update_mmu_cache(vma, addr, pte_val); spin_unlock(&mm->page_table_lock); pte_chain_free(pte_chain); return 0; @@ -98,6 +100,47 @@ return err; } EXPORT_SYMBOL(install_page); + + +/* + * Install a file pte to a given virtual memory address, release any + * previously existing mapping. + */ +int install_file_pte(struct mm_struct *mm, struct vm_area_struct *vma, + unsigned long addr, unsigned long pgoff, pgprot_t prot) +{ + int err = -ENOMEM, flush; + pte_t *pte; + pgd_t *pgd; + pmd_t *pmd; + pte_t pte_val; + + pgd = pgd_offset(mm, addr); + spin_lock(&mm->page_table_lock); + + pmd = pmd_alloc(mm, pgd, addr); + if (!pmd) + goto err_unlock; + + pte = pte_alloc_map(mm, pmd, addr); + if (!pte) + goto err_unlock; + + flush = zap_pte(mm, vma, addr, pte); + + set_pte(pte, pgoff_to_pte(pgoff)); + pte_val = *pte; + pte_unmap(pte); + if (flush) + flush_tlb_page(vma, addr); + update_mmu_cache(vma, addr, pte_val); + spin_unlock(&mm->page_table_lock); + return 0; + +err_unlock: + spin_unlock(&mm->page_table_lock); + return err; +} /*** diff -Nru a/mm/shmem.c b/mm/shmem.c --- a/mm/shmem.c Thu Sep 11 23:03:12 2003 +++ b/mm/shmem.c Thu Sep 11 23:03:12 2003 @@ -984,7 +984,22 @@ page_cache_release(page); return err; } + } else if (nonblock) { + /* + * If a nonlinear mapping then store the file page + * offset in the pte. + */ + unsigned long pgidx; + pgidx = (addr - vma->vm_start) >> PAGE_SHIFT; + pgidx += vma->vm_pgoff; + pgidx >>= PAGE_CACHE_SHIFT - PAGE_SHIFT; + if (pgoff != pgidx) { + err = install_file_pte(mm, vma, addr, pgoff, prot); + if (err) + return err; + } } + len -= PAGE_SIZE; addr += PAGE_SIZE; pgoff++; diff -Nru a/net/802/tr.c b/net/802/tr.c --- a/net/802/tr.c Thu Sep 11 23:03:11 2003 +++ b/net/802/tr.c Thu Sep 11 23:03:11 2003 @@ -464,8 +464,6 @@ */ #ifdef CONFIG_PROC_FS -/* Magic token to indicate first entry (header line) */ -#define RIF_PROC_START ((void *)1) static struct rif_cache_s *rif_get_idx(loff_t pos) { @@ -487,7 +485,7 @@ { spin_lock_bh(&rif_lock); - return *pos ? rif_get_idx(*pos - 1) : RIF_PROC_START; + return *pos ? rif_get_idx(*pos - 1) : SEQ_START_TOKEN; } static void *rif_seq_next(struct seq_file *seq, void *v, loff_t *pos) @@ -497,7 +495,7 @@ ++*pos; - if (v == RIF_PROC_START) { + if (v == SEQ_START_TOKEN) { i = -1; goto scan; } @@ -524,7 +522,7 @@ int j, rcf_len, segment, brdgnmb; struct rif_cache_s *entry = v; - if (v == RIF_PROC_START) + if (v == SEQ_START_TOKEN) seq_puts(seq, "if TR address TTL rcf routing segments\n"); else { diff -Nru a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c --- a/net/8021q/vlanproc.c Thu Sep 11 23:03:12 2003 +++ b/net/8021q/vlanproc.c Thu Sep 11 23:03:12 2003 @@ -46,10 +46,6 @@ static void vlan_seq_stop(struct seq_file *seq, void *); static int vlandev_seq_show(struct seq_file *seq, void *v); -/* Miscellaneous */ -#define SEQ_START_TOKEN ((void *) 1) - - /* * Global Data */ diff -Nru a/net/appletalk/aarp.c b/net/appletalk/aarp.c --- a/net/appletalk/aarp.c Thu Sep 11 23:03:14 2003 +++ b/net/appletalk/aarp.c Thu Sep 11 23:03:14 2003 @@ -941,7 +941,7 @@ iter->table = resolved; iter->bucket = 0; - return *pos ? iter_next(iter, pos) : ((void *)1); + return *pos ? iter_next(iter, pos) : SEQ_START_TOKEN; } static void *aarp_seq_next(struct seq_file *seq, void *v, loff_t *pos) @@ -952,7 +952,7 @@ ++*pos; /* first line after header */ - if (v == ((void *)1)) + if (v == SEQ_START_TOKEN) entry = iter_next(iter, NULL); /* next entry in current bucket */ @@ -987,7 +987,7 @@ struct aarp_entry *entry = v; unsigned long now = jiffies; - if (v == ((void *)1)) + if (v == SEQ_START_TOKEN) seq_puts(seq, "Address Interface Hardware Address" " Expires LastSend Retry Status\n"); diff -Nru a/net/appletalk/atalk_proc.c b/net/appletalk/atalk_proc.c --- a/net/appletalk/atalk_proc.c Thu Sep 11 23:03:13 2003 +++ b/net/appletalk/atalk_proc.c Thu Sep 11 23:03:13 2003 @@ -33,7 +33,7 @@ loff_t l = *pos; read_lock_bh(&atalk_interfaces_lock); - return l ? atalk_get_interface_idx(--l) : (void *)1; + return l ? atalk_get_interface_idx(--l) : SEQ_START_TOKEN; } static void *atalk_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos) @@ -41,7 +41,7 @@ struct atalk_iface *i; ++*pos; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { i = NULL; if (atalk_interfaces) i = atalk_interfaces; @@ -62,7 +62,7 @@ { struct atalk_iface *iface; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { seq_puts(seq, "Interface Address Networks " "Status\n"); goto out; @@ -92,7 +92,7 @@ loff_t l = *pos; read_lock_bh(&atalk_routes_lock); - return l ? atalk_get_route_idx(--l) : (void *)1; + return l ? atalk_get_route_idx(--l) : SEQ_START_TOKEN; } static void *atalk_seq_route_next(struct seq_file *seq, void *v, loff_t *pos) @@ -100,7 +100,7 @@ struct atalk_route *r; ++*pos; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { r = NULL; if (atalk_routes) r = atalk_routes; @@ -121,7 +121,7 @@ { struct atalk_route *rt; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { seq_puts(seq, "Target Router Flags Dev\n"); goto out; } @@ -160,7 +160,7 @@ loff_t l = *pos; read_lock_bh(&atalk_sockets_lock); - return l ? atalk_get_socket_idx(--l) : (void *)1; + return l ? atalk_get_socket_idx(--l) : SEQ_START_TOKEN; } static void *atalk_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) @@ -168,7 +168,7 @@ struct sock *i; ++*pos; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { i = sk_head(&atalk_sockets); goto out; } @@ -187,7 +187,7 @@ struct sock *s; struct atalk_sock *at; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { seq_printf(seq, "Type Local_addr Remote_addr Tx_queue " "Rx_queue St UID\n"); goto out; diff -Nru a/net/atm/br2684.c b/net/atm/br2684.c --- a/net/atm/br2684.c Thu Sep 11 23:03:12 2003 +++ b/net/atm/br2684.c Thu Sep 11 23:03:12 2003 @@ -732,9 +732,10 @@ #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)); + if (brvcc->filter.netmask != 0) + seq_printf(seq, " filter=%d.%d.%d.%d/" + "%d.%d.%d.%d\n", + bs(prefix), bs(netmask)); #undef bs #undef b1 #endif /* CONFIG_ATM_BR2684_IPFILTER */ diff -Nru a/net/atm/clip.c b/net/atm/clip.c --- a/net/atm/clip.c Thu Sep 11 23:03:14 2003 +++ b/net/atm/clip.c Thu Sep 11 23:03:14 2003 @@ -189,6 +189,13 @@ return 0; } +static const unsigned char llc_oui[] = { + 0xaa, /* DSAP: non-ISO */ + 0xaa, /* SSAP: non-ISO */ + 0x03, /* Ctrl: Unnumbered Information Command PDU */ + 0x00, /* OUI: EtherType */ + 0x00, + 0x00 }; static void clip_push(struct atm_vcc *vcc,struct sk_buff *skb) { diff -Nru a/net/atm/ipcommon.c b/net/atm/ipcommon.c --- a/net/atm/ipcommon.c Thu Sep 11 23:03:12 2003 +++ b/net/atm/ipcommon.c Thu Sep 11 23:03:12 2003 @@ -22,15 +22,6 @@ #endif -const unsigned char llc_oui[] = { - 0xaa, /* DSAP: non-ISO */ - 0xaa, /* SSAP: non-ISO */ - 0x03, /* Ctrl: Unnumbered Information Command PDU */ - 0x00, /* OUI: EtherType */ - 0x00, - 0x00 }; - - /* * skb_migrate appends the list at "from" to "to", emptying "from" in the * process. skb_migrate is atomic with respect to all other skb operations on @@ -67,5 +58,4 @@ } -EXPORT_SYMBOL(llc_oui); EXPORT_SYMBOL(skb_migrate); diff -Nru a/net/atm/proc.c b/net/atm/proc.c --- a/net/atm/proc.c Thu Sep 11 23:03:12 2003 +++ b/net/atm/proc.c Thu Sep 11 23:03:12 2003 @@ -1,21 +1,13 @@ -/* net/atm/proc.c - ATM /proc interface */ - -/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ - -/* - * The mechanism used here isn't designed for speed but rather for convenience - * of implementation. We only return one entry per read system call, so we can - * be reasonably sure not to overrun the page and race conditions may lead to - * the addition or omission of some lines but never to any corruption of a - * line's internal structure. +/* net/atm/proc.c - ATM /proc interface + * + * Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA * - * Making the whole thing slightly more efficient is left as an exercise to the - * reader. (Suggestions: wrapper which loops to get several entries per system - * call; or make --left slightly more clever to avoid O(n^2) characteristics.) - * I find it fast enough on my unloaded 266 MHz Pentium 2 :-) + * seq_file api usage by romieu@fr.zoreil.com + * + * Evaluating the efficiency of the whole thing if left as an exercise to + * the reader. */ - #include #include /* for EXPORT_SYMBOL */ #include @@ -24,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -51,119 +44,202 @@ static ssize_t proc_dev_atm_read(struct file *file,char *buf,size_t count, loff_t *pos); -static ssize_t proc_spec_atm_read(struct file *file,char *buf,size_t count, - loff_t *pos); -static struct file_operations proc_dev_atm_operations = { +static struct file_operations proc_atm_dev_ops = { .owner = THIS_MODULE, .read = proc_dev_atm_read, }; -static struct file_operations proc_spec_atm_operations = { - .owner = THIS_MODULE, - .read = proc_spec_atm_read, -}; - -static void add_stats(char *buf,const char *aal, +static void add_stats(struct seq_file *seq, const char *aal, const struct k_atm_aal_stats *stats) { - sprintf(strchr(buf,0),"%s ( %d %d %d %d %d )",aal, + seq_printf(seq, "%s ( %d %d %d %d %d )", aal, atomic_read(&stats->tx),atomic_read(&stats->tx_err), atomic_read(&stats->rx),atomic_read(&stats->rx_err), atomic_read(&stats->rx_drop)); } - -static void atm_dev_info(const struct atm_dev *dev,char *buf) +static void atm_dev_info(struct seq_file *seq, const struct atm_dev *dev) { - int off,i; + int i; - off = sprintf(buf,"%3d %-8s",dev->number,dev->type); + seq_printf(seq, "%3d %-8s", dev->number, dev->type); for (i = 0; i < ESI_LEN; i++) - off += sprintf(buf+off,"%02x",dev->esi[i]); - strcat(buf," "); - add_stats(buf,"0",&dev->stats.aal0); - strcat(buf," "); - add_stats(buf,"5",&dev->stats.aal5); - sprintf(strchr(buf,0), "\t[%d]", atomic_read(&dev->refcnt)); - strcat(buf,"\n"); + seq_printf(seq, "%02x", dev->esi[i]); + seq_puts(seq, " "); + add_stats(seq, "0", &dev->stats.aal0); + seq_puts(seq, " "); + add_stats(seq, "5", &dev->stats.aal5); + seq_printf(seq, "\t[%d]", atomic_read(&dev->refcnt)); + seq_putc(seq, '\n'); } - #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) - -static int svc_addr(char *buf,struct sockaddr_atmsvc *addr) +static void svc_addr(struct seq_file *seq, struct sockaddr_atmsvc *addr) { static int code[] = { 1,2,10,6,1,0 }; static int e164[] = { 1,8,4,6,1,0 }; - int *fields; - int len,i,j,pos; - len = 0; if (*addr->sas_addr.pub) { - strcpy(buf,addr->sas_addr.pub); - len = strlen(addr->sas_addr.pub); - buf += len; - if (*addr->sas_addr.prv) { - *buf++ = '+'; - len++; - } + seq_printf(seq, "%s", addr->sas_addr.pub); + if (*addr->sas_addr.prv) + seq_putc(seq, '+'); + } else if (!*addr->sas_addr.prv) { + seq_printf(seq, "%s", "(none)"); + return; } - else if (!*addr->sas_addr.prv) { - strcpy(buf,"(none)"); - return strlen(buf); - } if (*addr->sas_addr.prv) { - len += 44; - pos = 0; - fields = *addr->sas_addr.prv == ATM_AFI_E164 ? e164 : code; + unsigned char *prv = addr->sas_addr.prv; + int *fields; + int i, j; + + fields = *prv == ATM_AFI_E164 ? e164 : code; for (i = 0; fields[i]; i++) { - for (j = fields[i]; j; j--) { - sprintf(buf,"%02X",addr->sas_addr.prv[pos++]); - buf += 2; - } - if (fields[i+1]) *buf++ = '.'; + for (j = fields[i]; j; j--) + seq_printf(seq, "%02X", *prv++); + if (fields[i+1]) + seq_putc(seq, '.'); } } - return len; } - -static void atmarp_info(struct net_device *dev,struct atmarp_entry *entry, - struct clip_vcc *clip_vcc,char *buf) +static void atmarp_info(struct seq_file *seq, struct net_device *dev, + struct atmarp_entry *entry, struct clip_vcc *clip_vcc) { - unsigned char *ip; - int svc,off,ip_len; + char buf[17]; + int svc, off; svc = !clip_vcc || clip_vcc->vcc->sk->sk_family == AF_ATMSVC; - off = sprintf(buf,"%-6s%-4s%-4s%5ld ",dev->name,svc ? "SVC" : "PVC", + seq_printf(seq, "%-6s%-4s%-4s%5ld ", dev->name, svc ? "SVC" : "PVC", !clip_vcc || clip_vcc->encap ? "LLC" : "NULL", - (jiffies-(clip_vcc ? clip_vcc->last_use : entry->neigh->used))/ - HZ); - ip = (unsigned char *) &entry->ip; - ip_len = sprintf(buf+off,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]); - off += ip_len; - while (ip_len++ < 16) buf[off++] = ' '; - if (!clip_vcc) + (jiffies-(clip_vcc ? clip_vcc->last_use : entry->neigh->used))/HZ); + + off = snprintf(buf, sizeof(buf) - 1, "%d.%d.%d.%d", NIPQUAD(entry->ip)); + while (off < 16) + buf[off++] = ' '; + buf[off] = '\0'; + seq_printf(seq, "%s", buf); + + if (!clip_vcc) { if (time_before(jiffies, entry->expires)) - strcpy(buf+off,"(resolving)\n"); - else sprintf(buf+off,"(expired, ref %d)\n", - atomic_read(&entry->neigh->refcnt)); - else if (!svc) - sprintf(buf+off,"%d.%d.%d\n",clip_vcc->vcc->dev->number, - clip_vcc->vcc->vpi,clip_vcc->vcc->vci); - else { - off += svc_addr(buf+off,&clip_vcc->vcc->remote); - strcpy(buf+off,"\n"); - } + seq_printf(seq, "(resolving)\n"); + else + seq_printf(seq, "(expired, ref %d)\n", + atomic_read(&entry->neigh->refcnt)); + } else if (!svc) { + seq_printf(seq, "%d.%d.%d\n", clip_vcc->vcc->dev->number, + clip_vcc->vcc->vpi, clip_vcc->vcc->vci); + } else { + svc_addr(seq, &clip_vcc->vcc->remote); + seq_putc(seq, '\n'); + } +} + +#endif /* CONFIG_ATM_CLIP */ + +struct vcc_state { + struct sock *sk; + int family; + int clip_info; +}; + +static inline int compare_family(struct sock *sk, int family) +{ + struct atm_vcc *vcc = atm_sk(sk); + + return !family || (vcc->sk->sk_family == family); +} + +static int __vcc_walk(struct sock **sock, int family, loff_t l) +{ + struct sock *sk = *sock; + + if (sk == (void *)1) { + sk = hlist_empty(&vcc_sklist) ? NULL : __sk_head(&vcc_sklist); + l--; + } + for (; sk; sk = sk_next(sk)) { + l -= compare_family(sk, family); + if (l < 0) + goto out; + } + sk = (void *)1; +out: + *sock = sk; + return (l < 0); +} + +static inline void *vcc_walk(struct vcc_state *state, loff_t l) +{ + return __vcc_walk(&state->sk, state->family, l) ? + state : NULL; +} + +static int __vcc_seq_open(struct inode *inode, struct file *file, + int family, struct seq_operations *ops) +{ + struct vcc_state *state; + struct seq_file *seq; + int rc = -ENOMEM; + + state = kmalloc(sizeof(*state), GFP_KERNEL); + if (!state) + goto out; + + rc = seq_open(file, ops); + if (rc) + goto out_kfree; + + state->family = family; + state->clip_info = try_atm_clip_ops(); + + seq = file->private_data; + seq->private = state; +out: + return rc; +out_kfree: + kfree(state); + goto out; } +static int vcc_seq_release(struct inode *inode, struct file *file) +{ +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) + struct seq_file *seq = file->private_data; + struct vcc_state *state = seq->private; + if (state->clip_info) + module_put(atm_clip_ops->owner); #endif + return seq_release_private(inode, file); +} +static void *vcc_seq_start(struct seq_file *seq, loff_t *pos) +{ + struct vcc_state *state = seq->private; + loff_t left = *pos; -static void pvc_info(struct atm_vcc *vcc, char *buf, int clip_info) + read_lock(&vcc_sklist_lock); + state->sk = (void *)1; + return left ? vcc_walk(state, left) : (void *)1; +} + +static void vcc_seq_stop(struct seq_file *seq, void *v) +{ + read_unlock(&vcc_sklist_lock); +} + +static void *vcc_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct vcc_state *state = seq->private; + + v = vcc_walk(state, 1); + *pos += !!PTR_ERR(v); + return v; +} + +static void pvc_info(struct seq_file *seq, struct atm_vcc *vcc, int clip_info) { static const char *class_name[] = { "off","UBR","CBR","VBR","ABR" }; static const char *aal_name[] = { @@ -171,9 +247,8 @@ "???", "5", "???", "???", /* 4- 7 */ "???", "???", "???", "???", /* 8-11 */ "???", "0", "???", "???"}; /* 12-15 */ - int off; - off = sprintf(buf,"%3d %3d %5d %-3s %7d %-5s %7d %-6s", + seq_printf(seq, "%3d %3d %5d %-3s %7d %-5s %7d %-6s", vcc->dev->number,vcc->vpi,vcc->vci, vcc->qos.aal >= sizeof(aal_name)/sizeof(aal_name[0]) ? "err" : aal_name[vcc->qos.aal],vcc->qos.rxtp.min_pcr, @@ -185,18 +260,14 @@ struct net_device *dev; dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : NULL; - off += sprintf(buf+off,"CLIP, Itf:%s, Encap:", + seq_printf(seq, "CLIP, Itf:%s, Encap:", dev ? dev->name : "none?"); - if (clip_vcc->encap) - off += sprintf(buf+off,"LLC/SNAP"); - else - off += sprintf(buf+off,"None"); + seq_printf(seq, "%s", clip_vcc->encap ? "LLC/SNAP" : "None"); } #endif - strcpy(buf+off,"\n"); + seq_putc(seq, '\n'); } - static const char *vcc_state(struct atm_vcc *vcc) { static const char *map[] = { ATM_VS2TXT_MAP }; @@ -204,337 +275,592 @@ return map[ATM_VF2VS(vcc->flags)]; } - -static void vc_info(struct atm_vcc *vcc,char *buf) +static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc) { - char *here; - - here = buf+sprintf(buf,"%p ",vcc); - if (!vcc->dev) here += sprintf(here,"Unassigned "); - else here += sprintf(here,"%3d %3d %5d ",vcc->dev->number,vcc->vpi, - vcc->vci); + seq_printf(seq, "%p ", vcc); + if (!vcc->dev) + seq_printf(seq, "Unassigned "); + else + seq_printf(seq, "%3d %3d %5d ", vcc->dev->number, vcc->vpi, + vcc->vci); switch (vcc->sk->sk_family) { case AF_ATMPVC: - here += sprintf(here,"PVC"); + seq_printf(seq, "PVC"); break; case AF_ATMSVC: - here += sprintf(here,"SVC"); + seq_printf(seq, "SVC"); break; default: - here += sprintf(here, "%3d", vcc->sk->sk_family); + seq_printf(seq, "%3d", vcc->sk->sk_family); } - here += sprintf(here," %04lx %5d %7d/%7d %7d/%7d\n",vcc->flags, - vcc->sk->sk_err, - atomic_read(&vcc->sk->sk_wmem_alloc), vcc->sk->sk_sndbuf, - atomic_read(&vcc->sk->sk_rmem_alloc), vcc->sk->sk_rcvbuf); + seq_printf(seq, " %04lx %5d %7d/%7d %7d/%7d\n", vcc->flags, vcc->sk->sk_err, + atomic_read(&vcc->sk->sk_wmem_alloc),vcc->sk->sk_sndbuf, + atomic_read(&vcc->sk->sk_rmem_alloc),vcc->sk->sk_rcvbuf); } - -static void svc_info(struct atm_vcc *vcc,char *buf) +static void svc_info(struct seq_file *seq, struct atm_vcc *vcc) { - char *here; - int i; - if (!vcc->dev) - sprintf(buf,sizeof(void *) == 4 ? "N/A@%p%10s" : "N/A@%p%2s", - vcc,""); - else sprintf(buf,"%3d %3d %5d ",vcc->dev->number,vcc->vpi, - vcc->vci); - here = strchr(buf,0); - here += sprintf(here,"%-10s ",vcc_state(vcc)); - here += sprintf(here,"%s%s",vcc->remote.sas_addr.pub, + seq_printf(seq, sizeof(void *) == 4 ? + "N/A@%p%10s" : "N/A@%p%2s", vcc, ""); + else + seq_printf(seq, "%3d %3d %5d ", + vcc->dev->number, vcc->vpi, vcc->vci); + seq_printf(seq, "%-10s ", vcc_state(vcc)); + seq_printf(seq, "%s%s", vcc->remote.sas_addr.pub, *vcc->remote.sas_addr.pub && *vcc->remote.sas_addr.prv ? "+" : ""); - if (*vcc->remote.sas_addr.prv) + if (*vcc->remote.sas_addr.prv) { + int i; + for (i = 0; i < ATM_ESA_LEN; i++) - here += sprintf(here,"%02x", - vcc->remote.sas_addr.prv[i]); - strcat(here,"\n"); + seq_printf(seq, "%02x", vcc->remote.sas_addr.prv[i]); + } + seq_putc(seq, '\n'); } - #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) -static char* -lec_arp_get_status_string(unsigned char status) +static char* lec_arp_get_status_string(unsigned char status) { - switch(status) { - case ESI_UNKNOWN: - return "ESI_UNKNOWN "; - case ESI_ARP_PENDING: - return "ESI_ARP_PENDING "; - case ESI_VC_PENDING: - return "ESI_VC_PENDING "; - case ESI_FLUSH_PENDING: - return "ESI_FLUSH_PENDING "; - case ESI_FORWARD_DIRECT: - return "ESI_FORWARD_DIRECT"; - default: - return " "; - } + static char *lec_arp_status_string[] = { + "ESI_UNKNOWN ", + "ESI_ARP_PENDING ", + "ESI_VC_PENDING ", + " ", + "ESI_FLUSH_PENDING ", + "ESI_FORWARD_DIRECT", + "" + }; + + if (status > ESI_FORWARD_DIRECT) + status = ESI_FORWARD_DIRECT + 1; + return lec_arp_status_string[status]; } -static void -lec_info(struct lec_arp_table *entry, char *buf) +static void lec_info(struct seq_file *seq, struct lec_arp_table *entry) { - int j, offset=0; + int i; - for(j=0;jmac_addr[j]); - } - offset+=sprintf(buf+offset, " "); - for(j=0;jatm_addr[j]); + for (i = 0; i < ETH_ALEN; i++) + seq_printf(seq, "%2.2x", entry->mac_addr[i] & 0xff); + seq_printf(seq, " "); + for (i = 0; i < ATM_ESA_LEN; i++) + seq_printf(seq, "%2.2x", entry->atm_addr[i] & 0xff); + seq_printf(seq, " %s %4.4x", lec_arp_get_status_string(entry->status), + entry->flags & 0xffff); + if (entry->vcc) + seq_printf(seq, "%3d %3d ", entry->vcc->vpi, entry->vcc->vci); + else + seq_printf(seq, " "); + if (entry->recv_vcc) { + seq_printf(seq, " %3d %3d", entry->recv_vcc->vpi, + entry->recv_vcc->vci); } - offset+=sprintf(buf+offset, " %s %4.4x", - lec_arp_get_status_string(entry->status), - entry->flags&0xffff); - if (entry->vcc) { - offset+=sprintf(buf+offset, "%3d %3d ", entry->vcc->vpi, - entry->vcc->vci); - } else - offset+=sprintf(buf+offset, " "); - if (entry->recv_vcc) { - offset+=sprintf(buf+offset, " %3d %3d", - entry->recv_vcc->vpi, entry->recv_vcc->vci); - } - - sprintf(buf+offset,"\n"); + seq_putc(seq, '\n'); } -#endif +#endif /* CONFIG_ATM_LANE */ -static int atm_devices_info(loff_t pos,char *buf) +static int atm_dev_seq_show(struct seq_file *seq, void *v) { - struct atm_dev *dev; - struct list_head *p; - int left; + static char atm_dev_banner[] = + "Itf Type ESI/\"MAC\"addr " + "AAL(TX,err,RX,err,drop) ... [refcnt]\n"; + + if (v == (void *)1) + seq_puts(seq, atm_dev_banner); + else { + struct atm_dev *dev = list_entry(v, struct atm_dev, dev_list); - if (!pos) { - return sprintf(buf,"Itf Type ESI/\"MAC\"addr " - "AAL(TX,err,RX,err,drop) ... [refcnt]\n"); - } - left = pos-1; - spin_lock(&atm_dev_lock); - list_for_each(p, &atm_devs) { - dev = list_entry(p, struct atm_dev, dev_list); - if (left-- == 0) { - atm_dev_info(dev,buf); - spin_unlock(&atm_dev_lock); - return strlen(buf); - } + atm_dev_info(seq, dev); + } + return 0; +} + +static struct seq_operations atm_dev_seq_ops = { + .start = atm_dev_seq_start, + .next = atm_dev_seq_next, + .stop = atm_dev_seq_stop, + .show = atm_dev_seq_show, +}; + +static int atm_dev_seq_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &atm_dev_seq_ops); +} + +static struct file_operations devices_seq_fops = { + .open = atm_dev_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static int pvc_seq_show(struct seq_file *seq, void *v) +{ + static char atm_pvc_banner[] = + "Itf VPI VCI AAL RX(PCR,Class) TX(PCR,Class)\n"; + + if (v == (void *)1) + seq_puts(seq, atm_pvc_banner); + else { + struct vcc_state *state = seq->private; + struct atm_vcc *vcc = atm_sk(state->sk); + + pvc_info(seq, vcc, state->clip_info); } - spin_unlock(&atm_dev_lock); return 0; } -/* - * FIXME: it isn't safe to walk the VCC list without turning off interrupts. - * What is really needed is some lock on the devices. Ditto for ATMARP. - */ +static struct seq_operations pvc_seq_ops = { + .start = vcc_seq_start, + .next = vcc_seq_next, + .stop = vcc_seq_stop, + .show = pvc_seq_show, +}; + +static int pvc_seq_open(struct inode *inode, struct file *file) +{ + return __vcc_seq_open(inode, file, PF_ATMPVC, &pvc_seq_ops); +} + +static struct file_operations pvc_seq_fops = { + .open = pvc_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = vcc_seq_release, +}; -static int atm_pvc_info(loff_t pos,char *buf) +static int vcc_seq_show(struct seq_file *seq, void *v) { - struct hlist_node *node; - struct sock *s; - struct atm_vcc *vcc; - int left, clip_info = 0; - - if (!pos) { - return sprintf(buf,"Itf VPI VCI AAL RX(PCR,Class) " - "TX(PCR,Class)\n"); + if (v == (void *)1) { + seq_printf(seq, sizeof(void *) == 4 ? "%-8s%s" : "%-16s%s", + "Address ", "Itf VPI VCI Fam Flags Reply " + "Send buffer Recv buffer\n"); + } else { + struct vcc_state *state = seq->private; + struct atm_vcc *vcc = atm_sk(state->sk); + + vcc_info(seq, vcc); + } + return 0; +} + +static struct seq_operations vcc_seq_ops = { + .start = vcc_seq_start, + .next = vcc_seq_next, + .stop = vcc_seq_stop, + .show = vcc_seq_show, +}; + +static int vcc_seq_open(struct inode *inode, struct file *file) +{ + return __vcc_seq_open(inode, file, 0, &vcc_seq_ops); +} + +static struct file_operations vcc_seq_fops = { + .open = vcc_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = vcc_seq_release, +}; + +static int svc_seq_show(struct seq_file *seq, void *v) +{ + static char atm_svc_banner[] = + "Itf VPI VCI State Remote\n"; + + if (v == (void *)1) + seq_puts(seq, atm_svc_banner); + else { + struct vcc_state *state = seq->private; + struct atm_vcc *vcc = atm_sk(state->sk); + + svc_info(seq, vcc); } - left = pos-1; -#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) - if (try_atm_clip_ops()) - clip_info = 1; -#endif - read_lock(&vcc_sklist_lock); - sk_for_each(s, node, &vcc_sklist) { - vcc = atm_sk(s); - if (vcc->sk->sk_family == PF_ATMPVC && vcc->dev && !left--) { - pvc_info(vcc,buf,clip_info); - read_unlock(&vcc_sklist_lock); + return 0; +} + +static struct seq_operations svc_seq_ops = { + .start = vcc_seq_start, + .next = vcc_seq_next, + .stop = vcc_seq_stop, + .show = svc_seq_show, +}; + +static int svc_seq_open(struct inode *inode, struct file *file) +{ + return __vcc_seq_open(inode, file, PF_ATMSVC, &svc_seq_ops); +} + +static struct file_operations svc_seq_fops = { + .open = svc_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = vcc_seq_release, +}; + #if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) - if (clip_info) - module_put(atm_clip_ops->owner); -#endif - return strlen(buf); - } + +struct arp_state { + int bucket; + struct neighbour *n; + struct clip_vcc *vcc; +}; + +static void *arp_vcc_walk(struct arp_state *state, + struct atmarp_entry *e, loff_t *l) +{ + struct clip_vcc *vcc = state->vcc; + + if (!vcc) + vcc = e->vccs; + if (vcc == (void *)1) { + vcc = e->vccs; + --*l; + } + for (; vcc; vcc = vcc->next) { + if (--*l < 0) + break; } - read_unlock(&vcc_sklist_lock); -#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) - if (clip_info) - module_put(atm_clip_ops->owner); -#endif - return 0; + state->vcc = vcc; + return (*l < 0) ? state : NULL; } + +static void *arp_get_idx(struct arp_state *state, loff_t l) +{ + void *v = NULL; + for (; state->bucket <= NEIGH_HASHMASK; state->bucket++) { + for (; state->n; state->n = state->n->next) { + v = arp_vcc_walk(state, NEIGH2ENTRY(state->n), &l); + if (v) + goto done; + } + state->n = clip_tbl_hook->hash_buckets[state->bucket + 1]; + } +done: + return v; +} -static int atm_vc_info(loff_t pos,char *buf) +static void *arp_seq_start(struct seq_file *seq, loff_t *pos) { - struct atm_vcc *vcc; - struct hlist_node *node; - struct sock *s; - int left; - - if (!pos) - return sprintf(buf,sizeof(void *) == 4 ? "%-8s%s" : "%-16s%s", - "Address"," Itf VPI VCI Fam Flags Reply Send buffer" - " Recv buffer\n"); - left = pos-1; - read_lock(&vcc_sklist_lock); - sk_for_each(s, node, &vcc_sklist) { - vcc = atm_sk(s); - if (!left--) { - vc_info(vcc,buf); - read_unlock(&vcc_sklist_lock); - return strlen(buf); - } + struct arp_state *state = seq->private; + void *ret = (void *)1; + + if (!clip_tbl_hook) { + state->bucket = -1; + goto out; } - read_unlock(&vcc_sklist_lock); - return 0; + read_lock_bh(&clip_tbl_hook->lock); + state->bucket = 0; + state->n = clip_tbl_hook->hash_buckets[0]; + state->vcc = (void *)1; + if (*pos) + ret = arp_get_idx(state, *pos); +out: + return ret; } +static void arp_seq_stop(struct seq_file *seq, void *v) +{ + struct arp_state *state = seq->private; -static int atm_svc_info(loff_t pos,char *buf) + if (state->bucket != -1) + read_unlock_bh(&clip_tbl_hook->lock); +} + +static void *arp_seq_next(struct seq_file *seq, void *v, loff_t *pos) { - struct hlist_node *node; - struct sock *s; - struct atm_vcc *vcc; - int left; - - if (!pos) - return sprintf(buf,"Itf VPI VCI State Remote\n"); - left = pos-1; - read_lock(&vcc_sklist_lock); - sk_for_each(s, node, &vcc_sklist) { - vcc = atm_sk(s); - if (vcc->sk->sk_family == PF_ATMSVC && !left--) { - svc_info(vcc,buf); - read_unlock(&vcc_sklist_lock); - return strlen(buf); - } - } - read_unlock(&vcc_sklist_lock); + struct arp_state *state = seq->private; - return 0; + v = arp_get_idx(state, 1); + *pos += !!PTR_ERR(v); + return v; } -#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) -static int atm_arp_info(loff_t pos,char *buf) +static int arp_seq_show(struct seq_file *seq, void *v) { - struct neighbour *n; - int i,count; + static char atm_arp_banner[] = + "IPitf TypeEncp Idle IP address ATM address\n"; + + if (v == (void *)1) + seq_puts(seq, atm_arp_banner); + else { + struct arp_state *state = seq->private; + struct neighbour *n = state->n; + struct clip_vcc *vcc = state->vcc; - if (!pos) { - return sprintf(buf,"IPitf TypeEncp Idle IP address " - "ATM address\n"); + atmarp_info(seq, n->dev, NEIGH2ENTRY(n), vcc); } + return 0; +} + +static struct seq_operations arp_seq_ops = { + .start = arp_seq_start, + .next = arp_seq_next, + .stop = arp_seq_stop, + .show = arp_seq_show, +}; + +static int arp_seq_open(struct inode *inode, struct file *file) +{ + struct arp_state *state; + struct seq_file *seq; + int rc = -EAGAIN; + if (!try_atm_clip_ops()) - return 0; - count = pos; - read_lock_bh(&clip_tbl_hook->lock); - for (i = 0; i <= NEIGH_HASHMASK; i++) - for (n = clip_tbl_hook->hash_buckets[i]; n; n = n->next) { - struct atmarp_entry *entry = NEIGH2ENTRY(n); - struct clip_vcc *vcc; - - if (!entry->vccs) { - if (--count) continue; - atmarp_info(n->dev,entry,NULL,buf); - read_unlock_bh(&clip_tbl_hook->lock); - module_put(atm_clip_ops->owner); - return strlen(buf); - } - for (vcc = entry->vccs; vcc; - vcc = vcc->next) { - if (--count) continue; - atmarp_info(n->dev,entry,vcc,buf); - read_unlock_bh(&clip_tbl_hook->lock); - module_put(atm_clip_ops->owner); - return strlen(buf); - } - } - read_unlock_bh(&clip_tbl_hook->lock); + goto out; + + state = kmalloc(sizeof(*state), GFP_KERNEL); + if (!state) { + rc = -ENOMEM; + goto out_put; + } + + rc = seq_open(file, &arp_seq_ops); + if (rc) + goto out_kfree; + + seq = file->private_data; + seq->private = state; +out: + return rc; + +out_put: module_put(atm_clip_ops->owner); - return 0; +out_kfree: + kfree(state); + goto out; } -#endif -#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) -static int atm_lec_info(loff_t pos,char *buf) +static int arp_seq_release(struct inode *inode, struct file *file) { + module_put(atm_clip_ops->owner); + return seq_release_private(inode, file); +} + +static struct file_operations arp_seq_fops = { + .open = arp_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = arp_seq_release, +}; + +#endif /* CONFIG_ATM_CLIP */ + +#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) + +struct lec_state { unsigned long flags; - struct lec_priv *priv; + struct lec_priv *locked; struct lec_arp_table *entry; - int i, count, d, e; struct net_device *dev; + int itf; + int arp_table; + int misc_table; +}; - if (!pos) { - return sprintf(buf,"Itf MAC ATM destination" - " Status Flags " - "VPI/VCI Recv VPI/VCI\n"); +static void *lec_tbl_walk(struct lec_state *state, struct lec_arp_table *tbl, + loff_t *l) +{ + struct lec_arp_table *e = state->entry; + + if (!e) + e = tbl; + if (e == (void *)1) { + e = tbl; + --*l; } - if (!try_atm_lane_ops()) - return 0; /* the lane module is not there yet */ + for (; e; e = e->next) { + if (--*l < 0) + break; + } + state->entry = e; + return (*l < 0) ? state : NULL; +} - count = pos; - for(d = 0; d < MAX_LEC_ITF; d++) { - dev = atm_lane_ops->get_lec(d); - if (!dev || !(priv = (struct lec_priv *) dev->priv)) - continue; - spin_lock_irqsave(&priv->lec_arp_lock, flags); - for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) { - for(entry = priv->lec_arp_tables[i]; entry; entry = entry->next) { - if (--count) - continue; - e = sprintf(buf,"%s ", dev->name); - lec_info(entry, buf+e); - spin_unlock_irqrestore(&priv->lec_arp_lock, flags); - dev_put(dev); - module_put(atm_lane_ops->owner); - return strlen(buf); - } - } - for(entry = priv->lec_arp_empty_ones; entry; entry = entry->next) { - if (--count) - continue; - e = sprintf(buf,"%s ", dev->name); - lec_info(entry, buf+e); - spin_unlock_irqrestore(&priv->lec_arp_lock, flags); - dev_put(dev); - module_put(atm_lane_ops->owner); - return strlen(buf); - } - for(entry = priv->lec_no_forward; entry; entry=entry->next) { - if (--count) - continue; - e = sprintf(buf,"%s ", dev->name); - lec_info(entry, buf+e); - spin_unlock_irqrestore(&priv->lec_arp_lock, flags); - dev_put(dev); - module_put(atm_lane_ops->owner); - return strlen(buf); - } - for(entry = priv->mcast_fwds; entry; entry = entry->next) { - if (--count) - continue; - e = sprintf(buf,"%s ", dev->name); - lec_info(entry, buf+e); - spin_unlock_irqrestore(&priv->lec_arp_lock, flags); - dev_put(dev); - module_put(atm_lane_ops->owner); - return strlen(buf); - } - spin_unlock_irqrestore(&priv->lec_arp_lock, flags); +static void *lec_arp_walk(struct lec_state *state, loff_t *l, + struct lec_priv *priv) +{ + void *v = NULL; + int p; + + for (p = state->arp_table; p < LEC_ARP_TABLE_SIZE; p++) { + v = lec_tbl_walk(state, priv->lec_arp_tables[p], l); + if (v) + break; + } + state->arp_table = p; + return v; +} + +static void *lec_misc_walk(struct lec_state *state, loff_t *l, + struct lec_priv *priv) +{ + struct lec_arp_table *lec_misc_tables[] = { + priv->lec_arp_empty_ones, + priv->lec_no_forward, + priv->mcast_fwds + }; + void *v = NULL; + int q; + + for (q = state->misc_table; q < ARRAY_SIZE(lec_misc_tables); q++) { + v = lec_tbl_walk(state, lec_misc_tables[q], l); + if (v) + break; + } + state->misc_table = q; + return v; +} + +static void *lec_priv_walk(struct lec_state *state, loff_t *l, + struct lec_priv *priv) +{ + if (!state->locked) { + state->locked = priv; + spin_lock_irqsave(&priv->lec_arp_lock, state->flags); + } + if (!lec_arp_walk(state, l, priv) && + !lec_misc_walk(state, l, priv)) { + spin_unlock_irqrestore(&priv->lec_arp_lock, state->flags); + state->locked = NULL; + /* Partial state reset for the next time we get called */ + state->arp_table = state->misc_table = 0; + } + return state->locked; +} + +static void *lec_itf_walk(struct lec_state *state, loff_t *l) +{ + struct net_device *dev; + void *v; + + dev = state->dev ? state->dev : atm_lane_ops->get_lec(state->itf); + v = (dev && dev->priv) ? lec_priv_walk(state, l, dev->priv) : NULL; + if (!v && dev) { dev_put(dev); + /* Partial state reset for the next time we get called */ + dev = NULL; + } + state->dev = dev; + return v; +} + +static void *lec_get_idx(struct lec_state *state, loff_t l) +{ + void *v = NULL; + + for (; state->itf < MAX_LEC_ITF; state->itf++) { + v = lec_itf_walk(state, &l); + if (v) + break; + } + return v; +} + +static void *lec_seq_start(struct seq_file *seq, loff_t *pos) +{ + struct lec_state *state = seq->private; + + state->itf = 0; + state->dev = NULL; + state->locked = NULL; + state->arp_table = 0; + state->misc_table = 0; + state->entry = (void *)1; + + return *pos ? lec_get_idx(state, *pos) : (void*)1; +} + +static void lec_seq_stop(struct seq_file *seq, void *v) +{ + struct lec_state *state = seq->private; + + if (state->dev) { + spin_unlock_irqrestore(&state->locked->lec_arp_lock, + state->flags); + dev_put(state->dev); + } +} + +static void *lec_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct lec_state *state = seq->private; + + v = lec_get_idx(state, 1); + *pos += !!PTR_ERR(v); + return v; +} + +static int lec_seq_show(struct seq_file *seq, void *v) +{ + static char lec_banner[] = "Itf MAC ATM destination" + " Status Flags " + "VPI/VCI Recv VPI/VCI\n"; + + if (v == (void *)1) + seq_puts(seq, lec_banner); + else { + struct lec_state *state = seq->private; + struct net_device *dev = state->dev; + + seq_printf(seq, "%s ", dev->name); + lec_info(seq, state->entry); } - module_put(atm_lane_ops->owner); return 0; } -#endif +static struct seq_operations lec_seq_ops = { + .start = lec_seq_start, + .next = lec_seq_next, + .stop = lec_seq_stop, + .show = lec_seq_show, +}; + +static int lec_seq_open(struct inode *inode, struct file *file) +{ + struct lec_state *state; + struct seq_file *seq; + int rc = -EAGAIN; + + if (!try_atm_lane_ops()) + goto out; + + state = kmalloc(sizeof(*state), GFP_KERNEL); + if (!state) { + rc = -ENOMEM; + goto out; + } + + rc = seq_open(file, &lec_seq_ops); + if (rc) + goto out_kfree; + seq = file->private_data; + seq->private = state; +out: + return rc; +out_kfree: + kfree(state); + goto out; +} + +static int lec_seq_release(struct inode *inode, struct file *file) +{ + module_put(atm_lane_ops->owner); + return seq_release_private(inode, file); +} + +static struct file_operations lec_seq_fops = { + .open = lec_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = lec_seq_release, +}; + +#endif /* CONFIG_ATM_LANE */ static ssize_t proc_dev_atm_read(struct file *file,char *buf,size_t count, loff_t *pos) @@ -562,28 +888,6 @@ } -static ssize_t proc_spec_atm_read(struct file *file,char *buf,size_t count, - loff_t *pos) -{ - unsigned long page; - int length; - int (*info)(loff_t,char *); - info = PDE(file->f_dentry->d_inode)->data; - - if (count == 0) return 0; - page = get_zeroed_page(GFP_KERNEL); - if (!page) return -ENOMEM; - length = (*info)(*pos,(char *) page); - if (length > count) length = -EINVAL; - if (length >= 0) { - if (copy_to_user(buf,(char *) page,length)) length = -EFAULT; - (*pos)++; - } - free_page(page); - return length; -} - - struct proc_dir_entry *atm_proc_root; EXPORT_SYMBOL(atm_proc_root); @@ -604,19 +908,19 @@ dev->proc_name = kmalloc(strlen(dev->type) + digits + 2, GFP_KERNEL); if (!dev->proc_name) - goto fail1; + goto err_out; sprintf(dev->proc_name,"%s:%d",dev->type, dev->number); dev->proc_entry = create_proc_entry(dev->proc_name, 0, atm_proc_root); if (!dev->proc_entry) - goto fail0; + goto err_free_name; dev->proc_entry->data = dev; - dev->proc_entry->proc_fops = &proc_dev_atm_operations; + dev->proc_entry->proc_fops = &proc_atm_dev_ops; dev->proc_entry->owner = THIS_MODULE; return 0; -fail0: +err_free_name: kfree(dev->proc_name); -fail1: +err_out: return error; } @@ -630,57 +934,65 @@ kfree(dev->proc_name); } +static struct atm_proc_entry { + char *name; + struct file_operations *proc_fops; + struct proc_dir_entry *dirent; +} atm_proc_ents[] = { + { .name = "devices", .proc_fops = &devices_seq_fops }, + { .name = "pvc", .proc_fops = &pvc_seq_fops }, + { .name = "svc", .proc_fops = &svc_seq_fops }, + { .name = "vc", .proc_fops = &vcc_seq_fops }, +#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) + { .name = "arp", .proc_fops = &arp_seq_fops }, +#endif +#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) + { .name = "lec", .proc_fops = &lec_seq_fops }, +#endif + { .name = NULL, .proc_fops = NULL } +}; + +static void atm_proc_dirs_remove(void) +{ + static struct atm_proc_entry *e; -#define CREATE_ENTRY(name) \ - name = create_proc_entry(#name,0,atm_proc_root); \ - if (!name) goto cleanup; \ - name->data = atm_##name##_info; \ - name->proc_fops = &proc_spec_atm_operations; \ - name->owner = THIS_MODULE - -static struct proc_dir_entry *devices = NULL, *pvc = NULL, - *svc = NULL, *arp = NULL, *lec = NULL, *vc = NULL; - -static void atm_proc_cleanup(void) -{ - if (devices) - remove_proc_entry("devices",atm_proc_root); - if (pvc) - remove_proc_entry("pvc",atm_proc_root); - if (svc) - remove_proc_entry("svc",atm_proc_root); - if (arp) - remove_proc_entry("arp",atm_proc_root); - if (lec) - remove_proc_entry("lec",atm_proc_root); - if (vc) - remove_proc_entry("vc",atm_proc_root); - remove_proc_entry("net/atm",NULL); + for (e = atm_proc_ents; e->name; e++) { + if (e->dirent) + remove_proc_entry(e->name, atm_proc_root); + } + remove_proc_entry("net/atm", NULL); } int __init atm_proc_init(void) { + static struct atm_proc_entry *e; + int ret; + atm_proc_root = proc_mkdir("net/atm",NULL); if (!atm_proc_root) - return -ENOMEM; - CREATE_ENTRY(devices); - CREATE_ENTRY(pvc); - CREATE_ENTRY(svc); - CREATE_ENTRY(vc); -#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE) - CREATE_ENTRY(arp); -#endif -#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) - CREATE_ENTRY(lec); -#endif - return 0; - -cleanup: - atm_proc_cleanup(); - return -ENOMEM; + goto err_out; + for (e = atm_proc_ents; e->name; e++) { + struct proc_dir_entry *dirent; + + dirent = create_proc_entry(e->name, S_IRUGO, atm_proc_root); + if (!dirent) + goto err_out_remove; + dirent->proc_fops = e->proc_fops; + dirent->owner = THIS_MODULE; + e->dirent = dirent; + } + ret = 0; +out: + return ret; + +err_out_remove: + atm_proc_dirs_remove(); +err_out: + ret = -ENOMEM; + goto out; } -void atm_proc_exit(void) +void __exit atm_proc_exit(void) { - atm_proc_cleanup(); + atm_proc_dirs_remove(); } diff -Nru a/net/atm/resources.c b/net/atm/resources.c --- a/net/atm/resources.c Thu Sep 11 23:03:14 2003 +++ b/net/atm/resources.c Thu Sep 11 23:03:14 2003 @@ -30,7 +30,7 @@ { struct atm_dev *dev; - dev = kmalloc(sizeof(*dev), GFP_ATOMIC); + dev = kmalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return NULL; memset(dev, 0, sizeof(*dev)); @@ -393,6 +393,35 @@ done: atm_dev_put(dev); return error; +} + +static __inline__ void *dev_get_idx(loff_t left) +{ + struct list_head *p; + + list_for_each(p, &atm_devs) { + if (!--left) + break; + } + return (p != &atm_devs) ? p : NULL; +} + +void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos) +{ + spin_lock(&atm_dev_lock); + return *pos ? dev_get_idx(*pos) : (void *) 1; +} + +void atm_dev_seq_stop(struct seq_file *seq, void *v) +{ + spin_unlock(&atm_dev_lock); +} + +void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + ++*pos; + v = (v == (void *)1) ? atm_devs.next : ((struct list_head *)v)->next; + return (v == &atm_devs) ? NULL : v; } diff -Nru a/net/atm/resources.h b/net/atm/resources.h --- a/net/atm/resources.h Thu Sep 11 23:03:13 2003 +++ b/net/atm/resources.h Thu Sep 11 23:03:13 2003 @@ -21,6 +21,11 @@ #include +void *atm_dev_seq_start(struct seq_file *seq, loff_t *pos); +void atm_dev_seq_stop(struct seq_file *seq, void *v); +void *atm_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos); + + int atm_proc_dev_register(struct atm_dev *dev); void atm_proc_dev_deregister(struct atm_dev *dev); diff -Nru a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c --- a/net/ax25/ax25_route.c Thu Sep 11 23:03:13 2003 +++ b/net/ax25/ax25_route.c Thu Sep 11 23:03:13 2003 @@ -281,8 +281,6 @@ #ifdef CONFIG_PROC_FS -#define AX25_PROC_START ((void *)1) - static void *ax25_rt_seq_start(struct seq_file *seq, loff_t *pos) { struct ax25_route *ax25_rt; @@ -290,7 +288,7 @@ read_lock(&ax25_route_lock); if (*pos == 0) - return AX25_PROC_START; + return SEQ_START_TOKEN; for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) { if (i == *pos) @@ -304,7 +302,7 @@ static void *ax25_rt_seq_next(struct seq_file *seq, void *v, loff_t *pos) { ++*pos; - return (v == AX25_PROC_START) ? ax25_route_list : + return (v == SEQ_START_TOKEN) ? ax25_route_list : ((struct ax25_route *) v)->next; } @@ -315,7 +313,7 @@ static int ax25_rt_seq_show(struct seq_file *seq, void *v) { - if (v == AX25_PROC_START) + if (v == SEQ_START_TOKEN) seq_puts(seq, "callsign dev mode digipeaters\n"); else { struct ax25_route *ax25_rt = v; diff -Nru a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c --- a/net/ax25/ax25_uid.c Thu Sep 11 23:03:11 2003 +++ b/net/ax25/ax25_uid.c Thu Sep 11 23:03:11 2003 @@ -144,8 +144,6 @@ #ifdef CONFIG_PROC_FS -#define AX25_PROC_START ((void *)1) - static void *ax25_uid_seq_start(struct seq_file *seq, loff_t *pos) { struct ax25_uid_assoc *pt; @@ -153,7 +151,7 @@ read_lock(&ax25_uid_lock); if (*pos == 0) - return AX25_PROC_START; + return SEQ_START_TOKEN; for (pt = ax25_uid_list; pt != NULL; pt = pt->next) { if (i == *pos) @@ -166,7 +164,7 @@ static void *ax25_uid_seq_next(struct seq_file *seq, void *v, loff_t *pos) { ++*pos; - return (v == AX25_PROC_START) ? ax25_uid_list : + return (v == SEQ_START_TOKEN) ? ax25_uid_list : ((struct ax25_uid_assoc *) v)->next; } @@ -177,7 +175,7 @@ static int ax25_uid_seq_show(struct seq_file *seq, void *v) { - if (v == AX25_PROC_START) + if (v == SEQ_START_TOKEN) seq_printf(seq, "Policy: %d\n", ax25_uid_policy); else { struct ax25_uid_assoc *pt = v; diff -Nru a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c --- a/net/bluetooth/af_bluetooth.c Thu Sep 11 23:03:11 2003 +++ b/net/bluetooth/af_bluetooth.c Thu Sep 11 23:03:11 2003 @@ -130,7 +130,6 @@ } sock_init_data(sock, sk); - sk_set_owner(sk, THIS_MODULE); INIT_LIST_HEAD(&bt_sk(sk)->accept_q); sk->sk_zapped = 0; diff -Nru a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c --- a/net/bluetooth/bnep/sock.c Thu Sep 11 23:03:14 2003 +++ b/net/bluetooth/bnep/sock.c Thu Sep 11 23:03:14 2003 @@ -175,6 +175,9 @@ if (!(sk = bt_sock_alloc(sock, PF_BLUETOOTH, 0, GFP_KERNEL))) return -ENOMEM; + + sk_set_owner(sk, THIS_MODULE); + sock->ops = &bnep_sock_ops; sock->state = SS_UNCONNECTED; diff -Nru a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c --- a/net/bluetooth/hci_sock.c Thu Sep 11 23:03:12 2003 +++ b/net/bluetooth/hci_sock.c Thu Sep 11 23:03:12 2003 @@ -587,6 +587,8 @@ if (!sk) return -ENOMEM; + sk_set_owner(sk, THIS_MODULE); + sock->state = SS_UNCONNECTED; sk->sk_state = BT_OPEN; diff -Nru a/net/bridge/br_forward.c b/net/bridge/br_forward.c --- a/net/bridge/br_forward.c Thu Sep 11 23:03:12 2003 +++ b/net/bridge/br_forward.c Thu Sep 11 23:03:12 2003 @@ -69,6 +69,7 @@ indev = skb->dev; skb->dev = to->dev; + skb->ip_summed = CHECKSUM_NONE; NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev, br_forward_finish); diff -Nru a/net/core/dev.c b/net/core/dev.c --- a/net/core/dev.c Thu Sep 11 23:03:12 2003 +++ b/net/core/dev.c Thu Sep 11 23:03:12 2003 @@ -841,7 +841,11 @@ * engine, but this requires more changes in devices. */ smp_mb__after_clear_bit(); /* Commit netif_running(). */ - netif_poll_disable(dev); + while (test_bit(__LINK_STATE_RX_SCHED, &dev->state)) { + /* No hurry. */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + } /* * Call the device specific close. This cannot fail. @@ -1840,13 +1844,13 @@ void *dev_seq_start(struct seq_file *seq, loff_t *pos) { read_lock(&dev_base_lock); - return *pos ? dev_get_idx(*pos - 1) : (void *)1; + return *pos ? dev_get_idx(*pos - 1) : SEQ_START_TOKEN; } void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) { ++*pos; - return v == (void *)1 ? dev_base : ((struct net_device *)v)->next; + return v == SEQ_START_TOKEN ? dev_base : ((struct net_device *)v)->next; } void dev_seq_stop(struct seq_file *seq, void *v) @@ -1886,7 +1890,7 @@ */ static int dev_seq_show(struct seq_file *seq, void *v) { - if (v == (void *)1) + if (v == SEQ_START_TOKEN) seq_puts(seq, "Inter-| Receive " " | Transmit\n" " face |bytes packets errs drop fifo frame " @@ -1990,26 +1994,21 @@ static int __init dev_proc_init(void) { - struct proc_dir_entry *p; int rc = -ENOMEM; - p = create_proc_entry("dev", S_IRUGO, proc_net); - if (!p) + if (!proc_net_fops_create("dev", S_IRUGO, &dev_seq_fops)) goto out; - p->proc_fops = &dev_seq_fops; - p = create_proc_entry("softnet_stat", S_IRUGO, proc_net); - if (!p) + if (!proc_net_fops_create("softnet_stat", S_IRUGO, &softnet_seq_fops)) goto out_dev; - p->proc_fops = &softnet_seq_fops; if (wireless_proc_init()) goto out_softnet; rc = 0; out: return rc; out_softnet: - remove_proc_entry("softnet_stat", proc_net); + proc_net_remove("softnet_stat"); out_dev: - remove_proc_entry("dev", proc_net); + proc_net_remove("dev"); goto out; } #else @@ -2755,7 +2754,6 @@ current->state = TASK_INTERRUPTIBLE; schedule_timeout(HZ / 4); - current->state = TASK_RUNNING; if (time_after(jiffies, warning_time + 10 * HZ)) { printk(KERN_EMERG "unregister_netdevice: " diff -Nru a/net/core/wireless.c b/net/core/wireless.c --- a/net/core/wireless.c Thu Sep 11 23:03:13 2003 +++ b/net/core/wireless.c Thu Sep 11 23:03:13 2003 @@ -458,7 +458,7 @@ */ static int wireless_seq_show(struct seq_file *seq, void *v) { - if (v == (void *)1) + if (v == SEQ_START_TOKEN) seq_printf(seq, "Inter-| sta-| Quality | Discarded " "packets | Missed | WE\n" " face | tus | link level noise | nwid " diff -Nru a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c --- a/net/decnet/af_decnet.c Thu Sep 11 23:03:12 2003 +++ b/net/decnet/af_decnet.c Thu Sep 11 23:03:12 2003 @@ -2146,14 +2146,14 @@ static void *dn_socket_seq_start(struct seq_file *seq, loff_t *pos) { - return *pos ? dn_socket_get_idx(seq, *pos - 1) : (void*)1; + return *pos ? dn_socket_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; } static void *dn_socket_seq_next(struct seq_file *seq, void *v, loff_t *pos) { void *rc; - if (v == (void*)1) { + if (v == SEQ_START_TOKEN) { rc = dn_socket_get_idx(seq, 0); goto out; } @@ -2169,7 +2169,7 @@ static void dn_socket_seq_stop(struct seq_file *seq, void *v) { - if (v && v != (void*)1) + if (v && v != SEQ_START_TOKEN) read_unlock_bh(&dn_hash_lock); } @@ -2269,7 +2269,7 @@ static int dn_socket_seq_show(struct seq_file *seq, void *v) { - if (v == (void*)1) { + if (v == SEQ_START_TOKEN) { seq_puts(seq, "Local Remote\n"); } else { dn_socket_format_entry(seq, v); diff -Nru a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c --- a/net/decnet/dn_dev.c Thu Sep 11 23:03:12 2003 +++ b/net/decnet/dn_dev.c Thu Sep 11 23:03:12 2003 @@ -1365,7 +1365,7 @@ read_unlock(&dev_base_lock); return dev; } - return (void*)1; + return SEQ_START_TOKEN; } static void *dn_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos) @@ -1373,7 +1373,7 @@ struct net_device *dev = v; loff_t one = 1; - if (v == (void*)1) { + if (v == SEQ_START_TOKEN) { dev = dn_dev_seq_start(seq, &one); } else { dev = dn_dev_get_next(seq, dev); @@ -1386,7 +1386,7 @@ static void dn_dev_seq_stop(struct seq_file *seq, void *v) { - if (v && v != (void*)1) + if (v && v != SEQ_START_TOKEN) read_unlock(&dev_base_lock); } @@ -1406,7 +1406,7 @@ static int dn_dev_seq_show(struct seq_file *seq, void *v) { - if (v == (void*)1) + if (v == SEQ_START_TOKEN) seq_puts(seq, "Name Flags T1 Timer1 T3 Timer3 BlkSize Pri State DevType Router Peer\n"); else { struct net_device *dev = v; diff -Nru a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c --- a/net/decnet/dn_neigh.c Thu Sep 11 23:03:13 2003 +++ b/net/decnet/dn_neigh.c Thu Sep 11 23:03:13 2003 @@ -604,7 +604,7 @@ static void *dn_neigh_seq_start(struct seq_file *seq, loff_t *pos) { - return *pos ? dn_neigh_get_idx(seq, *pos - 1) : (void*)1; + return *pos ? dn_neigh_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; } static void *dn_neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos) @@ -612,7 +612,7 @@ void *rc; - if (v == (void*)1) { + if (v == SEQ_START_TOKEN) { rc = dn_neigh_get_idx(seq, 0); goto out; } @@ -628,7 +628,7 @@ static void dn_neigh_seq_stop(struct seq_file *seq, void *v) { - if (v && v != (void*)1) + if (v && v != SEQ_START_TOKEN) read_unlock_bh(&dn_neigh_table.lock); } @@ -653,7 +653,7 @@ static int dn_neigh_seq_show(struct seq_file *seq, void *v) { - if (v == (void*)1) { + if (v == SEQ_START_TOKEN) { seq_puts(seq, "Addr Flags State Use Blksize Dev\n"); } else { dn_neigh_format_entry(seq, v); diff -Nru a/net/ipv4/arp.c b/net/ipv4/arp.c --- a/net/ipv4/arp.c Thu Sep 11 23:03:13 2003 +++ b/net/ipv4/arp.c Thu Sep 11 23:03:13 2003 @@ -1275,7 +1275,7 @@ static void *arp_seq_start(struct seq_file *seq, loff_t *pos) { - return *pos ? arp_get_idx(seq, *pos - 1) : (void *)1; + return *pos ? arp_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; } static void *arp_seq_next(struct seq_file *seq, void *v, loff_t *pos) @@ -1283,7 +1283,7 @@ void *rc; struct arp_iter_state* state; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { rc = arp_get_idx(seq, 0); goto out; } @@ -1306,7 +1306,7 @@ { struct arp_iter_state* state = seq->private; - if (!state->is_pneigh && v != (void *)1) + if (!state->is_pneigh && v != SEQ_START_TOKEN) read_unlock_bh(&arp_tbl.lock); } @@ -1359,7 +1359,7 @@ static int arp_seq_show(struct seq_file *seq, void *v) { - if (v == (void *)1) + if (v == SEQ_START_TOKEN) seq_puts(seq, "IP address HW type Flags " "HW address Mask Device\n"); else { @@ -1416,14 +1416,9 @@ static int __init arp_proc_init(void) { - int rc = 0; - struct proc_dir_entry *p = create_proc_entry("arp", S_IRUGO, proc_net); - - if (p) - p->proc_fops = &arp_seq_fops; - else - rc = -ENOMEM; - return rc; + if (!proc_net_fops_create("arp", S_IRUGO, &arp_seq_fops)) + return -ENOMEM; + return 0; } #else /* CONFIG_PROC_FS */ diff -Nru a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c --- a/net/ipv4/fib_hash.c Thu Sep 11 23:03:12 2003 +++ b/net/ipv4/fib_hash.c Thu Sep 11 23:03:12 2003 @@ -979,14 +979,14 @@ read_lock(&fib_hash_lock); if (ip_fib_main_table) - v = *pos ? fib_get_next(seq) : (void *)1; + v = *pos ? fib_get_next(seq) : SEQ_START_TOKEN; return v; } static void *fib_seq_next(struct seq_file *seq, void *v, loff_t *pos) { ++*pos; - return v == (void *)1 ? fib_get_first(seq) : fib_get_next(seq); + return v == SEQ_START_TOKEN ? fib_get_first(seq) : fib_get_next(seq); } static void fib_seq_stop(struct seq_file *seq, void *v) @@ -1025,7 +1025,7 @@ struct fib_node *f; struct fib_info *fi; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { seq_printf(seq, "%-127s\n", "Iface\tDestination\tGateway " "\tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU" "\tWindow\tIRTT"); @@ -1096,19 +1096,13 @@ int __init fib_proc_init(void) { - struct proc_dir_entry *p; - int rc = 0; - - p = create_proc_entry("route", S_IRUGO, proc_net); - if (p) - p->proc_fops = &fib_seq_fops; - else - rc = -ENOMEM; - return rc; + if (!proc_net_fops_create("route", S_IRUGO, &fib_seq_fops)) + return -ENOMEM; + return 0; } void __init fib_proc_exit(void) { - remove_proc_entry("route", proc_net); + proc_net_remove("route"); } #endif /* CONFIG_PROC_FS */ diff -Nru a/net/ipv4/icmp.c b/net/ipv4/icmp.c --- a/net/ipv4/icmp.c Thu Sep 11 23:03:14 2003 +++ b/net/ipv4/icmp.c Thu Sep 11 23:03:14 2003 @@ -669,7 +669,7 @@ printk(KERN_WARNING "%u.%u.%u.%u sent an invalid ICMP " "type %u, code %u " "error to a broadcast: %u.%u.%u.%u on %s\n", - NIPQUAD(iph->saddr), + NIPQUAD(skb->nh.iph->saddr), icmph->type, icmph->code, NIPQUAD(iph->daddr), skb->dev->name); diff -Nru a/net/ipv4/igmp.c b/net/ipv4/igmp.c --- a/net/ipv4/igmp.c Thu Sep 11 23:03:14 2003 +++ b/net/ipv4/igmp.c Thu Sep 11 23:03:14 2003 @@ -2162,13 +2162,13 @@ static void *igmp_mc_seq_start(struct seq_file *seq, loff_t *pos) { read_lock(&dev_base_lock); - return *pos ? igmp_mc_get_idx(seq, *pos) : (void *)1; + return *pos ? igmp_mc_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; } static void *igmp_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct ip_mc_list *im; - if (v == (void *)1) + if (v == SEQ_START_TOKEN) im = igmp_mc_get_first(seq); else im = igmp_mc_get_next(seq, v); @@ -2190,7 +2190,7 @@ static int igmp_mc_seq_show(struct seq_file *seq, void *v) { - if (v == (void *)1) + if (v == SEQ_START_TOKEN) seq_printf(seq, "Idx\tDevice : Count Querier\tGroup Users Timer\tReporter\n"); else { @@ -2337,13 +2337,13 @@ static void *igmp_mcf_seq_start(struct seq_file *seq, loff_t *pos) { read_lock(&dev_base_lock); - return *pos ? igmp_mcf_get_idx(seq, *pos) : (void *)1; + return *pos ? igmp_mcf_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; } static void *igmp_mcf_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct ip_sf_list *psf; - if (v == (void *)1) + if (v == SEQ_START_TOKEN) psf = igmp_mcf_get_first(seq); else psf = igmp_mcf_get_next(seq, v); @@ -2372,7 +2372,7 @@ struct ip_sf_list *psf = (struct ip_sf_list *)v; struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq); - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { seq_printf(seq, "%3s %6s " "%10s %10s %6s %6s\n", "Idx", @@ -2430,15 +2430,8 @@ int __init igmp_mc_proc_init(void) { - struct proc_dir_entry *p; - - p = create_proc_entry("igmp", S_IRUGO, proc_net); - if (p) - p->proc_fops = &igmp_mc_seq_fops; - - p = create_proc_entry("mcfilter", S_IRUGO, proc_net); - if (p) - p->proc_fops = &igmp_mcf_seq_fops; + proc_net_fops_create("igmp", S_IRUGO, &igmp_mc_seq_fops); + proc_net_fops_create("mcfilter", S_IRUGO, &igmp_mcf_seq_fops); return 0; } #endif diff -Nru a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c --- a/net/ipv4/ip_input.c Thu Sep 11 23:03:11 2003 +++ b/net/ipv4/ip_input.c Thu Sep 11 23:03:11 2003 @@ -201,6 +201,7 @@ #ifdef CONFIG_NETFILTER_DEBUG nf_debug_ip_local_deliver(skb); + skb->nf_debug =3D 0; #endif /*CONFIG_NETFILTER_DEBUG*/ __skb_pull(skb, ihl); 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 Sep 11 23:03:12 2003 +++ b/net/ipv4/netfilter/ip_nat_tftp.c Thu Sep 11 23:03:12 2003 @@ -30,7 +30,7 @@ #include MODULE_AUTHOR("Magnus Boden "); -MODULE_DESCRIPTION("tfpt NAT helper"); +MODULE_DESCRIPTION("tftp NAT helper"); MODULE_LICENSE("GPL"); #define MAX_PORTS 8 diff -Nru a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c --- a/net/ipv4/netfilter/ipt_MASQUERADE.c Thu Sep 11 23:03:13 2003 +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c Thu Sep 11 23:03:13 2003 @@ -130,57 +130,35 @@ } static inline int -device_cmp(const struct ip_conntrack *i, void *ifindex) +device_cmp(const struct ip_conntrack *i, void *_ina) { - int ret; + int ret = 0; + struct in_ifaddr *ina = _ina; READ_LOCK(&masq_lock); - ret = (i->nat.masq_index == (int)(long)ifindex); + /* If it's masquerading out this interface with a different address, + or we don't know the new address of this interface. */ + if (i->nat.masq_index == ina->ifa_dev->dev->ifindex + && i->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip != ina->ifa_address) + ret = 1; READ_UNLOCK(&masq_lock); return ret; } -static int masq_device_event(struct notifier_block *this, - unsigned long event, - void *ptr) -{ - struct net_device *dev = ptr; - - if (event == NETDEV_DOWN) { - /* Device was downed. Search entire table for - conntracks which were associated with that device, - and forget them. */ - IP_NF_ASSERT(dev->ifindex != 0); - - ip_ct_selective_cleanup(device_cmp, (void *)(long)dev->ifindex); - } - - return NOTIFY_DONE; -} - static int masq_inet_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev; - - if (event == NETDEV_DOWN) { - /* IP address was deleted. Search entire table for - conntracks which were associated with that device, - and forget them. */ - IP_NF_ASSERT(dev->ifindex != 0); - - ip_ct_selective_cleanup(device_cmp, (void *)(long)dev->ifindex); - } + /* For some configurations, interfaces often come back with + * the same address. If not, clean up old conntrack + * entries. */ + if (event == NETDEV_UP) + ip_ct_selective_cleanup(device_cmp, ptr); return NOTIFY_DONE; } -static struct notifier_block masq_dev_notifier = { - .notifier_call = masq_device_event, -}; - static struct notifier_block masq_inet_notifier = { .notifier_call = masq_inet_event, }; @@ -198,12 +176,9 @@ ret = ipt_register_target(&masquerade); - if (ret == 0) { - /* Register for device down reports */ - register_netdevice_notifier(&masq_dev_notifier); + if (ret == 0) /* Register IP address change reports */ register_inetaddr_notifier(&masq_inet_notifier); - } return ret; } @@ -211,7 +186,6 @@ static void __exit fini(void) { ipt_unregister_target(&masquerade); - unregister_netdevice_notifier(&masq_dev_notifier); unregister_inetaddr_notifier(&masq_inet_notifier); } diff -Nru a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c --- a/net/ipv4/netfilter/ipt_REJECT.c Thu Sep 11 23:03:13 2003 +++ b/net/ipv4/netfilter/ipt_REJECT.c Thu Sep 11 23:03:13 2003 @@ -84,45 +84,34 @@ static void send_reset(struct sk_buff *oldskb, int local) { struct sk_buff *nskb; - struct tcphdr *otcph, *tcph; + struct tcphdr otcph, *tcph; struct rtable *rt; - unsigned int otcplen; u_int16_t tmp_port; u_int32_t tmp_addr; int needs_ack; int hh_len; - /* IP header checks: fragment, too short. */ - if (oldskb->nh.iph->frag_off & htons(IP_OFFSET) - || oldskb->len < (oldskb->nh.iph->ihl<<2) + sizeof(struct tcphdr)) + /* IP header checks: fragment. */ + if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)) return; - otcph = (struct tcphdr *)((u_int32_t*)oldskb->nh.iph + oldskb->nh.iph->ihl); - otcplen = oldskb->len - oldskb->nh.iph->ihl*4; - if (skb_copy_bits(oldskb, oldskb->nh.iph->ihl*4, - otcph, sizeof(*otcph)) < 0) - return; + &otcph, sizeof(otcph)) < 0) + return; /* No RST for RST. */ - if (otcph->rst) - return; - - /* Check checksum. */ - if (tcp_v4_check(otcph, otcplen, oldskb->nh.iph->saddr, - oldskb->nh.iph->daddr, - csum_partial((char *)otcph, otcplen, 0)) != 0) + if (otcph.rst) return; + /* FIXME: Check checksum --RR */ if ((rt = route_reverse(oldskb, local)) == NULL) return; hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15; - /* Copy skb (even if skb is about to be dropped, we can't just - clone it because there may be other things, such as tcpdump, - interested in it). We also need to expand headroom in case - hh_len of incoming interface < hh_len of outgoing interface */ + /* We need a linear, writeable skb. We also need to expand + headroom in case hh_len of incoming interface < hh_len of + outgoing interface */ nskb = skb_copy_expand(oldskb, hh_len, skb_tailroom(oldskb), GFP_ATOMIC); if (!nskb) { @@ -163,12 +152,13 @@ if (tcph->ack) { needs_ack = 0; - tcph->seq = otcph->ack_seq; + tcph->seq = otcph.ack_seq; tcph->ack_seq = 0; } else { needs_ack = 1; - tcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn + otcph->fin - + otcplen - (otcph->doff<<2)); + tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin + + oldskb->len - oldskb->nh.iph->ihl*4 + - (otcph.doff<<2)); tcph->seq = 0; } diff -Nru a/net/ipv4/proc.c b/net/ipv4/proc.c --- a/net/ipv4/proc.c Thu Sep 11 23:03:11 2003 +++ b/net/ipv4/proc.c Thu Sep 11 23:03:11 2003 @@ -238,28 +238,21 @@ int __init ip_misc_proc_init(void) { int rc = 0; - struct proc_dir_entry *p; - p = create_proc_entry("netstat", S_IRUGO, proc_net); - if (!p) + if (!proc_net_fops_create("netstat", S_IRUGO, &netstat_seq_fops)) goto out_netstat; - p->proc_fops = &netstat_seq_fops; - p = create_proc_entry("snmp", S_IRUGO, proc_net); - if (!p) + if (!proc_net_fops_create("snmp", S_IRUGO, &snmp_seq_fops)) goto out_snmp; - p->proc_fops = &snmp_seq_fops; - p = create_proc_entry("sockstat", S_IRUGO, proc_net); - if (!p) + if (!proc_net_fops_create("sockstat", S_IRUGO, &sockstat_seq_fops)) goto out_sockstat; - p->proc_fops = &sockstat_seq_fops; out: return rc; out_sockstat: - remove_proc_entry("snmp", proc_net); + proc_net_remove("snmp"); out_snmp: - remove_proc_entry("netstat", proc_net); + proc_net_remove("netstat"); out_netstat: rc = -ENOMEM; goto out; diff -Nru a/net/ipv4/raw.c b/net/ipv4/raw.c --- a/net/ipv4/raw.c Thu Sep 11 23:03:12 2003 +++ b/net/ipv4/raw.c Thu Sep 11 23:03:12 2003 @@ -736,14 +736,14 @@ static void *raw_seq_start(struct seq_file *seq, loff_t *pos) { read_lock(&raw_v4_lock); - return *pos ? raw_get_idx(seq, *pos) : (void *)1; + return *pos ? raw_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; } static void *raw_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct sock *sk; - if (v == (void *)1) + if (v == SEQ_START_TOKEN) sk = raw_get_first(seq); else sk = raw_get_next(seq, v); @@ -778,7 +778,7 @@ { char tmpbuf[129]; - if (v == (void *)1) + if (v == SEQ_START_TOKEN) seq_printf(seq, "%-127s\n", " sl local_address rem_address st tx_queue " "rx_queue tr tm->when retrnsmt uid timeout " @@ -831,19 +831,13 @@ int __init raw_proc_init(void) { - struct proc_dir_entry *p; - int rc = 0; - - p = create_proc_entry("raw", S_IRUGO, proc_net); - if (p) - p->proc_fops = &raw_seq_fops; - else - rc = -ENOMEM; - return rc; + if (!proc_net_fops_create("raw", S_IRUGO, &raw_seq_fops)) + return -ENOMEM; + return 0; } void __init raw_proc_exit(void) { - remove_proc_entry("raw", proc_net); + proc_net_remove("raw"); } #endif /* CONFIG_PROC_FS */ diff -Nru a/net/ipv4/route.c b/net/ipv4/route.c --- a/net/ipv4/route.c Thu Sep 11 23:03:14 2003 +++ b/net/ipv4/route.c Thu Sep 11 23:03:14 2003 @@ -259,14 +259,14 @@ static void *rt_cache_seq_start(struct seq_file *seq, loff_t *pos) { - return *pos ? rt_cache_get_idx(seq, *pos) : (void *)1; + return *pos ? rt_cache_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; } static void *rt_cache_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct rtable *r = NULL; - if (v == (void *)1) + if (v == SEQ_START_TOKEN) r = rt_cache_get_first(seq); else r = rt_cache_get_next(seq, v); @@ -276,13 +276,13 @@ static void rt_cache_seq_stop(struct seq_file *seq, void *v) { - if (v && v != (void *)1) + if (v && v != SEQ_START_TOKEN) rcu_read_unlock(); } static int rt_cache_seq_show(struct seq_file *seq, void *v) { - if (v == (void *)1) + if (v == SEQ_START_TOKEN) seq_printf(seq, "%-127s\n", "Iface\tDestination\tGateway \tFlags\t\tRefCnt\tUse\t" "Metric\tSource\t\tMTU\tWindow\tIRTT\tTOS\tHHRef\t" diff -Nru a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c --- a/net/ipv4/tcp_ipv4.c Thu Sep 11 23:03:12 2003 +++ b/net/ipv4/tcp_ipv4.c Thu Sep 11 23:03:12 2003 @@ -2351,7 +2351,7 @@ static void *tcp_seq_start(struct seq_file *seq, loff_t *pos) { - return *pos ? tcp_get_idx(seq, *pos - 1) : (void *)1; + return *pos ? tcp_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; } static void *tcp_seq_next(struct seq_file *seq, void *v, loff_t *pos) @@ -2359,7 +2359,7 @@ void *rc = NULL; struct tcp_iter_state* st; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { rc = tcp_get_idx(seq, 0); goto out; } @@ -2397,7 +2397,7 @@ read_unlock_bh(&tp->syn_wait_lock); } case TCP_SEQ_STATE_LISTENING: - if (v != (void *)1) + if (v != SEQ_START_TOKEN) tcp_listen_unlock(); break; case TCP_SEQ_STATE_TIME_WAIT: @@ -2413,11 +2413,15 @@ { struct tcp_seq_afinfo *afinfo = PDE(inode)->data; struct seq_file *seq; - int rc = -ENOMEM; - struct tcp_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL); + struct tcp_iter_state *s; + int rc; + if (unlikely(afinfo == NULL)) + return -EINVAL; + + s = kmalloc(sizeof(*s), GFP_KERNEL); if (!s) - goto out; + return -ENOMEM; memset(s, 0, sizeof(*s)); s->family = afinfo->family; s->seq_ops.start = tcp_seq_start; @@ -2450,11 +2454,10 @@ afinfo->seq_fops->llseek = seq_lseek; afinfo->seq_fops->release = seq_release_private; - p = create_proc_entry(afinfo->name, S_IRUGO, proc_net); - if (p) { + p = proc_net_fops_create(afinfo->name, S_IRUGO, afinfo->seq_fops); + if (p) p->data = afinfo; - p->proc_fops = afinfo->seq_fops; - } else + else rc = -ENOMEM; return rc; } @@ -2463,7 +2466,7 @@ { if (!afinfo) return; - remove_proc_entry(afinfo->name, proc_net); + proc_net_remove(afinfo->name); memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops)); } @@ -2559,7 +2562,7 @@ struct tcp_iter_state* st; char tmpbuf[TMPSZ + 1]; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { seq_printf(seq, "%-*s\n", TMPSZ - 1, " sl local_address rem_address st tx_queue " "rx_queue tr tm->when retrnsmt uid timeout " diff -Nru a/net/ipv4/udp.c b/net/ipv4/udp.c --- a/net/ipv4/udp.c Thu Sep 11 23:03:11 2003 +++ b/net/ipv4/udp.c Thu Sep 11 23:03:11 2003 @@ -1460,11 +1460,10 @@ afinfo->seq_fops->llseek = seq_lseek; afinfo->seq_fops->release = seq_release_private; - p = create_proc_entry(afinfo->name, S_IRUGO, proc_net); - if (p) { + p = proc_net_fops_create(afinfo->name, S_IRUGO, afinfo->seq_fops); + if (p) p->data = afinfo; - p->proc_fops = afinfo->seq_fops; - } else + else rc = -ENOMEM; return rc; } @@ -1473,7 +1472,7 @@ { if (!afinfo) return; - remove_proc_entry(afinfo->name, proc_net); + proc_net_remove(afinfo->name); memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops)); } @@ -1497,7 +1496,7 @@ static int udp4_seq_show(struct seq_file *seq, void *v) { - if (v == (void *)1) + if (v == SEQ_START_TOKEN) seq_printf(seq, "%-127s\n", " sl local_address rem_address st tx_queue " "rx_queue tr tm->when retrnsmt uid timeout " diff -Nru a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c --- a/net/ipv6/addrconf.c Thu Sep 11 23:03:13 2003 +++ b/net/ipv6/addrconf.c Thu Sep 11 23:03:13 2003 @@ -2149,59 +2149,65 @@ int bucket; }; -static inline struct inet6_ifaddr *if6_get_bucket(struct seq_file *seq, loff_t *pos) +static struct inet6_ifaddr *if6_get_first(struct seq_file *seq) { - int i; struct inet6_ifaddr *ifa = NULL; - loff_t l = *pos; struct if6_iter_state *state = seq->private; - for (; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) - for (i = 0, ifa = inet6_addr_lst[state->bucket]; ifa; ++i, ifa=ifa->lst_next) { - if (l--) - continue; - *pos = i; - goto out; - } -out: + for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { + ifa = inet6_addr_lst[state->bucket]; + if (ifa) + break; + } + return ifa; +} + +static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct inet6_ifaddr *ifa) +{ + struct if6_iter_state *state = seq->private; + + ifa = ifa->lst_next; +try_again: + if (!ifa && ++state->bucket < IN6_ADDR_HSIZE) { + ifa = inet6_addr_lst[state->bucket]; + goto try_again; + } return ifa; } +static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos) +{ + struct inet6_ifaddr *ifa = if6_get_first(seq); + + if (ifa) + while(pos && (ifa = if6_get_next(seq, ifa)) != NULL) + --pos; + return pos ? NULL : ifa; +} + static void *if6_seq_start(struct seq_file *seq, loff_t *pos) { read_lock_bh(&addrconf_hash_lock); - return *pos ? if6_get_bucket(seq, pos) : (void *)1; + return if6_get_idx(seq, *pos); } static void *if6_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct inet6_ifaddr *ifa; - struct if6_iter_state *state; - - if (v == (void *)1) { - ifa = if6_get_bucket(seq, pos); - goto out; - } - - state = seq->private; - - ifa = v; - ifa = ifa->lst_next; - if (ifa) - goto out; - if (++state->bucket >= IN6_ADDR_HSIZE) - goto out; - - *pos = 0; - ifa = if6_get_bucket(seq, pos); -out: + ifa = if6_get_next(seq, v); ++*pos; return ifa; } -static inline void if6_iface_seq_show(struct seq_file *seq, struct inet6_ifaddr *ifp) +static void if6_seq_stop(struct seq_file *seq, void *v) { + read_unlock_bh(&addrconf_hash_lock); +} + +static int if6_seq_show(struct seq_file *seq, void *v) +{ + struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)v; seq_printf(seq, "%04x%04x%04x%04x%04x%04x%04x%04x %02x %02x %02x %02x %8s\n", NIP6(ifp->addr), @@ -2210,22 +2216,9 @@ ifp->scope, ifp->flags, ifp->idev->dev->name); -} - -static int if6_seq_show(struct seq_file *seq, void *v) -{ - if (v == (void *)1) - return 0; - else - if6_iface_seq_show(seq, v); return 0; } -static void if6_seq_stop(struct seq_file *seq, void *v) -{ - read_unlock_bh(&addrconf_hash_lock); -} - static struct seq_operations if6_seq_ops = { .start = if6_seq_start, .next = if6_seq_next, @@ -2266,16 +2259,11 @@ int __init if6_proc_init(void) { - struct proc_dir_entry *p; - int rc = 0; - - p = create_proc_entry("if_inet6", S_IRUGO, proc_net); - if (p) - p->proc_fops = &if6_fops; - else - rc = -ENOMEM; - return rc; + if (!proc_net_fops_create("if_inet6", S_IRUGO, &if6_fops)) + return -ENOMEM; + return 0; } + void if6_proc_exit(void) { proc_net_remove("if_inet6"); diff -Nru a/net/ipv6/anycast.c b/net/ipv6/anycast.c --- a/net/ipv6/anycast.c Thu Sep 11 23:03:11 2003 +++ b/net/ipv6/anycast.c Thu Sep 11 23:03:11 2003 @@ -505,7 +505,7 @@ static void *ac6_seq_start(struct seq_file *seq, loff_t *pos) { read_lock(&dev_base_lock); - return *pos ? ac6_get_idx(seq, *pos) : ac6_get_first(seq); + return ac6_get_idx(seq, *pos); } static void *ac6_seq_next(struct seq_file *seq, void *v, loff_t *pos) @@ -581,11 +581,9 @@ int __init ac6_proc_init(void) { - struct proc_dir_entry *p; + if (!proc_net_fops_create("anycast6", S_IRUGO, &ac6_seq_fops)) + return -ENOMEM; - p = create_proc_entry("anycast6", S_IRUGO, proc_net); - if (p) - p->proc_fops = &ac6_seq_fops; return 0; } diff -Nru a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c --- a/net/ipv6/ip6_flowlabel.c Thu Sep 11 23:03:11 2003 +++ b/net/ipv6/ip6_flowlabel.c Thu Sep 11 23:03:11 2003 @@ -603,14 +603,14 @@ static void *ip6fl_seq_start(struct seq_file *seq, loff_t *pos) { read_lock_bh(&ip6_fl_lock); - return *pos ? ip6fl_get_idx(seq, *pos) : (void *)1; + return *pos ? ip6fl_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; } static void *ip6fl_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct ip6_flowlabel *fl; - if (v == (void *)1) + if (v == SEQ_START_TOKEN) fl = ip6fl_get_first(seq); else fl = ip6fl_get_next(seq, v); @@ -644,7 +644,7 @@ static int ip6fl_seq_show(struct seq_file *seq, void *v) { - if (v == (void *)1) + if (v == SEQ_START_TOKEN) seq_printf(seq, "Label S Owner Users Linger Expires " "Dst Opt\n"); else @@ -695,12 +695,7 @@ void ip6_flowlabel_init() { #ifdef CONFIG_PROC_FS - struct proc_dir_entry *p; -#endif -#ifdef CONFIG_PROC_FS - p = create_proc_entry("ip6_flowlabel", S_IRUGO, proc_net); - if (p) - p->proc_fops = &ip6fl_seq_fops; + proc_net_fops_create("ip6_flowlabel", S_IRUGO, &ip6fl_seq_fops); #endif } diff -Nru a/net/ipv6/mcast.c b/net/ipv6/mcast.c --- a/net/ipv6/mcast.c Thu Sep 11 23:03:13 2003 +++ b/net/ipv6/mcast.c Thu Sep 11 23:03:13 2003 @@ -2119,7 +2119,7 @@ static void *igmp6_mc_seq_start(struct seq_file *seq, loff_t *pos) { read_lock(&dev_base_lock); - return *pos ? igmp6_mc_get_idx(seq, *pos) : igmp6_mc_get_first(seq); + return igmp6_mc_get_idx(seq, *pos); } static void *igmp6_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos) @@ -2278,13 +2278,13 @@ static void *igmp6_mcf_seq_start(struct seq_file *seq, loff_t *pos) { read_lock(&dev_base_lock); - return *pos ? igmp6_mcf_get_idx(seq, *pos) : (void *)1; + return *pos ? igmp6_mcf_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; } static void *igmp6_mcf_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct ip6_sf_list *psf; - if (v == (void *)1) + if (v == SEQ_START_TOKEN) psf = igmp6_mcf_get_first(seq); else psf = igmp6_mcf_get_next(seq, v); @@ -2313,7 +2313,7 @@ struct ip6_sf_list *psf = (struct ip6_sf_list *)v; struct igmp6_mcf_iter_state *state = igmp6_mcf_seq_private(seq); - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { seq_printf(seq, "%3s %6s " "%32s %32s %6s %6s\n", "Idx", @@ -2378,9 +2378,6 @@ struct ipv6_pinfo *np; struct sock *sk; int err; -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *p; -#endif err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &igmp6_socket); if (err < 0) { @@ -2399,12 +2396,8 @@ np->hop_limit = 1; #ifdef CONFIG_PROC_FS - p = create_proc_entry("igmp6", S_IRUGO, proc_net); - if (p) - p->proc_fops = &igmp6_mc_seq_fops; - p = create_proc_entry("mcfilter6", S_IRUGO, proc_net); - if (p) - p->proc_fops = &igmp6_mcf_seq_fops; + proc_net_fops_create("igmp6", S_IRUGO, &igmp6_mc_seq_fops); + proc_net_fops_create("mcfilter6", S_IRUGO, &igmp6_mcf_seq_fops); #endif return 0; @@ -2414,6 +2407,7 @@ { sock_release(igmp6_socket); igmp6_socket = NULL; /* for safety */ + #ifdef CONFIG_PROC_FS proc_net_remove("mcfilter6"); proc_net_remove("igmp6"); diff -Nru a/net/ipv6/proc.c b/net/ipv6/proc.c --- a/net/ipv6/proc.c Thu Sep 11 23:03:12 2003 +++ b/net/ipv6/proc.c Thu Sep 11 23:03:12 2003 @@ -32,7 +32,6 @@ #ifdef CONFIG_PROC_FS static struct proc_dir_entry *proc_net_devsnmp6; -#endif static int fold_prot_inuse(struct proto *proto) { @@ -58,7 +57,6 @@ return 0; } - struct snmp6_item { char *name; @@ -221,9 +219,7 @@ int snmp6_register_dev(struct inet6_dev *idev) { int err = -ENOMEM; -#ifdef CONFIG_PROC_FS struct proc_dir_entry *p; -#endif if (!idev || !idev->dev) return -EINVAL; @@ -232,7 +228,6 @@ __alignof__(struct icmpv6_mib)) < 0) goto err_icmp; -#ifdef CONFIG_PROC_FS if (!proc_net_devsnmp6) { err = -ENOENT; goto err_proc; @@ -244,27 +239,22 @@ p->proc_fops = &snmp6_seq_fops; idev->stats.proc_dir_entry = p; -#endif return 0; -#ifdef CONFIG_PROC_FS err_proc: snmp6_mib_free((void **)idev->stats.icmpv6); -#endif err_icmp: return err; } int snmp6_unregister_dev(struct inet6_dev *idev) { -#ifdef CONFIG_PROC_FS if (!proc_net_devsnmp6) return -ENOENT; if (!idev || !idev->stats.proc_dir_entry) return -EINVAL; remove_proc_entry(idev->stats.proc_dir_entry->name, proc_net_devsnmp6); -#endif snmp6_mib_free((void **)idev->stats.icmpv6); return 0; @@ -273,21 +263,16 @@ int __init ipv6_misc_proc_init(void) { int rc = 0; - struct proc_dir_entry *p; - p = create_proc_entry("snmp6", S_IRUGO, proc_net); - if (!p) + if (!proc_net_fops_create("snmp6", S_IRUGO, &snmp6_seq_fops)) goto proc_snmp6_fail; - else - p->proc_fops = &snmp6_seq_fops; + proc_net_devsnmp6 = proc_mkdir("dev_snmp6", proc_net); if (!proc_net_devsnmp6) goto proc_dev_snmp6_fail; - p = create_proc_entry("sockstat6", S_IRUGO, proc_net); - if (!p) + + if (!proc_net_fops_create("sockstat6", S_IRUGO, &sockstat6_seq_fops)) goto proc_sockstat6_fail; - else - p->proc_fops = &sockstat6_seq_fops; out: return rc; @@ -306,4 +291,32 @@ proc_net_remove("dev_snmp6"); proc_net_remove("snmp6"); } + +#else /* CONFIG_PROC_FS */ + + +int snmp6_register_dev(struct inet6_dev *idev) +{ + int err = -ENOMEM; + + if (!idev || !idev->dev) + return -EINVAL; + + if (snmp6_mib_init((void **)idev->stats.icmpv6, sizeof(struct icmpv6_mib), + __alignof__(struct icmpv6_mib)) < 0) + goto err_icmp; + + return 0; + +err_icmp: + return err; +} + +int snmp6_unregister_dev(struct inet6_dev *idev) +{ + snmp6_mib_free((void **)idev->stats.icmpv6); + return 0; +} + +#endif diff -Nru a/net/ipv6/raw.c b/net/ipv6/raw.c --- a/net/ipv6/raw.c Thu Sep 11 23:03:12 2003 +++ b/net/ipv6/raw.c Thu Sep 11 23:03:12 2003 @@ -961,14 +961,14 @@ static void *raw6_seq_start(struct seq_file *seq, loff_t *pos) { read_lock(&raw_v6_lock); - return *pos ? raw6_get_idx(seq, *pos) : (void *)1; + return *pos ? raw6_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; } static void *raw6_seq_next(struct seq_file *seq, void *v, loff_t *pos) { struct sock *sk; - if (v == (void *)1) + if (v == SEQ_START_TOKEN) sk = raw6_get_first(seq); else sk = raw6_get_next(seq, v); @@ -1010,7 +1010,7 @@ static int raw6_seq_show(struct seq_file *seq, void *v) { - if (v == (void *)1) + if (v == SEQ_START_TOKEN) seq_printf(seq, " sl " "local_address " @@ -1059,12 +1059,8 @@ int __init raw6_proc_init(void) { - struct proc_dir_entry *p = create_proc_entry("raw6", S_IRUGO, proc_net); - - if (!p) + if (!proc_net_fops_create("raw6", S_IRUGO, &raw6_seq_fops)) return -ENOMEM; - p->proc_fops = &raw6_seq_fops; - return 0; } diff -Nru a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c --- a/net/ipv6/tcp_ipv6.c Thu Sep 11 23:03:12 2003 +++ b/net/ipv6/tcp_ipv6.c Thu Sep 11 23:03:12 2003 @@ -2023,11 +2023,12 @@ atomic_read(&tw->tw_refcnt), tw); } +#ifdef CONFIG_PROC_FS static int tcp6_seq_show(struct seq_file *seq, void *v) { struct tcp_iter_state *st; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { seq_printf(seq, " sl " "local_address " @@ -2072,6 +2073,7 @@ { tcp_proc_unregister(&tcp6_seq_afinfo); } +#endif struct proto tcpv6_prot = { .name = "TCPv6", diff -Nru a/net/ipv6/udp.c b/net/ipv6/udp.c --- a/net/ipv6/udp.c Thu Sep 11 23:03:13 2003 +++ b/net/ipv6/udp.c Thu Sep 11 23:03:13 2003 @@ -1113,7 +1113,7 @@ static int udp6_seq_show(struct seq_file *seq, void *v) { - if (v == (void *)1) + if (v == SEQ_START_TOKEN) seq_printf(seq, " sl " "local_address " diff -Nru a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c --- a/net/ipx/ipx_proc.c Thu Sep 11 23:03:11 2003 +++ b/net/ipx/ipx_proc.c Thu Sep 11 23:03:11 2003 @@ -39,7 +39,7 @@ loff_t l = *pos; spin_lock_bh(&ipx_interfaces_lock); - return l ? ipx_get_interface_idx(--l) : (void *)1; + return l ? ipx_get_interface_idx(--l) : SEQ_START_TOKEN; } static void *ipx_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos) @@ -47,7 +47,7 @@ struct ipx_interface *i; ++*pos; - if (v == (void *)1) + if (v == SEQ_START_TOKEN) i = ipx_interfaces_head(); else i = ipx_interfaces_next(v); @@ -63,7 +63,7 @@ { struct ipx_interface *i; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { seq_puts(seq, "Network Node_Address Primary Device " "Frame_Type"); #ifdef IPX_REFCNT_DEBUG @@ -123,7 +123,7 @@ { loff_t l = *pos; read_lock_bh(&ipx_routes_lock); - return l ? ipx_get_route_idx(--l) : (void *)1; + return l ? ipx_get_route_idx(--l) : SEQ_START_TOKEN; } static void *ipx_seq_route_next(struct seq_file *seq, void *v, loff_t *pos) @@ -131,7 +131,7 @@ struct ipx_route *r; ++*pos; - if (v == (void *)1) + if (v == SEQ_START_TOKEN) r = ipx_routes_head(); else r = ipx_routes_next(v); @@ -147,7 +147,7 @@ { struct ipx_route *rt; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { seq_puts(seq, "Network Router_Net Router_Node\n"); goto out; } @@ -195,7 +195,7 @@ loff_t l = *pos; spin_lock_bh(&ipx_interfaces_lock); - return l ? ipx_get_socket_idx(--l) : (void *)1; + return l ? ipx_get_socket_idx(--l) : SEQ_START_TOKEN; } static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) @@ -205,7 +205,7 @@ struct ipx_opt *ipxs; ++*pos; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { sk = NULL; i = ipx_interfaces_head(); if (!i) @@ -245,7 +245,7 @@ struct sock *s; struct ipx_opt *ipxs; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { #ifdef CONFIG_IPX_INTERN seq_puts(seq, "Local_Address " "Remote_Address Tx_Queue " diff -Nru a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c --- a/net/irda/irlan/irlan_common.c Thu Sep 11 23:03:12 2003 +++ b/net/irda/irlan/irlan_common.c Thu Sep 11 23:03:12 2003 @@ -1068,7 +1068,6 @@ } #ifdef CONFIG_PROC_FS -#define IRLAN_PROC_START_TOKEN ((void *)1) /* * Start of reading /proc entries. @@ -1083,7 +1082,7 @@ rcu_read_lock(); if (*pos == 0) - return IRLAN_PROC_START_TOKEN; + return SEQ_START_TOKEN; list_for_each_entry(self, &irlans, dev_list) { if (*pos == i) @@ -1099,7 +1098,7 @@ struct list_head *nxt; ++*pos; - if (v == IRLAN_PROC_START_TOKEN) + if (v == SEQ_START_TOKEN) nxt = irlans.next; else nxt = ((struct irlan_cb *)v)->dev_list.next; @@ -1120,7 +1119,7 @@ */ static int irlan_seq_show(struct seq_file *seq, void *v) { - if (v == IRLAN_PROC_START_TOKEN) + if (v == SEQ_START_TOKEN) seq_puts(seq, "IrLAN instances:\n"); else { struct irlan_cb *self = v; diff -Nru a/net/llc/llc_proc.c b/net/llc/llc_proc.c --- a/net/llc/llc_proc.c Thu Sep 11 23:03:11 2003 +++ b/net/llc/llc_proc.c Thu Sep 11 23:03:11 2003 @@ -67,7 +67,7 @@ loff_t l = *pos; read_lock_bh(&llc_main_station.sap_list.lock); - return l ? llc_get_sk_idx(--l) : (void *)1; + return l ? llc_get_sk_idx(--l) : SEQ_START_TOKEN; } static void *llc_seq_next(struct seq_file *seq, void *v, loff_t *pos) @@ -77,7 +77,7 @@ struct llc_sap *sap; ++*pos; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { sk = llc_get_sk_idx(0); goto out; } @@ -123,7 +123,7 @@ struct sock* sk; struct llc_opt *llc; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { seq_puts(seq, "SKt Mc local_mac_sap remote_mac_sap " " tx_queue rx_queue st uid link\n"); goto out; @@ -172,7 +172,7 @@ struct sock* sk; struct llc_opt *llc; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { seq_puts(seq, "Connection list:\n" "dsap state retr txw rxw pf ff sf df rs cs " "tack tpfc trs tbs blog busr\n"); diff -Nru a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c --- a/net/netrom/af_netrom.c Thu Sep 11 23:03:12 2003 +++ b/net/netrom/af_netrom.c Thu Sep 11 23:03:12 2003 @@ -1241,8 +1241,6 @@ #ifdef CONFIG_PROC_FS -/* Marker for header entry */ -#define NETROM_PROC_START ((void *)1) static void *nr_info_start(struct seq_file *seq, loff_t *pos) { struct sock *s; @@ -1251,7 +1249,7 @@ spin_lock_bh(&nr_list_lock); if (*pos == 0) - return NETROM_PROC_START; + return SEQ_START_TOKEN; sk_for_each(s, node, &nr_list) { if (i == *pos) @@ -1265,7 +1263,7 @@ { ++*pos; - return (v == NETROM_PROC_START) ? sk_head(&nr_list) + return (v == SEQ_START_TOKEN) ? sk_head(&nr_list) : sk_next((struct sock *)v); } @@ -1281,7 +1279,7 @@ nr_cb *nr; const char *devname; - if (v == NETROM_PROC_START) + if (v == SEQ_START_TOKEN) seq_puts(seq, "user_addr dest_node src_node dev my your st vs vr va t1 t2 t4 idle n2 wnd Snd-Q Rcv-Q inode\n"); diff -Nru a/net/netrom/nr_route.c b/net/netrom/nr_route.c --- a/net/netrom/nr_route.c Thu Sep 11 23:03:14 2003 +++ b/net/netrom/nr_route.c Thu Sep 11 23:03:14 2003 @@ -841,7 +841,6 @@ } #ifdef CONFIG_PROC_FS -#define NETROM_PROC_START ((void *) 1) static void *nr_node_start(struct seq_file *seq, loff_t *pos) { @@ -851,7 +850,7 @@ spin_lock_bh(&nr_node_list_lock); if (*pos == 0) - return NETROM_PROC_START; + return SEQ_START_TOKEN; nr_node_for_each(nr_node, node, &nr_node_list) { if (i == *pos) @@ -867,7 +866,7 @@ struct hlist_node *node; ++*pos; - node = (v == NETROM_PROC_START) + node = (v == SEQ_START_TOKEN) ? nr_node_list.first : ((struct nr_node *)v)->node_node.next; @@ -883,7 +882,7 @@ { int i; - if (v == NETROM_PROC_START) + if (v == SEQ_START_TOKEN) seq_puts(seq, "callsign mnemonic w n qual obs neigh qual obs neigh qual obs neigh\n"); else { @@ -936,7 +935,7 @@ spin_lock_bh(&nr_neigh_list_lock); if (*pos == 0) - return NETROM_PROC_START; + return SEQ_START_TOKEN; nr_neigh_for_each(nr_neigh, node, &nr_neigh_list) { if (i == *pos) @@ -950,7 +949,7 @@ struct hlist_node *node; ++*pos; - node = (v == NETROM_PROC_START) + node = (v == SEQ_START_TOKEN) ? nr_neigh_list.first : ((struct nr_neigh *)v)->neigh_node.next; @@ -966,7 +965,7 @@ { int i; - if (v == NETROM_PROC_START) + if (v == SEQ_START_TOKEN) seq_puts(seq, "addr callsign dev qual lock count failed digipeaters\n"); else { struct nr_neigh *nr_neigh = v; diff -Nru a/net/rose/af_rose.c b/net/rose/af_rose.c --- a/net/rose/af_rose.c Thu Sep 11 23:03:12 2003 +++ b/net/rose/af_rose.c Thu Sep 11 23:03:12 2003 @@ -1344,7 +1344,7 @@ spin_lock_bh(&rose_list_lock); if (*pos == 0) - return ROSE_PROC_START; + return SEQ_START_TOKEN; i = 1; sk_for_each(s, node, &rose_list) { @@ -1359,7 +1359,7 @@ { ++*pos; - return (v == ROSE_PROC_START) ? sk_head(&rose_list) + return (v == SEQ_START_TOKEN) ? sk_head(&rose_list) : sk_next((struct sock *)v); } @@ -1370,7 +1370,7 @@ static int rose_info_show(struct seq_file *seq, void *v) { - if (v == ROSE_PROC_START) + if (v == SEQ_START_TOKEN) seq_puts(seq, "dest_addr dest_call src_addr src_call dev lci neigh st vs vr va t t1 t2 t3 hb idle Snd-Q Rcv-Q inode\n"); diff -Nru a/net/rose/rose_route.c b/net/rose/rose_route.c --- a/net/rose/rose_route.c Thu Sep 11 23:03:14 2003 +++ b/net/rose/rose_route.c Thu Sep 11 23:03:14 2003 @@ -1076,7 +1076,7 @@ spin_lock_bh(&rose_neigh_list_lock); if (*pos == 0) - return ROSE_PROC_START; + return SEQ_START_TOKEN; for (rose_node = rose_node_list; rose_node && i < *pos; rose_node = rose_node->next, ++i); @@ -1088,7 +1088,7 @@ { ++*pos; - return (v == ROSE_PROC_START) ? rose_node_list + return (v == SEQ_START_TOKEN) ? rose_node_list : ((struct rose_node *)v)->next; } @@ -1101,7 +1101,7 @@ { int i; - if (v == ROSE_PROC_START) + if (v == SEQ_START_TOKEN) seq_puts(seq, "address mask n neigh neigh neigh\n"); else { const struct rose_node *rose_node = v; @@ -1152,7 +1152,7 @@ spin_lock_bh(&rose_neigh_list_lock); if (*pos == 0) - return ROSE_PROC_START; + return SEQ_START_TOKEN; for (rose_neigh = rose_neigh_list; rose_neigh && i < *pos; rose_neigh = rose_neigh->next, ++i); @@ -1164,7 +1164,7 @@ { ++*pos; - return (v == ROSE_PROC_START) ? rose_neigh_list + return (v == SEQ_START_TOKEN) ? rose_neigh_list : ((struct rose_neigh *)v)->next; } @@ -1177,7 +1177,7 @@ { int i; - if (v == ROSE_PROC_START) + if (v == SEQ_START_TOKEN) seq_puts(seq, "addr callsign dev count use mode restart t0 tf digipeaters\n"); else { @@ -1234,7 +1234,7 @@ spin_lock_bh(&rose_route_list_lock); if (*pos == 0) - return ROSE_PROC_START; + return SEQ_START_TOKEN; for (rose_route = rose_route_list; rose_route && i < *pos; rose_route = rose_route->next, ++i); @@ -1246,7 +1246,7 @@ { ++*pos; - return (v == ROSE_PROC_START) ? rose_route_list + return (v == SEQ_START_TOKEN) ? rose_route_list : ((struct rose_route *)v)->next; } @@ -1257,7 +1257,7 @@ static int rose_route_show(struct seq_file *seq, void *v) { - if (v == ROSE_PROC_START) + if (v == SEQ_START_TOKEN) seq_puts(seq, "lci address callsign neigh <-> lci address callsign neigh\n"); else { diff -Nru a/net/rxrpc/Makefile b/net/rxrpc/Makefile --- a/net/rxrpc/Makefile Thu Sep 11 23:03:13 2003 +++ b/net/rxrpc/Makefile Thu Sep 11 23:03:13 2003 @@ -2,7 +2,9 @@ # Makefile for Linux kernel Rx RPC # -rxrpc-y := \ +#CFLAGS += -finstrument-functions + +rxrpc-objs := \ call.o \ connection.o \ krxiod.o \ @@ -13,7 +15,11 @@ rxrpc_syms.o \ transport.o -rxrpc-$(CONFIG_PROC_FS) += proc.o -rxrpc-$(CONFIG_SYSCTL) += sysctl.o +ifeq ($(CONFIG_PROC_FS),y) +rxrpc-objs += proc.o +endif +ifeq ($(CONFIG_SYSCTL),y) +rxrpc-objs += sysctl.o +endif obj-$(CONFIG_RXRPC) := rxrpc.o diff -Nru a/net/rxrpc/call.c b/net/rxrpc/call.c --- a/net/rxrpc/call.c Thu Sep 11 23:03:13 2003 +++ b/net/rxrpc/call.c Thu Sep 11 23:03:13 2003 @@ -53,20 +53,25 @@ }; const char *rxrpc_pkts[] = { - "?00", "data", "ack", "busy", "abort", "ackall", "chall", "resp", "debug", + "?00", + "data", "ack", "busy", "abort", "ackall", "chall", "resp", "debug", "?09", "?10", "?11", "?12", "?13", "?14", "?15" }; const char *rxrpc_acks[] = { - "---", "REQ", "DUP", "SEQ", "WIN", "MEM", "PNG", "PNR", "DLY", "IDL", "-?-" + "---", "REQ", "DUP", "SEQ", "WIN", "MEM", "PNG", "PNR", "DLY", "IDL", + "-?-" }; static const char _acktype[] = "NA-"; static void rxrpc_call_receive_packet(struct rxrpc_call *call); -static void rxrpc_call_receive_data_packet(struct rxrpc_call *call, struct rxrpc_message *msg); -static void rxrpc_call_receive_ack_packet(struct rxrpc_call *call, struct rxrpc_message *msg); -static void rxrpc_call_definitively_ACK(struct rxrpc_call *call, rxrpc_seq_t higest); +static void rxrpc_call_receive_data_packet(struct rxrpc_call *call, + struct rxrpc_message *msg); +static void rxrpc_call_receive_ack_packet(struct rxrpc_call *call, + struct rxrpc_message *msg); +static void rxrpc_call_definitively_ACK(struct rxrpc_call *call, + rxrpc_seq_t higest); static void rxrpc_call_resend(struct rxrpc_call *call, rxrpc_seq_t highest); static int __rxrpc_call_read_data(struct rxrpc_call *call); @@ -75,7 +80,7 @@ rxrpc_seq_t seq, size_t count); #define _state(call) \ - _debug("[[[ state %s ]]]",rxrpc_call_states[call->app_call_state]); + _debug("[[[ state %s ]]]", rxrpc_call_states[call->app_call_state]); static void rxrpc_call_default_attn_func(struct rxrpc_call *call) { @@ -103,7 +108,7 @@ { struct rxrpc_call *call = (struct rxrpc_call *) _call; - _debug("ACKS TIMEOUT %05lu",jiffies - call->cjif); + _debug("ACKS TIMEOUT %05lu", jiffies - call->cjif); call->flags |= RXRPC_CALL_ACKS_TIMO; rxrpc_krxiod_queue_call(call); @@ -113,7 +118,7 @@ { struct rxrpc_call *call = (struct rxrpc_call *) _call; - _debug("RCV TIMEOUT %05lu",jiffies - call->cjif); + _debug("RCV TIMEOUT %05lu", jiffies - call->cjif); call->flags |= RXRPC_CALL_RCV_TIMO; rxrpc_krxiod_queue_call(call); @@ -133,15 +138,18 @@ /* * calculate a timeout based on an RTT value */ -static inline unsigned long __rxrpc_rtt_based_timeout(struct rxrpc_call *call, unsigned long val) +static inline unsigned long __rxrpc_rtt_based_timeout(struct rxrpc_call *call, + unsigned long val) { - unsigned long expiry = call->conn->peer->rtt / (1000000/HZ); + unsigned long expiry = call->conn->peer->rtt / (1000000 / HZ); expiry += 10; - if (expiryHZ) expiry = HZ; + if (expiry < HZ / 25) + expiry = HZ / 25; + if (expiry > HZ) + expiry = HZ; - _leave(" = %lu jiffies",expiry); + _leave(" = %lu jiffies", expiry); return jiffies + expiry; } /* end __rxrpc_rtt_based_timeout() */ @@ -154,7 +162,7 @@ { struct rxrpc_call *call; - _enter("%p",conn); + _enter("%p", conn); /* allocate and initialise a call record */ call = (struct rxrpc_call *) get_zeroed_page(GFP_KERNEL); @@ -163,7 +171,7 @@ return -ENOMEM; } - atomic_set(&call->usage,1); + atomic_set(&call->usage, 1); init_waitqueue_head(&call->waitq); spin_lock_init(&call->lock); @@ -200,7 +208,7 @@ call->cjif = jiffies; - _leave(" = 0 (%p)",call); + _leave(" = 0 (%p)", call); *_call = call; @@ -217,34 +225,37 @@ rxrpc_call_aemap_func_t aemap, struct rxrpc_call **_call) { - DECLARE_WAITQUEUE(myself,current); + DECLARE_WAITQUEUE(myself, current); struct rxrpc_call *call; int ret, cix, loop; - _enter("%p",conn); + _enter("%p", conn); /* allocate and initialise a call record */ - ret = __rxrpc_create_call(conn,&call); - if (ret<0) { - _leave(" = %d",ret); + ret = __rxrpc_create_call(conn, &call); + if (ret < 0) { + _leave(" = %d", ret); return ret; } call->app_call_state = RXRPC_CSTATE_CLNT_SND_ARGS; - if (attn) call->app_attn_func = attn; - if (error) call->app_error_func = error; - if (aemap) call->app_aemap_func = aemap; + if (attn) + call->app_attn_func = attn; + if (error) + call->app_error_func = error; + if (aemap) + call->app_aemap_func = aemap; _state(call); spin_lock(&conn->lock); set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&conn->chanwait,&myself); + add_wait_queue(&conn->chanwait, &myself); try_again: /* try to find an unused channel */ - for (cix=0; cix<4; cix++) + for (cix = 0; cix < 4; cix++) if (!conn->channels[cix]) goto obtained_chan; @@ -263,14 +274,15 @@ /* got a channel - now attach to the connection */ obtained_chan: - remove_wait_queue(&conn->chanwait,&myself); + remove_wait_queue(&conn->chanwait, &myself); set_current_state(TASK_RUNNING); /* concoct a unique call number */ next_callid: call->call_id = htonl(++conn->call_counter); - for (loop=0; loop<4; loop++) - if (conn->channels[loop] && conn->channels[loop]->call_id==call->call_id) + for (loop = 0; loop < 4; loop++) + if (conn->channels[loop] && + conn->channels[loop]->call_id == call->call_id) goto next_callid; rxrpc_get_connection(conn); @@ -281,24 +293,23 @@ spin_unlock(&conn->lock); down_write(&rxrpc_calls_sem); - list_add_tail(&call->call_link,&rxrpc_calls); + list_add_tail(&call->call_link, &rxrpc_calls); up_write(&rxrpc_calls_sem); __RXACCT(atomic_inc(&rxrpc_call_count)); *_call = call; - _leave(" = 0 (call=%p cix=%u)",call,cix); + _leave(" = 0 (call=%p cix=%u)", call, cix); return 0; error_unwait: - remove_wait_queue(&conn->chanwait,&myself); + remove_wait_queue(&conn->chanwait, &myself); set_current_state(TASK_RUNNING); spin_unlock(&conn->lock); - free_page((unsigned long)call); - _leave(" = %d",ret); + free_page((unsigned long) call); + _leave(" = %d", ret); return ret; - } /* end rxrpc_create_call() */ /*****************************************************************************/ @@ -315,18 +326,18 @@ cix = ntohl(msg->hdr.cid) & RXRPC_CHANNELMASK; - _enter("%p,%u,%u",conn,ntohl(msg->hdr.callNumber),cix); + _enter("%p,%u,%u", conn, ntohl(msg->hdr.callNumber), cix); /* allocate and initialise a call record */ - ret = __rxrpc_create_call(conn,&call); - if (ret<0) { - _leave(" = %d",ret); + ret = __rxrpc_create_call(conn, &call); + if (ret < 0) { + _leave(" = %d", ret); return ret; } call->pkt_rcv_count = 1; call->app_call_state = RXRPC_CSTATE_SRVR_RCV_OPID; - call->app_mark = sizeof(u32); + call->app_mark = sizeof(uint32_t); _state(call); @@ -348,20 +359,20 @@ spin_unlock(&conn->lock); - if (ret<0) { - free_page((unsigned long)call); + if (ret < 0) { + free_page((unsigned long) call); call = NULL; } - if (ret==0) { + if (ret == 0) { down_write(&rxrpc_calls_sem); - list_add_tail(&call->call_link,&rxrpc_calls); + list_add_tail(&call->call_link, &rxrpc_calls); up_write(&rxrpc_calls_sem); __RXACCT(atomic_inc(&rxrpc_call_count)); *_call = call; } - _leave(" = %d [%p]",ret,call); + _leave(" = %d [%p]", ret, call); return ret; } /* end rxrpc_incoming_call() */ @@ -377,10 +388,11 @@ _enter("%p{u=%d}",call,atomic_read(&call->usage)); /* sanity check */ - if (atomic_read(&call->usage)<=0) + if (atomic_read(&call->usage) <= 0) BUG(); - /* to prevent a race, the decrement and the de-list must be effectively atomic */ + /* to prevent a race, the decrement and the de-list must be effectively + * atomic */ spin_lock(&conn->lock); if (likely(!atomic_dec_and_test(&call->usage))) { spin_unlock(&conn->lock); @@ -388,7 +400,7 @@ return; } - if (conn->channels[ntohl(call->chan_ix)]==call) + if (conn->channels[ntohl(call->chan_ix)] == call) conn->channels[ntohl(call->chan_ix)] = NULL; spin_unlock(&conn->lock); @@ -412,25 +424,29 @@ rxrpc_put_message(call->snd_ping); while (!list_empty(&call->acks_pendq)) { - msg = list_entry(call->acks_pendq.next,struct rxrpc_message,link); + msg = list_entry(call->acks_pendq.next, + struct rxrpc_message, link); list_del(&msg->link); rxrpc_put_message(msg); } while (!list_empty(&call->rcv_receiveq)) { - msg = list_entry(call->rcv_receiveq.next,struct rxrpc_message,link); + msg = list_entry(call->rcv_receiveq.next, + struct rxrpc_message, link); list_del(&msg->link); rxrpc_put_message(msg); } while (!list_empty(&call->app_readyq)) { - msg = list_entry(call->app_readyq.next,struct rxrpc_message,link); + msg = list_entry(call->app_readyq.next, + struct rxrpc_message, link); list_del(&msg->link); rxrpc_put_message(msg); } while (!list_empty(&call->app_unreadyq)) { - msg = list_entry(call->app_unreadyq.next,struct rxrpc_message,link); + msg = list_entry(call->app_unreadyq.next, + struct rxrpc_message, link); list_del(&msg->link); rxrpc_put_message(msg); } @@ -442,7 +458,7 @@ up_write(&rxrpc_calls_sem); __RXACCT(atomic_dec(&rxrpc_call_count)); - free_page((unsigned long)call); + free_page((unsigned long) call); _leave(" [destroyed]"); } /* end rxrpc_put_call() */ @@ -451,7 +467,8 @@ /* * actually generate a normal ACK */ -static inline int __rxrpc_call_gen_normal_ACK(struct rxrpc_call *call, rxrpc_seq_t seq) +static inline int __rxrpc_call_gen_normal_ACK(struct rxrpc_call *call, + rxrpc_seq_t seq) { struct rxrpc_message *msg; struct iovec diov[3]; @@ -478,35 +495,36 @@ diov[0].iov_len = sizeof(struct rxrpc_ackpacket); diov[0].iov_base = &call->ackr; - diov[1].iov_len = (call->ackr_pend_cnt+3); + diov[1].iov_len = call->ackr_pend_cnt + 3; diov[1].iov_base = call->ackr_array; diov[2].iov_len = sizeof(aux); diov[2].iov_base = &aux; /* build and send the message */ - ret = rxrpc_conn_newmsg(call->conn,call,RXRPC_PACKET_TYPE_ACK,3,diov,GFP_KERNEL,&msg); - if (ret<0) + ret = rxrpc_conn_newmsg(call->conn,call, RXRPC_PACKET_TYPE_ACK, + 3, diov, GFP_KERNEL, &msg); + if (ret < 0) goto out; msg->seq = seq; msg->hdr.seq = htonl(seq); msg->hdr.flags |= RXRPC_SLOW_START_OK; - ret = rxrpc_conn_sendmsg(call->conn,msg); + ret = rxrpc_conn_sendmsg(call->conn, msg); rxrpc_put_message(msg); - if (ret<0) + if (ret < 0) goto out; call->pkt_snd_count++; /* count how many actual ACKs there were at the front */ - for (delta=0; deltaackr_pend_cnt; delta++) - if (call->ackr_array[delta]!=RXRPC_ACK_TYPE_ACK) + for (delta = 0; delta < call->ackr_pend_cnt; delta++) + if (call->ackr_array[delta] != RXRPC_ACK_TYPE_ACK) break; call->ackr_pend_cnt -= delta; /* all ACK'd to this point */ /* crank the ACK window around */ - if (delta==0) { + if (delta == 0) { /* un-ACK'd window */ } else if (delta < RXRPC_CALL_ACK_WINDOW_SIZE) { @@ -528,22 +546,26 @@ /* fully ACK'd window * - just clear the whole thing */ - memset(&call->ackr_array,RXRPC_ACK_TYPE_NACK,sizeof(call->ackr_array)); + memset(&call->ackr_array, + RXRPC_ACK_TYPE_NACK, + sizeof(call->ackr_array)); } /* clear this ACK */ - memset(&call->ackr,0,sizeof(call->ackr)); + memset(&call->ackr, 0, sizeof(call->ackr)); out: - if (!call->app_call_state) printk("___ STATE 0 ___\n"); + if (!call->app_call_state) + printk("___ STATE 0 ___\n"); return ret; } /* end __rxrpc_call_gen_normal_ACK() */ /*****************************************************************************/ /* - * note the reception of a packet in the call's ACK records and generate an appropriate ACK packet - * if necessary - * - returns 0 if packet should be processed, 1 if packet should be ignored and -ve on an error + * note the reception of a packet in the call's ACK records and generate an + * appropriate ACK packet if necessary + * - returns 0 if packet should be processed, 1 if packet should be ignored + * and -ve on an error */ static int rxrpc_call_generate_ACK(struct rxrpc_call *call, struct rxrpc_header *hdr, @@ -555,19 +577,20 @@ int ret = 0, err; u8 special_ACK, do_ACK, force; - _enter("%p,%p { seq=%d tp=%d fl=%02x }",call,hdr,ntohl(hdr->seq),hdr->type,hdr->flags); + _enter("%p,%p { seq=%d tp=%d fl=%02x }", + call, hdr, ntohl(hdr->seq), hdr->type, hdr->flags); seq = ntohl(hdr->seq); offset = seq - call->ackr_win_bot; do_ACK = RXRPC_ACK_DELAY; special_ACK = 0; - force = (seq==1); + force = (seq == 1); if (call->ackr_high_seq < seq) call->ackr_high_seq = seq; /* deal with generation of obvious special ACKs first */ - if (ack && ack->reason==RXRPC_ACK_PING) { + if (ack && ack->reason == RXRPC_ACK_PING) { special_ACK = RXRPC_ACK_PING_RESPONSE; ret = 1; goto gen_ACK; @@ -594,9 +617,9 @@ /* okay... it's a normal data packet inside the ACK window */ call->ackr_array[offset] = RXRPC_ACK_TYPE_ACK; - if (offsetackr_pend_cnt) { + if (offset < call->ackr_pend_cnt) { } - else if (offset>call->ackr_pend_cnt) { + else if (offset > call->ackr_pend_cnt) { do_ACK = RXRPC_ACK_OUT_OF_SEQUENCE; call->ackr_pend_cnt = offset; goto gen_ACK; @@ -616,8 +639,8 @@ } /* re-ACK packets previously received out-of-order */ - for (offset++; offsetackr_array[offset]!=RXRPC_ACK_TYPE_ACK) + for (offset++; offset < RXRPC_CALL_ACK_WINDOW_SIZE; offset++) + if (call->ackr_array[offset] != RXRPC_ACK_TYPE_ACK) break; call->ackr_pend_cnt = offset; @@ -629,55 +652,61 @@ gen_ACK: _debug("%05lu ACKs pend=%u norm=%s special=%s%s", jiffies - call->cjif, - call->ackr_pend_cnt,rxrpc_acks[do_ACK],rxrpc_acks[special_ACK], + call->ackr_pend_cnt, + rxrpc_acks[do_ACK], + rxrpc_acks[special_ACK], force ? " immediate" : - do_ACK==RXRPC_ACK_REQUESTED ? " merge-req" : + do_ACK == RXRPC_ACK_REQUESTED ? " merge-req" : hdr->flags & RXRPC_LAST_PACKET ? " finalise" : " defer" ); /* send any pending normal ACKs if need be */ - if (call->ackr_pend_cnt>0) { + if (call->ackr_pend_cnt > 0) { /* fill out the appropriate form */ - call->ackr.bufferSpace = htons(RXRPC_CALL_ACK_WINDOW_SIZE); - call->ackr.maxSkew = htons(min(call->ackr_high_seq - seq,65535U)); - call->ackr.firstPacket = htonl(call->ackr_win_bot); - call->ackr.previousPacket = call->ackr_prev_seq; - call->ackr.serial = hdr->serial; - call->ackr.nAcks = call->ackr_pend_cnt; + call->ackr.bufferSpace = htons(RXRPC_CALL_ACK_WINDOW_SIZE); + call->ackr.maxSkew = htons(min(call->ackr_high_seq - seq, + 65535U)); + call->ackr.firstPacket = htonl(call->ackr_win_bot); + call->ackr.previousPacket = call->ackr_prev_seq; + call->ackr.serial = hdr->serial; + call->ackr.nAcks = call->ackr_pend_cnt; - if (do_ACK==RXRPC_ACK_REQUESTED) + if (do_ACK == RXRPC_ACK_REQUESTED) call->ackr.reason = do_ACK; /* generate the ACK immediately if necessary */ if (special_ACK || force) { - err = __rxrpc_call_gen_normal_ACK(call,do_ACK==RXRPC_ACK_DELAY ? 0 : seq); - if (err<0) { + err = __rxrpc_call_gen_normal_ACK( + call, do_ACK == RXRPC_ACK_DELAY ? 0 : seq); + if (err < 0) { ret = err; goto out; } } } - if (call->ackr.reason==RXRPC_ACK_REQUESTED) + if (call->ackr.reason == RXRPC_ACK_REQUESTED) call->ackr_dfr_seq = seq; - /* start the ACK timer if not running if there are any pending deferred ACKs */ - if (call->ackr_pend_cnt>0 && - call->ackr.reason!=RXRPC_ACK_REQUESTED && + /* start the ACK timer if not running if there are any pending deferred + * ACKs */ + if (call->ackr_pend_cnt > 0 && + call->ackr.reason != RXRPC_ACK_REQUESTED && !timer_pending(&call->ackr_dfr_timo) ) { unsigned long timo; timo = rxrpc_call_dfr_ack_timeout + jiffies; - _debug("START ACKR TIMER for cj=%lu",timo-call->cjif); + _debug("START ACKR TIMER for cj=%lu", timo-call->cjif); spin_lock(&call->lock); - mod_timer(&call->ackr_dfr_timo,timo); + mod_timer(&call->ackr_dfr_timo, timo); spin_unlock(&call->lock); } - else if ((call->ackr_pend_cnt==0 || call->ackr.reason==RXRPC_ACK_REQUESTED) && + else if ((call->ackr_pend_cnt == 0 || + call->ackr.reason == RXRPC_ACK_REQUESTED) && timer_pending(&call->ackr_dfr_timo) ) { /* stop timer if no pending ACKs */ @@ -689,21 +718,25 @@ if (special_ACK) { struct rxrpc_ackpacket ack; struct iovec diov[2]; - u8 acks[1] = { RXRPC_ACK_TYPE_ACK }; + uint8_t acks[1] = { RXRPC_ACK_TYPE_ACK }; /* fill out the appropriate form */ - ack.bufferSpace = htons(RXRPC_CALL_ACK_WINDOW_SIZE); - ack.maxSkew = htons(min(call->ackr_high_seq - seq,65535U)); - ack.firstPacket = htonl(call->ackr_win_bot); - ack.previousPacket = call->ackr_prev_seq; - ack.serial = hdr->serial; - ack.reason = special_ACK; - ack.nAcks = 0; - //ack.nAcks = special_ACK==RXRPC_ACK_OUT_OF_SEQUENCE ? 0 : hdr->seq ? 1 : 0; - - _proto("Rx Sending s-ACK { m=%hu f=#%u p=#%u s=%%%u r=%s n=%u }", - ntohs(ack.maxSkew),ntohl(ack.firstPacket),ntohl(ack.previousPacket), - ntohl(ack.serial),rxrpc_acks[ack.reason],ack.nAcks); + ack.bufferSpace = htons(RXRPC_CALL_ACK_WINDOW_SIZE); + ack.maxSkew = htons(min(call->ackr_high_seq - seq,65535U)); + ack.firstPacket = htonl(call->ackr_win_bot); + ack.previousPacket = call->ackr_prev_seq; + ack.serial = hdr->serial; + ack.reason = special_ACK; + ack.nAcks = 0; + + _proto("Rx Sending s-ACK" + " { m=%hu f=#%u p=#%u s=%%%u r=%s n=%u }", + ntohs(ack.maxSkew), + ntohl(ack.firstPacket), + ntohl(ack.previousPacket), + ntohl(ack.serial), + rxrpc_acks[ack.reason], + ack.nAcks); diov[0].iov_len = sizeof(struct rxrpc_ackpacket); diov[0].iov_base = &ack; @@ -711,11 +744,11 @@ diov[1].iov_base = acks; /* build and send the message */ - err = rxrpc_conn_newmsg(call->conn,call,RXRPC_PACKET_TYPE_ACK, - hdr->seq ? 2 : 1,diov, + err = rxrpc_conn_newmsg(call->conn,call, RXRPC_PACKET_TYPE_ACK, + hdr->seq ? 2 : 1, diov, GFP_KERNEL, &msg); - if (err<0) { + if (err < 0) { ret = err; goto out; } @@ -724,9 +757,9 @@ msg->hdr.seq = htonl(seq); msg->hdr.flags |= RXRPC_SLOW_START_OK; - err = rxrpc_conn_sendmsg(call->conn,msg); + err = rxrpc_conn_sendmsg(call->conn, msg); rxrpc_put_message(msg); - if (err<0) { + if (err < 0) { ret = err; goto out; } @@ -737,7 +770,7 @@ if (hdr->seq) call->ackr_prev_seq = hdr->seq; - _leave(" = %d",ret); + _leave(" = %d", ret); return ret; } /* end rxrpc_call_generate_ACK() */ @@ -748,7 +781,7 @@ */ void rxrpc_call_do_stuff(struct rxrpc_call *call) { - _enter("%p{flags=%lx}",call,call->flags); + _enter("%p{flags=%lx}", call, call->flags); /* handle packet reception */ if (call->flags & RXRPC_CALL_RCV_PKT) { @@ -761,19 +794,19 @@ if (call->flags & RXRPC_CALL_ACKS_TIMO) { _debug("- overdue ACK timeout"); call->flags &= ~RXRPC_CALL_ACKS_TIMO; - rxrpc_call_resend(call,call->snd_seq_count); + rxrpc_call_resend(call, call->snd_seq_count); } /* handle lack of reception */ if (call->flags & RXRPC_CALL_RCV_TIMO) { _debug("- reception timeout"); call->flags &= ~RXRPC_CALL_RCV_TIMO; - rxrpc_call_abort(call,-EIO); + rxrpc_call_abort(call, -EIO); } /* handle deferred ACKs */ if (call->flags & RXRPC_CALL_ACKR_TIMO || - (call->ackr.nAcks>0 && call->ackr.reason==RXRPC_ACK_REQUESTED) + (call->ackr.nAcks > 0 && call->ackr.reason == RXRPC_ACK_REQUESTED) ) { _debug("- deferred ACK timeout: cj=%05lu r=%s n=%u", jiffies - call->cjif, @@ -782,9 +815,10 @@ call->flags &= ~RXRPC_CALL_ACKR_TIMO; - if (call->ackr.nAcks>0 && call->app_call_state!=RXRPC_CSTATE_ERROR) { + if (call->ackr.nAcks > 0 && + call->app_call_state != RXRPC_CSTATE_ERROR) { /* generate ACK */ - __rxrpc_call_gen_normal_ACK(call,call->ackr_dfr_seq); + __rxrpc_call_gen_normal_ACK(call, call->ackr_dfr_seq); call->ackr_dfr_seq = 0; } } @@ -807,10 +841,11 @@ int ret; u32 _error; - _enter("%p{%08x},%p{%d},%d",conn,ntohl(conn->conn_id),call,ntohl(call->call_id),errno); + _enter("%p{%08x},%p{%d},%d", + conn, ntohl(conn->conn_id), call, ntohl(call->call_id), errno); /* if this call is already aborted, then just wake up any waiters */ - if (call->app_call_state==RXRPC_CSTATE_ERROR) { + if (call->app_call_state == RXRPC_CSTATE_ERROR) { spin_unlock(&call->lock); call->app_error_func(call); _leave(" = 0"); @@ -820,12 +855,12 @@ rxrpc_get_call(call); /* change the state _with_ the lock still held */ - call->app_call_state = RXRPC_CSTATE_ERROR; - call->app_err_state = RXRPC_ESTATE_LOCAL_ABORT; - call->app_errno = errno; - call->app_mark = RXRPC_APP_MARK_EOF; - call->app_read_buf = NULL; - call->app_async_read = 0; + call->app_call_state = RXRPC_CSTATE_ERROR; + call->app_err_state = RXRPC_ESTATE_LOCAL_ABORT; + call->app_errno = errno; + call->app_mark = RXRPC_APP_MARK_EOF; + call->app_read_buf = NULL; + call->app_async_read = 0; _state(call); @@ -840,22 +875,25 @@ del_timer_sync(&call->ackr_dfr_timo); if (rxrpc_call_is_ack_pending(call)) - __rxrpc_call_gen_normal_ACK(call,0); + __rxrpc_call_gen_normal_ACK(call, 0); - /* send the abort packet only if we actually traded some other packets */ + /* send the abort packet only if we actually traded some other + * packets */ ret = 0; if (call->pkt_snd_count || call->pkt_rcv_count) { /* actually send the abort */ - _proto("Rx Sending Call ABORT { data=%d }",call->app_abort_code); + _proto("Rx Sending Call ABORT { data=%d }", + call->app_abort_code); _error = htonl(call->app_abort_code); diov[0].iov_len = sizeof(_error); diov[0].iov_base = &_error; - ret = rxrpc_conn_newmsg(conn,call,RXRPC_PACKET_TYPE_ABORT,1,diov,GFP_KERNEL,&msg); - if (ret==0) { - ret = rxrpc_conn_sendmsg(conn,msg); + ret = rxrpc_conn_newmsg(conn, call, RXRPC_PACKET_TYPE_ABORT, + 1, diov, GFP_KERNEL, &msg); + if (ret == 0) { + ret = rxrpc_conn_sendmsg(conn, msg); rxrpc_put_message(msg); } } @@ -865,8 +903,7 @@ rxrpc_put_call(call); - _leave(" = %d",ret); - + _leave(" = %d", ret); return ret; } /* end __rxrpc_call_abort() */ @@ -879,7 +916,7 @@ { spin_lock(&call->lock); - return __rxrpc_call_abort(call,error); + return __rxrpc_call_abort(call, error); } /* end rxrpc_call_abort() */ @@ -891,11 +928,12 @@ { struct rxrpc_message *msg; struct list_head *_p; - u32 data32; + uint32_t data32; - _enter("%p",call); + _enter("%p", call); - rxrpc_get_call(call); /* must not go away too soon if aborted by app-layer */ + rxrpc_get_call(call); /* must not go away too soon if aborted by + * app-layer */ while (!list_empty(&call->rcv_receiveq)) { /* try to get next packet */ @@ -907,9 +945,10 @@ } spin_unlock(&call->lock); - if (!_p) break; + if (!_p) + break; - msg = list_entry(_p,struct rxrpc_message,link); + msg = list_entry(_p, struct rxrpc_message, link); _proto("Rx %05lu Received %s packet (%%%u,#%u,%c%c%c%c%c)", jiffies - call->cjif, @@ -927,9 +966,10 @@ /* deal with data packets */ case RXRPC_PACKET_TYPE_DATA: /* ACK the packet if necessary */ - switch (rxrpc_call_generate_ACK(call,&msg->hdr,NULL)) { + switch (rxrpc_call_generate_ACK(call, &msg->hdr, + NULL)) { case 0: /* useful packet */ - rxrpc_call_receive_data_packet(call,msg); + rxrpc_call_receive_data_packet(call, msg); break; case 1: /* duplicate or out-of-window packet */ break; @@ -941,29 +981,30 @@ /* deal with ACK packets */ case RXRPC_PACKET_TYPE_ACK: - rxrpc_call_receive_ack_packet(call,msg); + rxrpc_call_receive_ack_packet(call, msg); break; /* deal with abort packets */ case RXRPC_PACKET_TYPE_ABORT: data32 = 0; - if (skb_copy_bits(msg->pkt,msg->offset,&data32,sizeof(data32))<0) { + if (skb_copy_bits(msg->pkt, msg->offset, + &data32, sizeof(data32)) < 0) { printk("Rx Received short ABORT packet\n"); } else { data32 = ntohl(data32); } - _proto("Rx Received Call ABORT { data=%d }",data32); + _proto("Rx Received Call ABORT { data=%d }", data32); spin_lock(&call->lock); - call->app_call_state = RXRPC_CSTATE_ERROR; - call->app_err_state = RXRPC_ESTATE_PEER_ABORT; - call->app_abort_code = data32; - call->app_errno = -ECONNABORTED; - call->app_mark = RXRPC_APP_MARK_EOF; - call->app_read_buf = NULL; - call->app_async_read = 0; + call->app_call_state = RXRPC_CSTATE_ERROR; + call->app_err_state = RXRPC_ESTATE_PEER_ABORT; + call->app_abort_code = data32; + call->app_errno = -ECONNABORTED; + call->app_mark = RXRPC_APP_MARK_EOF; + call->app_read_buf = NULL; + call->app_async_read = 0; /* ask the app to translate the error code */ call->app_aemap_func(call); @@ -974,7 +1015,8 @@ default: /* deal with other packet types */ - _proto("Rx Unsupported packet type %u (#%u)",msg->hdr.type,msg->seq); + _proto("Rx Unsupported packet type %u (#%u)", + msg->hdr.type, msg->seq); break; } @@ -990,14 +1032,18 @@ /* * process next data packet * - as the next data packet arrives: - * - it is queued on app_readyq _if_ it is the next one expected (app_ready_seq+1) + * - it is queued on app_readyq _if_ it is the next one expected + * (app_ready_seq+1) * - it is queued on app_unreadyq _if_ it is not the next one expected - * - if a packet placed on app_readyq completely fills a hole leading up to the first packet - * on app_unreadyq, then packets now in sequence are tranferred to app_readyq - * - the application layer can only see packets on app_readyq (app_ready_qty bytes) + * - if a packet placed on app_readyq completely fills a hole leading up to + * the first packet on app_unreadyq, then packets now in sequence are + * tranferred to app_readyq + * - the application layer can only see packets on app_readyq + * (app_ready_qty bytes) * - the application layer is prodded every time a new packet arrives */ -static void rxrpc_call_receive_data_packet(struct rxrpc_call *call, struct rxrpc_message *msg) +static void rxrpc_call_receive_data_packet(struct rxrpc_call *call, + struct rxrpc_message *msg) { const struct rxrpc_operation *optbl, *op; struct rxrpc_message *pmsg; @@ -1005,22 +1051,23 @@ int ret, lo, hi, rmtimo; u32 opid; - _enter("%p{%u},%p{%u}",call,ntohl(call->call_id),msg,msg->seq); + _enter("%p{%u},%p{%u}", call, ntohl(call->call_id), msg, msg->seq); rxrpc_get_message(msg); - /* add to the unready queue if we'd have to create a hole in the ready queue otherwise */ - if (msg->seq != call->app_ready_seq+1) { - _debug("Call add packet %d to unreadyq",msg->seq); + /* add to the unready queue if we'd have to create a hole in the ready + * queue otherwise */ + if (msg->seq != call->app_ready_seq + 1) { + _debug("Call add packet %d to unreadyq", msg->seq); /* insert in seq order */ list_for_each(_p,&call->app_unreadyq) { - pmsg = list_entry(_p,struct rxrpc_message,link); - if (pmsg->seq>msg->seq) + pmsg = list_entry(_p, struct rxrpc_message, link); + if (pmsg->seq > msg->seq) break; } - list_add_tail(&msg->link,_p); + list_add_tail(&msg->link, _p); _leave(" [unreadyq]"); return; @@ -1028,33 +1075,35 @@ /* next in sequence - simply append into the call's ready queue */ _debug("Call add packet %d to readyq (+%Zd => %Zd bytes)", - msg->seq,msg->dsize,call->app_ready_qty); + msg->seq, msg->dsize, call->app_ready_qty); spin_lock(&call->lock); call->app_ready_seq = msg->seq; call->app_ready_qty += msg->dsize; - list_add_tail(&msg->link,&call->app_readyq); + list_add_tail(&msg->link, &call->app_readyq); /* move unready packets to the readyq if we got rid of a hole */ while (!list_empty(&call->app_unreadyq)) { - pmsg = list_entry(call->app_unreadyq.next,struct rxrpc_message,link); + pmsg = list_entry(call->app_unreadyq.next, + struct rxrpc_message, link); - if (pmsg->seq != call->app_ready_seq+1) + if (pmsg->seq != call->app_ready_seq + 1) break; /* next in sequence - just move list-to-list */ _debug("Call transfer packet %d to readyq (+%Zd => %Zd bytes)", - pmsg->seq,pmsg->dsize,call->app_ready_qty); + pmsg->seq, pmsg->dsize, call->app_ready_qty); call->app_ready_seq = pmsg->seq; call->app_ready_qty += pmsg->dsize; list_del_init(&pmsg->link); - list_add_tail(&pmsg->link,&call->app_readyq); + list_add_tail(&pmsg->link, &call->app_readyq); } /* see if we've got the last packet yet */ if (!list_empty(&call->app_readyq)) { - pmsg = list_entry(call->app_readyq.prev,struct rxrpc_message,link); + pmsg = list_entry(call->app_readyq.prev, + struct rxrpc_message, link); if (pmsg->hdr.flags & RXRPC_LAST_PACKET) { call->app_last_rcv = 1; _debug("Last packet on readyq"); @@ -1068,25 +1117,27 @@ _leave(" [error]"); return; - /* extract the operation ID from an incoming call if that's not yet been done */ + /* extract the operation ID from an incoming call if that's not + * yet been done */ case RXRPC_CSTATE_SRVR_RCV_OPID: spin_unlock(&call->lock); /* handle as yet insufficient data for the operation ID */ - if (call->app_ready_qty<4) { + if (call->app_ready_qty < 4) { if (call->app_last_rcv) - rxrpc_call_abort(call,-EINVAL); /* trouble - last packet seen */ + /* trouble - last packet seen */ + rxrpc_call_abort(call, -EINVAL); _leave(""); return; } /* pull the operation ID out of the buffer */ - ret = rxrpc_call_read_data(call,&opid,sizeof(opid),0); - if (ret<0) { - printk("Unexpected error from read-data: %d\n",ret); - if (call->app_call_state!=RXRPC_CSTATE_ERROR) - rxrpc_call_abort(call,ret); + ret = rxrpc_call_read_data(call, &opid, sizeof(opid), 0); + if (ret < 0) { + printk("Unexpected error from read-data: %d\n", ret); + if (call->app_call_state != RXRPC_CSTATE_ERROR) + rxrpc_call_abort(call, ret); _leave(""); return; } @@ -1097,38 +1148,42 @@ lo = 0; hi = call->conn->service->ops_end - optbl; - while (loapp_opcode==op->id) + if (call->app_opcode == op->id) goto found_op; - if (call->app_opcode>op->id) - lo = mid+1; + if (call->app_opcode > op->id) + lo = mid + 1; else hi = mid; } /* search failed */ kproto("Rx Client requested operation %d from %s service", - call->app_opcode,call->conn->service->name); - rxrpc_call_abort(call,-EINVAL); + call->app_opcode, call->conn->service->name); + rxrpc_call_abort(call, -EINVAL); _leave(" [inval]"); return; found_op: _proto("Rx Client requested operation %s from %s service", - op->name,call->conn->service->name); + op->name, call->conn->service->name); - /* we're now waiting for the argument block (unless the call was aborted) */ + /* we're now waiting for the argument block (unless the call + * was aborted) */ spin_lock(&call->lock); - if (call->app_call_state==RXRPC_CSTATE_SRVR_RCV_OPID || - call->app_call_state==RXRPC_CSTATE_SRVR_SND_REPLY) { + if (call->app_call_state == RXRPC_CSTATE_SRVR_RCV_OPID || + call->app_call_state == RXRPC_CSTATE_SRVR_SND_REPLY) { if (!call->app_last_rcv) - call->app_call_state = RXRPC_CSTATE_SRVR_RCV_ARGS; - else if (call->app_ready_qty>0) - call->app_call_state = RXRPC_CSTATE_SRVR_GOT_ARGS; + call->app_call_state = + RXRPC_CSTATE_SRVR_RCV_ARGS; + else if (call->app_ready_qty > 0) + call->app_call_state = + RXRPC_CSTATE_SRVR_GOT_ARGS; else - call->app_call_state = RXRPC_CSTATE_SRVR_SND_REPLY; + call->app_call_state = + RXRPC_CSTATE_SRVR_SND_REPLY; call->app_mark = op->asize; call->app_user = op->user; } @@ -1166,20 +1221,21 @@ default: /* deal with data reception in an unexpected state */ - printk("Unexpected state [[[ %u ]]]\n",call->app_call_state); - __rxrpc_call_abort(call,-EBADMSG); + printk("Unexpected state [[[ %u ]]]\n", call->app_call_state); + __rxrpc_call_abort(call, -EBADMSG); _leave(""); return; } - if (call->app_call_state==RXRPC_CSTATE_CLNT_RCV_REPLY && call->app_last_rcv) + if (call->app_call_state == RXRPC_CSTATE_CLNT_RCV_REPLY && + call->app_last_rcv) BUG(); /* otherwise just invoke the data function whenever we can satisfy its desire for more * data */ _proto("Rx Received Op Data: st=%u qty=%Zu mk=%Zu%s", - call->app_call_state,call->app_ready_qty,call->app_mark, + call->app_call_state, call->app_ready_qty, call->app_mark, call->app_last_rcv ? " last-rcvd" : ""); spin_lock(&call->lock); @@ -1196,8 +1252,8 @@ case -ECONNABORTED: spin_unlock(&call->lock); break; - default: - __rxrpc_call_abort(call,ret); + default: + __rxrpc_call_abort(call, ret); break; } @@ -1211,17 +1267,18 @@ /* * received an ACK packet */ -static void rxrpc_call_receive_ack_packet(struct rxrpc_call *call, struct rxrpc_message *msg) +static void rxrpc_call_receive_ack_packet(struct rxrpc_call *call, + struct rxrpc_message *msg) { struct rxrpc_ackpacket ack; rxrpc_serial_t serial; rxrpc_seq_t seq; int ret; - _enter("%p{%u},%p{%u}",call,ntohl(call->call_id),msg,msg->seq); + _enter("%p{%u},%p{%u}", call, ntohl(call->call_id), msg, msg->seq); /* extract the basic ACK record */ - if (skb_copy_bits(msg->pkt,msg->offset,&ack,sizeof(ack))<0) { + if (skb_copy_bits(msg->pkt, msg->offset, &ack, sizeof(ack)) < 0) { printk("Rx Received short ACK packet\n"); return; } @@ -1241,10 +1298,14 @@ call->ackr.nAcks ); - /* check the other side isn't ACK'ing a sequence number I haven't sent yet */ - if (ack.nAcks>0 && (seq > call->snd_seq_count || seq+ack.nAcks-1 > call->snd_seq_count)) { - printk("Received ACK (#%u-#%u) for unsent packet\n",seq,seq+ack.nAcks-1); - rxrpc_call_abort(call,-EINVAL); + /* check the other side isn't ACK'ing a sequence number I haven't sent + * yet */ + if (ack.nAcks > 0 && + (seq > call->snd_seq_count || + seq + ack.nAcks - 1 > call->snd_seq_count)) { + printk("Received ACK (#%u-#%u) for unsent packet\n", + seq, seq + ack.nAcks - 1); + rxrpc_call_abort(call, -EINVAL); _leave(""); return; } @@ -1255,7 +1316,7 @@ /* find the prompting packet */ spin_lock(&call->lock); - if (call->snd_ping && call->snd_ping->hdr.serial==serial) { + if (call->snd_ping && call->snd_ping->hdr.serial == serial) { /* it was a ping packet */ rttmsg = call->snd_ping; call->snd_ping = NULL; @@ -1263,22 +1324,28 @@ if (rttmsg) { rttmsg->rttdone = 1; - rxrpc_peer_calculate_rtt(call->conn->peer,rttmsg,msg); + rxrpc_peer_calculate_rtt(call->conn->peer, + rttmsg, msg); rxrpc_put_message(rttmsg); } } else { struct list_head *_p; - /* it ought to be a data packet - look in the pending ACK list */ - list_for_each(_p,&call->acks_pendq) { - rttmsg = list_entry(_p,struct rxrpc_message,link); - if (rttmsg->hdr.serial==serial) { + /* it ought to be a data packet - look in the pending + * ACK list */ + list_for_each(_p, &call->acks_pendq) { + rttmsg = list_entry(_p, struct rxrpc_message, + link); + if (rttmsg->hdr.serial == serial) { if (rttmsg->rttdone) - break; /* never do RTT twice without resending */ + /* never do RTT twice without + * resending */ + break; rttmsg->rttdone = 1; - rxrpc_peer_calculate_rtt(call->conn->peer,rttmsg,msg); + rxrpc_peer_calculate_rtt( + call->conn->peer, rttmsg, msg); break; } } @@ -1287,24 +1354,25 @@ } switch (ack.reason) { - /* deal with negative/positive acknowledgement of data packets */ + /* deal with negative/positive acknowledgement of data + * packets */ case RXRPC_ACK_REQUESTED: case RXRPC_ACK_DELAY: case RXRPC_ACK_IDLE: - rxrpc_call_definitively_ACK(call,seq-1); + rxrpc_call_definitively_ACK(call, seq - 1); case RXRPC_ACK_DUPLICATE: case RXRPC_ACK_OUT_OF_SEQUENCE: case RXRPC_ACK_EXCEEDS_WINDOW: call->snd_resend_cnt = 0; - ret = rxrpc_call_record_ACK(call,msg,seq,ack.nAcks); - if (ret<0) - rxrpc_call_abort(call,ret); + ret = rxrpc_call_record_ACK(call, msg, seq, ack.nAcks); + if (ret < 0) + rxrpc_call_abort(call, ret); break; /* respond to ping packets immediately */ case RXRPC_ACK_PING: - rxrpc_call_generate_ACK(call,&msg->hdr,&ack); + rxrpc_call_generate_ACK(call, &msg->hdr, &ack); break; /* only record RTT on ping response packets */ @@ -1312,10 +1380,12 @@ if (call->snd_ping) { struct rxrpc_message *rttmsg; - /* only do RTT stuff if the response matches the retained ping */ + /* only do RTT stuff if the response matches the + * retained ping */ rttmsg = NULL; spin_lock(&call->lock); - if (call->snd_ping && call->snd_ping->hdr.serial==ack.serial) { + if (call->snd_ping && + call->snd_ping->hdr.serial == ack.serial) { rttmsg = call->snd_ping; call->snd_ping = NULL; } @@ -1323,14 +1393,15 @@ if (rttmsg) { rttmsg->rttdone = 1; - rxrpc_peer_calculate_rtt(call->conn->peer,rttmsg,msg); + rxrpc_peer_calculate_rtt(call->conn->peer, + rttmsg, msg); rxrpc_put_message(rttmsg); } } break; default: - printk("Unsupported ACK reason %u\n",ack.reason); + printk("Unsupported ACK reason %u\n", ack.reason); break; } @@ -1339,38 +1410,44 @@ /*****************************************************************************/ /* - * record definitive ACKs for all messages up to and including the one with the 'highest' seq + * record definitive ACKs for all messages up to and including the one with the + * 'highest' seq */ -static void rxrpc_call_definitively_ACK(struct rxrpc_call *call, rxrpc_seq_t highest) +static void rxrpc_call_definitively_ACK(struct rxrpc_call *call, + rxrpc_seq_t highest) { struct rxrpc_message *msg; int now_complete; - _enter("%p{ads=%u},%u",call,call->acks_dftv_seq,highest); + _enter("%p{ads=%u},%u", call, call->acks_dftv_seq, highest); - while (call->acks_dftv_seqacks_dftv_seq < highest) { call->acks_dftv_seq++; - _proto("Definitive ACK on packet #%u",call->acks_dftv_seq); + _proto("Definitive ACK on packet #%u", call->acks_dftv_seq); - /* discard those at front of queue until message with highest ACK is found */ + /* discard those at front of queue until message with highest + * ACK is found */ spin_lock(&call->lock); msg = NULL; if (!list_empty(&call->acks_pendq)) { - msg = list_entry(call->acks_pendq.next,struct rxrpc_message,link); + msg = list_entry(call->acks_pendq.next, + struct rxrpc_message, link); list_del_init(&msg->link); /* dequeue */ - if (msg->state==RXRPC_MSG_SENT) + if (msg->state == RXRPC_MSG_SENT) call->acks_pend_cnt--; } spin_unlock(&call->lock); /* insanity check */ if (!msg) - panic("%s(): acks_pendq unexpectedly empty\n",__FUNCTION__); + panic("%s(): acks_pendq unexpectedly empty\n", + __FUNCTION__); - if (msg->seq!=call->acks_dftv_seq) - panic("%s(): Packet #%u expected at front of acks_pendq (#%u found)\n", - __FUNCTION__,call->acks_dftv_seq,msg->seq); + if (msg->seq != call->acks_dftv_seq) + panic("%s(): Packet #%u expected at front of acks_pendq" + " (#%u found)\n", + __FUNCTION__, call->acks_dftv_seq, msg->seq); /* discard the message */ msg->state = RXRPC_MSG_DONE; @@ -1380,8 +1457,8 @@ /* if all sent packets are definitively ACK'd then prod any sleepers just in case */ now_complete = 0; spin_lock(&call->lock); - if (call->acks_dftv_seq==call->snd_seq_count) { - if (call->app_call_state!=RXRPC_CSTATE_COMPLETE) { + if (call->acks_dftv_seq == call->snd_seq_count) { + if (call->app_call_state != RXRPC_CSTATE_COMPLETE) { call->app_call_state = RXRPC_CSTATE_COMPLETE; _state(call); now_complete = 1; @@ -1417,13 +1494,15 @@ u8 acks[16]; _enter("%p{apc=%u ads=%u},%p,%u,%Zu", - call,call->acks_pend_cnt,call->acks_dftv_seq,msg,seq,count); + call, call->acks_pend_cnt, call->acks_dftv_seq, + msg, seq, count); - /* handle re-ACK'ing of definitively ACK'd packets (may be out-of-order ACKs) */ - if (seq<=call->acks_dftv_seq) { + /* handle re-ACK'ing of definitively ACK'd packets (may be out-of-order + * ACKs) */ + if (seq <= call->acks_dftv_seq) { unsigned delta = call->acks_dftv_seq - seq; - if (count<=delta) { + if (count <= delta) { _leave(" = 0 [all definitively ACK'd]"); return 0; } @@ -1435,14 +1514,14 @@ highest = seq + count - 1; resend = 0; - while (count>0) { + while (count > 0) { /* extract up to 16 ACK slots at a time */ - chunk = min(count,sizeof(acks)); + chunk = min(count, sizeof(acks)); count -= chunk; - memset(acks,2,sizeof(acks)); + memset(acks, 2, sizeof(acks)); - if (skb_copy_bits(msg->pkt,msg->offset,&acks,chunk)<0) { + if (skb_copy_bits(msg->pkt, msg->offset, &acks, chunk) < 0) { printk("Rx Received short ACK packet\n"); _leave(" = -EINVAL"); return -EINVAL; @@ -1450,7 +1529,7 @@ msg->offset += chunk; /* check that the ACK set is valid */ - for (ix=0; ixacks_pend_cnt ); - /* mark the packets in the ACK queue as being provisionally ACK'd */ + /* mark the packets in the ACK queue as being provisionally + * ACK'd */ ix = 0; spin_lock(&call->lock); /* find the first packet ACK'd/NAK'd here */ - list_for_each(_p,&call->acks_pendq) { - dmsg = list_entry(_p,struct rxrpc_message,link); - if (dmsg->seq==seq) + list_for_each(_p, &call->acks_pendq) { + dmsg = list_entry(_p, struct rxrpc_message, link); + if (dmsg->seq == seq) goto found_first; - _debug("- %u: skipping #%u",ix,dmsg->seq); + _debug("- %u: skipping #%u", ix, dmsg->seq); } goto bad_queue; found_first: do { _debug("- %u: processing #%u (%c) apc=%u", - ix,dmsg->seq,_acktype[acks[ix]],call->acks_pend_cnt); + ix, dmsg->seq, _acktype[acks[ix]], + call->acks_pend_cnt); - if (acks[ix]==RXRPC_ACK_TYPE_ACK) { - if (dmsg->state==RXRPC_MSG_SENT) call->acks_pend_cnt--; + if (acks[ix] == RXRPC_ACK_TYPE_ACK) { + if (dmsg->state == RXRPC_MSG_SENT) + call->acks_pend_cnt--; dmsg->state = RXRPC_MSG_ACKED; } else { - if (dmsg->state==RXRPC_MSG_ACKED) call->acks_pend_cnt++; + if (dmsg->state == RXRPC_MSG_ACKED) + call->acks_pend_cnt++; dmsg->state = RXRPC_MSG_SENT; } ix++; seq++; _p = dmsg->link.next; - dmsg = list_entry(_p,struct rxrpc_message,link); - } while(ixacks_pendq && dmsg->seq==seq); + dmsg = list_entry(_p, struct rxrpc_message, link); + } while(ix < chunk && + _p != &call->acks_pendq && + dmsg->seq == seq); - if (ixlock); } if (resend) - rxrpc_call_resend(call,highest); + rxrpc_call_resend(call, highest); - /* if all packets are provisionally ACK'd, then wake up anyone who's waiting for that */ + /* if all packets are provisionally ACK'd, then wake up anyone who's + * waiting for that */ now_complete = 0; spin_lock(&call->lock); - if (call->acks_pend_cnt==0) { - if (call->app_call_state==RXRPC_CSTATE_SRVR_RCV_FINAL_ACK) { + if (call->acks_pend_cnt == 0) { + if (call->app_call_state == RXRPC_CSTATE_SRVR_RCV_FINAL_ACK) { call->app_call_state = RXRPC_CSTATE_COMPLETE; _state(call); } @@ -1547,19 +1635,21 @@ call->app_attn_func(call); } - _leave(" = 0 (apc=%u)",call->acks_pend_cnt); + _leave(" = 0 (apc=%u)", call->acks_pend_cnt); return 0; bad_queue: - panic("%s(): acks_pendq in bad state (packet #%u absent)\n",__FUNCTION__,seq); + panic("%s(): acks_pendq in bad state (packet #%u absent)\n", + __FUNCTION__, seq); } /* end rxrpc_call_record_ACK() */ /*****************************************************************************/ /* * transfer data from the ready packet queue to the asynchronous read buffer - * - since this func is the only one going to look at packets queued on app_readyq, we don't need - * a lock to modify or access them, only to modify the queue pointers + * - since this func is the only one going to look at packets queued on + * app_readyq, we don't need a lock to modify or access them, only to modify + * the queue pointers * - called with call->lock held * - the buffer must be in kernel space * - returns: @@ -1575,16 +1665,20 @@ int ret; _enter("%p{as=%d buf=%p qty=%Zu/%Zu}", - call,call->app_async_read,call->app_read_buf,call->app_ready_qty,call->app_mark); + call, + call->app_async_read, call->app_read_buf, + call->app_ready_qty, call->app_mark); /* check the state */ switch (call->app_call_state) { case RXRPC_CSTATE_SRVR_RCV_ARGS: case RXRPC_CSTATE_CLNT_RCV_REPLY: if (call->app_last_rcv) { - printk("%s(%p,%p,%Zd): Inconsistent call state (%s, last pkt)", - __FUNCTION__,call,call->app_read_buf,call->app_mark, - rxrpc_call_states[call->app_call_state]); + printk("%s(%p,%p,%Zd):" + " Inconsistent call state (%s, last pkt)", + __FUNCTION__, + call, call->app_read_buf, call->app_mark, + rxrpc_call_states[call->app_call_state]); BUG(); } break; @@ -1596,9 +1690,11 @@ case RXRPC_CSTATE_SRVR_SND_REPLY: if (!call->app_last_rcv) { - printk("%s(%p,%p,%Zd): Inconsistent call state (%s, not last pkt)", - __FUNCTION__,call,call->app_read_buf,call->app_mark, - rxrpc_call_states[call->app_call_state]); + printk("%s(%p,%p,%Zd):" + " Inconsistent call state (%s, not last pkt)", + __FUNCTION__, + call, call->app_read_buf, call->app_mark, + rxrpc_call_states[call->app_call_state]); BUG(); } _debug("Trying to read data from call in SND_REPLY state"); @@ -1609,13 +1705,14 @@ return -ECONNABORTED; default: - printk("reading in unexpected state [[[ %u ]]]\n",call->app_call_state); + printk("reading in unexpected state [[[ %u ]]]\n", + call->app_call_state); BUG(); } /* handle the case of not having an async buffer */ if (!call->app_async_read) { - if (call->app_mark==RXRPC_APP_MARK_EOF) { + if (call->app_mark == RXRPC_APP_MARK_EOF) { ret = call->app_last_rcv ? 0 : -EAGAIN; } else { @@ -1628,28 +1725,33 @@ } } - _leave(" = %d [no buf]",ret); + _leave(" = %d [no buf]", ret); return 0; } - while (!list_empty(&call->app_readyq) && call->app_mark>0) { - msg = list_entry(call->app_readyq.next,struct rxrpc_message,link); + while (!list_empty(&call->app_readyq) && call->app_mark > 0) { + msg = list_entry(call->app_readyq.next, + struct rxrpc_message, link); /* drag as much data as we need out of this packet */ - qty = min(call->app_mark,msg->dsize); + qty = min(call->app_mark, msg->dsize); - _debug("reading %Zu from skb=%p off=%lu",qty,msg->pkt,msg->offset); + _debug("reading %Zu from skb=%p off=%lu", + qty, msg->pkt, msg->offset); if (call->app_read_buf) - if (skb_copy_bits(msg->pkt,msg->offset,call->app_read_buf,qty)<0) - panic("%s: Failed to copy data from packet: (%p,%p,%Zd)", - __FUNCTION__,call,call->app_read_buf,qty); + if (skb_copy_bits(msg->pkt, msg->offset, + call->app_read_buf, qty) < 0) + panic("%s: Failed to copy data from packet:" + " (%p,%p,%Zd)", + __FUNCTION__, + call, call->app_read_buf, qty); /* if that packet is now empty, discard it */ call->app_ready_qty -= qty; msg->dsize -= qty; - if (msg->dsize==0) { + if (msg->dsize == 0) { list_del_init(&msg->link); rxrpc_put_message(msg); } @@ -1658,10 +1760,11 @@ } call->app_mark -= qty; - if (call->app_read_buf) call->app_read_buf += qty; + if (call->app_read_buf) + call->app_read_buf += qty; } - if (call->app_mark==0) { + if (call->app_mark == 0) { call->app_async_read = 0; call->app_mark = RXRPC_APP_MARK_EOF; call->app_read_buf = NULL; @@ -1695,7 +1798,8 @@ } if (call->app_last_rcv) { - _debug("Insufficient data (%Zu/%Zu)",call->app_ready_qty,call->app_mark); + _debug("Insufficient data (%Zu/%Zu)", + call->app_ready_qty, call->app_mark); call->app_async_read = 0; call->app_mark = RXRPC_APP_MARK_EOF; call->app_read_buf = NULL; @@ -1710,22 +1814,26 @@ /*****************************************************************************/ /* - * attempt to read the specified amount of data from the call's ready queue into the buffer - * provided - * - since this func is the only one going to look at packets queued on app_readyq, we don't need - * a lock to modify or access them, only to modify the queue pointers + * attempt to read the specified amount of data from the call's ready queue + * into the buffer provided + * - since this func is the only one going to look at packets queued on + * app_readyq, we don't need a lock to modify or access them, only to modify + * the queue pointers * - if the buffer pointer is NULL, then data is merely drained, not copied - * - if flags&RXRPC_CALL_READ_BLOCK, then the function will wait until there is enough data or an - * error will be generated - * - note that the caller must have added the calling task to the call's wait queue beforehand - * - if flags&RXRPC_CALL_READ_ALL, then an error will be generated if this function doesn't read - * all available data + * - if flags&RXRPC_CALL_READ_BLOCK, then the function will wait until there is + * enough data or an error will be generated + * - note that the caller must have added the calling task to the call's wait + * queue beforehand + * - if flags&RXRPC_CALL_READ_ALL, then an error will be generated if this + * function doesn't read all available data */ -int rxrpc_call_read_data(struct rxrpc_call *call, void *buffer, size_t size, int flags) +int rxrpc_call_read_data(struct rxrpc_call *call, + void *buffer, size_t size, int flags) { int ret; - _enter("%p{arq=%Zu},%p,%Zd,%x",call,call->app_ready_qty,buffer,size,flags); + _enter("%p{arq=%Zu},%p,%Zd,%x", + call, call->app_ready_qty, buffer, size, flags); spin_lock(&call->lock); @@ -1744,9 +1852,10 @@ ret = __rxrpc_call_read_data(call); switch (ret) { case 0: - if (flags&RXRPC_CALL_READ_ALL && (!call->app_last_rcv || call->app_ready_qty>0)) { + if (flags & RXRPC_CALL_READ_ALL && + (!call->app_last_rcv || call->app_ready_qty > 0)) { _leave(" = -EBADMSG"); - __rxrpc_call_abort(call,-EBADMSG); + __rxrpc_call_abort(call, -EBADMSG); return -EBADMSG; } @@ -1757,18 +1866,18 @@ case -ECONNABORTED: spin_unlock(&call->lock); - _leave(" = %d [aborted]",ret); + _leave(" = %d [aborted]", ret); return ret; - default: - __rxrpc_call_abort(call,ret); - _leave(" = %d",ret); + default: + __rxrpc_call_abort(call, ret); + _leave(" = %d", ret); return ret; case -EAGAIN: spin_unlock(&call->lock); - if (!(flags&RXRPC_CALL_READ_BLOCK)) { + if (!(flags & RXRPC_CALL_READ_BLOCK)) { _leave(" = -EAGAIN"); return -EAGAIN; } @@ -1789,7 +1898,7 @@ return -EINTR; } - if (call->app_call_state==RXRPC_CSTATE_ERROR) { + if (call->app_call_state == RXRPC_CSTATE_ERROR) { _leave(" = -ECONNABORTED"); return -ECONNABORTED; } @@ -1804,8 +1913,8 @@ /* * write data to a call * - the data may not be sent immediately if it doesn't fill a buffer - * - if we can't queue all the data for buffering now, siov[] will have been adjusted to take - * account of what has been sent + * - if we can't queue all the data for buffering now, siov[] will have been + * adjusted to take account of what has been sent */ int rxrpc_call_write_data(struct rxrpc_call *call, size_t sioc, @@ -1821,7 +1930,9 @@ char *buf; int ret; - _enter("%p,%Zu,%p,%02x,%x,%d,%p",call,sioc,siov,rxhdr_flags,alloc_flags,dup_data,size_sent); + _enter("%p,%Zu,%p,%02x,%x,%d,%p", + call, sioc, siov, rxhdr_flags, alloc_flags, dup_data, + size_sent); *size_sent = 0; size = 0; @@ -1840,8 +1951,9 @@ /* calculate how much data we've been given */ sptr = siov; - for (; sioc>0; sptr++, sioc--) { - if (!sptr->iov_len) continue; + for (; sioc > 0; sptr++, sioc--) { + if (!sptr->iov_len) + continue; if (!sptr->iov_base) goto out; @@ -1849,27 +1961,30 @@ size += sptr->iov_len; } - _debug("- size=%Zu mtu=%Zu",size,call->conn->mtu_size); + _debug("- size=%Zu mtu=%Zu", size, call->conn->mtu_size); do { /* make sure there's a message under construction */ if (!call->snd_nextmsg) { /* no - allocate a message with no data yet attached */ - ret = rxrpc_conn_newmsg(call->conn,call,RXRPC_PACKET_TYPE_DATA, - 0,NULL,alloc_flags,&call->snd_nextmsg); - if (ret<0) + ret = rxrpc_conn_newmsg(call->conn, call, + RXRPC_PACKET_TYPE_DATA, + 0, NULL, alloc_flags, + &call->snd_nextmsg); + if (ret < 0) goto out; - _debug("- allocated new message [ds=%Zu]",call->snd_nextmsg->dsize); + _debug("- allocated new message [ds=%Zu]", + call->snd_nextmsg->dsize); } msg = call->snd_nextmsg; msg->hdr.flags |= rxhdr_flags; /* deal with zero-length terminal packet */ - if (size==0) { + if (size == 0) { if (rxhdr_flags & RXRPC_LAST_PACKET) { ret = rxrpc_call_flush(call); - if (ret<0) + if (ret < 0) goto out; } break; @@ -1877,24 +1992,27 @@ /* work out how much space current packet has available */ space = call->conn->mtu_size - msg->dsize; - chunk = min(space,size); + chunk = min(space, size); - _debug("- [before] space=%Zu chunk=%Zu",space,chunk); + _debug("- [before] space=%Zu chunk=%Zu", space, chunk); while (!siov->iov_len) siov++; - /* if we are going to have to duplicate the data then coalesce it too */ + /* if we are going to have to duplicate the data then coalesce + * it too */ if (dup_data) { /* don't allocate more that 1 page at a time */ - if (chunk>PAGE_SIZE) + if (chunk > PAGE_SIZE) chunk = PAGE_SIZE; /* allocate a data buffer and attach to the message */ - buf = kmalloc(chunk,alloc_flags); + buf = kmalloc(chunk, alloc_flags); if (unlikely(!buf)) { - if (msg->dsize==sizeof(struct rxrpc_header)) { - /* discard an empty msg and wind back the seq counter */ + if (msg->dsize == + sizeof(struct rxrpc_header)) { + /* discard an empty msg and wind back + * the seq counter */ rxrpc_put_message(msg); call->snd_nextmsg = NULL; call->snd_seq_count--; @@ -1905,7 +2023,7 @@ } tmp = msg->dcount++; - set_bit(tmp,&msg->dfree); + set_bit(tmp, &msg->dfree); msg->data[tmp].iov_base = buf; msg->data[tmp].iov_len = chunk; msg->dsize += chunk; @@ -1913,9 +2031,9 @@ size -= chunk; /* load the buffer with data */ - while (chunk>0) { - tmp = min(chunk,siov->iov_len); - memcpy(buf,siov->iov_base,tmp); + while (chunk > 0) { + tmp = min(chunk, siov->iov_len); + memcpy(buf, siov->iov_base, tmp); buf += tmp; siov->iov_base += tmp; siov->iov_len -= tmp; @@ -1926,7 +2044,8 @@ } else { /* we want to attach the supplied buffers directly */ - while (chunk>0 && msg->dcount 0 && + msg->dcount < RXRPC_MSG_MAX_IOCS) { tmp = msg->dcount++; msg->data[tmp].iov_base = siov->iov_base; msg->data[tmp].iov_len = siov->iov_len; @@ -1938,20 +2057,20 @@ } } - _debug("- [loaded] chunk=%Zu size=%Zu",chunk,size); + _debug("- [loaded] chunk=%Zu size=%Zu", chunk, size); /* dispatch the message when full, final or requesting ACK */ - if (msg->dsize>=call->conn->mtu_size || rxhdr_flags) { + if (msg->dsize >= call->conn->mtu_size || rxhdr_flags) { ret = rxrpc_call_flush(call); - if (ret<0) + if (ret < 0) goto out; } - } while(size>0); + } while(size > 0); ret = 0; out: - _leave(" = %d (%Zd queued, %Zd rem)",ret,*size_sent,size); + _leave(" = %d (%Zd queued, %Zd rem)", ret, *size_sent, size); return ret; } /* end rxrpc_call_write_data() */ @@ -1965,7 +2084,7 @@ struct rxrpc_message *msg; int ret = 0; - _enter("%p",call); + _enter("%p", call); rxrpc_get_call(call); @@ -1983,25 +2102,28 @@ } _proto("Sending DATA message { ds=%Zu dc=%u df=%02lu }", - msg->dsize,msg->dcount,msg->dfree); + msg->dsize, msg->dcount, msg->dfree); /* queue and adjust call state */ spin_lock(&call->lock); - list_add_tail(&msg->link,&call->acks_pendq); + list_add_tail(&msg->link, &call->acks_pendq); - /* decide what to do depending on current state and if this is the last packet */ + /* decide what to do depending on current state and if this is + * the last packet */ ret = -EINVAL; switch (call->app_call_state) { case RXRPC_CSTATE_SRVR_SND_REPLY: if (msg->hdr.flags & RXRPC_LAST_PACKET) { - call->app_call_state = RXRPC_CSTATE_SRVR_RCV_FINAL_ACK; + call->app_call_state = + RXRPC_CSTATE_SRVR_RCV_FINAL_ACK; _state(call); } break; case RXRPC_CSTATE_CLNT_SND_ARGS: if (msg->hdr.flags & RXRPC_LAST_PACKET) { - call->app_call_state = RXRPC_CSTATE_CLNT_RCV_REPLY; + call->app_call_state = + RXRPC_CSTATE_CLNT_RCV_REPLY; _state(call); } break; @@ -2016,19 +2138,20 @@ call->acks_pend_cnt++; mod_timer(&call->acks_timeout, - __rxrpc_rtt_based_timeout(call,rxrpc_call_acks_timeout)); + __rxrpc_rtt_based_timeout(call, + rxrpc_call_acks_timeout)); spin_unlock(&call->lock); - ret = rxrpc_conn_sendmsg(call->conn,msg); - if (ret==0) + ret = rxrpc_conn_sendmsg(call->conn, msg); + if (ret == 0) call->pkt_snd_count++; } out: rxrpc_put_call(call); - _leave(" = %d",ret); + _leave(" = %d", ret); return ret; } /* end rxrpc_call_flush() */ @@ -2043,14 +2166,16 @@ struct list_head *_p; rxrpc_seq_t seq = 0; - _enter("%p,%u",call,highest); + _enter("%p,%u", call, highest); _proto("Rx Resend required"); /* handle too many resends */ - if (call->snd_resend_cnt>=rxrpc_call_max_resend) { - _debug("Aborting due to too many resends (rcv=%d)",call->pkt_rcv_count); - rxrpc_call_abort(call,call->pkt_rcv_count>0?-EIO:-ETIMEDOUT); + if (call->snd_resend_cnt >= rxrpc_call_max_resend) { + _debug("Aborting due to too many resends (rcv=%d)", + call->pkt_rcv_count); + rxrpc_call_abort(call, + call->pkt_rcv_count > 0 ? -EIO : -ETIMEDOUT); _leave(""); return; } @@ -2059,35 +2184,38 @@ call->snd_resend_cnt++; for (;;) { /* determine which the next packet we might need to ACK is */ - if (seq<=call->acks_dftv_seq) + if (seq <= call->acks_dftv_seq) seq = call->acks_dftv_seq; seq++; - if (seq>highest) + if (seq > highest) break; /* look for the packet in the pending-ACK queue */ - list_for_each(_p,&call->acks_pendq) { - msg = list_entry(_p,struct rxrpc_message,link); - if (msg->seq==seq) + list_for_each(_p, &call->acks_pendq) { + msg = list_entry(_p, struct rxrpc_message, link); + if (msg->seq == seq) goto found_msg; } - panic("%s(%p,%d): Inconsistent pending-ACK queue (ds=%u sc=%u sq=%u)\n", - __FUNCTION__,call,highest,call->acks_dftv_seq,call->snd_seq_count,seq); + panic("%s(%p,%d):" + " Inconsistent pending-ACK queue (ds=%u sc=%u sq=%u)\n", + __FUNCTION__, call, highest, + call->acks_dftv_seq, call->snd_seq_count, seq); found_msg: - if (msg->state!=RXRPC_MSG_SENT) + if (msg->state != RXRPC_MSG_SENT) continue; /* only un-ACK'd packets */ rxrpc_get_message(msg); spin_unlock(&call->lock); - /* send each message again (and ignore any errors we might incur) */ + /* send each message again (and ignore any errors we might + * incur) */ _proto("Resending DATA message { ds=%Zu dc=%u df=%02lu }", - msg->dsize,msg->dcount,msg->dfree); + msg->dsize, msg->dcount, msg->dfree); - if (rxrpc_conn_sendmsg(call->conn,msg)==0) + if (rxrpc_conn_sendmsg(call->conn, msg) == 0) call->pkt_snd_count++; rxrpc_put_message(msg); @@ -2096,7 +2224,8 @@ } /* reset the timeout */ - mod_timer(&call->acks_timeout,__rxrpc_rtt_based_timeout(call,rxrpc_call_acks_timeout)); + mod_timer(&call->acks_timeout, + __rxrpc_rtt_based_timeout(call, rxrpc_call_acks_timeout)); spin_unlock(&call->lock); @@ -2109,10 +2238,10 @@ */ void rxrpc_call_handle_error(struct rxrpc_call *call, int local, int errno) { - _enter("%p{%u},%d",call,ntohl(call->call_id),errno); + _enter("%p{%u},%d", call, ntohl(call->call_id), errno); /* if this call is already aborted, then just wake up any waiters */ - if (call->app_call_state==RXRPC_CSTATE_ERROR) { + if (call->app_call_state == RXRPC_CSTATE_ERROR) { call->app_error_func(call); } else { @@ -2124,10 +2253,10 @@ call->app_err_state = RXRPC_ESTATE_LOCAL_ERROR; else call->app_err_state = RXRPC_ESTATE_REMOTE_ERROR; - call->app_errno = errno; - call->app_mark = RXRPC_APP_MARK_EOF; - call->app_read_buf = NULL; - call->app_async_read = 0; + call->app_errno = errno; + call->app_mark = RXRPC_APP_MARK_EOF; + call->app_read_buf = NULL; + call->app_async_read = 0; /* map the error */ call->app_aemap_func(call); diff -Nru a/net/rxrpc/connection.c b/net/rxrpc/connection.c --- a/net/rxrpc/connection.c Thu Sep 11 23:03:13 2003 +++ b/net/rxrpc/connection.c Thu Sep 11 23:03:13 2003 @@ -28,18 +28,20 @@ LIST_HEAD(rxrpc_conns); DECLARE_RWSEM(rxrpc_conns_sem); +unsigned long rxrpc_conn_timeout = 60 * 60; static void __rxrpc_conn_timeout(rxrpc_timer_t *timer) { - struct rxrpc_connection *conn = list_entry(timer,struct rxrpc_connection,timeout); + struct rxrpc_connection *conn = + list_entry(timer, struct rxrpc_connection, timeout); - _debug("Rx CONN TIMEOUT [%p{u=%d}]",conn,atomic_read(&conn->usage)); + _debug("Rx CONN TIMEOUT [%p{u=%d}]", conn, atomic_read(&conn->usage)); rxrpc_conn_do_timeout(conn); } static const struct rxrpc_timer_ops rxrpc_conn_timer_ops = { - .timed_out = __rxrpc_conn_timeout, + timed_out: __rxrpc_conn_timeout, }; /*****************************************************************************/ @@ -54,19 +56,20 @@ _enter("%p",peer); /* allocate and initialise a connection record */ - conn = kmalloc(sizeof(struct rxrpc_connection),GFP_KERNEL); + conn = kmalloc(sizeof(struct rxrpc_connection), GFP_KERNEL); if (!conn) { _leave(" = -ENOMEM"); return -ENOMEM; } - memset(conn,0,sizeof(struct rxrpc_connection)); - atomic_set(&conn->usage,1); + memset(conn, 0, sizeof(struct rxrpc_connection)); + atomic_set(&conn->usage, 1); INIT_LIST_HEAD(&conn->link); + INIT_LIST_HEAD(&conn->id_link); init_waitqueue_head(&conn->chanwait); spin_lock_init(&conn->lock); - rxrpc_timer_init(&conn->timeout,&rxrpc_conn_timer_ops); + rxrpc_timer_init(&conn->timeout, &rxrpc_conn_timer_ops); do_gettimeofday(&conn->atime); conn->mtu_size = 1024; @@ -75,7 +78,7 @@ __RXACCT(atomic_inc(&rxrpc_connection_count)); *_conn = conn; - _leave(" = 0 (%p)",conn); + _leave(" = 0 (%p)", conn); return 0; } /* end __rxrpc_create_connection() */ @@ -85,61 +88,123 @@ * create a new connection record for outgoing connections */ int rxrpc_create_connection(struct rxrpc_transport *trans, - u16 port, - u32 addr, - unsigned short service_id, + uint16_t port, + uint32_t addr, + uint16_t service_id, void *security, struct rxrpc_connection **_conn) { - struct rxrpc_connection *conn; + struct rxrpc_connection *candidate, *conn; struct rxrpc_peer *peer; + struct list_head *_p; + uint32_t connid; int ret; - _enter("%p{%hu},%u,%hu",trans,trans->port,ntohs(port),service_id); + _enter("%p{%hu},%u,%hu", trans, trans->port, ntohs(port), service_id); /* get a peer record */ - ret = rxrpc_peer_lookup(trans,addr,&peer); - if (ret<0) { - _leave(" = %d",ret); + ret = rxrpc_peer_lookup(trans, addr, &peer); + if (ret < 0) { + _leave(" = %d", ret); return ret; } /* allocate and initialise a connection record */ - ret = __rxrpc_create_connection(peer,&conn); - if (ret<0) { + ret = __rxrpc_create_connection(peer, &candidate); + if (ret < 0) { rxrpc_put_peer(peer); - _leave(" = %d",ret); + _leave(" = %d", ret); return ret; } /* fill in the specific bits */ - conn->addr.sin_family = AF_INET; - conn->addr.sin_port = port; - conn->addr.sin_addr.s_addr = addr; - - conn->in_epoch = rxrpc_epoch; - conn->out_epoch = rxrpc_epoch; - conn->in_clientflag = 0; - conn->out_clientflag = RXRPC_CLIENT_INITIATED; - conn->conn_id = htonl((unsigned long) conn & RXRPC_CIDMASK); - conn->service_id = htons(service_id); + candidate->addr.sin_family = AF_INET; + candidate->addr.sin_port = port; + candidate->addr.sin_addr.s_addr = addr; + + candidate->in_epoch = rxrpc_epoch; + candidate->out_epoch = rxrpc_epoch; + candidate->in_clientflag = 0; + candidate->out_clientflag = RXRPC_CLIENT_INITIATED; + candidate->service_id = htons(service_id); + + /* invent a unique connection ID */ + write_lock(&peer->conn_idlock); + + try_next_id: + connid = htonl(peer->conn_idcounter & RXRPC_CIDMASK); + peer->conn_idcounter += RXRPC_MAXCALLS; + + list_for_each(_p, &peer->conn_idlist) { + conn = list_entry(_p, struct rxrpc_connection, id_link); + if (connid == conn->conn_id) + goto try_next_id; + if (connid > conn->conn_id) + break; + } + + _debug("selected candidate conn ID %x.%u", + ntohl(peer->addr.s_addr), ntohl(connid)); + + candidate->conn_id = connid; + list_add_tail(&candidate->id_link, _p); + + write_unlock(&peer->conn_idlock); /* attach to peer */ - conn->peer = peer; + candidate->peer = peer; write_lock(&peer->conn_lock); - list_add_tail(&conn->link,&peer->conn_active); + + /* search the peer's transport graveyard list */ + spin_lock(&peer->conn_gylock); + list_for_each(_p, &peer->conn_graveyard) { + conn = list_entry(_p, struct rxrpc_connection, link); + if (conn->addr.sin_port == candidate->addr.sin_port && + conn->security_ix == candidate->security_ix && + conn->service_id == candidate->service_id && + conn->in_clientflag == 0) + goto found_in_graveyard; + } + spin_unlock(&peer->conn_gylock); + + /* pick the new candidate */ + _debug("created connection: {%08x} [out]", htonl(candidate->conn_id)); atomic_inc(&peer->conn_count); + conn = candidate; + candidate = NULL; + + make_active: + list_add_tail(&conn->link, &peer->conn_active); write_unlock(&peer->conn_lock); - down_write(&rxrpc_conns_sem); - list_add_tail(&conn->proc_link,&rxrpc_conns); - up_write(&rxrpc_conns_sem); + if (candidate) { + write_lock(&peer->conn_idlock); + list_del(&candidate->id_link); + write_unlock(&peer->conn_idlock); + + __RXACCT(atomic_dec(&rxrpc_connection_count)); + kfree(candidate); + } + else { + down_write(&rxrpc_conns_sem); + list_add_tail(&conn->proc_link, &rxrpc_conns); + up_write(&rxrpc_conns_sem); + } *_conn = conn; - _leave(" = 0 (%p)",conn); + _leave(" = 0 (%p)", conn); return 0; + + /* handle resurrecting a connection from the graveyard */ + found_in_graveyard: + _debug("resurrecting connection: {%08x} [out]", htonl(conn->conn_id)); + rxrpc_get_connection(conn); + rxrpc_krxtimod_del_timer(&conn->timeout); + list_del_init(&conn->link); + spin_unlock(&peer->conn_gylock); + goto make_active; } /* end rxrpc_create_connection() */ /*****************************************************************************/ @@ -159,7 +224,10 @@ u8 x_clflag; _enter("%p{{%hu}},%u,%hu", - peer,peer->trans->port,ntohs(msg->pkt->h.uh->source),ntohs(msg->hdr.serviceId)); + peer, + peer->trans->port, + ntohs(msg->pkt->h.uh->source), + ntohs(msg->hdr.serviceId)); x_port = msg->pkt->h.uh->source; x_epoch = msg->hdr.epoch; @@ -170,8 +238,8 @@ /* [common case] search the transport's active list first */ read_lock(&peer->conn_lock); - list_for_each(_p,&peer->conn_active) { - conn = list_entry(_p,struct rxrpc_connection,link); + list_for_each(_p, &peer->conn_active) { + conn = list_entry(_p, struct rxrpc_connection, link); if (conn->addr.sin_port == x_port && conn->in_epoch == x_epoch && conn->conn_id == x_connid && @@ -187,9 +255,9 @@ * - only examine the graveyard for an outbound connection */ if (x_clflag) { - ret = __rxrpc_create_connection(peer,&candidate); - if (ret<0) { - _leave(" = %d",ret); + ret = __rxrpc_create_connection(peer, &candidate); + if (ret < 0) { + _leave(" = %d", ret); return ret; } @@ -206,10 +274,11 @@ candidate->security_ix = x_secix; } - /* search the active list again, just in case it appeared whilst we were busy */ + /* search the active list again, just in case it appeared whilst we + * were busy */ write_lock(&peer->conn_lock); - list_for_each(_p,&peer->conn_active) { - conn = list_entry(_p,struct rxrpc_connection,link); + list_for_each(_p, &peer->conn_active) { + conn = list_entry(_p, struct rxrpc_connection, link); if (conn->addr.sin_port == x_port && conn->in_epoch == x_epoch && conn->conn_id == x_connid && @@ -221,8 +290,8 @@ /* search the transport's graveyard list */ spin_lock(&peer->conn_gylock); - list_for_each(_p,&peer->conn_graveyard) { - conn = list_entry(_p,struct rxrpc_connection,link); + list_for_each(_p, &peer->conn_graveyard) { + conn = list_entry(_p, struct rxrpc_connection, link); if (conn->addr.sin_port == x_port && conn->in_epoch == x_epoch && conn->conn_id == x_connid && @@ -241,6 +310,7 @@ } /* we can now add the new candidate to the list */ + _debug("created connection: {%08x} [in]", htonl(candidate->conn_id)); rxrpc_get_peer(peer); conn = candidate; candidate = NULL; @@ -248,25 +318,29 @@ fresh = 1; make_active: - list_add_tail(&conn->link,&peer->conn_active); + list_add_tail(&conn->link, &peer->conn_active); success_uwfree: write_unlock(&peer->conn_lock); if (candidate) { + write_lock(&peer->conn_idlock); + list_del(&candidate->id_link); + write_unlock(&peer->conn_idlock); + __RXACCT(atomic_dec(&rxrpc_connection_count)); kfree(candidate); } if (fresh) { down_write(&rxrpc_conns_sem); - list_add_tail(&conn->proc_link,&rxrpc_conns); + list_add_tail(&conn->proc_link, &rxrpc_conns); up_write(&rxrpc_conns_sem); } success: *_conn = conn; - _leave(" = 0 (%p)",conn); + _leave(" = 0 (%p)", conn); return 0; /* handle the connection being found in the active list straight off */ @@ -277,6 +351,7 @@ /* handle resurrecting a connection from the graveyard */ found_in_graveyard: + _debug("resurrecting connection: {%08x} [in]", htonl(conn->conn_id)); rxrpc_get_peer(peer); rxrpc_get_connection(conn); rxrpc_krxtimod_del_timer(&conn->timeout); @@ -284,7 +359,8 @@ spin_unlock(&peer->conn_gylock); goto make_active; - /* handle finding the connection on the second time through the active list */ + /* handle finding the connection on the second time through the active + * list */ found_active_second_chance: rxrpc_get_connection(conn); goto success_uwfree; @@ -294,19 +370,26 @@ /*****************************************************************************/ /* * finish using a connection record - * - it will be transferred to the peer's connection graveyard when refcount reaches 0 + * - it will be transferred to the peer's connection graveyard when refcount + * reaches 0 */ void rxrpc_put_connection(struct rxrpc_connection *conn) { - struct rxrpc_peer *peer = conn->peer; + struct rxrpc_peer *peer; + + if (!conn) + return; + + _enter("%p{u=%d p=%hu}", + conn, atomic_read(&conn->usage), ntohs(conn->addr.sin_port)); - _enter("%p{u=%d p=%hu}",conn,atomic_read(&conn->usage),ntohs(conn->addr.sin_port)); + peer = conn->peer; + spin_lock(&peer->conn_gylock); /* sanity check */ - if (atomic_read(&conn->usage)<=0) + if (atomic_read(&conn->usage) <= 0) BUG(); - spin_lock(&peer->conn_gylock); if (likely(!atomic_dec_and_test(&conn->usage))) { spin_unlock(&peer->conn_gylock); _leave(""); @@ -314,11 +397,11 @@ } /* move to graveyard queue */ + _debug("burying connection: {%08x}", htonl(conn->conn_id)); list_del(&conn->link); - list_add_tail(&conn->link,&peer->conn_graveyard); + list_add_tail(&conn->link, &peer->conn_graveyard); - /* discard in 100 secs */ - rxrpc_krxtimod_add_timer(&conn->timeout,20*HZ); + rxrpc_krxtimod_add_timer(&conn->timeout, rxrpc_conn_timeout * HZ); spin_unlock(&peer->conn_gylock); @@ -335,16 +418,17 @@ { struct rxrpc_peer *peer; - _enter("%p{u=%d p=%hu}",conn,atomic_read(&conn->usage),ntohs(conn->addr.sin_port)); + _enter("%p{u=%d p=%hu}", + conn, atomic_read(&conn->usage), ntohs(conn->addr.sin_port)); peer = conn->peer; - if (atomic_read(&conn->usage)<0) + if (atomic_read(&conn->usage) < 0) BUG(); /* remove from graveyard if still dead */ spin_lock(&peer->conn_gylock); - if (atomic_read(&conn->usage)==0) { + if (atomic_read(&conn->usage) == 0) { list_del_init(&conn->link); } else { @@ -357,12 +441,17 @@ return; /* resurrected */ } - _debug("--- Destroying Connection %p ---",conn); + _debug("--- Destroying Connection %p{%08x} ---", + conn, htonl(conn->conn_id)); down_write(&rxrpc_conns_sem); list_del(&conn->proc_link); up_write(&rxrpc_conns_sem); + write_lock(&peer->conn_idlock); + list_del(&conn->id_link); + write_unlock(&peer->conn_idlock); + __RXACCT(atomic_dec(&rxrpc_connection_count)); kfree(conn); @@ -379,12 +468,12 @@ */ void rxrpc_conn_clearall(struct rxrpc_peer *peer) { - DECLARE_WAITQUEUE(myself,current); + DECLARE_WAITQUEUE(myself, current); struct rxrpc_connection *conn; int err; - _enter("%p",peer); + _enter("%p", peer); /* there shouldn't be any active conns remaining */ if (!list_empty(&peer->conn_active)) @@ -393,11 +482,12 @@ /* manually timeout all conns in the graveyard */ spin_lock(&peer->conn_gylock); while (!list_empty(&peer->conn_graveyard)) { - conn = list_entry(peer->conn_graveyard.next,struct rxrpc_connection,link); + conn = list_entry(peer->conn_graveyard.next, + struct rxrpc_connection, link); err = rxrpc_krxtimod_del_timer(&conn->timeout); spin_unlock(&peer->conn_gylock); - if (err==0) + if (err == 0) rxrpc_conn_do_timeout(conn); spin_lock(&peer->conn_gylock); @@ -406,27 +496,27 @@ /* wait for the the conn graveyard to be completely cleared */ set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&peer->conn_gy_waitq,&myself); + add_wait_queue(&peer->conn_gy_waitq, &myself); - while (atomic_read(&peer->conn_count)!=0) { + while (atomic_read(&peer->conn_count) != 0) { schedule(); set_current_state(TASK_UNINTERRUPTIBLE); } - remove_wait_queue(&peer->conn_gy_waitq,&myself); + remove_wait_queue(&peer->conn_gy_waitq, &myself); set_current_state(TASK_RUNNING); _leave(""); - } /* end rxrpc_conn_clearall() */ /*****************************************************************************/ /* - * allocate and prepare a message for sending out through the transport endpoint + * allocate and prepare a message for sending out through the transport + * endpoint */ int rxrpc_conn_newmsg(struct rxrpc_connection *conn, struct rxrpc_call *call, - u8 type, + uint8_t type, int dcount, struct iovec diov[], int alloc_flags, @@ -435,21 +525,21 @@ struct rxrpc_message *msg; int loop; - _enter("%p{%d},%p,%u",conn,ntohs(conn->addr.sin_port),call,type); + _enter("%p{%d},%p,%u", conn, ntohs(conn->addr.sin_port), call, type); - if (dcount>3) { + if (dcount > 3) { _leave(" = -EINVAL"); return -EINVAL; } - msg = kmalloc(sizeof(struct rxrpc_message),alloc_flags); + msg = kmalloc(sizeof(struct rxrpc_message), alloc_flags); if (!msg) { _leave(" = -ENOMEM"); return -ENOMEM; } - memset(msg,0,sizeof(*msg)); - atomic_set(&msg->usage,1); + memset(msg, 0, sizeof(*msg)); + atomic_set(&msg->usage, 1); INIT_LIST_HEAD(&msg->link); @@ -471,7 +561,8 @@ msg->hdr.seq = htonl(msg->seq); break; case RXRPC_PACKET_TYPE_ACK: - /* ACK sequence numbers are complicated. The following may be wrong: + /* ACK sequence numbers are complicated. The following + * may be wrong: * - jumbo packet ACKs should have a seq number * - normal ACKs should not */ @@ -485,7 +576,7 @@ msg->data[0].iov_len = sizeof(msg->hdr); msg->data[0].iov_base = &msg->hdr; - for (loop=0; loopdsize += diov[loop].iov_len; msg->data[loop+1].iov_len = diov[loop].iov_len; msg->data[loop+1].iov_base = diov[loop].iov_base; @@ -493,7 +584,7 @@ __RXACCT(atomic_inc(&rxrpc_message_count)); *_msg = msg; - _leave(" = 0 (%p) #%d",msg,atomic_read(&rxrpc_message_count)); + _leave(" = 0 (%p) #%d", msg, atomic_read(&rxrpc_message_count)); return 0; } /* end rxrpc_conn_newmsg() */ @@ -505,13 +596,14 @@ { int loop; - _enter("%p #%d",msg,atomic_read(&rxrpc_message_count)); + _enter("%p #%d", msg, atomic_read(&rxrpc_message_count)); - if (msg->pkt) kfree_skb(msg->pkt); - if (msg->conn) rxrpc_put_connection(msg->conn); + if (msg->pkt) + kfree_skb(msg->pkt); + rxrpc_put_connection(msg->conn); - for (loop=0; loop<8; loop++) - if (test_bit(loop,&msg->dfree)) + for (loop = 0; loop < 8; loop++) + if (test_bit(loop, &msg->dfree)) kfree(msg->data[loop].iov_base); __RXACCT(atomic_dec(&rxrpc_message_count)); @@ -524,13 +616,14 @@ /* * send a message out through the transport endpoint */ -int rxrpc_conn_sendmsg(struct rxrpc_connection *conn, struct rxrpc_message *msg) +int rxrpc_conn_sendmsg(struct rxrpc_connection *conn, + struct rxrpc_message *msg) { struct msghdr msghdr; mm_segment_t oldfs; int ret; - _enter("%p{%d}",conn,ntohs(conn->addr.sin_port)); + _enter("%p{%d}", conn, ntohs(conn->addr.sin_port)); /* fill in some fields in the header */ spin_lock(&conn->lock); @@ -545,7 +638,7 @@ msghdr.msg_iovlen = msg->dcount; msghdr.msg_control = NULL; msghdr.msg_controllen = 0; - msghdr.msg_flags = MSG_CONFIRM|MSG_DONTWAIT; + msghdr.msg_flags = MSG_CONFIRM | MSG_DONTWAIT; _net("Sending message type %d of %Zd bytes to %08x:%d", msg->hdr.type, @@ -556,10 +649,10 @@ /* send the message */ oldfs = get_fs(); set_fs(KERNEL_DS); - ret = sock_sendmsg(conn->trans->socket,&msghdr,msg->dsize); + ret = sock_sendmsg(conn->trans->socket, &msghdr, msg->dsize); set_fs(oldfs); - if (ret<0) { + if (ret < 0) { msg->state = RXRPC_MSG_ERROR; } else { @@ -572,7 +665,7 @@ spin_unlock(&conn->lock); } - _leave(" = %d",ret); + _leave(" = %d", ret); return ret; } /* end rxrpc_conn_sendmsg() */ @@ -590,7 +683,7 @@ unsigned cix, seq; int ret = 0; - _enter("%p,%p,%p",conn,call,msg); + _enter("%p,%p,%p", conn, call, msg); if (!call) { cix = ntohl(msg->hdr.cid) & RXRPC_CHANNELMASK; @@ -600,7 +693,7 @@ if (!call || call->call_id != msg->hdr.callNumber) { spin_unlock(&conn->lock); - rxrpc_trans_immediate_abort(conn->trans,msg,-ENOENT); + rxrpc_trans_immediate_abort(conn->trans, msg, -ENOENT); goto out; } else { @@ -622,19 +715,21 @@ call->pkt_rcv_count++; if (msg->pkt->dst && msg->pkt->dst->dev) - conn->peer->if_mtu = msg->pkt->dst->dev->mtu - msg->pkt->dst->dev->hard_header_len; + conn->peer->if_mtu = + msg->pkt->dst->dev->mtu - + msg->pkt->dst->dev->hard_header_len; /* queue on the call in seq order */ rxrpc_get_message(msg); seq = msg->seq; spin_lock(&call->lock); - list_for_each(_p,&call->rcv_receiveq) { - pmsg = list_entry(_p,struct rxrpc_message,link); - if (pmsg->seq>seq) + list_for_each(_p, &call->rcv_receiveq) { + pmsg = list_entry(_p, struct rxrpc_message, link); + if (pmsg->seq > seq) break; } - list_add_tail(&msg->link,_p); + list_add_tail(&msg->link, _p); /* reset the activity timeout */ call->flags |= RXRPC_CALL_RCV_PKT; @@ -646,8 +741,7 @@ rxrpc_put_call(call); out: - _leave(" = %d",ret); - + _leave(" = %d", ret); return ret; } /* end rxrpc_conn_receive_call_packet() */ @@ -655,18 +749,19 @@ /* * handle an ICMP error being applied to a connection */ -void rxrpc_conn_handle_error(struct rxrpc_connection *conn, int local, int errno) +void rxrpc_conn_handle_error(struct rxrpc_connection *conn, + int local, int errno) { struct rxrpc_call *calls[4]; int loop; - _enter("%p{%d},%d",conn,ntohs(conn->addr.sin_port),errno); + _enter("%p{%d},%d", conn, ntohs(conn->addr.sin_port), errno); /* get a ref to all my calls in one go */ - memset(calls,0,sizeof(calls)); + memset(calls, 0, sizeof(calls)); spin_lock(&conn->lock); - for (loop=3; loop>=0; loop--) { + for (loop = 3; loop >= 0; loop--) { if (conn->channels[loop]) { calls[loop] = conn->channels[loop]; rxrpc_get_call(calls[loop]); @@ -676,9 +771,9 @@ spin_unlock(&conn->lock); /* now kick them all */ - for (loop=3; loop>=0; loop--) { + for (loop = 3; loop >= 0; loop--) { if (calls[loop]) { - rxrpc_call_handle_error(calls[loop],local,errno); + rxrpc_call_handle_error(calls[loop], local, errno); rxrpc_put_call(calls[loop]); } } diff -Nru a/net/rxrpc/internal.h b/net/rxrpc/internal.h --- a/net/rxrpc/internal.h Thu Sep 11 23:03:11 2003 +++ b/net/rxrpc/internal.h Thu Sep 11 23:03:11 2003 @@ -55,7 +55,7 @@ siginfo_t sinfo; spin_lock_irq(¤t->sighand->siglock); - dequeue_signal(current,¤t->blocked,&sinfo); + dequeue_signal(current, ¤t->blocked, &sinfo); spin_unlock_irq(¤t->sighand->siglock); } } @@ -71,6 +71,7 @@ */ extern struct list_head rxrpc_conns; extern struct rw_semaphore rxrpc_conns_sem; +extern unsigned long rxrpc_conn_timeout; extern void rxrpc_conn_do_timeout(struct rxrpc_connection *conn); extern void rxrpc_conn_clearall(struct rxrpc_peer *peer); @@ -80,6 +81,7 @@ */ extern struct list_head rxrpc_peers; extern struct rw_semaphore rxrpc_peers_sem; +extern unsigned long rxrpc_peer_timeout; extern void rxrpc_peer_calculate_rtt(struct rxrpc_peer *peer, struct rxrpc_message *msg, diff -Nru a/net/rxrpc/krxiod.c b/net/rxrpc/krxiod.c --- a/net/rxrpc/krxiod.c Thu Sep 11 23:03:11 2003 +++ b/net/rxrpc/krxiod.c Thu Sep 11 23:03:11 2003 @@ -44,6 +44,12 @@ daemonize("krxiod"); + /* only certain signals are of interest */ + spin_lock_irq(¤t->sighand->siglock); + siginitsetinv(¤t->blocked, 0); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + /* loop around waiting for work to do */ do { /* wait for work or to be told to exit */ @@ -51,7 +57,7 @@ if (!atomic_read(&rxrpc_krxiod_qcount)) { set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&rxrpc_krxiod_sleepq,&krxiod); + add_wait_queue(&rxrpc_krxiod_sleepq, &krxiod); for (;;) { set_current_state(TASK_INTERRUPTIBLE); @@ -63,7 +69,7 @@ schedule(); } - remove_wait_queue(&rxrpc_krxiod_sleepq,&krxiod); + remove_wait_queue(&rxrpc_krxiod_sleepq, &krxiod); set_current_state(TASK_RUNNING); } _debug("### End Wait"); @@ -78,12 +84,16 @@ spin_lock_irq(&rxrpc_krxiod_transportq_lock); if (!list_empty(&rxrpc_krxiod_transportq)) { - trans = list_entry(rxrpc_krxiod_transportq.next, - struct rxrpc_transport,krxiodq_link); + trans = list_entry( + rxrpc_krxiod_transportq.next, + struct rxrpc_transport, + krxiodq_link); + list_del_init(&trans->krxiodq_link); atomic_dec(&rxrpc_krxiod_qcount); - /* make sure it hasn't gone away and doesn't go away */ + /* make sure it hasn't gone away and doesn't go + * away */ if (atomic_read(&trans->usage)>0) rxrpc_get_transport(trans); else @@ -106,13 +116,16 @@ if (!list_empty(&rxrpc_krxiod_callq)) { call = list_entry(rxrpc_krxiod_callq.next, - struct rxrpc_call,rcv_krxiodq_lk); + struct rxrpc_call, + rcv_krxiodq_lk); list_del_init(&call->rcv_krxiodq_lk); atomic_dec(&rxrpc_krxiod_qcount); - /* make sure it hasn't gone away and doesn't go away */ - if (atomic_read(&call->usage)>0) { - _debug("@@@ KRXIOD Begin Attend Call %p",call); + /* make sure it hasn't gone away and doesn't go + * away */ + if (atomic_read(&call->usage) > 0) { + _debug("@@@ KRXIOD" + " Begin Attend Call %p",call); rxrpc_get_call(call); } else { @@ -125,7 +138,7 @@ if (call) { rxrpc_call_do_stuff(call); rxrpc_put_call(call); - _debug("@@@ KRXIOD End Attend Call %p",call); + _debug("@@@ KRXIOD End Attend Call %p", call); } } @@ -137,7 +150,7 @@ } while (!rxrpc_krxiod_die); /* and that's all */ - complete_and_exit(&rxrpc_krxiod_dead,0); + complete_and_exit(&rxrpc_krxiod_dead, 0); } /* end rxrpc_krxiod() */ @@ -147,7 +160,7 @@ */ int __init rxrpc_krxiod_init(void) { - return kernel_thread(rxrpc_krxiod,NULL,0); + return kernel_thread(rxrpc_krxiod, NULL, 0); } /* end rxrpc_krxiod_init() */ @@ -174,16 +187,17 @@ _enter(""); if (list_empty(&trans->krxiodq_link)) { - spin_lock_irqsave(&rxrpc_krxiod_transportq_lock,flags); + spin_lock_irqsave(&rxrpc_krxiod_transportq_lock, flags); if (list_empty(&trans->krxiodq_link)) { - if (atomic_read(&trans->usage)>0) { - list_add_tail(&trans->krxiodq_link,&rxrpc_krxiod_transportq); + if (atomic_read(&trans->usage) > 0) { + list_add_tail(&trans->krxiodq_link, + &rxrpc_krxiod_transportq); atomic_inc(&rxrpc_krxiod_qcount); } } - spin_unlock_irqrestore(&rxrpc_krxiod_transportq_lock,flags); + spin_unlock_irqrestore(&rxrpc_krxiod_transportq_lock, flags); wake_up_all(&rxrpc_krxiod_sleepq); } @@ -201,12 +215,12 @@ _enter(""); - spin_lock_irqsave(&rxrpc_krxiod_transportq_lock,flags); + spin_lock_irqsave(&rxrpc_krxiod_transportq_lock, flags); if (!list_empty(&trans->krxiodq_link)) { list_del_init(&trans->krxiodq_link); atomic_dec(&rxrpc_krxiod_qcount); } - spin_unlock_irqrestore(&rxrpc_krxiod_transportq_lock,flags); + spin_unlock_irqrestore(&rxrpc_krxiod_transportq_lock, flags); _leave(""); @@ -221,15 +235,16 @@ unsigned long flags; if (list_empty(&call->rcv_krxiodq_lk)) { - spin_lock_irqsave(&rxrpc_krxiod_callq_lock,flags); - if (atomic_read(&call->usage)>0) { - list_add_tail(&call->rcv_krxiodq_lk,&rxrpc_krxiod_callq); + spin_lock_irqsave(&rxrpc_krxiod_callq_lock, flags); + if (atomic_read(&call->usage) > 0) { + list_add_tail(&call->rcv_krxiodq_lk, + &rxrpc_krxiod_callq); atomic_inc(&rxrpc_krxiod_qcount); } - spin_unlock_irqrestore(&rxrpc_krxiod_callq_lock,flags); + spin_unlock_irqrestore(&rxrpc_krxiod_callq_lock, flags); } wake_up_all(&rxrpc_krxiod_sleepq); - + } /* end rxrpc_krxiod_queue_call() */ /*****************************************************************************/ @@ -240,11 +255,11 @@ { unsigned long flags; - spin_lock_irqsave(&rxrpc_krxiod_callq_lock,flags); + spin_lock_irqsave(&rxrpc_krxiod_callq_lock, flags); if (!list_empty(&call->rcv_krxiodq_lk)) { list_del_init(&call->rcv_krxiodq_lk); atomic_dec(&rxrpc_krxiod_qcount); } - spin_unlock_irqrestore(&rxrpc_krxiod_callq_lock,flags); + spin_unlock_irqrestore(&rxrpc_krxiod_callq_lock, flags); } /* end rxrpc_krxiod_dequeue_call() */ diff -Nru a/net/rxrpc/krxsecd.c b/net/rxrpc/krxsecd.c --- a/net/rxrpc/krxsecd.c Thu Sep 11 23:03:11 2003 +++ b/net/rxrpc/krxsecd.c Thu Sep 11 23:03:11 2003 @@ -36,7 +36,8 @@ static atomic_t rxrpc_krxsecd_qcount; -/* queue of unprocessed inbound messages with seqno #1 and RXRPC_CLIENT_INITIATED flag set */ +/* queue of unprocessed inbound messages with seqno #1 and + * RXRPC_CLIENT_INITIATED flag set */ static LIST_HEAD(rxrpc_krxsecd_initmsgq); static spinlock_t rxrpc_krxsecd_initmsgq_lock = SPIN_LOCK_UNLOCKED; @@ -48,14 +49,20 @@ */ static int rxrpc_krxsecd(void *arg) { - DECLARE_WAITQUEUE(krxsecd,current); + DECLARE_WAITQUEUE(krxsecd, current); int die; - printk("Started krxsecd %d\n",current->pid); + printk("Started krxsecd %d\n", current->pid); daemonize("krxsecd"); + /* only certain signals are of interest */ + spin_lock_irq(¤t->sighand->siglock); + siginitsetinv(¤t->blocked, 0); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + /* loop around waiting for work to do */ do { /* wait for work or to be told to exit */ @@ -63,7 +70,7 @@ if (!atomic_read(&rxrpc_krxsecd_qcount)) { set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&rxrpc_krxsecd_sleepq,&krxsecd); + add_wait_queue(&rxrpc_krxsecd_sleepq, &krxsecd); for (;;) { set_current_state(TASK_INTERRUPTIBLE); @@ -75,7 +82,7 @@ schedule(); } - remove_wait_queue(&rxrpc_krxsecd_sleepq,&krxsecd); + remove_wait_queue(&rxrpc_krxsecd_sleepq, &krxsecd); set_current_state(TASK_RUNNING); } die = rxrpc_krxsecd_die; @@ -91,7 +98,7 @@ if (!list_empty(&rxrpc_krxsecd_initmsgq)) { msg = list_entry(rxrpc_krxsecd_initmsgq.next, - struct rxrpc_message,link); + struct rxrpc_message, link); list_del_init(&msg->link); atomic_dec(&rxrpc_krxsecd_qcount); } @@ -112,7 +119,7 @@ } while (!die); /* and that's all */ - complete_and_exit(&rxrpc_krxsecd_dead,0); + complete_and_exit(&rxrpc_krxsecd_dead, 0); } /* end rxrpc_krxsecd() */ @@ -122,7 +129,7 @@ */ int __init rxrpc_krxsecd_init(void) { - return kernel_thread(rxrpc_krxsecd,NULL,0); + return kernel_thread(rxrpc_krxsecd, NULL, 0); } /* end rxrpc_krxsecd_init() */ @@ -154,11 +161,11 @@ /* move all the messages for this transport onto a temp list */ spin_lock(&rxrpc_krxsecd_initmsgq_lock); - list_for_each_safe(_p,_n,&rxrpc_krxsecd_initmsgq) { - msg = list_entry(_p,struct rxrpc_message,link); - if (msg->trans==trans) { + list_for_each_safe(_p, _n, &rxrpc_krxsecd_initmsgq) { + msg = list_entry(_p, struct rxrpc_message, link); + if (msg->trans == trans) { list_del(&msg->link); - list_add_tail(&msg->link,&tmp); + list_add_tail(&msg->link, &tmp); atomic_dec(&rxrpc_krxsecd_qcount); } } @@ -167,7 +174,7 @@ /* zap all messages on the temp list */ while (!list_empty(&tmp)) { - msg = list_entry(tmp.next,struct rxrpc_message,link); + msg = list_entry(tmp.next, struct rxrpc_message, link); list_del_init(&msg->link); rxrpc_put_message(msg); } @@ -181,14 +188,14 @@ */ void rxrpc_krxsecd_queue_incoming_call(struct rxrpc_message *msg) { - _enter("%p",msg); + _enter("%p", msg); /* queue for processing by krxsecd */ spin_lock(&rxrpc_krxsecd_initmsgq_lock); if (!rxrpc_krxsecd_die) { rxrpc_get_message(msg); - list_add_tail(&msg->link,&rxrpc_krxsecd_initmsgq); + list_add_tail(&msg->link, &rxrpc_krxsecd_initmsgq); atomic_inc(&rxrpc_krxsecd_qcount); } @@ -212,10 +219,10 @@ unsigned short sid; int ret; - _enter("%p{tr=%p}",msg,trans); + _enter("%p{tr=%p}", msg, trans); - ret = rxrpc_incoming_call(msg->conn,msg,&call); - if (ret<0) + ret = rxrpc_incoming_call(msg->conn, msg, &call); + if (ret < 0) goto out; /* find the matching service on the transport */ @@ -223,11 +230,11 @@ srv = NULL; spin_lock(&trans->lock); - list_for_each(_p,&trans->services) { - srv = list_entry(_p,struct rxrpc_service,link); - if (srv->service_id==sid && try_module_get(srv->owner)) { + list_for_each(_p, &trans->services) { + srv = list_entry(_p, struct rxrpc_service, link); + if (srv->service_id == sid && try_module_get(srv->owner)) { /* found a match (made sure it won't vanish) */ - _debug("found service '%s'",srv->name); + _debug("found service '%s'", srv->name); call->owner = srv->owner; break; } @@ -238,7 +245,7 @@ * - the func must inc the call's usage count to keep it */ ret = -ENOENT; - if (_p!=&trans->services) { + if (_p != &trans->services) { /* attempt to accept the call */ call->conn->service = srv; call->app_attn_func = srv->attn_func; @@ -248,19 +255,20 @@ ret = srv->new_call(call); /* send an abort if an error occurred */ - if (ret<0) { - rxrpc_call_abort(call,ret); + if (ret < 0) { + rxrpc_call_abort(call, ret); } else { /* formally receive and ACK the new packet */ - ret = rxrpc_conn_receive_call_packet(call->conn,call,msg); + ret = rxrpc_conn_receive_call_packet(call->conn, + call, msg); } } rxrpc_put_call(call); out: - if (ret<0) - rxrpc_trans_immediate_abort(trans,msg,ret); + if (ret < 0) + rxrpc_trans_immediate_abort(trans, msg, ret); - _leave(" (%d)",ret); + _leave(" (%d)", ret); } /* end rxrpc_krxsecd_process_incoming_call() */ diff -Nru a/net/rxrpc/krxtimod.c b/net/rxrpc/krxtimod.c --- a/net/rxrpc/krxtimod.c Thu Sep 11 23:03:11 2003 +++ b/net/rxrpc/krxtimod.c Thu Sep 11 23:03:11 2003 @@ -36,8 +36,8 @@ { int ret; - ret = kernel_thread(krxtimod,NULL,0); - if (ret<0) + ret = kernel_thread(krxtimod, NULL, 0); + if (ret < 0) return ret; wait_for_completion(&krxtimod_alive); @@ -64,30 +64,36 @@ */ static int krxtimod(void *arg) { - DECLARE_WAITQUEUE(myself,current); + DECLARE_WAITQUEUE(myself, current); rxrpc_timer_t *timer; - printk("Started krxtimod %d\n",current->pid); + printk("Started krxtimod %d\n", current->pid); daemonize("krxtimod"); complete(&krxtimod_alive); + /* only certain signals are of interest */ + spin_lock_irq(¤t->sighand->siglock); + siginitsetinv(¤t->blocked, 0); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + /* loop around looking for things to attend to */ loop: set_current_state(TASK_INTERRUPTIBLE); - add_wait_queue(&krxtimod_sleepq,&myself); + add_wait_queue(&krxtimod_sleepq, &myself); for (;;) { unsigned long jif; - unsigned long timeout; + signed long timeout; /* deal with the server being asked to die */ if (krxtimod_die) { - remove_wait_queue(&krxtimod_sleepq,&myself); + remove_wait_queue(&krxtimod_sleepq, &myself); _leave(""); - complete_and_exit(&krxtimod_dead,0); + complete_and_exit(&krxtimod_dead, 0); } /* discard pending signals */ @@ -97,18 +103,19 @@ spin_lock(&krxtimod_lock); if (list_empty(&krxtimod_list)) { timeout = MAX_SCHEDULE_TIMEOUT; - } else { - unsigned long tmo; - + } + else { timer = list_entry(krxtimod_list.next, rxrpc_timer_t, link); - tmo = timer->timo_jif; + timeout = timer->timo_jif; jif = jiffies; - if (time_before_eq(tmo,jif)) + if (time_before_eq((unsigned long) timeout, jif)) goto immediate; - timeout = (long)tmo - (long)jiffies; + else { + timeout = (long) timeout - (long) jiffies; + } } spin_unlock(&krxtimod_lock); @@ -118,13 +125,14 @@ } /* the thing on the front of the queue needs processing - * - we come here with the lock held and timer pointing to the expired entry + * - we come here with the lock held and timer pointing to the expired + * entry */ immediate: - remove_wait_queue(&krxtimod_sleepq,&myself); + remove_wait_queue(&krxtimod_sleepq, &myself); set_current_state(TASK_RUNNING); - _debug("@@@ Begin Timeout of %p",timer); + _debug("@@@ Begin Timeout of %p", timer); /* dequeue the timer */ list_del_init(&timer->link); @@ -147,29 +155,30 @@ struct list_head *_p; rxrpc_timer_t *ptimer; - _enter("%p,%lu",timer,timeout); + _enter("%p,%lu", timer, timeout); spin_lock(&krxtimod_lock); list_del(&timer->link); - /* the timer was deferred or reset - put it back in the queue at the right place */ + /* the timer was deferred or reset - put it back in the queue at the + * right place */ timer->timo_jif = jiffies + timeout; - list_for_each(_p,&krxtimod_list) { - ptimer = list_entry(_p,rxrpc_timer_t,link); - if (time_before(timer->timo_jif,ptimer->timo_jif)) + list_for_each(_p, &krxtimod_list) { + ptimer = list_entry(_p, rxrpc_timer_t, link); + if (time_before(timer->timo_jif, ptimer->timo_jif)) break; } - list_add_tail(&timer->link,_p); /* insert before stopping point */ + list_add_tail(&timer->link, _p); /* insert before stopping point */ spin_unlock(&krxtimod_lock); wake_up(&krxtimod_sleepq); _leave(""); -} /* end rxrpc_krxtimod_queue_vlocation() */ +} /* end rxrpc_krxtimod_add_timer() */ /*****************************************************************************/ /* @@ -180,7 +189,7 @@ { int ret = 0; - _enter("%p",timer); + _enter("%p", timer); spin_lock(&krxtimod_lock); @@ -193,6 +202,6 @@ wake_up(&krxtimod_sleepq); - _leave(" = %d",ret); + _leave(" = %d", ret); return ret; } /* end rxrpc_krxtimod_del_timer() */ diff -Nru a/net/rxrpc/main.c b/net/rxrpc/main.c --- a/net/rxrpc/main.c Thu Sep 11 23:03:13 2003 +++ b/net/rxrpc/main.c Thu Sep 11 23:03:13 2003 @@ -32,7 +32,7 @@ MODULE_AUTHOR("Red Hat, Inc."); MODULE_LICENSE("GPL"); -u32 rxrpc_epoch; +uint32_t rxrpc_epoch; /*****************************************************************************/ /* @@ -101,11 +101,16 @@ { kenter(""); - __RXACCT(printk("Outstanding Messages : %d\n",atomic_read(&rxrpc_message_count))); - __RXACCT(printk("Outstanding Calls : %d\n",atomic_read(&rxrpc_call_count))); - __RXACCT(printk("Outstanding Connections: %d\n",atomic_read(&rxrpc_connection_count))); - __RXACCT(printk("Outstanding Peers : %d\n",atomic_read(&rxrpc_peer_count))); - __RXACCT(printk("Outstanding Transports : %d\n",atomic_read(&rxrpc_transport_count))); + __RXACCT(printk("Outstanding Messages : %d\n", + atomic_read(&rxrpc_message_count))); + __RXACCT(printk("Outstanding Calls : %d\n", + atomic_read(&rxrpc_call_count))); + __RXACCT(printk("Outstanding Connections: %d\n", + atomic_read(&rxrpc_connection_count))); + __RXACCT(printk("Outstanding Peers : %d\n", + atomic_read(&rxrpc_peer_count))); + __RXACCT(printk("Outstanding Transports : %d\n", + atomic_read(&rxrpc_transport_count))); rxrpc_krxsecd_kill(); rxrpc_krxiod_kill(); @@ -117,11 +122,61 @@ rxrpc_proc_cleanup(); #endif - __RXACCT(printk("Outstanding Messages : %d\n",atomic_read(&rxrpc_message_count))); - __RXACCT(printk("Outstanding Calls : %d\n",atomic_read(&rxrpc_call_count))); - __RXACCT(printk("Outstanding Connections: %d\n",atomic_read(&rxrpc_connection_count))); - __RXACCT(printk("Outstanding Peers : %d\n",atomic_read(&rxrpc_peer_count))); - __RXACCT(printk("Outstanding Transports : %d\n",atomic_read(&rxrpc_transport_count))); + __RXACCT(printk("Outstanding Messages : %d\n", + atomic_read(&rxrpc_message_count))); + __RXACCT(printk("Outstanding Calls : %d\n", + atomic_read(&rxrpc_call_count))); + __RXACCT(printk("Outstanding Connections: %d\n", + atomic_read(&rxrpc_connection_count))); + __RXACCT(printk("Outstanding Peers : %d\n", + atomic_read(&rxrpc_peer_count))); + __RXACCT(printk("Outstanding Transports : %d\n", + atomic_read(&rxrpc_transport_count))); kleave(""); } /* end rxrpc_cleanup() */ + +/*****************************************************************************/ +/* + * clear the dead space between task_struct and kernel stack + * - called by supplying -finstrument-functions to gcc + */ +#if 0 +void __cyg_profile_func_enter (void *this_fn, void *call_site) +__attribute__((no_instrument_function)); + +void __cyg_profile_func_enter (void *this_fn, void *call_site) +{ + asm volatile(" movl %%esp,%%edi \n" + " andl %0,%%edi \n" + " addl %1,%%edi \n" + " movl %%esp,%%ecx \n" + " subl %%edi,%%ecx \n" + " shrl $2,%%ecx \n" + " movl $0xedededed,%%eax \n" + " rep stosl \n" + : + : "i"(~(THREAD_SIZE-1)), "i"(sizeof(struct thread_info)) + : "eax", "ecx", "edi", "memory", "cc" + ); +} + +void __cyg_profile_func_exit(void *this_fn, void *call_site) +__attribute__((no_instrument_function)); + +void __cyg_profile_func_exit(void *this_fn, void *call_site) +{ + asm volatile(" movl %%esp,%%edi \n" + " andl %0,%%edi \n" + " addl %1,%%edi \n" + " movl %%esp,%%ecx \n" + " subl %%edi,%%ecx \n" + " shrl $2,%%ecx \n" + " movl $0xdadadada,%%eax \n" + " rep stosl \n" + : + : "i"(~(THREAD_SIZE-1)), "i"(sizeof(struct thread_info)) + : "eax", "ecx", "edi", "memory", "cc" + ); +} +#endif diff -Nru a/net/rxrpc/peer.c b/net/rxrpc/peer.c --- a/net/rxrpc/peer.c Thu Sep 11 23:03:12 2003 +++ b/net/rxrpc/peer.c Thu Sep 11 23:03:12 2003 @@ -28,12 +28,14 @@ __RXACCT_DECL(atomic_t rxrpc_peer_count); LIST_HEAD(rxrpc_peers); DECLARE_RWSEM(rxrpc_peers_sem); +unsigned long rxrpc_peer_timeout = 12 * 60 * 60; static void __rxrpc_peer_timeout(rxrpc_timer_t *timer) { - struct rxrpc_peer *peer = list_entry(timer,struct rxrpc_peer,timeout); + struct rxrpc_peer *peer = + list_entry(timer, struct rxrpc_peer, timeout); - _debug("Rx PEER TIMEOUT [%p{u=%d}]",peer,atomic_read(&peer->usage)); + _debug("Rx PEER TIMEOUT [%p{u=%d}]", peer, atomic_read(&peer->usage)); rxrpc_peer_do_timeout(peer); } @@ -46,32 +48,35 @@ /* * create a peer record */ -static int __rxrpc_create_peer(struct rxrpc_transport *trans, u32 addr, struct rxrpc_peer **_peer) +static int __rxrpc_create_peer(struct rxrpc_transport *trans, uint32_t addr, + struct rxrpc_peer **_peer) { struct rxrpc_peer *peer; - _enter("%p,%08x",trans,ntohl(addr)); + _enter("%p,%08x", trans, ntohl(addr)); /* allocate and initialise a peer record */ - peer = kmalloc(sizeof(struct rxrpc_peer),GFP_KERNEL); + peer = kmalloc(sizeof(struct rxrpc_peer), GFP_KERNEL); if (!peer) { _leave(" = -ENOMEM"); return -ENOMEM; } - memset(peer,0,sizeof(struct rxrpc_peer)); - atomic_set(&peer->usage,1); + memset(peer, 0, sizeof(struct rxrpc_peer)); + atomic_set(&peer->usage, 1); INIT_LIST_HEAD(&peer->link); INIT_LIST_HEAD(&peer->proc_link); + INIT_LIST_HEAD(&peer->conn_idlist); INIT_LIST_HEAD(&peer->conn_active); INIT_LIST_HEAD(&peer->conn_graveyard); spin_lock_init(&peer->conn_gylock); init_waitqueue_head(&peer->conn_gy_waitq); + rwlock_init(&peer->conn_idlock); rwlock_init(&peer->conn_lock); - atomic_set(&peer->conn_count,0); + atomic_set(&peer->conn_count, 0); spin_lock_init(&peer->lock); - rxrpc_timer_init(&peer->timeout,&rxrpc_peer_timer_ops); + rxrpc_timer_init(&peer->timeout, &rxrpc_peer_timer_ops); peer->addr.s_addr = addr; @@ -80,7 +85,7 @@ __RXACCT(atomic_inc(&rxrpc_peer_count)); *_peer = peer; - _leave(" = 0 (%p)",peer); + _leave(" = 0 (%p)", peer); return 0; } /* end __rxrpc_create_peer() */ @@ -91,43 +96,45 @@ * - returns (if successful) with peer record usage incremented * - resurrects it from the graveyard if found there */ -int rxrpc_peer_lookup(struct rxrpc_transport *trans, u32 addr, struct rxrpc_peer **_peer) +int rxrpc_peer_lookup(struct rxrpc_transport *trans, uint32_t addr, + struct rxrpc_peer **_peer) { struct rxrpc_peer *peer, *candidate = NULL; struct list_head *_p; int ret; - _enter("%p{%hu},%08x",trans,trans->port,ntohl(addr)); + _enter("%p{%hu},%08x", trans, trans->port, ntohl(addr)); /* [common case] search the transport's active list first */ read_lock(&trans->peer_lock); - list_for_each(_p,&trans->peer_active) { - peer = list_entry(_p,struct rxrpc_peer,link); - if (peer->addr.s_addr==addr) + list_for_each(_p, &trans->peer_active) { + peer = list_entry(_p, struct rxrpc_peer, link); + if (peer->addr.s_addr == addr) goto found_active; } read_unlock(&trans->peer_lock); /* [uncommon case] not active - create a candidate for a new record */ - ret = __rxrpc_create_peer(trans,addr,&candidate); - if (ret<0) { - _leave(" = %d",ret); + ret = __rxrpc_create_peer(trans, addr, &candidate); + if (ret < 0) { + _leave(" = %d", ret); return ret; } - /* search the active list again, just in case it appeared whilst we were busy */ + /* search the active list again, just in case it appeared whilst we + * were busy */ write_lock(&trans->peer_lock); - list_for_each(_p,&trans->peer_active) { - peer = list_entry(_p,struct rxrpc_peer,link); - if (peer->addr.s_addr==addr) + list_for_each(_p, &trans->peer_active) { + peer = list_entry(_p, struct rxrpc_peer, link); + if (peer->addr.s_addr == addr) goto found_active_second_chance; } /* search the transport's graveyard list */ spin_lock(&trans->peer_gylock); - list_for_each(_p,&trans->peer_graveyard) { - peer = list_entry(_p,struct rxrpc_peer,link); - if (peer->addr.s_addr==addr) + list_for_each(_p, &trans->peer_graveyard) { + peer = list_entry(_p, struct rxrpc_peer, link); + if (peer->addr.s_addr == addr) goto found_in_graveyard; } spin_unlock(&trans->peer_gylock); @@ -141,12 +148,12 @@ if (peer->ops && peer->ops->adding) { ret = peer->ops->adding(peer); - if (ret<0) { + if (ret < 0) { write_unlock(&trans->peer_lock); __RXACCT(atomic_dec(&rxrpc_peer_count)); kfree(peer); rxrpc_put_transport(trans); - _leave(" = %d",ret); + _leave(" = %d", ret); return ret; } } @@ -154,7 +161,7 @@ atomic_inc(&trans->peer_count); make_active: - list_add_tail(&peer->link,&trans->peer_active); + list_add_tail(&peer->link, &trans->peer_active); success_uwfree: write_unlock(&trans->peer_lock); @@ -166,7 +173,7 @@ if (list_empty(&peer->proc_link)) { down_write(&rxrpc_peers_sem); - list_add_tail(&peer->proc_link,&rxrpc_peers); + list_add_tail(&peer->proc_link, &rxrpc_peers); up_write(&rxrpc_peers_sem); } @@ -174,7 +181,9 @@ *_peer = peer; _leave(" = 0 (%p{u=%d cc=%d})", - peer,atomic_read(&peer->usage),atomic_read(&peer->conn_count)); + peer, + atomic_read(&peer->usage), + atomic_read(&peer->conn_count)); return 0; /* handle the peer being found in the active list straight off */ @@ -192,7 +201,8 @@ spin_unlock(&trans->peer_gylock); goto make_active; - /* handle finding the peer on the second time through the active list */ + /* handle finding the peer on the second time through the active + * list */ found_active_second_chance: rxrpc_get_peer(peer); goto success_uwfree; @@ -202,16 +212,20 @@ /*****************************************************************************/ /* * finish with a peer record - * - it gets sent to the graveyard from where it can be resurrected or timed out + * - it gets sent to the graveyard from where it can be resurrected or timed + * out */ void rxrpc_put_peer(struct rxrpc_peer *peer) { struct rxrpc_transport *trans = peer->trans; - _enter("%p{cc=%d a=%08x}",peer,atomic_read(&peer->conn_count),ntohl(peer->addr.s_addr)); + _enter("%p{cc=%d a=%08x}", + peer, + atomic_read(&peer->conn_count), + ntohl(peer->addr.s_addr)); /* sanity check */ - if (atomic_read(&peer->usage)<=0) + if (atomic_read(&peer->usage) <= 0) BUG(); write_lock(&trans->peer_lock); @@ -227,12 +241,11 @@ list_del(&peer->link); write_unlock(&trans->peer_lock); - list_add_tail(&peer->link,&trans->peer_graveyard); + list_add_tail(&peer->link, &trans->peer_graveyard); - if (!list_empty(&peer->conn_active)) BUG(); + BUG_ON(!list_empty(&peer->conn_active)); - /* discard in 600 secs */ - rxrpc_krxtimod_add_timer(&peer->timeout,100*HZ); + rxrpc_krxtimod_add_timer(&peer->timeout, rxrpc_peer_timeout * HZ); spin_unlock(&trans->peer_gylock); @@ -251,15 +264,16 @@ struct rxrpc_transport *trans = peer->trans; _enter("%p{u=%d cc=%d a=%08x}", - peer,atomic_read(&peer->usage),atomic_read(&peer->conn_count), + peer, + atomic_read(&peer->usage), + atomic_read(&peer->conn_count), ntohl(peer->addr.s_addr)); - if (atomic_read(&peer->usage)<0) - BUG(); + BUG_ON(atomic_read(&peer->usage) < 0); /* remove from graveyard if still dead */ spin_lock(&trans->peer_gylock); - if (atomic_read(&peer->usage)==0) + if (atomic_read(&peer->usage) == 0) list_del_init(&peer->link); else peer = NULL; @@ -273,8 +287,8 @@ /* clear all connections on this peer */ rxrpc_conn_clearall(peer); - if (!list_empty(&peer->conn_active)) BUG(); - if (!list_empty(&peer->conn_graveyard)) BUG(); + BUG_ON(!list_empty(&peer->conn_active)); + BUG_ON(!list_empty(&peer->conn_graveyard)); /* inform the application layer */ if (peer->ops && peer->ops->discarding) @@ -310,18 +324,18 @@ _enter("%p",trans); /* there shouldn't be any active peers remaining */ - if (!list_empty(&trans->peer_active)) - BUG(); + BUG_ON(!list_empty(&trans->peer_active)); /* manually timeout all peers in the graveyard */ spin_lock(&trans->peer_gylock); while (!list_empty(&trans->peer_graveyard)) { - peer = list_entry(trans->peer_graveyard.next,struct rxrpc_peer,link); - _debug("Clearing peer %p\n",peer); + peer = list_entry(trans->peer_graveyard.next, + struct rxrpc_peer, link); + _debug("Clearing peer %p\n", peer); err = rxrpc_krxtimod_del_timer(&peer->timeout); spin_unlock(&trans->peer_gylock); - if (err==0) + if (err == 0) rxrpc_peer_do_timeout(peer); spin_lock(&trans->peer_gylock); @@ -330,18 +344,17 @@ /* wait for the the peer graveyard to be completely cleared */ set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&trans->peer_gy_waitq,&myself); + add_wait_queue(&trans->peer_gy_waitq, &myself); - while (atomic_read(&trans->peer_count)!=0) { + while (atomic_read(&trans->peer_count) != 0) { schedule(); set_current_state(TASK_UNINTERRUPTIBLE); } - remove_wait_queue(&trans->peer_gy_waitq,&myself); + remove_wait_queue(&trans->peer_gy_waitq, &myself); set_current_state(TASK_RUNNING); _leave(""); - } /* end rxrpc_peer_clearall() */ /*****************************************************************************/ @@ -355,7 +368,7 @@ unsigned long long rtt; int loop; - _enter("%p,%p,%p",peer,msg,resp); + _enter("%p,%p,%p", peer, msg, resp); /* calculate the latest RTT */ rtt = resp->stamp.tv_sec - msg->stamp.tv_sec; @@ -367,16 +380,18 @@ peer->rtt_point++; peer->rtt_point %= RXRPC_RTT_CACHE_SIZE; - if (peer->rtt_usagertt_usage++; + if (peer->rtt_usage < RXRPC_RTT_CACHE_SIZE) + peer->rtt_usage++; /* recalculate RTT */ rtt = 0; - for (loop=peer->rtt_usage-1; loop>=0; loop--) + for (loop = peer->rtt_usage - 1; loop >= 0; loop--) rtt += peer->rtt_cache[loop]; - do_div(rtt,peer->rtt_usage); + do_div(rtt, peer->rtt_usage); peer->rtt = rtt; - _leave(" RTT=%lu.%lums",(long)(peer->rtt/1000),(long)(peer->rtt%1000)); + _leave(" RTT=%lu.%lums", + (long) (peer->rtt / 1000), (long) (peer->rtt % 1000)); } /* end rxrpc_peer_calculate_rtt() */ diff -Nru a/net/rxrpc/proc.c b/net/rxrpc/proc.c --- a/net/rxrpc/proc.c Thu Sep 11 23:03:13 2003 +++ b/net/rxrpc/proc.c Thu Sep 11 23:03:13 2003 @@ -38,7 +38,6 @@ }; static struct file_operations rxrpc_proc_transports_fops = { - .owner = THIS_MODULE, .open = rxrpc_proc_transports_open, .read = seq_read, .llseek = seq_lseek, @@ -59,7 +58,6 @@ }; static struct file_operations rxrpc_proc_peers_fops = { - .owner = THIS_MODULE, .open = rxrpc_proc_peers_open, .read = seq_read, .llseek = seq_lseek, @@ -80,7 +78,6 @@ }; static struct file_operations rxrpc_proc_conns_fops = { - .owner = THIS_MODULE, .open = rxrpc_proc_conns_open, .read = seq_read, .llseek = seq_lseek, @@ -101,7 +98,6 @@ }; static struct file_operations rxrpc_proc_calls_fops = { - .owner = THIS_MODULE, .open = rxrpc_proc_calls_open, .read = seq_read, .llseek = seq_lseek, @@ -137,30 +133,30 @@ { struct proc_dir_entry *p; - proc_rxrpc = proc_mkdir("rxrpc",proc_net); + proc_rxrpc = proc_mkdir("rxrpc", proc_net); if (!proc_rxrpc) goto error; proc_rxrpc->owner = THIS_MODULE; - p = create_proc_entry("calls",0,proc_rxrpc); + p = create_proc_entry("calls", 0, proc_rxrpc); if (!p) goto error_proc; p->proc_fops = &rxrpc_proc_calls_fops; p->owner = THIS_MODULE; - p = create_proc_entry("connections",0,proc_rxrpc); + p = create_proc_entry("connections", 0, proc_rxrpc); if (!p) goto error_calls; p->proc_fops = &rxrpc_proc_conns_fops; p->owner = THIS_MODULE; - p = create_proc_entry("peers",0,proc_rxrpc); + p = create_proc_entry("peers", 0, proc_rxrpc); if (!p) goto error_calls; p->proc_fops = &rxrpc_proc_peers_fops; p->owner = THIS_MODULE; - p = create_proc_entry("transports",0,proc_rxrpc); + p = create_proc_entry("transports", 0, proc_rxrpc); if (!p) goto error_conns; p->proc_fops = &rxrpc_proc_transports_fops; @@ -169,11 +165,11 @@ return 0; error_conns: - remove_proc_entry("conns",proc_rxrpc); + remove_proc_entry("connections", proc_rxrpc); error_calls: - remove_proc_entry("calls",proc_rxrpc); + remove_proc_entry("calls", proc_rxrpc); error_proc: - remove_proc_entry("rxrpc",proc_net); + remove_proc_entry("rxrpc", proc_net); error: return -ENOMEM; } /* end rxrpc_proc_init() */ @@ -184,12 +180,12 @@ */ void rxrpc_proc_cleanup(void) { - remove_proc_entry("transports",proc_rxrpc); - remove_proc_entry("peers",proc_rxrpc); - remove_proc_entry("connections",proc_rxrpc); - remove_proc_entry("calls",proc_rxrpc); + remove_proc_entry("transports", proc_rxrpc); + remove_proc_entry("peers", proc_rxrpc); + remove_proc_entry("connections", proc_rxrpc); + remove_proc_entry("calls", proc_rxrpc); - remove_proc_entry("rxrpc",proc_net); + remove_proc_entry("rxrpc", proc_net); } /* end rxrpc_proc_cleanup() */ @@ -202,8 +198,8 @@ struct seq_file *m; int ret; - ret = seq_open(file,&rxrpc_proc_transports_ops); - if (ret<0) + ret = seq_open(file, &rxrpc_proc_transports_ops); + if (ret < 0) return ret; m = file->private_data; @@ -226,15 +222,15 @@ /* allow for the header line */ if (!pos) - return (void *)1; + return SEQ_START_TOKEN; pos--; /* find the n'th element in the list */ - list_for_each(_p,&rxrpc_proc_transports) + list_for_each(_p, &rxrpc_proc_transports) if (!pos--) break; - return _p!=&rxrpc_proc_transports ? _p : NULL; + return _p != &rxrpc_proc_transports ? _p : NULL; } /* end rxrpc_proc_transports_start() */ /*****************************************************************************/ @@ -248,9 +244,9 @@ (*pos)++; _p = v; - _p = v==(void*)1 ? rxrpc_proc_transports.next : _p->next; + _p = (v == SEQ_START_TOKEN) ? rxrpc_proc_transports.next : _p->next; - return _p!=&rxrpc_proc_transports ? _p : NULL; + return _p != &rxrpc_proc_transports ? _p : NULL; } /* end rxrpc_proc_transports_next() */ /*****************************************************************************/ @@ -269,16 +265,17 @@ */ static int rxrpc_proc_transports_show(struct seq_file *m, void *v) { - struct rxrpc_transport *trans = list_entry(v,struct rxrpc_transport,proc_link); + struct rxrpc_transport *trans = + list_entry(v, struct rxrpc_transport, proc_link); /* display header on line 1 */ - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { seq_puts(m, "LOCAL USE\n"); return 0; } /* display one transport per line on subsequent lines */ - seq_printf(m,"%5hu %3d\n", + seq_printf(m, "%5hu %3d\n", trans->port, atomic_read(&trans->usage) ); @@ -295,8 +292,8 @@ struct seq_file *m; int ret; - ret = seq_open(file,&rxrpc_proc_peers_ops); - if (ret<0) + ret = seq_open(file, &rxrpc_proc_peers_ops); + if (ret < 0) return ret; m = file->private_data; @@ -307,7 +304,8 @@ /*****************************************************************************/ /* - * set up the iterator to start reading from the peers list and return the first item + * set up the iterator to start reading from the peers list and return the + * first item */ static void *rxrpc_proc_peers_start(struct seq_file *m, loff_t *_pos) { @@ -319,15 +317,15 @@ /* allow for the header line */ if (!pos) - return (void *)1; + return SEQ_START_TOKEN; pos--; /* find the n'th element in the list */ - list_for_each(_p,&rxrpc_peers) + list_for_each(_p, &rxrpc_peers) if (!pos--) break; - return _p!=&rxrpc_peers ? _p : NULL; + return _p != &rxrpc_peers ? _p : NULL; } /* end rxrpc_proc_peers_start() */ /*****************************************************************************/ @@ -341,9 +339,9 @@ (*pos)++; _p = v; - _p = v==(void*)1 ? rxrpc_peers.next : _p->next; + _p = (v == SEQ_START_TOKEN) ? rxrpc_peers.next : _p->next; - return _p!=&rxrpc_peers ? _p : NULL; + return _p != &rxrpc_peers ? _p : NULL; } /* end rxrpc_proc_peers_next() */ /*****************************************************************************/ @@ -362,21 +360,23 @@ */ static int rxrpc_proc_peers_show(struct seq_file *m, void *v) { - struct rxrpc_peer *peer = list_entry(v,struct rxrpc_peer,proc_link); + struct rxrpc_peer *peer = list_entry(v, struct rxrpc_peer, proc_link); signed long timeout; /* display header on line 1 */ - if (v == (void *)1) { - seq_puts(m,"LOCAL REMOTE USAGE CONNS TIMEOUT MTU RTT(uS)\n"); + if (v == SEQ_START_TOKEN) { + seq_puts(m, "LOCAL REMOTE USAGE CONNS TIMEOUT" + " MTU RTT(uS)\n"); return 0; } /* display one peer per line on subsequent lines */ timeout = 0; if (!list_empty(&peer->timeout.link)) - timeout = (signed long)peer->timeout.timo_jif - (signed long)jiffies; + timeout = (signed long) peer->timeout.timo_jif - + (signed long) jiffies; - seq_printf(m,"%5hu %08x %5d %5d %8ld %5Zu %7lu\n", + seq_printf(m, "%5hu %08x %5d %5d %8ld %5Zu %7lu\n", peer->trans->port, ntohl(peer->addr.s_addr), atomic_read(&peer->usage), @@ -391,15 +391,16 @@ /*****************************************************************************/ /* - * open "/proc/net/rxrpc/connections" which provides a summary of extant connections + * open "/proc/net/rxrpc/connections" which provides a summary of extant + * connections */ static int rxrpc_proc_conns_open(struct inode *inode, struct file *file) { struct seq_file *m; int ret; - ret = seq_open(file,&rxrpc_proc_conns_ops); - if (ret<0) + ret = seq_open(file, &rxrpc_proc_conns_ops); + if (ret < 0) return ret; m = file->private_data; @@ -410,7 +411,8 @@ /*****************************************************************************/ /* - * set up the iterator to start reading from the conns list and return the first item + * set up the iterator to start reading from the conns list and return the + * first item */ static void *rxrpc_proc_conns_start(struct seq_file *m, loff_t *_pos) { @@ -422,15 +424,15 @@ /* allow for the header line */ if (!pos) - return (void *)1; + return SEQ_START_TOKEN; pos--; /* find the n'th element in the list */ - list_for_each(_p,&rxrpc_conns) + list_for_each(_p, &rxrpc_conns) if (!pos--) break; - return _p!=&rxrpc_conns ? _p : NULL; + return _p != &rxrpc_conns ? _p : NULL; } /* end rxrpc_proc_conns_start() */ /*****************************************************************************/ @@ -444,9 +446,9 @@ (*pos)++; _p = v; - _p = v==(void*)1 ? rxrpc_conns.next : _p->next; + _p = (v == SEQ_START_TOKEN) ? rxrpc_conns.next : _p->next; - return _p!=&rxrpc_conns ? _p : NULL; + return _p != &rxrpc_conns ? _p : NULL; } /* end rxrpc_proc_conns_next() */ /*****************************************************************************/ @@ -465,13 +467,16 @@ */ static int rxrpc_proc_conns_show(struct seq_file *m, void *v) { - struct rxrpc_connection *conn = list_entry(v,struct rxrpc_connection,proc_link); + struct rxrpc_connection *conn; signed long timeout; + conn = list_entry(v, struct rxrpc_connection, proc_link); + /* display header on line 1 */ - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { seq_puts(m, - "LOCAL REMOTE RPORT SRVC CONN END SERIALNO CALLNO MTU TIMEOUT" + "LOCAL REMOTE RPORT SRVC CONN END SERIALNO " + "CALLNO MTU TIMEOUT" "\n"); return 0; } @@ -479,9 +484,11 @@ /* display one conn per line on subsequent lines */ timeout = 0; if (!list_empty(&conn->timeout.link)) - timeout = (signed long)conn->timeout.timo_jif - (signed long)jiffies; + timeout = (signed long) conn->timeout.timo_jif - + (signed long) jiffies; - seq_printf(m,"%5hu %08x %5hu %04hx %08x %-3.3s %08x %08x %5Zu %8ld\n", + seq_printf(m, + "%5hu %08x %5hu %04hx %08x %-3.3s %08x %08x %5Zu %8ld\n", conn->trans->port, ntohl(conn->addr.sin_addr.s_addr), ntohs(conn->addr.sin_port), @@ -506,8 +513,8 @@ struct seq_file *m; int ret; - ret = seq_open(file,&rxrpc_proc_calls_ops); - if (ret<0) + ret = seq_open(file, &rxrpc_proc_calls_ops); + if (ret < 0) return ret; m = file->private_data; @@ -518,7 +525,8 @@ /*****************************************************************************/ /* - * set up the iterator to start reading from the calls list and return the first item + * set up the iterator to start reading from the calls list and return the + * first item */ static void *rxrpc_proc_calls_start(struct seq_file *m, loff_t *_pos) { @@ -530,15 +538,15 @@ /* allow for the header line */ if (!pos) - return (void *)1; + return SEQ_START_TOKEN; pos--; /* find the n'th element in the list */ - list_for_each(_p,&rxrpc_calls) + list_for_each(_p, &rxrpc_calls) if (!pos--) break; - return _p!=&rxrpc_calls ? _p : NULL; + return _p != &rxrpc_calls ? _p : NULL; } /* end rxrpc_proc_calls_start() */ /*****************************************************************************/ @@ -552,9 +560,9 @@ (*pos)++; _p = v; - _p = v==(void*)1 ? rxrpc_calls.next : _p->next; + _p = (v == SEQ_START_TOKEN) ? rxrpc_calls.next : _p->next; - return _p!=&rxrpc_calls ? _p : NULL; + return _p != &rxrpc_calls ? _p : NULL; } /* end rxrpc_proc_calls_next() */ /*****************************************************************************/ @@ -573,10 +581,10 @@ */ static int rxrpc_proc_calls_show(struct seq_file *m, void *v) { - struct rxrpc_call *call = list_entry(v,struct rxrpc_call,call_link); + struct rxrpc_call *call = list_entry(v, struct rxrpc_call, call_link); /* display header on line 1 */ - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { seq_puts(m, "LOCAL REMOT SRVC CONN CALL DIR USE " " L STATE OPCODE ABORT ERRNO\n" diff -Nru a/net/rxrpc/sysctl.c b/net/rxrpc/sysctl.c --- a/net/rxrpc/sysctl.c Thu Sep 11 23:03:12 2003 +++ b/net/rxrpc/sysctl.c Thu Sep 11 23:03:12 2003 @@ -60,6 +60,22 @@ .mode = 0644, .proc_handler = &proc_dointvec }, + { + .ctl_name = 5, + .procname = "peertimo", + .data = &rxrpc_peer_timeout, + .maxlen = sizeof(unsigned long), + .mode = 0644, + .proc_handler = &proc_doulongvec_minmax + }, + { + .ctl_name = 6, + .procname = "conntimo", + .data = &rxrpc_conn_timeout, + .maxlen = sizeof(unsigned long), + .mode = 0644, + .proc_handler = &proc_doulongvec_minmax + }, { .ctl_name = 0 } }; @@ -67,6 +83,7 @@ { .ctl_name = 1, .procname = "rxrpc", + .maxlen = 0, .mode = 0555, .child = rxrpc_sysctl_table }, @@ -81,7 +98,7 @@ int rxrpc_sysctl_init(void) { #ifdef CONFIG_SYSCTL - rxrpc_sysctl = register_sysctl_table(rxrpc_dir_sysctl_table,0); + rxrpc_sysctl = register_sysctl_table(rxrpc_dir_sysctl_table, 0); if (!rxrpc_sysctl) return -ENOMEM; #endif /* CONFIG_SYSCTL */ diff -Nru a/net/rxrpc/transport.c b/net/rxrpc/transport.c --- a/net/rxrpc/transport.c Thu Sep 11 23:03:13 2003 +++ b/net/rxrpc/transport.c Thu Sep 11 23:03:13 2003 @@ -56,7 +56,8 @@ /* * create a new transport endpoint using the specified UDP port */ -int rxrpc_create_transport(unsigned short port, struct rxrpc_transport **_trans) +int rxrpc_create_transport(unsigned short port, + struct rxrpc_transport **_trans) { struct rxrpc_transport *trans; struct sockaddr_in sin; @@ -64,14 +65,14 @@ struct sock *sock; int ret, opt; - _enter("%hu",port); + _enter("%hu", port); - trans = kmalloc(sizeof(struct rxrpc_transport),GFP_KERNEL); + trans = kmalloc(sizeof(struct rxrpc_transport), GFP_KERNEL); if (!trans) return -ENOMEM; - memset(trans,0,sizeof(struct rxrpc_transport)); - atomic_set(&trans->usage,1); + memset(trans, 0, sizeof(struct rxrpc_transport)); + atomic_set(&trans->usage, 1); INIT_LIST_HEAD(&trans->services); INIT_LIST_HEAD(&trans->link); INIT_LIST_HEAD(&trans->krxiodq_link); @@ -81,58 +82,58 @@ spin_lock_init(&trans->peer_gylock); init_waitqueue_head(&trans->peer_gy_waitq); rwlock_init(&trans->peer_lock); - atomic_set(&trans->peer_count,0); + atomic_set(&trans->peer_count, 0); trans->port = port; /* create a UDP socket to be my actual transport endpoint */ - ret = sock_create(PF_INET,SOCK_DGRAM,IPPROTO_UDP,&trans->socket); - if (ret<0) + ret = sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &trans->socket); + if (ret < 0) goto error; /* use the specified port */ if (port) { - memset(&sin,0,sizeof(sin)); + memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(port); - ret = trans->socket->ops->bind(trans->socket,(struct sockaddr *)&sin,sizeof(sin)); - if (ret<0) + ret = trans->socket->ops->bind(trans->socket, + (struct sockaddr *) &sin, + sizeof(sin)); + if (ret < 0) goto error; } opt = 1; oldfs = get_fs(); set_fs(KERNEL_DS); - ret = trans->socket->ops->setsockopt(trans->socket,SOL_IP,IP_RECVERR, - (char*)&opt,sizeof(opt)); + ret = trans->socket->ops->setsockopt(trans->socket, SOL_IP, IP_RECVERR, + (char *) &opt, sizeof(opt)); set_fs(oldfs); spin_lock(&rxrpc_transports_lock); - list_add(&trans->link,&rxrpc_transports); + list_add(&trans->link, &rxrpc_transports); spin_unlock(&rxrpc_transports_lock); /* set the socket up */ sock = trans->socket->sk; - sock->sk_user_data = trans; - sock->sk_data_ready = rxrpc_data_ready; - sock->sk_error_report = rxrpc_error_report; + sock->sk_user_data = trans; + sock->sk_data_ready = rxrpc_data_ready; + sock->sk_error_report = rxrpc_error_report; down_write(&rxrpc_proc_transports_sem); - list_add_tail(&trans->proc_link,&rxrpc_proc_transports); + list_add_tail(&trans->proc_link, &rxrpc_proc_transports); up_write(&rxrpc_proc_transports_sem); __RXACCT(atomic_inc(&rxrpc_transport_count)); *_trans = trans; - _leave(" = 0 (%p)",trans); + _leave(" = 0 (%p)", trans); return 0; error: rxrpc_put_transport(trans); - _leave(" = %d",ret); - + _leave(" = %d", ret); return ret; - } /* end rxrpc_create_transport() */ /*****************************************************************************/ @@ -151,12 +152,13 @@ */ void rxrpc_put_transport(struct rxrpc_transport *trans) { - _enter("%p{u=%d p=%hu}",trans,atomic_read(&trans->usage),trans->port); + _enter("%p{u=%d p=%hu}", + trans, atomic_read(&trans->usage), trans->port); - if (atomic_read(&trans->usage)<=0) - BUG(); + BUG_ON(atomic_read(&trans->usage) <= 0); - /* to prevent a race, the decrement and the dequeue must be effectively atomic */ + /* to prevent a race, the decrement and the dequeue must be + * effectively atomic */ spin_lock(&rxrpc_transports_lock); if (likely(!atomic_dec_and_test(&trans->usage))) { spin_unlock(&rxrpc_transports_lock); @@ -169,7 +171,7 @@ /* finish cleaning up the transport */ if (trans->socket) - trans->socket->ops->shutdown(trans->socket,2); + trans->socket->ops->shutdown(trans->socket, 2); rxrpc_krxsecd_clear_transport(trans); rxrpc_krxiod_dequeue_transport(trans); @@ -192,41 +194,41 @@ kfree(trans); _leave(""); - } /* end rxrpc_put_transport() */ /*****************************************************************************/ /* * add a service to a transport to be listened upon */ -int rxrpc_add_service(struct rxrpc_transport *trans, struct rxrpc_service *newsrv) +int rxrpc_add_service(struct rxrpc_transport *trans, + struct rxrpc_service *newsrv) { struct rxrpc_service *srv; struct list_head *_p; int ret = -EEXIST; - _enter("%p{%hu},%p{%hu}",trans,trans->port,newsrv,newsrv->service_id); + _enter("%p{%hu},%p{%hu}", + trans, trans->port, newsrv, newsrv->service_id); /* verify that the service ID is not already present */ spin_lock(&trans->lock); - list_for_each(_p,&trans->services) { - srv = list_entry(_p,struct rxrpc_service,link); - if (srv->service_id==newsrv->service_id) + list_for_each(_p, &trans->services) { + srv = list_entry(_p, struct rxrpc_service, link); + if (srv->service_id == newsrv->service_id) goto out; } /* okay - add the transport to the list */ - list_add_tail(&newsrv->link,&trans->services); + list_add_tail(&newsrv->link, &trans->services); rxrpc_get_transport(trans); ret = 0; out: spin_unlock(&trans->lock); - _leave("= %d",ret); + _leave("= %d", ret); return ret; - } /* end rxrpc_add_service() */ /*****************************************************************************/ @@ -235,7 +237,7 @@ */ void rxrpc_del_service(struct rxrpc_transport *trans, struct rxrpc_service *srv) { - _enter("%p{%hu},%p{%hu}",trans,trans->port,srv,srv->service_id); + _enter("%p{%hu},%p{%hu}", trans, trans->port, srv, srv->service_id); spin_lock(&trans->lock); list_del(&srv->link); @@ -244,7 +246,6 @@ rxrpc_put_transport(trans); _leave(""); - } /* end rxrpc_del_service() */ /*****************************************************************************/ @@ -255,7 +256,7 @@ { struct rxrpc_transport *trans; - _enter("%p{t=%p},%d",sk,sk->sk_user_data,count); + _enter("%p{t=%p},%d", sk, sk->sk_user_data, count); /* queue the transport for attention by krxiod */ trans = (struct rxrpc_transport *) sk->sk_user_data; @@ -267,7 +268,6 @@ wake_up_interruptible(sk->sk_sleep); _leave(""); - } /* end rxrpc_data_ready() */ /*****************************************************************************/ @@ -279,7 +279,7 @@ { struct rxrpc_transport *trans; - _enter("%p{t=%p}",sk,sk->sk_user_data); + _enter("%p{t=%p}", sk, sk->sk_user_data); /* queue the transport for attention by krxiod */ trans = (struct rxrpc_transport *) sk->sk_user_data; @@ -293,13 +293,12 @@ wake_up_interruptible(sk->sk_sleep); _leave(""); - } /* end rxrpc_error_report() */ /*****************************************************************************/ /* - * split a message up, allocating message records and filling them in from the contents of a - * socket buffer + * split a message up, allocating message records and filling them in + * from the contents of a socket buffer */ static int rxrpc_incoming_msg(struct rxrpc_transport *trans, struct sk_buff *pkt, @@ -310,18 +309,19 @@ _enter(""); - msg = kmalloc(sizeof(struct rxrpc_message),GFP_KERNEL); + msg = kmalloc(sizeof(struct rxrpc_message), GFP_KERNEL); if (!msg) { _leave(" = -ENOMEM"); return -ENOMEM; } - memset(msg,0,sizeof(*msg)); - atomic_set(&msg->usage,1); + memset(msg, 0, sizeof(*msg)); + atomic_set(&msg->usage, 1); list_add_tail(&msg->link,msgq); /* dig out the Rx routing parameters */ - if (skb_copy_bits(pkt,sizeof(struct udphdr),&msg->hdr,sizeof(msg->hdr))<0) { + if (skb_copy_bits(pkt, sizeof(struct udphdr), + &msg->hdr, sizeof(msg->hdr)) < 0) { ret = -EBADMSG; goto error; } @@ -352,7 +352,9 @@ __RXACCT(atomic_inc(&rxrpc_message_count)); /* split off jumbo packets */ - while (msg->hdr.type==RXRPC_PACKET_TYPE_DATA && msg->hdr.flags & RXRPC_JUMBO_PACKET) { + while (msg->hdr.type == RXRPC_PACKET_TYPE_DATA && + msg->hdr.flags & RXRPC_JUMBO_PACKET + ) { struct rxrpc_jumbo_header jumbo; struct rxrpc_message *jumbomsg = msg; @@ -360,23 +362,25 @@ /* quick sanity check */ ret = -EBADMSG; - if (msg->dsize < RXRPC_JUMBO_DATALEN+sizeof(struct rxrpc_jumbo_header)) + if (msg->dsize < + RXRPC_JUMBO_DATALEN + sizeof(struct rxrpc_jumbo_header)) goto error; if (msg->hdr.flags & RXRPC_LAST_PACKET) goto error; /* dig out the secondary header */ - if (skb_copy_bits(pkt,msg->offset+RXRPC_JUMBO_DATALEN,&jumbo,sizeof(jumbo))<0) + if (skb_copy_bits(pkt, msg->offset + RXRPC_JUMBO_DATALEN, + &jumbo, sizeof(jumbo)) < 0) goto error; /* allocate a new message record */ ret = -ENOMEM; - msg = kmalloc(sizeof(struct rxrpc_message),GFP_KERNEL); + msg = kmalloc(sizeof(struct rxrpc_message), GFP_KERNEL); if (!msg) goto error; - memcpy(msg,jumbomsg,sizeof(*msg)); - list_add_tail(&msg->link,msgq); + memcpy(msg, jumbomsg, sizeof(*msg)); + list_add_tail(&msg->link, msgq); /* adjust the jumbo packet */ jumbomsg->dsize = RXRPC_JUMBO_DATALEN; @@ -388,12 +392,15 @@ msg->seq++; msg->hdr.seq = htonl(msg->seq); msg->hdr.serial = htonl(ntohl(msg->hdr.serial) + 1); - msg->offset += RXRPC_JUMBO_DATALEN + sizeof(struct rxrpc_jumbo_header); - msg->dsize -= RXRPC_JUMBO_DATALEN + sizeof(struct rxrpc_jumbo_header); + msg->offset += RXRPC_JUMBO_DATALEN + + sizeof(struct rxrpc_jumbo_header); + msg->dsize -= RXRPC_JUMBO_DATALEN + + sizeof(struct rxrpc_jumbo_header); msg->hdr.flags = jumbo.flags; msg->hdr._rsvd = jumbo._rsvd; - _net("Rx Split jumbo packet from %s (%08x;%08x,%1x,%d,%s,%02x,%d,%d)", + _net("Rx Split jumbo packet from %s" + " (%08x;%08x,%1x,%d,%s,%02x,%d,%d)", msg->hdr.flags & RXRPC_CLIENT_INITIATED ? "client" : "server", ntohl(msg->hdr.epoch), (ntohl(msg->hdr.cid) & RXRPC_CIDMASK) >> RXRPC_CIDSHIFT, @@ -407,18 +414,18 @@ __RXACCT(atomic_inc(&rxrpc_message_count)); } - _leave(" = 0 #%d",atomic_read(&rxrpc_message_count)); + _leave(" = 0 #%d", atomic_read(&rxrpc_message_count)); return 0; error: while (!list_empty(msgq)) { - msg = list_entry(msgq->next,struct rxrpc_message,link); + msg = list_entry(msgq->next, struct rxrpc_message, link); list_del_init(&msg->link); rxrpc_put_message(msg); } - _leave(" = %d",ret); + _leave(" = %d", ret); return ret; } /* end rxrpc_incoming_msg() */ @@ -438,7 +445,7 @@ LIST_HEAD(msgq); - _enter("%p{%d}",trans,trans->port); + _enter("%p{%d}", trans, trans->port); for (;;) { /* deal with outstanting errors first */ @@ -446,22 +453,25 @@ rxrpc_trans_receive_error_report(trans); /* attempt to receive a packet */ - pkt = skb_recv_datagram(trans->socket->sk,0,1,&ret); + pkt = skb_recv_datagram(trans->socket->sk, 0, 1, &ret); if (!pkt) { - if (ret==-EAGAIN) { + if (ret == -EAGAIN) { _leave(" EAGAIN"); return; } /* an icmp error may have occurred */ rxrpc_krxiod_queue_transport(trans); - _leave(" error %d\n",ret); + _leave(" error %d\n", ret); return; } - /* we'll probably need to checksum it (didn't call sock_recvmsg) */ + /* we'll probably need to checksum it (didn't call + * sock_recvmsg) */ if (pkt->ip_summed != CHECKSUM_UNNECESSARY) { - if ((unsigned short)csum_fold(skb_checksum(pkt,0,pkt->len,pkt->csum))) { + if ((unsigned short) + csum_fold(skb_checksum(pkt, 0, pkt->len, + pkt->csum))) { kfree_skb(pkt); rxrpc_krxiod_queue_transport(trans); _leave(" CSUM failed"); @@ -472,34 +482,36 @@ addr = pkt->nh.iph->saddr; port = pkt->h.uh->source; - _net("Rx Received UDP packet from %08x:%04hu",ntohl(addr),ntohs(port)); + _net("Rx Received UDP packet from %08x:%04hu", + ntohl(addr), ntohs(port)); /* unmarshall the Rx parameters and split jumbo packets */ - ret = rxrpc_incoming_msg(trans,pkt,&msgq); - if (ret<0) { + ret = rxrpc_incoming_msg(trans, pkt, &msgq); + if (ret < 0) { kfree_skb(pkt); rxrpc_krxiod_queue_transport(trans); _leave(" bad packet"); return; } - if (list_empty(&msgq)) BUG(); + BUG_ON(list_empty(&msgq)); - msg = list_entry(msgq.next,struct rxrpc_message,link); + msg = list_entry(msgq.next, struct rxrpc_message, link); - /* locate the record for the peer from which it originated */ - ret = rxrpc_peer_lookup(trans,addr,&peer); - if (ret<0) { + /* locate the record for the peer from which it + * originated */ + ret = rxrpc_peer_lookup(trans, addr, &peer); + if (ret < 0) { kdebug("Rx No connections from that peer"); - rxrpc_trans_immediate_abort(trans,msg,-EINVAL); + rxrpc_trans_immediate_abort(trans, msg, -EINVAL); goto finished_msg; } /* try and find a matching connection */ - ret = rxrpc_connection_lookup(peer,msg,&msg->conn); - if (ret<0) { + ret = rxrpc_connection_lookup(peer, msg, &msg->conn); + if (ret < 0) { kdebug("Rx Unknown Connection"); - rxrpc_trans_immediate_abort(trans,msg,-EINVAL); + rxrpc_trans_immediate_abort(trans, msg, -EINVAL); rxrpc_put_peer(peer); goto finished_msg; } @@ -507,23 +519,23 @@ /* deal with the first packet of a new call */ if (msg->hdr.flags & RXRPC_CLIENT_INITIATED && - msg->hdr.type==RXRPC_PACKET_TYPE_DATA && - ntohl(msg->hdr.seq)==1 + msg->hdr.type == RXRPC_PACKET_TYPE_DATA && + ntohl(msg->hdr.seq) == 1 ) { _debug("Rx New server call"); - rxrpc_trans_receive_new_call(trans,&msgq); + rxrpc_trans_receive_new_call(trans, &msgq); goto finished_msg; } /* deal with subsequent packet(s) of call */ _debug("Rx Call packet"); while (!list_empty(&msgq)) { - msg = list_entry(msgq.next,struct rxrpc_message,link); + msg = list_entry(msgq.next, struct rxrpc_message, link); list_del_init(&msg->link); - ret = rxrpc_conn_receive_call_packet(msg->conn,NULL,msg); - if (ret<0) { - rxrpc_trans_immediate_abort(trans,msg,ret); + ret = rxrpc_conn_receive_call_packet(msg->conn, NULL, msg); + if (ret < 0) { + rxrpc_trans_immediate_abort(trans, msg, ret); rxrpc_put_message(msg); goto finished_msg; } @@ -536,7 +548,7 @@ /* dispose of the packets */ finished_msg: while (!list_empty(&msgq)) { - msg = list_entry(msgq.next,struct rxrpc_message,link); + msg = list_entry(msgq.next, struct rxrpc_message, link); list_del_init(&msg->link); rxrpc_put_message(msg); @@ -561,7 +573,7 @@ _enter(""); /* only bother with the first packet */ - msg = list_entry(msgq->next,struct rxrpc_message,link); + msg = list_entry(msgq->next, struct rxrpc_message, link); list_del_init(&msg->link); rxrpc_krxsecd_queue_incoming_call(msg); rxrpc_put_message(msg); @@ -584,13 +596,13 @@ struct msghdr msghdr; struct iovec iov[2]; mm_segment_t oldfs; + uint32_t _error; int len, ret; - u32 _error; - _enter("%p,%p,%d",trans,msg,error); + _enter("%p,%p,%d", trans, msg, error); /* don't abort an abort packet */ - if (msg->hdr.type==RXRPC_PACKET_TYPE_ABORT) { + if (msg->hdr.type == RXRPC_PACKET_TYPE_ABORT) { _leave(" = 0"); return 0; } @@ -598,12 +610,13 @@ _error = htonl(-error); /* set up the message to be transmitted */ - memcpy(&ahdr,&msg->hdr,sizeof(ahdr)); + memcpy(&ahdr, &msg->hdr, sizeof(ahdr)); ahdr.epoch = msg->hdr.epoch; ahdr.serial = htonl(1); ahdr.seq = 0; ahdr.type = RXRPC_PACKET_TYPE_ABORT; - ahdr.flags = RXRPC_LAST_PACKET | (~msg->hdr.flags & RXRPC_CLIENT_INITIATED); + ahdr.flags = RXRPC_LAST_PACKET; + ahdr.flags |= ~msg->hdr.flags & RXRPC_CLIENT_INITIATED; iov[0].iov_len = sizeof(ahdr); iov[0].iov_base = &ahdr; @@ -634,17 +647,17 @@ /* send the message */ oldfs = get_fs(); set_fs(KERNEL_DS); - ret = sock_sendmsg(trans->socket,&msghdr,len); + ret = sock_sendmsg(trans->socket, &msghdr, len); set_fs(oldfs); - _leave(" = %d",ret); + _leave(" = %d", ret); return ret; } /* end rxrpc_trans_immediate_abort() */ /*****************************************************************************/ /* - * receive an ICMP error report and percolate it to all connections heading to the affected - * host or port + * receive an ICMP error report and percolate it to all connections + * heading to the affected host or port */ static void rxrpc_trans_receive_error_report(struct rxrpc_transport *trans) { @@ -655,10 +668,10 @@ struct errormsg emsg; struct msghdr msg; mm_segment_t oldfs; + uint16_t port; int local, err; - u16 port; - _enter("%p",trans); + _enter("%p", trans); for (;;) { trans->error_rcvd = 0; @@ -674,48 +687,63 @@ oldfs = get_fs(); set_fs(KERNEL_DS); - err = sock_recvmsg(trans->socket,&msg,0,MSG_ERRQUEUE|MSG_DONTWAIT|MSG_TRUNC); + err = sock_recvmsg(trans->socket, &msg, 0, + MSG_ERRQUEUE | MSG_DONTWAIT | MSG_TRUNC); set_fs(oldfs); - if (err==-EAGAIN) { + if (err == -EAGAIN) { _leave(""); return; } - if (err<0) { - printk("%s: unable to recv an error report: %d\n",__FUNCTION__,err); + if (err < 0) { + printk("%s: unable to recv an error report: %d\n", + __FUNCTION__, err); _leave(""); return; } - msg.msg_controllen = (char*)msg.msg_control - (char*)&emsg; + msg.msg_controllen = (char *) msg.msg_control - (char *) &emsg; - if (msg.msg_controllenconn_lock); - list_for_each(_p,&peer->conn_active) { - conn = list_entry(_p,struct rxrpc_connection,link); - if (port && conn->addr.sin_port!=port) + list_for_each(_p, &peer->conn_active) { + conn = list_entry(_p, struct rxrpc_connection, + link); + if (port && conn->addr.sin_port != port) continue; if (!list_empty(&conn->err_link)) continue; rxrpc_get_connection(conn); - list_add_tail(&conn->err_link,&connq); + list_add_tail(&conn->err_link, &connq); } read_unlock(&peer->conn_lock); /* service all those connections */ while (!list_empty(&connq)) { - conn = list_entry(connq.next,struct rxrpc_connection,err_link); + conn = list_entry(connq.next, + struct rxrpc_connection, + err_link); list_del(&conn->err_link); - rxrpc_conn_handle_error(conn,local,err); + rxrpc_conn_handle_error(conn, local, err); rxrpc_put_connection(conn); } diff -Nru a/net/sched/estimator.c b/net/sched/estimator.c --- a/net/sched/estimator.c Thu Sep 11 23:03:11 2003 +++ b/net/sched/estimator.c Thu Sep 11 23:03:11 2003 @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff -Nru a/net/sched/police.c b/net/sched/police.c --- a/net/sched/police.c Thu Sep 11 23:03:13 2003 +++ b/net/sched/police.c Thu Sep 11 23:03:13 2003 @@ -27,7 +27,6 @@ #include #include #include -#include #include #include diff -Nru a/net/sched/sch_api.c b/net/sched/sch_api.c --- a/net/sched/sch_api.c Thu Sep 11 23:03:12 2003 +++ b/net/sched/sch_api.c Thu Sep 11 23:03:12 2003 @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -1059,27 +1060,27 @@ int psched_tick_per_us = 1; #ifdef CONFIG_PROC_FS -static int psched_read_proc(char *buffer, char **start, off_t offset, - int length, int *eof, void *data) +static int psched_show(struct seq_file *seq, void *v) { - int len; - - len = sprintf(buffer, "%08x %08x %08x %08x\n", + seq_printf(seq, "%08x %08x %08x %08x\n", psched_tick_per_us, psched_us_per_tick, 1000000, HZ); - len -= offset; - - if (len > length) - len = length; - if(len < 0) - len = 0; - - *start = buffer + offset; - *eof = 1; + return 0; +} - return len; +static int psched_open(struct inode *inode, struct file *file) +{ + return single_open(file, psched_show, PDE(inode)->data); } + +static struct file_operations psched_fops = { + .owner = THIS_MODULE, + .open = psched_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; #endif #if PSCHED_CLOCK_SOURCE == PSCHED_GETTIMEOFDAY @@ -1250,9 +1251,7 @@ tc_filter_init(); #endif -#ifdef CONFIG_PROC_FS - create_proc_read_entry("net/psched", 0, 0, psched_read_proc, NULL); -#endif + proc_net_fops_create("psched", 0, &psched_fops); return 0; } diff -Nru a/net/sched/sch_atm.c b/net/sched/sch_atm.c --- a/net/sched/sch_atm.c Thu Sep 11 23:03:12 2003 +++ b/net/sched/sch_atm.c Thu Sep 11 23:03:12 2003 @@ -216,6 +216,13 @@ tasklet_schedule(&p->task); } +static const u8 llc_oui_ip[] = { + 0xaa, /* DSAP: non-ISO */ + 0xaa, /* SSAP: non-ISO */ + 0x03, /* Ctrl: Unnumbered Information Command PDU */ + 0x00, /* OUI: EtherType */ + 0x00, 0x00, + 0x08, 0x00 }; /* Ethertype IP (0800) */ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent, struct rtattr **tca, unsigned long *arg) @@ -322,11 +329,10 @@ flow->next = p->link.next; p->link.next = flow; flow->hdr_len = hdr_len; - if (hdr) memcpy(flow->hdr,hdr,hdr_len); - else { - memcpy(flow->hdr,llc_oui,sizeof(llc_oui)); - ((u16 *) flow->hdr)[3] = htons(ETH_P_IP); - } + if (hdr) + memcpy(flow->hdr,hdr,hdr_len); + else + memcpy(flow->hdr,llc_oui_ip,sizeof(llc_oui_ip)); *arg = (unsigned long) flow; return 0; err_out: diff -Nru a/net/sched/sch_htb.c b/net/sched/sch_htb.c --- a/net/sched/sch_htb.c Thu Sep 11 23:03:13 2003 +++ b/net/sched/sch_htb.c Thu Sep 11 23:03:13 2003 @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff -Nru a/net/sunrpc/cache.c b/net/sunrpc/cache.c --- a/net/sunrpc/cache.c Thu Sep 11 23:03:12 2003 +++ b/net/sunrpc/cache.c Thu Sep 11 23:03:12 2003 @@ -1035,7 +1035,7 @@ read_lock(&cd->hash_lock); if (!n--) - return (void *)1; + return SEQ_START_TOKEN; hash = n >> 32; entry = n & ((1LL<<32) - 1); @@ -1060,7 +1060,7 @@ int hash = (*pos >> 32); struct cache_detail *cd = ((struct handle*)m->private)->cd; - if (p == (void *)1) + if (p == SEQ_START_TOKEN) hash = 0; else if (ch->next == NULL) { hash++; @@ -1092,7 +1092,7 @@ struct cache_head *cp = p; struct cache_detail *cd = ((struct handle*)m->private)->cd; - if (p == (void *)1) + if (p == SEQ_START_TOKEN) return cd->cache_show(m, cd, NULL); ifdebug(CACHE) diff -Nru a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c --- a/net/wanrouter/wanproc.c Thu Sep 11 23:03:12 2003 +++ b/net/wanrouter/wanproc.c Thu Sep 11 23:03:12 2003 @@ -86,7 +86,7 @@ lock_kernel(); if (!l--) - return (void *)1; + return SEQ_START_TOKEN; for (wandev = wanrouter_router_devlist; l-- && wandev; wandev = wandev->next) ; @@ -97,7 +97,7 @@ { struct wan_device *wandev = v; (*pos)++; - return (v == (void *)1) ? wanrouter_router_devlist : wandev->next; + return (v == SEQ_START_TOKEN) ? wanrouter_router_devlist : wandev->next; } static void r_stop(struct seq_file *m, void *v) @@ -108,7 +108,7 @@ static int config_show(struct seq_file *m, void *v) { struct wan_device *p = v; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { seq_puts(m, "Device name | port |IRQ|DMA| mem.addr |" "mem.size|option1|option2|option3|option4\n"); return 0; @@ -124,7 +124,7 @@ static int status_show(struct seq_file *m, void *v) { struct wan_device *p = v; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { seq_puts(m, "Device name |protocol|station|interface|" "clocking|baud rate| MTU |ndev|link state\n"); return 0; diff -Nru a/net/x25/x25_proc.c b/net/x25/x25_proc.c --- a/net/x25/x25_proc.c Thu Sep 11 23:03:11 2003 +++ b/net/x25/x25_proc.c Thu Sep 11 23:03:11 2003 @@ -44,7 +44,7 @@ loff_t l = *pos; read_lock_bh(&x25_route_list_lock); - return l ? x25_get_route_idx(--l) : (void *)1; + return l ? x25_get_route_idx(--l) : SEQ_START_TOKEN; } static void *x25_seq_route_next(struct seq_file *seq, void *v, loff_t *pos) @@ -52,7 +52,7 @@ struct x25_route *rt; ++*pos; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { rt = NULL; if (!list_empty(&x25_route_list)) rt = list_entry(x25_route_list.next, @@ -77,7 +77,7 @@ { struct x25_route *rt; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { seq_puts(seq, "Address Digits Device\n"); goto out; } @@ -108,7 +108,7 @@ loff_t l = *pos; read_lock_bh(&x25_list_lock); - return l ? x25_get_socket_idx(--l) : (void *)1; + return l ? x25_get_socket_idx(--l) : SEQ_START_TOKEN; } static void *x25_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) @@ -116,7 +116,7 @@ struct sock *s; ++*pos; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { s = sk_head(&x25_list); goto out; } @@ -137,7 +137,7 @@ struct net_device *dev; const char *devname; - if (v == (void *)1) { + if (v == SEQ_START_TOKEN) { seq_printf(seq, "dest_addr src_addr dev lci st vs vr " "va t t2 t21 t22 t23 Snd-Q Rcv-Q inode\n"); goto out; diff -Nru a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c --- a/net/xfrm/xfrm_user.c Thu Sep 11 23:03:12 2003 +++ b/net/xfrm/xfrm_user.c Thu Sep 11 23:03:12 2003 @@ -433,9 +433,9 @@ case IPPROTO_COMP: /* IPCOMP spi is 16-bits. */ - if (p->min >= 0x10000 || - p->max >= 0x10000) + if (p->max >= 0x10000) return -EINVAL; + break; default: return -EINVAL; @@ -470,7 +470,7 @@ spin_lock_bh(&x->lock); if (x->km.state != XFRM_STATE_DEAD) { - xfrm_alloc_spi(x, p->min, p->max); + xfrm_alloc_spi(x, htonl(p->min), htonl(p->max)); if (x->id.spi) resp_skb = xfrm_state_netlink(skb, x, nlh->nlmsg_seq); } diff -Nru a/scripts/Makefile b/scripts/Makefile --- a/scripts/Makefile Thu Sep 11 23:03:12 2003 +++ b/scripts/Makefile Thu Sep 11 23:03:12 2003 @@ -9,7 +9,7 @@ # conmakehash: Create arrays for initializing the kernel console tables host-progs := fixdep split-include conmakehash docproc kallsyms modpost \ - mk_elfconfig pnmtologo + mk_elfconfig pnmtologo bin2c always := $(host-progs) empty.o modpost-objs := modpost.o file2alias.o diff -Nru a/scripts/bin2c.c b/scripts/bin2c.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/scripts/bin2c.c Thu Sep 11 23:03:14 2003 @@ -0,0 +1,27 @@ +#include + +int main(int argc, char *argv[]) +{ + int ch, total=0; + + if (argc > 1) + printf("const char %s[] %s=\n", + argv[1], argc > 2 ? argv[2] : ""); + + do { + printf("\t\""); + while ((ch = getchar()) != EOF) + { + total++; + printf("\\x%02x",ch); + if (total % 16 == 0) + break; + } + printf("\"\n"); + } while (ch != EOF); + + if (argc > 1) + printf("\t;\n\nconst int %s_size = %d;\n", argv[1], total); + + return 0; +} diff -Nru a/scripts/mkcompile_h b/scripts/mkcompile_h --- a/scripts/mkcompile_h Thu Sep 11 23:03:14 2003 +++ b/scripts/mkcompile_h Thu Sep 11 23:03:14 2003 @@ -27,7 +27,7 @@ UTS_VERSION="#$VERSION" if [ -n "$SMP" ] ; then UTS_VERSION="$UTS_VERSION SMP"; fi -UTS_VERSION="$UTS_VERSION `LANG=C date`" +UTS_VERSION="$UTS_VERSION `LC_ALL=C LANG=C date`" # Truncate to maximum length @@ -42,7 +42,7 @@ echo \#define UTS_VERSION \"`echo $UTS_VERSION | $UTS_TRUNCATE`\" - echo \#define LINUX_COMPILE_TIME \"`LANG=C date +%T`\" + echo \#define LINUX_COMPILE_TIME \"`LC_ALL=C LANG=C date +%T`\" echo \#define LINUX_COMPILE_BY \"`whoami`\" echo \#define LINUX_COMPILE_HOST \"`hostname | $UTS_TRUNCATE`\" diff -Nru a/scripts/mkconfigs b/scripts/mkconfigs --- a/scripts/mkconfigs Thu Sep 11 23:03:12 2003 +++ b/scripts/mkconfigs Thu Sep 11 23:03:12 2003 @@ -66,15 +66,13 @@ * */" -echo "static char *ikconfig_built_with =" +echo "#ifdef CONFIG_IKCONFIG_PROC" +echo "static char const ikconfig_build_info[] =" echo " \"`uname -s` `uname -r` `uname -v` `uname -m`\";" +echo "#endif" echo kernel_version $makefile -echo "#ifdef CONFIG_IKCONFIG_PROC" -echo "static char *ikconfig_config = " -echo "#else" -echo "static char *ikconfig_config __initdata __attribute__((unused)) = " -echo "#endif" +echo "static char const ikconfig_config[] __attribute__((unused)) = " echo "\"CONFIG_BEGIN=n\\n\\" echo "`cat $config | sed 's/\"/\\\\\"/g' | grep "^#\? \?CONFIG_" | awk '{ print $0 "\\\\n\\\\" }' `" echo "CONFIG_END=n\\n\";" diff -Nru a/security/selinux/Kconfig b/security/selinux/Kconfig --- a/security/selinux/Kconfig Thu Sep 11 23:03:11 2003 +++ b/security/selinux/Kconfig Thu Sep 11 23:03:11 2003 @@ -8,9 +8,20 @@ You can obtain the policy compiler (checkpolicy), the utility for labeling filesystems (setfiles), and an example policy configuration from http://www.nsa.gov/selinux. - SELinux needs to be explicitly enabled on the kernel command line with - selinux=1. If you specify selinux=0 or do not use this parameter, - SELinux will not be enabled. + If you are unsure how to answer this question, answer N. + +config SECURITY_SELINUX_BOOTPARAM + bool "NSA SELinux boot parameter" + depends on SECURITY_SELINUX + default n + help + This option adds a kernel parameter 'selinux', which allows SELinux + to be disabled at boot. If this option is selected, SELinux + functionality can be disabled with selinux=0 on the kernel + command line. The purpose of this option is to allow a single + kernel image to be distributed with SELinux built in, but not + necessarily enabled. + If you are unsure how to answer this question, answer N. config SECURITY_SELINUX_DEVELOP diff -Nru a/security/selinux/hooks.c b/security/selinux/hooks.c --- a/security/selinux/hooks.c Thu Sep 11 23:03:14 2003 +++ b/security/selinux/hooks.c Thu Sep 11 23:03:14 2003 @@ -73,7 +73,8 @@ __setup("enforcing=", enforcing_setup); #endif -int selinux_enabled = 0; +#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM +int selinux_enabled = 1; static int __init selinux_enabled_setup(char *str) { @@ -81,6 +82,7 @@ return 1; } __setup("selinux=", selinux_enabled_setup); +#endif /* Original (dummy) security module. */ static struct security_operations *original_ops = NULL; @@ -3357,7 +3359,7 @@ struct task_security_struct *tsec; if (!selinux_enabled) { - printk(KERN_INFO "SELinux: Not enabled at boot.\n"); + printk(KERN_INFO "SELinux: Disabled at boot.\n"); return 0; } diff -Nru a/security/selinux/include/security.h b/security/selinux/include/security.h --- a/security/selinux/include/security.h Thu Sep 11 23:03:11 2003 +++ b/security/selinux/include/security.h Thu Sep 11 23:03:11 2003 @@ -14,6 +14,12 @@ #define SELINUX_MAGIC 0xf97cff8c +#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM +extern int selinux_enabled; +#else +#define selinux_enabled 1 +#endif + int security_load_policy(void * data, size_t len); struct av_decision { diff -Nru a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c --- a/security/selinux/selinuxfs.c Thu Sep 11 23:03:14 2003 +++ b/security/selinux/selinuxfs.c Thu Sep 11 23:03:14 2003 @@ -17,8 +17,6 @@ #include "security.h" #include "objsec.h" -extern int selinux_enabled; - /* Check whether a task is allowed to use a security operation. */ int task_has_security(struct task_struct *tsk, u32 perms) diff -Nru a/sound/core/ioctl32/ioctl32.c b/sound/core/ioctl32/ioctl32.c --- a/sound/core/ioctl32/ioctl32.c Thu Sep 11 23:03:11 2003 +++ b/sound/core/ioctl32/ioctl32.c Thu Sep 11 23:03:11 2003 @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff -Nru a/sound/oss/dmasound/Kconfig b/sound/oss/dmasound/Kconfig --- a/sound/oss/dmasound/Kconfig Thu Sep 11 23:03:12 2003 +++ b/sound/oss/dmasound/Kconfig Thu Sep 11 23:03:12 2003 @@ -12,9 +12,9 @@ want). If you want to compile it as a module, say M here and read . -config DMASOUND_AWACS +config DMASOUND_PMAC tristate "PowerMac DMA sound support" - depends on PPC_PMAC && SOUND + depends on PPC_PMAC && SOUND && I2C help If you want to use the internal audio of your PowerMac in Linux, answer Y to this question. This will provide a Sun-like /dev/audio, diff -Nru a/sound/oss/dmasound/Makefile b/sound/oss/dmasound/Makefile --- a/sound/oss/dmasound/Makefile Thu Sep 11 23:03:11 2003 +++ b/sound/oss/dmasound/Makefile Thu Sep 11 23:03:11 2003 @@ -2,7 +2,12 @@ # Makefile for the DMA sound driver # -obj-$(CONFIG_DMASOUND_ATARI) += dmasound_core.o dmasound_atari.o -obj-$(CONFIG_DMASOUND_AWACS) += dmasound_core.o dmasound_awacs.o -obj-$(CONFIG_DMASOUND_PAULA) += dmasound_core.o dmasound_paula.o -obj-$(CONFIG_DMASOUND_Q40) += dmasound_core.o dmasound_q40.o +dmasound_pmac-y += dmasound_awacs.o \ + trans_16.o dac3550a.o tas_common.o \ + tas3001c.o tas3001c_tables.o \ + tas3004.o tas3004_tables.o + +obj-$(CONFIG_DMASOUND_ATARI) += dmasound_core.o dmasound_atari.o +obj-$(CONFIG_DMASOUND_PMAC) += dmasound_core.o dmasound_pmac.o +obj-$(CONFIG_DMASOUND_PAULA) += dmasound_core.o dmasound_paula.o +obj-$(CONFIG_DMASOUND_Q40) += dmasound_core.o dmasound_q40.o diff -Nru a/sound/oss/dmasound/awacs_defs.h b/sound/oss/dmasound/awacs_defs.h --- a/sound/oss/dmasound/awacs_defs.h Thu Sep 11 23:03:11 2003 +++ b/sound/oss/dmasound/awacs_defs.h Thu Sep 11 23:03:11 2003 @@ -71,17 +71,20 @@ /* ------- - --- ----- - ------ */ #define MASK_GAINRIGHT (0xf) /* Gain Right Mask */ #define MASK_GAINLEFT (0xf << 4) /* Gain Left Mask */ -#define MASK_GAINLINE (0x1 << 8) /* Change Gain for Line??? */ -#define MASK_GAINMIC (0x0 << 8) /* Change Gain for Mic??? */ +#define MASK_GAINLINE (0x1 << 8) /* Disable Mic preamp */ +#define MASK_GAINMIC (0x0 << 8) /* Enable Mic preamp */ #define MASK_MUX_CD (0x1 << 9) /* Select CD in MUX */ -#define MASK_MUX_AUDIN (0x1 << 10) /* Select Audio In in MUX */ -#define MASK_MUX_MIC (0x1 << 11) /* Select Mic in MUX */ +#define MASK_MUX_MIC (0x1 << 10) /* Select Mic in MUX */ +#define MASK_MUX_AUDIN (0x1 << 11) /* Select Audio In in MUX */ #define MASK_MUX_LINE MASK_MUX_AUDIN #define GAINRIGHT(x) ((x) & MASK_GAINRIGHT) #define GAINLEFT(x) (((x) << 4) & MASK_GAINLEFT) +#define DEF_CD_GAIN 0x00bb +#define DEF_MIC_GAIN 0x00cc + /* Address 1 Bit Masks */ /* ------- - --- ----- */ #define MASK_ADDR1RES1 (0x3) /* Reserved */ @@ -93,7 +96,10 @@ #define MASK_ADDR1RES2 (0x1 << 8) /* Reserved */ #define MASK_AMUTE (0x1 << 9) /* Output A (Headphone) Mute when 1 */ #define MASK_HDMUTE MASK_AMUTE -#define MASK_PAROUT (0x3 << 10) /* Parallel Out (???) */ +#define MASK_PAROUT0 (0x1 << 10) /* Parallel Output 0 */ +#define MASK_PAROUT1 (0x2 << 10) /* Parallel Output 1 */ + +#define MASK_MIC_BOOST (0x4) /* screamer mic boost */ #define SAMPLERATE_48000 (0x0 << 3) /* 48 or 44.1 kHz */ #define SAMPLERATE_32000 (0x1 << 3) /* 32 or 29.4 kHz */ @@ -162,8 +168,9 @@ #define RATE_LOW 1 /* HIGH = 48kHz, etc; LOW = 44.1kHz, etc. */ - +/*******************/ /* Burgundy values */ +/*******************/ #define MASK_ADDR_BURGUNDY_INPSEL21 (0x11 << 12) #define MASK_ADDR_BURGUNDY_INPSEL3 (0x12 << 12) @@ -225,5 +232,20 @@ #define DEF_BURGUNDY_ATTENSPEAKER (0x44) #define DEF_BURGUNDY_ATTENLINEOUT (0xCC) #define DEF_BURGUNDY_ATTENHP (0xCC) + +/*********************/ +/* i2s layout values */ +/*********************/ + +#define I2S_REG_INT_CTL 0x00 +#define I2S_REG_SERIAL_FORMAT 0x10 +#define I2S_REG_CODEC_MSG_OUT 0x20 +#define I2S_REG_CODEC_MSG_IN 0x30 +#define I2S_REG_FRAME_COUNT 0x40 +#define I2S_REG_FRAME_MATCH 0x50 +#define I2S_REG_DATAWORD_SIZES 0x60 +#define I2S_REG_PEAKLEVEL_SEL 0x70 +#define I2S_REG_PEAKLEVEL_IN0 0x80 +#define I2S_REG_PEAKLEVEL_IN1 0x90 #endif /* _AWACS_DEFS_H_ */ diff -Nru a/sound/oss/dmasound/dac3550a.c b/sound/oss/dmasound/dac3550a.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sound/oss/dmasound/dac3550a.c Thu Sep 11 23:03:14 2003 @@ -0,0 +1,222 @@ +/* + * Driver for the i2c/i2s based DAC3550a sound chip used + * on some Apple iBooks. Also known as "DACA". + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dmasound.h" + +/* FYI: This code was derived from the tas3001c.c Texas/Tumbler mixer + * control code, as well as info derived from the AppleDACAAudio driver + * from Darwin CVS (main thing I derived being register numbers and + * values, as well as when to make the calls). */ + +#define I2C_DRIVERID_DACA (0xFDCB) + +#define DACA_VERSION "0.1" +#define DACA_DATE "20010930" + +static int cur_left_vol; +static int cur_right_vol; +static struct i2c_client *daca_client; + +static int daca_attach_adapter(struct i2c_adapter *adapter); +static int daca_detect_client(struct i2c_adapter *adapter, int address); +static int daca_detach_client(struct i2c_client *client); + +/* Unique ID allocation */ +static int daca_id; + +struct daca_data +{ + int arf; /* place holder for furture use */ +}; + +struct i2c_driver daca_driver = { + .owner = THIS_MODULE, + .name = "DAC3550A driver V " DACA_VERSION, + .id = I2C_DRIVERID_DACA, + .flags = I2C_DF_NOTIFY, + .attach_adapter = daca_attach_adapter, + .detach_client = daca_detach_client, +}; + +#define VOL_MAX ((1<<20) - 1) + +void daca_get_volume(uint * left_vol, uint *right_vol) +{ + *left_vol = cur_left_vol >> 5; + *right_vol = cur_right_vol >> 5; +} + +int daca_set_volume(uint left_vol, uint right_vol) +{ + unsigned short voldata; + + if (!daca_client) + return -1; + + /* Derived from experience, not from any specific values */ + left_vol <<= 5; + right_vol <<= 5; + + if (left_vol > VOL_MAX) + left_vol = VOL_MAX; + if (right_vol > VOL_MAX) + right_vol = VOL_MAX; + + voldata = ((left_vol >> 14) & 0x3f) << 8; + voldata |= (right_vol >> 14) & 0x3f; + + if (i2c_smbus_write_word_data(daca_client, 2, voldata) < 0) { + printk("daca: failed to set volume \n"); + return -1; + } + + cur_left_vol = left_vol; + cur_right_vol = right_vol; + + return 0; +} + +int daca_leave_sleep(void) +{ + if (!daca_client) + return -1; + + /* Do a short sleep, just to make sure I2C bus is awake and paying + * attention to us + */ + wait_ms(20); + /* Write the sample rate reg the value it needs */ + i2c_smbus_write_byte_data(daca_client, 1, 8); + daca_set_volume(cur_left_vol >> 5, cur_right_vol >> 5); + /* Another short delay, just to make sure the other I2C bus writes + * have taken... + */ + wait_ms(20); + /* Write the global config reg - invert right power amp, + * DAC on, use 5-volt mode */ + i2c_smbus_write_byte_data(daca_client, 3, 0x45); + + return 0; +} + +int daca_enter_sleep(void) +{ + if (!daca_client) + return -1; + + i2c_smbus_write_byte_data(daca_client, 1, 8); + daca_set_volume(cur_left_vol >> 5, cur_right_vol >> 5); + + /* Write the global config reg - invert right power amp, + * DAC on, enter low-power mode, use 5-volt mode + */ + i2c_smbus_write_byte_data(daca_client, 3, 0x65); + + return 0; +} + +static int daca_attach_adapter(struct i2c_adapter *adapter) +{ + if (!strncmp(adapter->name, "mac-io", 6)) + daca_detect_client(adapter, 0x4d); + return 0; +} + +static int daca_init_client(struct i2c_client * new_client) +{ + /* + * Probe is not working with the current i2c-keywest + * driver. We try to use addr 0x4d on each adapters + * instead, by setting the format register. + * + * FIXME: I'm sure that can be obtained from the + * device-tree. --BenH. + */ + + /* Write the global config reg - invert right power amp, + * DAC on, use 5-volt mode + */ + if (i2c_smbus_write_byte_data(new_client, 3, 0x45)) + return -1; + + i2c_smbus_write_byte_data(new_client, 1, 8); + daca_client = new_client; + daca_set_volume(15000, 15000); + + return 0; +} + +static int daca_detect_client(struct i2c_adapter *adapter, int address) +{ + const char *client_name = "DAC 3550A Digital Equalizer"; + struct i2c_client *new_client; + struct daca_data *data; + int rc = -ENODEV; + + new_client = kmalloc(sizeof(*new_client) + sizeof(*data), GFP_KERNEL); + if (!new_client) + return -ENOMEM; + + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &daca_driver; + new_client->flags = 0; + strcpy(new_client->name, client_name); + new_client->id = daca_id++; /* racy... */ + + data = (struct daca_data *)(new_client+1); + dev_set_drvdata(&new_client->dev, data); + + if (daca_init_client(new_client)) + goto bail; + + /* Tell the i2c layer a new client has arrived */ + if (i2c_attach_client(new_client)) + goto bail; + + return 0; + bail: + kfree(new_client); + return rc; +} + + +static int daca_detach_client(struct i2c_client *client) +{ + if (client == daca_client) + daca_client = NULL; + + i2c_detach_client(client); + kfree(client); + return 0; +} + +void daca_cleanup(void) +{ + i2c_del_driver(&daca_driver); +} + +int daca_init(void) +{ + printk("dac3550a driver version %s (%s)\n",DACA_VERSION,DACA_DATE); + return i2c_add_driver(&daca_driver); +} diff -Nru a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c --- a/sound/oss/dmasound/dmasound_awacs.c Thu Sep 11 23:03:12 2003 +++ b/sound/oss/dmasound/dmasound_awacs.c Thu Sep 11 23:03:12 2003 @@ -45,7 +45,14 @@ * 01/02/2002 [0.7] - BenH * - all sort of minor bits went in since the latest update, I * bumped the version number for that reason -*/ + * + * 07/26/2002 [0.8] - BenH + * - More minor bits since last changelog (I should be more careful + * with those) + * - Support for snapper & better tumbler integration by Toby Sargeant + * - Headphone detect for scremer by Julien Blache + * - More tumbler fixed by Andreas Schwab + */ /* GENERAL FIXME/TODO: check that the assumptions about what is written to mac-io is valid for DACA & Tumbler. @@ -68,6 +75,7 @@ #include #include #include +#include #include #ifdef CONFIG_ADB_CUDA #include @@ -89,10 +97,14 @@ #include "awacs_defs.h" #include "dmasound.h" +#include "tas3001c.h" +#include "tas3004.h" +#include "tas_common.h" #define DMASOUND_AWACS_REVISION 0 #define DMASOUND_AWACS_EDITION 7 +#define AWACS_SNAPPER 110 /* fake revision # for snapper */ #define AWACS_BURGUNDY 100 /* fake revision # for burgundy */ #define AWACS_TUMBLER 90 /* fake revision # for tumbler */ #define AWACS_DACA 80 /* fake revision # for daca (ibook) */ @@ -103,11 +115,13 @@ */ static int awacs_irq, awacs_tx_irq, awacs_rx_irq; static volatile struct awacs_regs *awacs; +static volatile u32 *i2s; static volatile struct dbdma_regs *awacs_txdma, *awacs_rxdma; static int awacs_rate_index; static int awacs_subframe; static int awacs_spkr_vol; static struct device_node* awacs_node; +static struct device_node* i2s_node; static char awacs_name[64]; static int awacs_revision; @@ -164,6 +178,8 @@ static int cd_lev = 0x6363 ; /* 99 % */ static int line_lev; +static int hdp_connected; + /* * Stuff for outputting a beep. The values range from -327 to +327 * so we can multiply by an amplitude in the range 0..100 to get a @@ -215,7 +231,6 @@ static short *beep_buf; static void *beep_dbdma_cmd_space; static volatile struct dbdma_cmd *beep_dbdma_cmd; -static void (*orig_mksound)(unsigned int, unsigned int); /* Burgundy functions */ static void awacs_burgundy_wcw(unsigned addr,unsigned newval); @@ -286,25 +301,12 @@ extern TRANS transAwacsNormalRead ; extern int daca_init(void); -extern int daca_cleanup(void); +extern void daca_cleanup(void); extern int daca_set_volume(uint left_vol, uint right_vol); extern void daca_get_volume(uint * left_vol, uint *right_vol); extern int daca_enter_sleep(void); extern int daca_leave_sleep(void); -extern int tas_init(void); -extern int tas_cleanup(void); -extern int tumbler_set_volume(uint left_vol, uint right_vol); -extern void tumbler_get_volume(uint * left_vol, uint *right_vol); -extern void tumbler_set_treble(int treble); -extern void tumbler_get_treble(int *treble); -extern void tumbler_set_bass(int bass); -extern void tumbler_get_bass(int *bass); -extern void tumbler_set_pcm_lvl(int pcm_lvl); -extern void tumbler_get_pcm_lvl(int *pcm_lvl); -extern int tumbler_enter_sleep(void); -extern int tumbler_leave_sleep(void); - #define TRY_LOCK() \ if ((rc = down_interruptible(&dmasound_sem)) != 0) \ return rc; @@ -331,7 +333,7 @@ } -/*** AE - TUMBLER START *********************************************************/ +/*** AE - TUMBLER / SNAPPER START ************************************************/ int gpio_audio_reset, gpio_audio_reset_pol; @@ -393,31 +395,35 @@ return ((pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, gpio_addr, 0) & 0x02) !=0); } +/* + * Headphone interrupt via GPIO (Tumbler, Snapper, DACA) + */ static irqreturn_t headphone_intr(int irq, void *devid, struct pt_regs *regs) { - int handled = 0; - spin_lock(&dmasound.lock); + unsigned long flags; + + spin_lock_irqsave(&dmasound.lock, flags); if (read_audio_gpio(gpio_headphone_detect) == gpio_headphone_detect_pol) { - handled = 1; printk(KERN_INFO "Audio jack plugged, muting speakers.\n"); - write_audio_gpio(gpio_amp_mute, gpio_amp_mute_pol); write_audio_gpio(gpio_headphone_mute, !gpio_headphone_mute_pol); + write_audio_gpio(gpio_amp_mute, gpio_amp_mute_pol); + tas_output_device_change(sound_device_id,TAS_OUTPUT_HEADPHONES,0); } else { - handled = 1; printk(KERN_INFO "Audio jack unplugged, enabling speakers.\n"); write_audio_gpio(gpio_amp_mute, !gpio_amp_mute_pol); write_audio_gpio(gpio_headphone_mute, gpio_headphone_mute_pol); + tas_output_device_change(sound_device_id,TAS_OUTPUT_INTERNAL_SPKR,0); } - spin_unlock(&dmasound.lock); - return IRQ_RETVAL(handled); + spin_unlock_irqrestore(&dmasound.lock, flags); + return IRQ_HANDLED; } /* Initialize tumbler */ static int -awacs_tumbler_init(void) +tas_dmasound_init(void) { setup_audio_gpio( "audio-hw-reset", @@ -474,15 +480,124 @@ static int -awacs_tumbler_cleanup(void) +tas_dmasound_cleanup(void) { if (gpio_headphone_irq) free_irq(gpio_headphone_irq, 0); return 0; } +/* We don't support 48k yet */ +static int tas_freqs[1] = { 44100 } ; +static int tas_freqs_ok[1] = { 1 } ; + +/* don't know what to do really - just have to leave it where + * OF left things +*/ + +static int +tas_set_frame_rate(void) +{ + if (i2s) { + out_le32(i2s + (I2S_REG_SERIAL_FORMAT >> 2), 0x41190000); + out_le32(i2s + (I2S_REG_DATAWORD_SIZES >> 2), 0x02000200); + } + dmasound.hard.speed = 44100 ; + awacs_rate_index = 0 ; + return 44100 ; +} + +static int +tas_mixer_ioctl(u_int cmd, u_long arg) +{ + int data; + int rc; + + rc=tas_device_ioctl(cmd, arg); + if (rc != -EINVAL) { + return rc; + } + + if ((cmd & ~0xff) == MIXER_WRITE(0) && + tas_supported_mixers() & (1<<(cmd & 0xff))) { + rc = get_user(data, (int *)(arg)); + if (rc<0) return rc; + tas_set_mixer_level(cmd & 0xff, data); + tas_get_mixer_level(cmd & 0xff, &data); + return ioctl_return2((int *)(arg), data); + } + if ((cmd & ~0xff) == MIXER_READ(0) && + tas_supported_mixers() & (1<<(cmd & 0xff))) { + tas_get_mixer_level(cmd & 0xff, &data); + return ioctl_return2((int *)(arg), data); + } + + switch(cmd) { + case SOUND_MIXER_READ_DEVMASK: + data = tas_supported_mixers() | SOUND_MASK_SPEAKER; + rc = IOCTL_OUT(arg, data); + break; + case SOUND_MIXER_READ_STEREODEVS: + data = tas_stereo_mixers(); + rc = IOCTL_OUT(arg, data); + break; + case SOUND_MIXER_READ_CAPS: + rc = IOCTL_OUT(arg, 0); + break; + case SOUND_MIXER_READ_RECMASK: + data = 0; + rc = IOCTL_OUT(arg, data); + break; + case SOUND_MIXER_READ_RECSRC: + data = 0; + rc = IOCTL_OUT(arg, data); + break; + case SOUND_MIXER_WRITE_RECSRC: + IOCTL_IN(arg, data); + data =0; + rc = IOCTL_OUT(arg, data); + break; + case SOUND_MIXER_WRITE_SPEAKER: /* really bell volume */ + IOCTL_IN(arg, data); + beep_vol = data & 0xff; + /* fall through */ + case SOUND_MIXER_READ_SPEAKER: + rc = IOCTL_OUT(arg, (beep_vol<<8) | beep_vol); + break; + case SOUND_MIXER_OUTMASK: + case SOUND_MIXER_OUTSRC: + default: + rc = -EINVAL; + } + + return rc; +} + +static void __init +tas_init_frame_rates(unsigned int *prop, unsigned int l) +{ + int i ; + if (prop) { + for (i=0; i<1; i++) + tas_freqs_ok[i] = 0; + for (l /= sizeof(int); l > 0; --l) { + unsigned int r = *prop++; + /* Apple 'Fixed' format */ + if (r >= 0x10000) + r >>= 16; + for (i = 0; i < 1; ++i) { + if (r == tas_freqs[i]) { + tas_freqs_ok[i] = 1; + break; + } + } + } + } + /* else we assume that all the rates are available */ +} + -/*** AE - TUMBLER END *********************************************************/ +/*** AE - TUMBLER / SNAPPER END ************************************************/ @@ -503,8 +618,10 @@ static int __init PMacIrqInit(void) { - if (request_irq(awacs_irq, pmac_awacs_intr, 0, "Built-in Sound misc", 0) - || request_irq(awacs_tx_irq, pmac_awacs_tx_intr, 0, "Built-in Sound out", 0) + if (awacs) + if (request_irq(awacs_irq, pmac_awacs_intr, 0, "Built-in Sound misc", 0)) + return 0; + if (request_irq(awacs_tx_irq, pmac_awacs_tx_intr, 0, "Built-in Sound out", 0) || request_irq(awacs_rx_irq, pmac_awacs_rx_intr, 0, "Built-in Sound in", 0)) return 0; return 1; @@ -517,23 +634,28 @@ DBDMA_DO_STOP(awacs_txdma); DBDMA_DO_STOP(awacs_rxdma); - /* disable interrupts from awacs interface */ - out_le32(&awacs->control, in_le32(&awacs->control) & 0xfff); - + if (awacs) + /* disable interrupts from awacs interface */ + out_le32(&awacs->control, in_le32(&awacs->control) & 0xfff); + /* Switch off the sound clock */ pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, awacs_node, 0, 0); /* Make sure proper bits are set on pismo & tipb */ - if (machine_is_compatible("PowerBook3,1") || - machine_is_compatible("PowerBook3,2")) { + if ((machine_is_compatible("PowerBook3,1") || + machine_is_compatible("PowerBook3,2")) && awacs) { awacs_reg[1] |= MASK_PAROUT0 | MASK_PAROUT1; awacs_write(MASK_ADDR1 | awacs_reg[1]); wait_ms(200); } - free_irq(awacs_irq, 0); + if (awacs) + free_irq(awacs_irq, 0); free_irq(awacs_tx_irq, 0); free_irq(awacs_rx_irq, 0); - /* all OF versions I've seen use this value */ - iounmap((void *)awacs); + + if (awacs) + iounmap((void *)awacs); + if (i2s) + iounmap((void *)i2s); iounmap((void *)awacs_txdma); iounmap((void *)awacs_rxdma); @@ -547,10 +669,8 @@ kfree(awacs_rx_cmd_space); if (beep_dbdma_cmd_space) kfree(beep_dbdma_cmd_space); - if (beep_buf) { + if (beep_buf) kfree(beep_buf); - kd_mksound = orig_mksound; - } #ifdef CONFIG_PMAC_PBOOK pmu_unregister_sleep_notifier(&awacs_sleep_notifier); #endif @@ -563,26 +683,16 @@ DBDMA_DO_STOP(awacs_txdma); } -static int tumbler_freqs[2] = { 48000, 44100 } ; -static int tumbler_freqs_ok[2] = { 1, 1 } ; - -/* don't know what to do really - just have to leave it where - * OF left things -*/ - -static int tumbler_set_frame_rate(void) -{ - dmasound.hard.speed = 44100 ; - awacs_rate_index = 0 ; - return 44100 ; -} - /* don't know what to do really - just have to leave it where * OF left things */ static int daca_set_frame_rate(void) { + if (i2s) { + out_le32(i2s + (I2S_REG_SERIAL_FORMAT >> 2), 0x41190000); + out_le32(i2s + (I2S_REG_DATAWORD_SIZES >> 2), 0x02000200); + } dmasound.hard.speed = 44100 ; awacs_rate_index = 0 ; return 44100 ; @@ -593,7 +703,8 @@ }; static int awacs_freqs_ok[8] = { 1, 1, 1, 1, 1, 1, 1, 1 }; -static int awacs_set_frame_rate(int desired, int catch_r) +static int +awacs_set_frame_rate(int desired, int catch_r) { int tolerance, i = 8 ; /* @@ -617,13 +728,9 @@ return dmasound.hard.speed; } -static int burgundy_frame_rates = 1 ; -static int burgundy_set_frame_rate(void) +static int +burgundy_set_frame_rate(void) { -#ifdef DEBUG_DMASOUND -if (burgundy_frame_rates > 1) - printk("dmasound_pmac: warning Burgundy had more than one frame rate\n"); -#endif awacs_rate_index = 0 ; awacs_reg[1] = (awacs_reg[1] & ~MASK_SAMPLERATE) ; /* XXX disable error interrupt on burgundy for now */ @@ -631,24 +738,24 @@ return 44100 ; } -static int set_frame_rate(int desired, int catch_r) +static int +set_frame_rate(int desired, int catch_r) { switch (awacs_revision) { case AWACS_BURGUNDY: - dmasound.hard.speed = - burgundy_set_frame_rate(); + dmasound.hard.speed = burgundy_set_frame_rate(); break ; case AWACS_TUMBLER: - dmasound.hard.speed = - tumbler_set_frame_rate(); + case AWACS_SNAPPER: + dmasound.hard.speed = tas_set_frame_rate(); break ; case AWACS_DACA: dmasound.hard.speed = daca_set_frame_rate(); break ; default: - dmasound.hard.speed = - awacs_set_frame_rate(desired, catch_r); + dmasound.hard.speed = awacs_set_frame_rate(desired, + catch_r); break ; } return dmasound.hard.speed ; @@ -698,11 +805,13 @@ dmasound.trans_write = &transAwacsExpand; dmasound.trans_read = &transAwacsNormalRead; - if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE)) - out_le32(&awacs->byteswap, BS_VAL); - else - out_le32(&awacs->byteswap, 0); - + if (awacs) { + if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE)) + out_le32(&awacs->byteswap, BS_VAL); + else + out_le32(&awacs->byteswap, 0); + } + expand_bal = -dmasound.soft.speed; } @@ -787,18 +896,28 @@ static int PMacSetVolume(int volume) { - return awacs_volume_setter(volume, 2, MASK_AMUTE, 6); + printk(KERN_WARNING "Bogus call to PMacSetVolume !\n"); + return 0; +} + +static void awacs_setup_for_beep(int speed) +{ + out_le32(&awacs->control, + (in_le32(&awacs->control) & ~0x1f00) + | ((speed > 0 ? speed : awacs_rate_index) << 8)); + + if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE) && speed == -1) + out_le32(&awacs->byteswap, BS_VAL); + else + out_le32(&awacs->byteswap, 0); } +/* CHECK: how much of this *really* needs IRQs masked? */ static void __PMacPlay(void) { volatile struct dbdma_cmd *cp; int next_frg, count; - unsigned long flags; - - /* CHECK: how much of this *really* needs IRQs masked? */ - spin_lock_irqsave(&dmasound.lock, flags); count = 300 ; /* > two cycles at the lowest sample rate */ /* what we want to send next */ @@ -810,15 +929,8 @@ out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); while ( (in_le32(&awacs_txdma->status) & RUN) && count--) udelay(1); - /* FIXME: check that this is OK for other chip sets */ - out_le32(&awacs->control, - (in_le32(&awacs->control) & ~0x1f00) - | (awacs_rate_index << 8)); - - if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE)) - out_le32(&awacs->byteswap, BS_VAL); - else - out_le32(&awacs->byteswap, 0); + if (awacs) + awacs_setup_for_beep(-1); out_le32(&awacs_txdma->cmdptr, virt_to_bus(&(awacs_tx_cmds[next_frg]))); @@ -865,14 +977,18 @@ out_le32(&awacs_txdma->control, ((RUN|WAKE) << 16) + (RUN|WAKE)); ++write_sq.active; } - spin_unlock_irqrestore(&dmasound.lock, flags); } static void PMacPlay(void) { LOCK(); - if (!awacs_sleeping) + if (!awacs_sleeping) { + unsigned long flags; + + spin_lock_irqsave(&dmasound.lock, flags); __PMacPlay(); + spin_unlock_irqrestore(&dmasound.lock, flags); + } UNLOCK(); } @@ -919,6 +1035,7 @@ { int i = write_sq.front; int stat; + int i_nowrap = write_sq.front; volatile struct dbdma_cmd *cp; /* != 0 when we are dealing with a DEAD xfer */ static int emergency_in_use; @@ -976,6 +1093,7 @@ emergency_in_use = 0 ; /* done that */ --write_sq.count; --write_sq.active; + i_nowrap++; if (++i >= write_sq.max_count) i = 0; } @@ -988,7 +1106,7 @@ } /* if we used some data up then wake the writer to supply some more*/ - if (i != write_sq.front) + if (i_nowrap != write_sq.front) WAKE_UP(write_sq.action_queue); write_sq.front = i; @@ -1091,11 +1209,30 @@ pmac_awacs_intr(int irq, void *devid, struct pt_regs *regs) { int ctrl; + int status; + int r1; + spin_lock(&dmasound.lock); ctrl = in_le32(&awacs->control); + status = in_le32(&awacs->codec_stat); if (ctrl & MASK_PORTCHG) { - /* do something when headphone is plugged/unplugged? */ + /* tested on Screamer, should work on others too */ + if (awacs_revision == AWACS_SCREAMER) { + if (((status & MASK_HDPCONN) >> 3) && (hdp_connected == 0)) { + hdp_connected = 1; + + r1 = awacs_reg[1] | MASK_SPKMUTE; + awacs_reg[1] = r1; + awacs_write(r1 | MASK_ADDR_MUTE); + } else if (((status & MASK_HDPCONN) >> 3 == 0) && (hdp_connected == 1)) { + hdp_connected = 0; + + r1 = awacs_reg[1] & ~MASK_SPKMUTE; + awacs_reg[1] = r1; + awacs_write(r1 | MASK_ADDR_MUTE); + } + } } if (ctrl & MASK_CNTLERR) { int err = (in_le32(&awacs->codec_stat) & MASK_ERRCODE) >> 16; @@ -1113,7 +1250,7 @@ awacs_write(int val) { int count = 300 ; - if (awacs_revision >= AWACS_DACA) + if (awacs_revision >= AWACS_DACA || !awacs) return ; while ((in_le32(&awacs->codec_ctrl) & MASK_NEWECMD) && count--) @@ -1136,22 +1273,16 @@ out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16); while ((in_le32(&awacs_txdma->status) & RUN) && count--) udelay(1); - /* FIXME: check this is OK for DACA, Tumbler */ - out_le32(&awacs->control, - (in_le32(&awacs->control) & ~0x1f00) - | (awacs_rate_index << 8)); - if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE)) - out_le32(&awacs->byteswap, BS_VAL); - else - out_le32(&awacs->byteswap, 0); + if (awacs) + awacs_setup_for_beep(-1); beep_playing = 0; } spin_unlock_irqrestore(&dmasound.lock, flags); } static struct timer_list beep_timer = TIMER_INITIALIZER(awacs_nosound, 0, 0); -}; +#if 0 /* would need to go through the input layer in 2.6, later.. --hch */ /* we generate the beep with a single dbdma command that loops a buffer forever - without generating interrupts. So, to stop it you have to stop dma output as per awacs_nosound. @@ -1237,17 +1368,15 @@ out_le32(&awacs_txdma->control, (RUN|WAKE|FLUSH|PAUSE) << 16); while ((in_le32(&awacs_txdma->status) & RUN) && count--) udelay(1); /* timeout > 2 samples at lowest rate*/ - /* FIXME: check this is OK on DACA, Tumbler */ - out_le32(&awacs->control, - (in_le32(&awacs->control) & ~0x1f00) - | (beep_speed << 8)); - out_le32(&awacs->byteswap, 0); /* force BE */ + if (awacs) + awacs_setup_for_beep(beep_speed); out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd)); (void)in_le32(&awacs_txdma->status); out_le32(&awacs_txdma->control, RUN | (RUN << 16)); } spin_unlock_irqrestore(&dmasound.lock, flags); } +#endif /* used in init and for wake-up */ @@ -1267,10 +1396,12 @@ awacs_write(awacs_reg[1] + MASK_ADDR1); awacs_write(awacs_reg[7] + MASK_ADDR7); } - if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE)) - out_le32(&awacs->byteswap, BS_VAL); - else - out_le32(&awacs->byteswap, 0); + if (awacs) { + if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE)) + out_le32(&awacs->byteswap, BS_VAL); + else + out_le32(&awacs->byteswap, 0); + } } #ifdef CONFIG_PMAC_PBOOK @@ -1280,6 +1411,8 @@ /* FIXME: sort out disabling/re-enabling of read stuff as well */ static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when) { + unsigned long flags; + switch (when) { case PBOOK_SLEEP_NOW: LOCK(); @@ -1297,9 +1430,18 @@ /* stop rx - if going - a bit of a daft user... but */ out_le32(&awacs_rxdma->control, (RUN|WAKE|FLUSH << 16)); /* deny interrupts */ + if (awacs) + disable_irq(awacs_irq); + disable_irq(awacs_tx_irq); + disable_irq(awacs_rx_irq); + /* Chip specific sleep code */ switch (awacs_revision) { case AWACS_TUMBLER: - tumbler_enter_sleep(); /* Stub for now */ + case AWACS_SNAPPER: + write_audio_gpio(gpio_headphone_mute, gpio_headphone_mute_pol); + write_audio_gpio(gpio_amp_mute, gpio_amp_mute_pol); + tas_enter_sleep(); + write_audio_gpio(gpio_audio_reset, gpio_audio_reset_pol); break ; case AWACS_DACA: daca_enter_sleep(); @@ -1312,17 +1454,14 @@ out_le32(&awacs->control, 0x11) ; break ; } - disable_irq(awacs_irq); - disable_irq(awacs_tx_irq); - disable_irq(awacs_rx_irq); /* Disable sound clock */ pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, awacs_node, 0, 0); /* According to Darwin, we do that after turning off the sound * chip clock. All this will have to be cleaned up once we properly * parse the OF sound-objects */ - if (machine_is_compatible("PowerBook3,1") || - machine_is_compatible("PowerBook3,2")) { + if ((machine_is_compatible("PowerBook3,1") || + machine_is_compatible("PowerBook3,2")) && awacs) { awacs_reg[1] |= MASK_PAROUT0 | MASK_PAROUT1; awacs_write(MASK_ADDR1 | awacs_reg[1]); wait_ms(200); @@ -1331,8 +1470,8 @@ case PBOOK_WAKE: /* Enable sound clock */ pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, awacs_node, 0, 1); - if (machine_is_compatible("PowerBook3,1") || - machine_is_compatible("PowerBook3,2")) { + if ((machine_is_compatible("PowerBook3,1") || + machine_is_compatible("PowerBook3,2")) && awacs) { wait_ms(100); awacs_reg[1] &= ~(MASK_PAROUT0 | MASK_PAROUT1); awacs_write(MASK_ADDR1 | awacs_reg[1]); @@ -1342,13 +1481,20 @@ /* restore settings */ switch (awacs_revision) { case AWACS_TUMBLER: + case AWACS_SNAPPER: + write_audio_gpio(gpio_headphone_mute, gpio_headphone_mute_pol); + write_audio_gpio(gpio_amp_mute, gpio_amp_mute_pol); + write_audio_gpio(gpio_audio_reset, gpio_audio_reset_pol); + wait_ms(100); + write_audio_gpio(gpio_audio_reset, !gpio_audio_reset_pol); + wait_ms(150); + tas_leave_sleep(); /* Stub for now */ headphone_intr(0,0,0); - tumbler_leave_sleep(); /* Stub for now */ break; case AWACS_DACA: wait_ms(10); /* Check this !!! */ daca_leave_sleep(); - break ; /* don't know how yet */ + break ; /* dont know how yet */ case AWACS_BURGUNDY: break ; case AWACS_SCREAMER: @@ -1358,17 +1504,20 @@ break ; } /* Recalibrate chip */ - if (awacs_revision == AWACS_SCREAMER) + if (awacs_revision == AWACS_SCREAMER && awacs) awacs_recalibrate(); /* Make sure dma is stopped */ PMacSilence(); - enable_irq(awacs_irq); + if (awacs) + enable_irq(awacs_irq); enable_irq(awacs_tx_irq); enable_irq(awacs_rx_irq); - /* OK, allow ints back again */ - out_le32(&awacs->control, MASK_IEPC - | (awacs_rate_index << 8) | 0x11 - | (awacs_revision < AWACS_DACA ? MASK_IEE: 0)); + if (awacs) { + /* OK, allow ints back again */ + out_le32(&awacs->control, MASK_IEPC + | (awacs_rate_index << 8) | 0x11 + | (awacs_revision < AWACS_DACA ? MASK_IEE: 0)); + } if (macio_base && is_pbook_g3) { /* FIXME: should restore the setup we had...*/ out_8(macio_base + 0x37, 3); @@ -1384,7 +1533,9 @@ awacs_sleeping = 0; /* Resume pending sounds. */ /* we don't try to restart input... */ + spin_lock_irqsave(&dmasound.lock, flags); __PMacPlay(); + spin_unlock_irqrestore(&dmasound.lock, flags); UNLOCK(); } return PBOOK_SLEEP_OK; @@ -1956,7 +2107,7 @@ case SOUND_MIXER_READ_SPEAKER: data = awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER); data = (((data & 0xf)*100)/16) + ((((data>>4)*100)/16)<<8); - rc = IOCTL_OUT(arg, ~data); + rc = IOCTL_OUT(arg, (~data) & 0x0000ffff); break; case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */ IOCTL_IN(arg, data); @@ -2011,89 +2162,6 @@ return rc; } -static int tumbler_mixer_ioctl(u_int cmd, u_long arg) -{ - int data; - int rc; - - /* We are, we are, we are... Tumbler (and very dumb) */ - /* Ok, we're not THAT dumb anymore, but still pretty dumb :-) */ - - switch(cmd) { - case SOUND_MIXER_READ_DEVMASK: - data = SOUND_MASK_VOLUME | SOUND_MASK_ALTPCM | - SOUND_MASK_BASS | SOUND_MASK_TREBLE | - SOUND_MASK_PCM; - rc = IOCTL_OUT(arg, data); - break; - case SOUND_MIXER_READ_RECMASK: - data = 0; - rc = IOCTL_OUT(arg, data); - break; - case SOUND_MIXER_READ_RECSRC: - data = 0; - rc = IOCTL_OUT(arg, data); - break; - case SOUND_MIXER_WRITE_RECSRC: - IOCTL_IN(arg, data); - data =0; - rc = IOCTL_OUT(arg, data); - break; - case SOUND_MIXER_READ_STEREODEVS: - data = SOUND_MASK_VOLUME | SOUND_MASK_PCM; - rc = IOCTL_OUT(arg, data); - break; - case SOUND_MIXER_READ_CAPS: - rc = IOCTL_OUT(arg, 0); - break; - case SOUND_MIXER_WRITE_BASS: - IOCTL_IN(arg, data); - tumbler_set_bass(data); - /* Fall through */ - case SOUND_MIXER_READ_BASS: - tumbler_get_bass(&data); - rc = IOCTL_OUT(arg, data); - break; - case SOUND_MIXER_WRITE_TREBLE: - IOCTL_IN(arg, data); - tumbler_set_treble(data); - /* Fall through */ - case SOUND_MIXER_READ_TREBLE: - tumbler_get_treble(&data); - rc = IOCTL_OUT(arg, data); - break; - case SOUND_MIXER_WRITE_PCM: - IOCTL_IN(arg, data); - tumbler_set_pcm_lvl(data); - /* Fall through */ - case SOUND_MIXER_READ_PCM: - tumbler_get_pcm_lvl(&data); - IOCTL_OUT(arg, data); - break; - case SOUND_MIXER_WRITE_VOLUME: - IOCTL_IN(arg, data); - tumbler_set_volume(data, data); - /* Fall through */ - case SOUND_MIXER_READ_VOLUME: - tumbler_get_volume(& data, &data); - rc = IOCTL_OUT(arg, data); - break; - case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */ - IOCTL_IN(arg, data); - beep_vol = data & 0xff; - /* fall through */ - case SOUND_MIXER_READ_ALTPCM: - rc = IOCTL_OUT(arg, beep_vol); - break; - case SOUND_MIXER_OUTMASK: - case SOUND_MIXER_OUTSRC: - default: - rc = -EINVAL; - } - - return rc; -} - static int daca_mixer_ioctl(u_int cmd, u_long arg) { int data; @@ -2158,7 +2226,8 @@ rc = daca_mixer_ioctl(cmd, arg); break; case AWACS_TUMBLER: - rc = tumbler_mixer_ioctl(cmd, arg); + case AWACS_SNAPPER: + rc = tas_mixer_ioctl(cmd, arg); break ; default: /* ;-)) */ rc = awacs_mixer_ioctl(cmd, arg); @@ -2175,7 +2244,9 @@ case AWACS_TUMBLER: printk("AE-Init tumbler mixer\n"); break ; - + case AWACS_SNAPPER: + printk("AE-Init snapper mixer\n"); + break ; case AWACS_DACA: case AWACS_BURGUNDY: break ; /* don't know yet */ @@ -2366,12 +2437,12 @@ len += sprintf(b,"44100 ") ; break ; case AWACS_TUMBLER: - for (i=0; i<2; i++){ - if (tumbler_freqs_ok[i]) - len += sprintf(b+len,"%d ", tumbler_freqs[i]) ; + case AWACS_SNAPPER: + for (i=0; i<1; i++){ + if (tas_freqs_ok[i]) + len += sprintf(b+len,"%d ", tas_freqs[i]) ; } break ; - case AWACS_AWACS: case AWACS_SCREAMER: default: @@ -2472,8 +2543,8 @@ code that looks for chip properties knows how to go about it. */ -static struct device_node -__init *get_snd_io_node(void) +static struct device_node* __init +get_snd_io_node(void) { struct device_node *np = NULL; @@ -2494,7 +2565,7 @@ * this seems to be what iBooks (& Tumbler) have. */ if (np == NULL) - np = find_devices("i2s-a"); + np = i2s_node = find_devices("i2s-a"); /* if we didn't find this - perhaps we are on an early model * which _only_ has an 'awacs' node @@ -2514,23 +2585,22 @@ we have to deduce the info other ways for these. */ -static struct device_node -__init *get_snd_info_node(struct device_node *io) +static struct device_node* __init +get_snd_info_node(struct device_node *io) { struct device_node *info; info = find_devices("sound"); - while (info != 0 && info->parent != io) + while (info && info->parent != io) info = info->next; - - return info ; + return info; } /* Find out what type of codec we have. */ -static int -__init get_codec_type(struct device_node *info) +static int __init +get_codec_type(struct device_node *info) { /* already set if pre-davbus model and info will be NULL */ int codec = awacs_revision ; @@ -2547,14 +2617,16 @@ codec = AWACS_DACA; if (device_is_compatible(info, "tumbler")) codec = AWACS_TUMBLER; + if (device_is_compatible(info, "snapper")) + codec = AWACS_SNAPPER; } return codec ; } /* find out what type, if any, of expansion card we have */ -static void -__init get_expansion_type(void) +static void __init +get_expansion_type(void) { if (find_devices("perch") != NULL) has_perch = 1; @@ -2572,8 +2644,8 @@ * Set dmasound.mach.max_dsp_rate on the basis of these routines. */ -static void -__init init_awacs_frame_rates(unsigned int *prop, unsigned int l) +static void __init +awacs_init_frame_rates(unsigned int *prop, unsigned int l) { int i ; if (prop) { @@ -2595,31 +2667,8 @@ /* else we assume that all the rates are available */ } -static void -__init init_tumbler_frame_rates(unsigned int *prop, unsigned int l) -{ - int i ; - if (prop) { - for (i=0; i<2; i++) - tumbler_freqs_ok[i] = 0; - for (l /= sizeof(int); l > 0; --l) { - unsigned int r = *prop++; - /* Apple 'Fixed' format */ - if (r >= 0x10000) - r >>= 16; - for (i = 0; i < 2; ++i) { - if (r == tumbler_freqs[i]) { - tumbler_freqs_ok[i] = 1; - break; - } - } - } - } - /* else we assume that all the rates are available */ -} - -static void -__init init_burgundy_frame_rates(unsigned int *prop, unsigned int l) +static void __init +burgundy_init_frame_rates(unsigned int *prop, unsigned int l) { int temp[9] ; int i = 0 ; @@ -2644,8 +2693,8 @@ #endif } -static void -__init init_daca_frame_rates(unsigned int *prop, unsigned int l) +static void __init +daca_init_frame_rates(unsigned int *prop, unsigned int l) { int temp[9] ; int i = 0 ; @@ -2671,21 +2720,22 @@ #endif } -static void -__init init_frame_rates(unsigned int *prop, unsigned int l) +static void __init +init_frame_rates(unsigned int *prop, unsigned int l) { - switch (awacs_revision){ + switch (awacs_revision) { case AWACS_TUMBLER: - init_tumbler_frame_rates(prop, l); + case AWACS_SNAPPER: + tas_init_frame_rates(prop, l); break ; case AWACS_DACA: - init_daca_frame_rates(prop, l); + daca_init_frame_rates(prop, l); break ; case AWACS_BURGUNDY: - init_burgundy_frame_rates(prop, l); + burgundy_init_frame_rates(prop, l); break ; - default: /* ;-))) */ - init_awacs_frame_rates(prop, l); + default: + awacs_init_frame_rates(prop, l); break ; } } @@ -2693,11 +2743,11 @@ /* find things/machines that can't do mac-io byteswap */ -static void -__init set_hw_byteswap(struct device_node *io) +static void __init +set_hw_byteswap(struct device_node *io) { struct device_node *mio ; - unsigned int *p, kl = 0 ; + unsigned int kl = 0 ; /* if seems that Keylargo can't byte-swap */ @@ -2744,9 +2794,6 @@ if( beep_dbdma_cmd_space ) kfree(beep_dbdma_cmd_space) ; return -ENOMEM ; } - /* OK, we should be safe to claim the mksound vector now */ - orig_mksound = kd_mksound; - kd_mksound = awacs_mksound; return 0 ; } @@ -2842,23 +2889,26 @@ } /* all OF versions I've seen use this value */ - awacs = (volatile struct awacs_regs *) - ioremap(io->addrs[0].address, 0x1000); + if (i2s_node) + i2s = (u32 *)ioremap(io->addrs[0].address, 0x1000); + else + awacs = (volatile struct awacs_regs *) + ioremap(io->addrs[0].address, 0x1000); awacs_txdma = (volatile struct dbdma_regs *) ioremap(io->addrs[1].address, 0x100); awacs_rxdma = (volatile struct dbdma_regs *) ioremap(io->addrs[2].address, 0x100); -#ifdef CONFIG_PMAC_PBOOK /* first of all make sure that the chip is powered up....*/ pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, io, 0, 1); - if (awacs_revision == AWACS_SCREAMER) + if (awacs_revision == AWACS_SCREAMER && awacs) awacs_recalibrate(); -#endif + awacs_irq = io->intrs[0].line; awacs_tx_irq = io->intrs[1].line; awacs_rx_irq = io->intrs[2].line; + /* Hack for legacy crap that will be killed someday */ awacs_node = io; /* if we have an awacs or screamer - probe the chip to make @@ -2909,8 +2959,9 @@ /* if it's there use it to set up frame rates */ init_frame_rates(prop, l) ; } - - out_le32(&awacs->control, 0x11); /* set everything quiesent */ + + if (awacs) + out_le32(&awacs->control, 0x11); /* set everything quiesent */ set_hw_byteswap(io) ; /* figure out if the h/w can do it */ @@ -2942,25 +2993,27 @@ switch (awacs_revision) { case AWACS_TUMBLER: -#ifdef CONFIG_KMOD - request_module("i2c-keywest"); -#endif /* CONFIG_KMOD */ - awacs_tumbler_init(); - tas_init(); - break ; + tas_register_driver(&tas3001c_hooks); + tas_init(I2C_DRIVERID_TAS3001C, I2C_DRIVERNAME_TAS3001C); + tas_dmasound_init(); + tas_post_init(); + break ; + case AWACS_SNAPPER: + tas_register_driver(&tas3004_hooks); + tas_init(I2C_DRIVERID_TAS3004,I2C_DRIVERNAME_TAS3004); + tas_dmasound_init(); + tas_post_init(); + break; case AWACS_DACA: -#ifdef CONFIG_KMOD - request_module("i2c-keywest"); -#endif /* CONFIG_KMOD */ daca_init(); - break ; /* don't know how yet */ + break; case AWACS_BURGUNDY: awacs_burgundy_init(); break ; case AWACS_SCREAMER: case AWACS_AWACS: default: - load_awacs() ; + load_awacs(); break ; } @@ -3031,11 +3084,15 @@ dmasound.mach.hardware_afmts = AFMT_S16_BE ; /* shut out chips that do output only. - may need to extend this to machines which have no inputs - even tho' - they use screamer - IIRC one of the powerbooks is like this. - */ + * may need to extend this to machines which have no inputs - even tho' + * they use screamer - IIRC one of the powerbooks is like this. + * + * FIXME: Actually, some TUMBLER and SNAPPER do have inputs... + */ - if (awacs_revision != AWACS_TUMBLER && awacs_revision != AWACS_DACA) { + if (awacs_revision != AWACS_TUMBLER && + awacs_revision != AWACS_SNAPPER && + awacs_revision != AWACS_DACA) { dmasound.mach.capabilities = DSP_CAP_DUPLEX ; dmasound.mach.record = PMacRecord ; } @@ -3053,6 +3110,9 @@ case AWACS_TUMBLER: sprintf(awacs_name, "PowerMac Tumbler ") ; break ; + case AWACS_SNAPPER: + sprintf(awacs_name, "PowerMac Snapper ") ; + break ; case AWACS_SCREAMER: sprintf(awacs_name, "PowerMac Screamer ") ; break ; @@ -3069,7 +3129,8 @@ { switch (awacs_revision) { case AWACS_TUMBLER: - awacs_tumbler_cleanup(); + case AWACS_SNAPPER: + tas_dmasound_cleanup(); tas_cleanup(); break ; case AWACS_DACA: diff -Nru a/sound/oss/dmasound/tas3001c.c b/sound/oss/dmasound/tas3001c.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sound/oss/dmasound/tas3001c.c Thu Sep 11 23:03:14 2003 @@ -0,0 +1,861 @@ +/* + * Driver for the i2c/i2s based TA3004 sound chip used + * on some Apple hardware. Also known as "snapper". + * + * Tobias Sargeant + * Based upon, tas3001c.c by Christopher C. Chimelis : + * + * TODO: + * ----- + * * Enable control over input line 2 (is this connected?) + * * Implement sleep support (at least mute everything and + * * set gains to minimum during sleep) + * * Look into some of Darwin's tweaks regarding the mute + * * lines (delays & different behaviour on some HW) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dmasound.h" +#include "tas_common.h" +#include "tas3001c.h" + +#include "tas_ioctl.h" + +#define TAS3001C_BIQUAD_FILTER_COUNT 6 +#define TAS3001C_BIQUAD_CHANNEL_COUNT 2 + +#define VOL_DEFAULT (100 * 4 / 5) +#define INPUT_DEFAULT (100 * 4 / 5) +#define BASS_DEFAULT (100 / 2) +#define TREBLE_DEFAULT (100 / 2) + +struct tas3001c_data_t { + struct tas_data_t super; + int device_id; + int output_id; + int speaker_id; + struct tas_drce_t drce_state; +}; + + +static const union tas_biquad_t +tas3001c_eq_unity={ + buf: { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } +}; + + +static inline unsigned char db_to_regval(short db) { + int r=0; + + r=(db+0x59a0) / 0x60; + + if (r < 0x91) return 0x91; + if (r > 0xef) return 0xef; + return r; +} + +static inline short quantize_db(short db) { + return db_to_regval(db) * 0x60 - 0x59a0; +} + + +static inline int +register_width(enum tas3001c_reg_t r) +{ + switch(r) { + case TAS3001C_REG_MCR: + case TAS3001C_REG_TREBLE: + case TAS3001C_REG_BASS: + return 1; + + case TAS3001C_REG_DRC: + return 2; + + case TAS3001C_REG_MIXER1: + case TAS3001C_REG_MIXER2: + return 3; + + case TAS3001C_REG_VOLUME: + return 6; + + case TAS3001C_REG_LEFT_BIQUAD0: + case TAS3001C_REG_LEFT_BIQUAD1: + case TAS3001C_REG_LEFT_BIQUAD2: + case TAS3001C_REG_LEFT_BIQUAD3: + case TAS3001C_REG_LEFT_BIQUAD4: + case TAS3001C_REG_LEFT_BIQUAD5: + case TAS3001C_REG_LEFT_BIQUAD6: + + case TAS3001C_REG_RIGHT_BIQUAD0: + case TAS3001C_REG_RIGHT_BIQUAD1: + case TAS3001C_REG_RIGHT_BIQUAD2: + case TAS3001C_REG_RIGHT_BIQUAD3: + case TAS3001C_REG_RIGHT_BIQUAD4: + case TAS3001C_REG_RIGHT_BIQUAD5: + case TAS3001C_REG_RIGHT_BIQUAD6: + return 15; + + default: + return 0; + } +} + +static int +tas3001c_write_register( struct tas3001c_data_t *self, + enum tas3001c_reg_t reg_num, + char *data, + uint write_mode) +{ + if (reg_num==TAS3001C_REG_MCR || + reg_num==TAS3001C_REG_BASS || + reg_num==TAS3001C_REG_TREBLE) { + return tas_write_byte_register(&self->super, + (uint)reg_num, + *data, + write_mode); + } else { + return tas_write_register(&self->super, + (uint)reg_num, + register_width(reg_num), + data, + write_mode); + } +} + +static int +tas3001c_sync_register( struct tas3001c_data_t *self, + enum tas3001c_reg_t reg_num) +{ + if (reg_num==TAS3001C_REG_MCR || + reg_num==TAS3001C_REG_BASS || + reg_num==TAS3001C_REG_TREBLE) { + return tas_sync_byte_register(&self->super, + (uint)reg_num, + register_width(reg_num)); + } else { + return tas_sync_register(&self->super, + (uint)reg_num, + register_width(reg_num)); + } +} + +static int +tas3001c_read_register( struct tas3001c_data_t *self, + enum tas3001c_reg_t reg_num, + char *data, + uint write_mode) +{ + return tas_read_register(&self->super, + (uint)reg_num, + register_width(reg_num), + data); +} + +static inline int +tas3001c_fast_load(struct tas3001c_data_t *self, int fast) +{ + if (fast) + self->super.shadow[TAS3001C_REG_MCR][0] |= 0x80; + else + self->super.shadow[TAS3001C_REG_MCR][0] &= 0x7f; + return tas3001c_sync_register(self,TAS3001C_REG_MCR); +} + +static uint +tas3001c_supported_mixers(struct tas3001c_data_t *self) +{ + return SOUND_MASK_VOLUME | + SOUND_MASK_PCM | + SOUND_MASK_ALTPCM | + SOUND_MASK_TREBLE | + SOUND_MASK_BASS; +} + +static int +tas3001c_mixer_is_stereo(struct tas3001c_data_t *self,int mixer) +{ + switch(mixer) { + case SOUND_MIXER_VOLUME: + return 1; + default: + return 0; + } +} + +static uint +tas3001c_stereo_mixers(struct tas3001c_data_t *self) +{ + uint r=tas3001c_supported_mixers(self); + uint i; + + for (i=1; isuper.mixer[mixer]; + + return 0; +} + +static int +tas3001c_set_mixer_level(struct tas3001c_data_t *self,int mixer,uint level) +{ + int rc; + tas_shadow_t *shadow; + + uint temp; + uint offset=0; + + if (!self) + return -1; + + shadow=self->super.shadow; + + if (!tas3001c_mixer_is_stereo(self,mixer)) + level = tas_mono_to_stereo(level); + + switch(mixer) { + case SOUND_MIXER_VOLUME: + temp = tas3001c_gain.master[level&0xff]; + shadow[TAS3001C_REG_VOLUME][0] = (temp >> 16) & 0xff; + shadow[TAS3001C_REG_VOLUME][1] = (temp >> 8) & 0xff; + shadow[TAS3001C_REG_VOLUME][2] = (temp >> 0) & 0xff; + temp = tas3001c_gain.master[(level>>8)&0xff]; + shadow[TAS3001C_REG_VOLUME][3] = (temp >> 16) & 0xff; + shadow[TAS3001C_REG_VOLUME][4] = (temp >> 8) & 0xff; + shadow[TAS3001C_REG_VOLUME][5] = (temp >> 0) & 0xff; + rc = tas3001c_sync_register(self,TAS3001C_REG_VOLUME); + break; + case SOUND_MIXER_ALTPCM: + /* tas3001c_fast_load(self, 1); */ + level = tas_mono_to_stereo(level); + temp = tas3001c_gain.mixer[level&0xff]; + shadow[TAS3001C_REG_MIXER2][offset+0] = (temp >> 16) & 0xff; + shadow[TAS3001C_REG_MIXER2][offset+1] = (temp >> 8) & 0xff; + shadow[TAS3001C_REG_MIXER2][offset+2] = (temp >> 0) & 0xff; + rc = tas3001c_sync_register(self,TAS3001C_REG_MIXER2); + /* tas3001c_fast_load(self, 0); */ + break; + case SOUND_MIXER_PCM: + /* tas3001c_fast_load(self, 1); */ + level = tas_mono_to_stereo(level); + temp = tas3001c_gain.mixer[level&0xff]; + shadow[TAS3001C_REG_MIXER1][offset+0] = (temp >> 16) & 0xff; + shadow[TAS3001C_REG_MIXER1][offset+1] = (temp >> 8) & 0xff; + shadow[TAS3001C_REG_MIXER1][offset+2] = (temp >> 0) & 0xff; + rc = tas3001c_sync_register(self,TAS3001C_REG_MIXER1); + /* tas3001c_fast_load(self, 0); */ + break; + case SOUND_MIXER_TREBLE: + temp = tas3001c_gain.treble[level&0xff]; + shadow[TAS3001C_REG_TREBLE][0]=temp&0xff; + rc = tas3001c_sync_register(self,TAS3001C_REG_TREBLE); + break; + case SOUND_MIXER_BASS: + temp = tas3001c_gain.bass[level&0xff]; + shadow[TAS3001C_REG_BASS][0]=temp&0xff; + rc = tas3001c_sync_register(self,TAS3001C_REG_BASS); + break; + default: + rc = -1; + break; + } + if (rc < 0) + return rc; + self->super.mixer[mixer]=level; + return 0; +} + +static int +tas3001c_leave_sleep(struct tas3001c_data_t *self) +{ + unsigned char mcr = (1<<6)+(2<<4)+(2<<2); + + if (!self) + return -1; + + /* Make sure something answers on the i2c bus */ + if (tas3001c_write_register(self, TAS3001C_REG_MCR, &mcr, + WRITE_NORMAL|FORCE_WRITE) < 0) + return -1; + + tas3001c_fast_load(self, 1); + + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD0); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD1); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD2); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD3); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD4); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD5); + + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD0); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD1); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD2); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD3); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD4); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD5); + + tas3001c_fast_load(self, 0); + + (void)tas3001c_sync_register(self,TAS3001C_REG_BASS); + (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE); + (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1); + (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2); + (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME); + + return 0; +} + +static int +tas3001c_enter_sleep(struct tas3001c_data_t *self) +{ + /* Stub for now, but I have the details on low-power mode */ + if (!self) + return -1; + return 0; +} + +static int +tas3001c_sync_biquad( struct tas3001c_data_t *self, + u_int channel, + u_int filter) +{ + enum tas3001c_reg_t reg; + + if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT || + filter >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL; + + reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter; + + return tas3001c_sync_register(self,reg); +} + +static int +tas3001c_write_biquad_shadow( struct tas3001c_data_t *self, + u_int channel, + u_int filter, + const union tas_biquad_t *biquad) +{ + tas_shadow_t *shadow=self->super.shadow; + enum tas3001c_reg_t reg; + + if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT || + filter >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL; + + reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter; + + SET_4_20(shadow[reg], 0,biquad->coeff.b0); + SET_4_20(shadow[reg], 3,biquad->coeff.b1); + SET_4_20(shadow[reg], 6,biquad->coeff.b2); + SET_4_20(shadow[reg], 9,biquad->coeff.a1); + SET_4_20(shadow[reg],12,biquad->coeff.a2); + + return 0; +} + +static int +tas3001c_write_biquad( struct tas3001c_data_t *self, + u_int channel, + u_int filter, + const union tas_biquad_t *biquad) +{ + int rc; + + rc=tas3001c_write_biquad_shadow(self, channel, filter, biquad); + if (rc < 0) return rc; + + return tas3001c_sync_biquad(self, channel, filter); +} + +static int +tas3001c_write_biquad_list( struct tas3001c_data_t *self, + u_int filter_count, + u_int flags, + struct tas_biquad_ctrl_t *biquads) +{ + int i; + int rc; + + if (flags & TAS_BIQUAD_FAST_LOAD) tas3001c_fast_load(self,1); + + for (i=0; isuper.shadow; + enum tas3001c_reg_t reg; + + if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT || + filter >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL; + + reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter; + + biquad->coeff.b0=GET_4_20(shadow[reg], 0); + biquad->coeff.b1=GET_4_20(shadow[reg], 3); + biquad->coeff.b2=GET_4_20(shadow[reg], 6); + biquad->coeff.a1=GET_4_20(shadow[reg], 9); + biquad->coeff.a2=GET_4_20(shadow[reg],12); + + return 0; +} + +static int +tas3001c_eq_rw( struct tas3001c_data_t *self, + u_int cmd, + u_long arg) +{ + int rc; + struct tas_biquad_ctrl_t biquad; + + if (copy_from_user((void *)&biquad, (const void *)arg, sizeof(struct tas_biquad_ctrl_t))) { + return -EFAULT; + } + + if (cmd & SIOC_IN) { + rc=tas3001c_write_biquad(self, biquad.channel, biquad.filter, &biquad.data); + if (rc != 0) return rc; + } + + if (cmd & SIOC_OUT) { + rc=tas3001c_read_biquad(self, biquad.channel, biquad.filter, &biquad.data); + if (rc != 0) return rc; + + if (copy_to_user((void *)arg, (const void *)&biquad, sizeof(struct tas_biquad_ctrl_t))) { + return -EFAULT; + } + + } + return 0; +} + +static int +tas3001c_eq_list_rw( struct tas3001c_data_t *self, + u_int cmd, + u_long arg) +{ + int rc; + int filter_count; + int flags; + int i,j; + char sync_required[2][6]; + struct tas_biquad_ctrl_t biquad; + + memset(sync_required,0,sizeof(sync_required)); + + if (copy_from_user((void *)&filter_count, + (const void *)arg + offsetof(struct tas_biquad_ctrl_list_t,filter_count), + sizeof(int))) { + return -EFAULT; + } + + if (copy_from_user((void *)&flags, + (const void *)arg + offsetof(struct tas_biquad_ctrl_list_t,flags), + sizeof(int))) { + return -EFAULT; + } + + if (cmd & SIOC_IN) { + } + + for (i=0; i < filter_count; i++) { + if (copy_from_user((void *)&biquad, + (const void *)arg + offsetof(struct tas_biquad_ctrl_list_t, biquads[i]), + sizeof(struct tas_biquad_ctrl_t))) { + return -EFAULT; + } + + if (cmd & SIOC_IN) { + sync_required[biquad.channel][biquad.filter]=1; + rc=tas3001c_write_biquad_shadow(self, biquad.channel, biquad.filter, &biquad.data); + if (rc != 0) return rc; + } + + if (cmd & SIOC_OUT) { + rc=tas3001c_read_biquad(self, biquad.channel, biquad.filter, &biquad.data); + if (rc != 0) return rc; + + if (copy_to_user((void *)arg + offsetof(struct tas_biquad_ctrl_list_t, biquads[i]), + (const void *)&biquad, + sizeof(struct tas_biquad_ctrl_t))) { + return -EFAULT; + } + } + } + + if (cmd & SIOC_IN) { + if (flags & TAS_BIQUAD_FAST_LOAD) tas3001c_fast_load(self,1); + for (i=0; i<2; i++) { + for (j=0; j<6; j++) { + if (sync_required[i][j]) { + rc=tas3001c_sync_biquad(self, i, j); + if (rc < 0) return rc; + } + } + } + if (flags & TAS_BIQUAD_FAST_LOAD) { + tas3001c_fast_load(self,0); + /* now we need to set up the mixers again, + because leaving fast mode resets them. */ + (void)tas3001c_sync_register(self,TAS3001C_REG_BASS); + (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE); + (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1); + (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2); + (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME); + } + } + + return 0; +} + +static int +tas3001c_update_drce( struct tas3001c_data_t *self, + int flags, + struct tas_drce_t *drce) +{ + tas_shadow_t *shadow; + shadow=self->super.shadow; + + shadow[TAS3001C_REG_DRC][1] = 0xc1; + + if (flags & TAS_DRCE_THRESHOLD) { + self->drce_state.threshold=quantize_db(drce->threshold); + shadow[TAS3001C_REG_DRC][2] = db_to_regval(self->drce_state.threshold); + } + + if (flags & TAS_DRCE_ENABLE) { + self->drce_state.enable = drce->enable; + } + + if (!self->drce_state.enable) { + shadow[TAS3001C_REG_DRC][0] = 0xf0; + } + +#ifdef DEBUG_DRCE + printk("DRCE IOCTL: set [ ENABLE:%x THRESH:%x\n", + self->drce_state.enable, + self->drce_state.threshold); + + printk("DRCE IOCTL: reg [ %02x %02x ]\n", + (unsigned char)shadow[TAS3001C_REG_DRC][0], + (unsigned char)shadow[TAS3001C_REG_DRC][1]); +#endif + + return tas3001c_sync_register(self, TAS3001C_REG_DRC); +} + +static int +tas3001c_drce_rw( struct tas3001c_data_t *self, + u_int cmd, + u_long arg) +{ + int rc; + struct tas_drce_ctrl_t drce_ctrl; + + if (copy_from_user((void *)&drce_ctrl, + (const void *)arg, + sizeof(struct tas_drce_ctrl_t))) { + return -EFAULT; + } + +#ifdef DEBUG_DRCE + printk("DRCE IOCTL: input [ FLAGS:%x ENABLE:%x THRESH:%x\n", + drce_ctrl.flags, + drce_ctrl.data.enable, + drce_ctrl.data.threshold); +#endif + + if (cmd & SIOC_IN) { + rc = tas3001c_update_drce(self, drce_ctrl.flags, &drce_ctrl.data); + if (rc < 0) + return rc; + } + + if (cmd & SIOC_OUT) { + if (drce_ctrl.flags & TAS_DRCE_ENABLE) + drce_ctrl.data.enable = self->drce_state.enable; + + if (drce_ctrl.flags & TAS_DRCE_THRESHOLD) + drce_ctrl.data.threshold = self->drce_state.threshold; + + if (copy_to_user((void *)arg, + (const void *)&drce_ctrl, + sizeof(struct tas_drce_ctrl_t))) { + return -EFAULT; + } + } + + return 0; +} + +static void +tas3001c_update_device_parameters(struct tas3001c_data_t *self) +{ + int i,j; + + if (!self) return; + + if (self->output_id == TAS_OUTPUT_HEADPHONES) { + tas3001c_fast_load(self, 1); + + for (i=0; idevice_id == self->device_id && + (eq->output_id == 0 || eq->output_id == self->output_id) && + (eq->speaker_id == 0 || eq->speaker_id == self->speaker_id)) { + + tas3001c_update_drce(self, TAS_DRCE_ALL, eq->drce); + tas3001c_write_biquad_list(self, eq->filter_count, TAS_BIQUAD_FAST_LOAD, eq->biquads); + + break; + } + } +} + +static void +tas3001c_device_change_handler(void *self) +{ + if (self) + tas3001c_update_device_parameters(self); +} + +static struct work_struct device_change; + +static int +tas3001c_output_device_change( struct tas3001c_data_t *self, + int device_id, + int output_id, + int speaker_id) +{ + self->device_id=device_id; + self->output_id=output_id; + self->speaker_id=speaker_id; + + schedule_work(&device_change); + return 0; +} + +static int +tas3001c_device_ioctl( struct tas3001c_data_t *self, + u_int cmd, + u_long arg) +{ + switch (cmd) { + case TAS_READ_EQ: + case TAS_WRITE_EQ: + return tas3001c_eq_rw(self, cmd, arg); + + case TAS_READ_EQ_LIST: + case TAS_WRITE_EQ_LIST: + return tas3001c_eq_list_rw(self, cmd, arg); + + case TAS_READ_EQ_FILTER_COUNT: + put_user(TAS3001C_BIQUAD_FILTER_COUNT, (uint *)(arg)); + return 0; + + case TAS_READ_EQ_CHANNEL_COUNT: + put_user(TAS3001C_BIQUAD_CHANNEL_COUNT, (uint *)(arg)); + return 0; + + case TAS_READ_DRCE: + case TAS_WRITE_DRCE: + return tas3001c_drce_rw(self, cmd, arg); + + case TAS_READ_DRCE_CAPS: + put_user(TAS_DRCE_ENABLE | TAS_DRCE_THRESHOLD, (uint *)(arg)); + return 0; + + case TAS_READ_DRCE_MIN: + case TAS_READ_DRCE_MAX: { + struct tas_drce_ctrl_t drce_ctrl; + + if (copy_from_user((void *)&drce_ctrl, + (const void *)arg, + sizeof(struct tas_drce_ctrl_t))) { + return -EFAULT; + } + + if (drce_ctrl.flags & TAS_DRCE_THRESHOLD) { + if (cmd == TAS_READ_DRCE_MIN) { + drce_ctrl.data.threshold=-36<<8; + } else { + drce_ctrl.data.threshold=-6<<8; + } + } + + if (copy_to_user((void *)arg, + (const void *)&drce_ctrl, + sizeof(struct tas_drce_ctrl_t))) { + return -EFAULT; + } + } + } + + return -EINVAL; +} + +static int +tas3001c_init_mixer(struct tas3001c_data_t *self) +{ + unsigned char mcr = (1<<6)+(2<<4)+(2<<2); + + /* Make sure something answers on the i2c bus */ + if (tas3001c_write_register(self, TAS3001C_REG_MCR, &mcr, + WRITE_NORMAL|FORCE_WRITE) < 0) + return -1; + + tas3001c_fast_load(self, 1); + + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD0); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD1); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD2); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD3); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD4); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD5); + (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD6); + + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD0); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD1); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD2); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD3); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD4); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD5); + (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD6); + + tas3001c_fast_load(self, 0); + + tas3001c_set_mixer_level(self, SOUND_MIXER_VOLUME, VOL_DEFAULT<<8 | VOL_DEFAULT); + tas3001c_set_mixer_level(self, SOUND_MIXER_PCM, INPUT_DEFAULT<<8 | INPUT_DEFAULT); + tas3001c_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0); + + tas3001c_set_mixer_level(self, SOUND_MIXER_BASS, BASS_DEFAULT); + tas3001c_set_mixer_level(self, SOUND_MIXER_TREBLE, TREBLE_DEFAULT); + + return 0; +} + +static int +tas3001c_uninit_mixer(struct tas3001c_data_t *self) +{ + tas3001c_set_mixer_level(self, SOUND_MIXER_VOLUME, 0); + tas3001c_set_mixer_level(self, SOUND_MIXER_PCM, 0); + tas3001c_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0); + + tas3001c_set_mixer_level(self, SOUND_MIXER_BASS, 0); + tas3001c_set_mixer_level(self, SOUND_MIXER_TREBLE, 0); + + return 0; +} + +static int +tas3001c_init(struct i2c_client *client) +{ + struct tas3001c_data_t *self; + size_t sz = sizeof(*self) + (TAS3001C_REG_MAX*sizeof(tas_shadow_t)); + int i, j; + + self = kmalloc(sz, GFP_KERNEL); + if (!self) + return -ENOMEM; + memset(self, 0, sz); + + self->super.client = client; + self->super.shadow = (tas_shadow_t *)(self+1); + self->output_id = TAS_OUTPUT_HEADPHONES; + + dev_set_drvdata(&client->dev, self); + + for (i = 0; i < TAS3001C_BIQUAD_CHANNEL_COUNT; i++) + for (j = 0; j < TAS3001C_BIQUAD_FILTER_COUNT; j++) + tas3001c_write_biquad_shadow(self, i, j, + &tas3001c_eq_unity); + + INIT_WORK(&device_change, tas3001c_device_change_handler, self); + return 0; +} + +static void +tas3001c_uninit(struct tas3001c_data_t *self) +{ + tas3001c_uninit_mixer(self); + kfree(self); +} + +struct tas_driver_hooks_t tas3001c_hooks = { + .init = (tas_hook_init_t)tas3001c_init, + .post_init = (tas_hook_post_init_t)tas3001c_init_mixer, + .uninit = (tas_hook_uninit_t)tas3001c_uninit, + .get_mixer_level = (tas_hook_get_mixer_level_t)tas3001c_get_mixer_level, + .set_mixer_level = (tas_hook_set_mixer_level_t)tas3001c_set_mixer_level, + .enter_sleep = (tas_hook_enter_sleep_t)tas3001c_enter_sleep, + .leave_sleep = (tas_hook_leave_sleep_t)tas3001c_leave_sleep, + .supported_mixers = (tas_hook_supported_mixers_t)tas3001c_supported_mixers, + .mixer_is_stereo = (tas_hook_mixer_is_stereo_t)tas3001c_mixer_is_stereo, + .stereo_mixers = (tas_hook_stereo_mixers_t)tas3001c_stereo_mixers, + .output_device_change = (tas_hook_output_device_change_t)tas3001c_output_device_change, + .device_ioctl = (tas_hook_device_ioctl_t)tas3001c_device_ioctl +}; diff -Nru a/sound/oss/dmasound/tas3001c.h b/sound/oss/dmasound/tas3001c.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sound/oss/dmasound/tas3001c.h Thu Sep 11 23:03:14 2003 @@ -0,0 +1,64 @@ +/* + * Header file for the i2c/i2s based TA3001c sound chip used + * on some Apple hardware. Also known as "tumbler". + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + * + * Written by Christopher C. Chimelis + */ + +#ifndef _TAS3001C_H_ +#define _TAS3001C_H_ + +#include + +#include "tas_common.h" +#include "tas_eq_prefs.h" + +/* + * Macros that correspond to the registers that we write to + * when setting the various values. + */ + +#define TAS3001C_VERSION "0.3" +#define TAS3001C_DATE "20011214" + +#define I2C_DRIVERNAME_TAS3001C "TAS3001c driver V " TAS3001C_VERSION +#define I2C_DRIVERID_TAS3001C (I2C_DRIVERID_TAS_BASE+0) + +extern struct tas_driver_hooks_t tas3001c_hooks; +extern struct tas_gain_t tas3001c_gain; +extern struct tas_eq_pref_t *tas3001c_eq_prefs[]; + +enum tas3001c_reg_t { + TAS3001C_REG_MCR = 0x01, + TAS3001C_REG_DRC = 0x02, + + TAS3001C_REG_VOLUME = 0x04, + TAS3001C_REG_TREBLE = 0x05, + TAS3001C_REG_BASS = 0x06, + TAS3001C_REG_MIXER1 = 0x07, + TAS3001C_REG_MIXER2 = 0x08, + + TAS3001C_REG_LEFT_BIQUAD0 = 0x0a, + TAS3001C_REG_LEFT_BIQUAD1 = 0x0b, + TAS3001C_REG_LEFT_BIQUAD2 = 0x0c, + TAS3001C_REG_LEFT_BIQUAD3 = 0x0d, + TAS3001C_REG_LEFT_BIQUAD4 = 0x0e, + TAS3001C_REG_LEFT_BIQUAD5 = 0x0f, + TAS3001C_REG_LEFT_BIQUAD6 = 0x10, + + TAS3001C_REG_RIGHT_BIQUAD0 = 0x13, + TAS3001C_REG_RIGHT_BIQUAD1 = 0x14, + TAS3001C_REG_RIGHT_BIQUAD2 = 0x15, + TAS3001C_REG_RIGHT_BIQUAD3 = 0x16, + TAS3001C_REG_RIGHT_BIQUAD4 = 0x17, + TAS3001C_REG_RIGHT_BIQUAD5 = 0x18, + TAS3001C_REG_RIGHT_BIQUAD6 = 0x19, + + TAS3001C_REG_MAX = 0x20 +}; + +#endif /* _TAS3001C_H_ */ diff -Nru a/sound/oss/dmasound/tas3001c_tables.c b/sound/oss/dmasound/tas3001c_tables.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sound/oss/dmasound/tas3001c_tables.c Thu Sep 11 23:03:14 2003 @@ -0,0 +1,375 @@ +#include "tas_common.h" +#include "tas_eq_prefs.h" + +static struct tas_drce_t eqp_0e_2_1_drce = { + enable: 1, + above: { val: 3.0 * (1<<8), expand: 0 }, + below: { val: 1.0 * (1<<8), expand: 0 }, + threshold: -15.33 * (1<<8), + energy: 2.4 * (1<<12), + attack: 0.013 * (1<<12), + decay: 0.212 * (1<<12), +}; + +static struct tas_biquad_ctrl_t eqp_0e_2_1_biquads[]={ + { channel: 0, filter: 0, data: { coeff: { 0x0FCAD3, 0xE06A58, 0x0FCAD3, 0xE06B09, 0x0F9657 } } }, + { channel: 0, filter: 1, data: { coeff: { 0x041731, 0x082E63, 0x041731, 0xFD8D08, 0x02CFBD } } }, + { channel: 0, filter: 2, data: { coeff: { 0x0FFDC7, 0xE0524C, 0x0FBFAA, 0xE0524C, 0x0FBD72 } } }, + { channel: 0, filter: 3, data: { coeff: { 0x0F3D35, 0xE228CA, 0x0EC7B2, 0xE228CA, 0x0E04E8 } } }, + { channel: 0, filter: 4, data: { coeff: { 0x0FCEBF, 0xE181C2, 0x0F2656, 0xE181C2, 0x0EF516 } } }, + { channel: 0, filter: 5, data: { coeff: { 0x0EC417, 0x073E22, 0x0B0633, 0x073E22, 0x09CA4A } } }, + + { channel: 1, filter: 0, data: { coeff: { 0x0FCAD3, 0xE06A58, 0x0FCAD3, 0xE06B09, 0x0F9657 } } }, + { channel: 1, filter: 1, data: { coeff: { 0x041731, 0x082E63, 0x041731, 0xFD8D08, 0x02CFBD } } }, + { channel: 1, filter: 2, data: { coeff: { 0x0FFDC7, 0xE0524C, 0x0FBFAA, 0xE0524C, 0x0FBD72 } } }, + { channel: 1, filter: 3, data: { coeff: { 0x0F3D35, 0xE228CA, 0x0EC7B2, 0xE228CA, 0x0E04E8 } } }, + { channel: 1, filter: 4, data: { coeff: { 0x0FCEBF, 0xE181C2, 0x0F2656, 0xE181C2, 0x0EF516 } } }, + { channel: 1, filter: 5, data: { coeff: { 0x0EC417, 0x073E22, 0x0B0633, 0x073E22, 0x09CA4A } } }, +}; + +static struct tas_eq_pref_t eqp_0e_2_1 = { + sample_rate: 44100, + device_id: 0x0e, + output_id: TAS_OUTPUT_EXTERNAL_SPKR, + speaker_id: 0x01, + + drce: &eqp_0e_2_1_drce, + + filter_count: 12, + biquads: eqp_0e_2_1_biquads +}; + +/* ======================================================================== */ + +static struct tas_drce_t eqp_10_1_0_drce={ + enable: 1, + above: { val: 3.0 * (1<<8), expand: 0 }, + below: { val: 1.0 * (1<<8), expand: 0 }, + threshold: -12.46 * (1<<8), + energy: 2.4 * (1<<12), + attack: 0.013 * (1<<12), + decay: 0.212 * (1<<12), +}; + +static struct tas_biquad_ctrl_t eqp_10_1_0_biquads[]={ + { channel: 0, filter: 0, data: { coeff: { 0x0F4A12, 0xE16BDA, 0x0F4A12, 0xE173F0, 0x0E9C3A } } }, + { channel: 0, filter: 1, data: { coeff: { 0x02DD54, 0x05BAA8, 0x02DD54, 0xF8001D, 0x037532 } } }, + { channel: 0, filter: 2, data: { coeff: { 0x0E2FC7, 0xE4D5DC, 0x0D7477, 0xE4D5DC, 0x0BA43F } } }, + { channel: 0, filter: 3, data: { coeff: { 0x0E7899, 0xE67CCA, 0x0D0E93, 0xE67CCA, 0x0B872D } } }, + { channel: 0, filter: 4, data: { coeff: { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } }, + { channel: 0, filter: 5, data: { coeff: { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } }, + + { channel: 1, filter: 0, data: { coeff: { 0x0F4A12, 0xE16BDA, 0x0F4A12, 0xE173F0, 0x0E9C3A } } }, + { channel: 1, filter: 1, data: { coeff: { 0x02DD54, 0x05BAA8, 0x02DD54, 0xF8001D, 0x037532 } } }, + { channel: 1, filter: 2, data: { coeff: { 0x0E2FC7, 0xE4D5DC, 0x0D7477, 0xE4D5DC, 0x0BA43F } } }, + { channel: 1, filter: 3, data: { coeff: { 0x0E7899, 0xE67CCA, 0x0D0E93, 0xE67CCA, 0x0B872D } } }, + { channel: 1, filter: 4, data: { coeff: { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } }, + { channel: 1, filter: 5, data: { coeff: { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } }, +}; + +static struct tas_eq_pref_t eqp_10_1_0 = { + sample_rate: 44100, + device_id: 0x10, + output_id: TAS_OUTPUT_INTERNAL_SPKR, + speaker_id: 0x00, + + drce: &eqp_10_1_0_drce, + + filter_count: 12, + biquads: eqp_10_1_0_biquads +}; + +/* ======================================================================== */ + +static struct tas_drce_t eqp_15_2_1_drce={ + enable: 1, + above: { val: 3.0 * (1<<8), expand: 0 }, + below: { val: 1.0 * (1<<8), expand: 0 }, + threshold: -15.33 * (1<<8), + energy: 2.4 * (1<<12), + attack: 0.013 * (1<<12), + decay: 0.212 * (1<<12), +}; + +static struct tas_biquad_ctrl_t eqp_15_2_1_biquads[]={ + { channel: 0, filter: 0, data: { coeff: { 0x0FE143, 0xE05204, 0x0FCCC5, 0xE05266, 0x0FAE6B } } }, + { channel: 0, filter: 1, data: { coeff: { 0x102383, 0xE03A03, 0x0FA325, 0xE03A03, 0x0FC6A8 } } }, + { channel: 0, filter: 2, data: { coeff: { 0x0FF2AB, 0xE06285, 0x0FB20A, 0xE06285, 0x0FA4B5 } } }, + { channel: 0, filter: 3, data: { coeff: { 0x0F544D, 0xE35971, 0x0D8F3A, 0xE35971, 0x0CE388 } } }, + { channel: 0, filter: 4, data: { coeff: { 0x13E1D3, 0xF3ECB5, 0x042227, 0xF3ECB5, 0x0803FA } } }, + { channel: 0, filter: 5, data: { coeff: { 0x0AC119, 0x034181, 0x078AB1, 0x034181, 0x024BCA } } }, + + { channel: 1, filter: 0, data: { coeff: { 0x0FE143, 0xE05204, 0x0FCCC5, 0xE05266, 0x0FAE6B } } }, + { channel: 1, filter: 1, data: { coeff: { 0x102383, 0xE03A03, 0x0FA325, 0xE03A03, 0x0FC6A8 } } }, + { channel: 1, filter: 2, data: { coeff: { 0x0FF2AB, 0xE06285, 0x0FB20A, 0xE06285, 0x0FA4B5 } } }, + { channel: 1, filter: 3, data: { coeff: { 0x0F544D, 0xE35971, 0x0D8F3A, 0xE35971, 0x0CE388 } } }, + { channel: 1, filter: 4, data: { coeff: { 0x13E1D3, 0xF3ECB5, 0x042227, 0xF3ECB5, 0x0803FA } } }, + { channel: 1, filter: 5, data: { coeff: { 0x0AC119, 0x034181, 0x078AB1, 0x034181, 0x024BCA } } }, +}; + +static struct tas_eq_pref_t eqp_15_2_1 = { + sample_rate: 44100, + device_id: 0x15, + output_id: TAS_OUTPUT_EXTERNAL_SPKR, + speaker_id: 0x01, + + drce: &eqp_15_2_1_drce, + + filter_count: 12, + biquads: eqp_15_2_1_biquads +}; + +/* ======================================================================== */ + +static struct tas_drce_t eqp_15_1_0_drce={ + enable: 1, + above: { val: 3.0 * (1<<8), expand: 0 }, + below: { val: 1.0 * (1<<8), expand: 0 }, + threshold: 0.0 * (1<<8), + energy: 2.4 * (1<<12), + attack: 0.013 * (1<<12), + decay: 0.212 * (1<<12), +}; + +static struct tas_biquad_ctrl_t eqp_15_1_0_biquads[]={ + { channel: 0, filter: 0, data: { coeff: { 0x0FAD08, 0xE0A5EF, 0x0FAD08, 0xE0A79D, 0x0F5BBE } } }, + { channel: 0, filter: 1, data: { coeff: { 0x04B38D, 0x09671B, 0x04B38D, 0x000F71, 0x02BEC5 } } }, + { channel: 0, filter: 2, data: { coeff: { 0x0FDD32, 0xE0A56F, 0x0F8A69, 0xE0A56F, 0x0F679C } } }, + { channel: 0, filter: 3, data: { coeff: { 0x0FD284, 0xE135FB, 0x0F2161, 0xE135FB, 0x0EF3E5 } } }, + { channel: 0, filter: 4, data: { coeff: { 0x0E81B1, 0xE6283F, 0x0CE49D, 0xE6283F, 0x0B664F } } }, + { channel: 0, filter: 5, data: { coeff: { 0x0F2D62, 0xE98797, 0x0D1E19, 0xE98797, 0x0C4B7B } } }, + + { channel: 1, filter: 0, data: { coeff: { 0x0FAD08, 0xE0A5EF, 0x0FAD08, 0xE0A79D, 0x0F5BBE } } }, + { channel: 1, filter: 1, data: { coeff: { 0x04B38D, 0x09671B, 0x04B38D, 0x000F71, 0x02BEC5 } } }, + { channel: 1, filter: 2, data: { coeff: { 0x0FDD32, 0xE0A56F, 0x0F8A69, 0xE0A56F, 0x0F679C } } }, + { channel: 1, filter: 3, data: { coeff: { 0x0FD284, 0xE135FB, 0x0F2161, 0xE135FB, 0x0EF3E5 } } }, + { channel: 1, filter: 4, data: { coeff: { 0x0E81B1, 0xE6283F, 0x0CE49D, 0xE6283F, 0x0B664F } } }, + { channel: 1, filter: 5, data: { coeff: { 0x0F2D62, 0xE98797, 0x0D1E19, 0xE98797, 0x0C4B7B } } }, +}; + +static struct tas_eq_pref_t eqp_15_1_0 = { + sample_rate: 44100, + device_id: 0x15, + output_id: TAS_OUTPUT_INTERNAL_SPKR, + speaker_id: 0x00, + + drce: &eqp_15_1_0_drce, + + filter_count: 12, + biquads: eqp_15_1_0_biquads +}; + +/* ======================================================================== */ + +static struct tas_drce_t eqp_0f_2_1_drce={ + enable: 1, + above: { val: 3.0 * (1<<8), expand: 0 }, + below: { val: 1.0 * (1<<8), expand: 0 }, + threshold: -15.33 * (1<<8), + energy: 2.4 * (1<<12), + attack: 0.013 * (1<<12), + decay: 0.212 * (1<<12), +}; + +static struct tas_biquad_ctrl_t eqp_0f_2_1_biquads[]={ + { channel: 0, filter: 0, data: { coeff: { 0x0FE143, 0xE05204, 0x0FCCC5, 0xE05266, 0x0FAE6B } } }, + { channel: 0, filter: 1, data: { coeff: { 0x102383, 0xE03A03, 0x0FA325, 0xE03A03, 0x0FC6A8 } } }, + { channel: 0, filter: 2, data: { coeff: { 0x0FF2AB, 0xE06285, 0x0FB20A, 0xE06285, 0x0FA4B5 } } }, + { channel: 0, filter: 3, data: { coeff: { 0x0F544D, 0xE35971, 0x0D8F3A, 0xE35971, 0x0CE388 } } }, + { channel: 0, filter: 4, data: { coeff: { 0x13E1D3, 0xF3ECB5, 0x042227, 0xF3ECB5, 0x0803FA } } }, + { channel: 0, filter: 5, data: { coeff: { 0x0AC119, 0x034181, 0x078AB1, 0x034181, 0x024BCA } } }, + + { channel: 1, filter: 0, data: { coeff: { 0x0FE143, 0xE05204, 0x0FCCC5, 0xE05266, 0x0FAE6B } } }, + { channel: 1, filter: 1, data: { coeff: { 0x102383, 0xE03A03, 0x0FA325, 0xE03A03, 0x0FC6A8 } } }, + { channel: 1, filter: 2, data: { coeff: { 0x0FF2AB, 0xE06285, 0x0FB20A, 0xE06285, 0x0FA4B5 } } }, + { channel: 1, filter: 3, data: { coeff: { 0x0F544D, 0xE35971, 0x0D8F3A, 0xE35971, 0x0CE388 } } }, + { channel: 1, filter: 4, data: { coeff: { 0x13E1D3, 0xF3ECB5, 0x042227, 0xF3ECB5, 0x0803FA } } }, + { channel: 1, filter: 5, data: { coeff: { 0x0AC119, 0x034181, 0x078AB1, 0x034181, 0x024BCA } } }, +}; + +static struct tas_eq_pref_t eqp_0f_2_1 = { + sample_rate: 44100, + device_id: 0x0f, + output_id: TAS_OUTPUT_EXTERNAL_SPKR, + speaker_id: 0x01, + + drce: &eqp_0f_2_1_drce, + + filter_count: 12, + biquads: eqp_0f_2_1_biquads +}; + +/* ======================================================================== */ + +static struct tas_drce_t eqp_0f_1_0_drce={ + enable: 1, + above: { val: 3.0 * (1<<8), expand: 0 }, + below: { val: 1.0 * (1<<8), expand: 0 }, + threshold: -15.33 * (1<<8), + energy: 2.4 * (1<<12), + attack: 0.013 * (1<<12), + decay: 0.212 * (1<<12), +}; + +static struct tas_biquad_ctrl_t eqp_0f_1_0_biquads[]={ + { channel: 0, filter: 0, data: { coeff: { 0x0FCAD3, 0xE06A58, 0x0FCAD3, 0xE06B09, 0x0F9657 } } }, + { channel: 0, filter: 1, data: { coeff: { 0x041731, 0x082E63, 0x041731, 0xFD8D08, 0x02CFBD } } }, + { channel: 0, filter: 2, data: { coeff: { 0x0FFDC7, 0xE0524C, 0x0FBFAA, 0xE0524C, 0x0FBD72 } } }, + { channel: 0, filter: 3, data: { coeff: { 0x0F3D35, 0xE228CA, 0x0EC7B2, 0xE228CA, 0x0E04E8 } } }, + { channel: 0, filter: 4, data: { coeff: { 0x0FCEBF, 0xE181C2, 0x0F2656, 0xE181C2, 0x0EF516 } } }, + { channel: 0, filter: 5, data: { coeff: { 0x0EC417, 0x073E22, 0x0B0633, 0x073E22, 0x09CA4A } } }, + + { channel: 1, filter: 0, data: { coeff: { 0x0FCAD3, 0xE06A58, 0x0FCAD3, 0xE06B09, 0x0F9657 } } }, + { channel: 1, filter: 1, data: { coeff: { 0x041731, 0x082E63, 0x041731, 0xFD8D08, 0x02CFBD } } }, + { channel: 1, filter: 2, data: { coeff: { 0x0FFDC7, 0xE0524C, 0x0FBFAA, 0xE0524C, 0x0FBD72 } } }, + { channel: 1, filter: 3, data: { coeff: { 0x0F3D35, 0xE228CA, 0x0EC7B2, 0xE228CA, 0x0E04E8 } } }, + { channel: 1, filter: 4, data: { coeff: { 0x0FCEBF, 0xE181C2, 0x0F2656, 0xE181C2, 0x0EF516 } } }, + { channel: 1, filter: 5, data: { coeff: { 0x0EC417, 0x073E22, 0x0B0633, 0x073E22, 0x09CA4A } } }, +}; + +static struct tas_eq_pref_t eqp_0f_1_0 = { + sample_rate: 44100, + device_id: 0x0f, + output_id: TAS_OUTPUT_INTERNAL_SPKR, + speaker_id: 0x00, + + drce: &eqp_0f_1_0_drce, + + filter_count: 12, + biquads: eqp_0f_1_0_biquads +}; + +/* ======================================================================== */ + +static uint tas3001c_master_tab[]={ + 0x0, 0x75, 0x9c, 0xbb, + 0xdb, 0xfb, 0x11e, 0x143, + 0x16b, 0x196, 0x1c3, 0x1f5, + 0x229, 0x263, 0x29f, 0x2e1, + 0x328, 0x373, 0x3c5, 0x41b, + 0x478, 0x4dc, 0x547, 0x5b8, + 0x633, 0x6b5, 0x740, 0x7d5, + 0x873, 0x91c, 0x9d2, 0xa92, + 0xb5e, 0xc39, 0xd22, 0xe19, + 0xf20, 0x1037, 0x1161, 0x129e, + 0x13ed, 0x1551, 0x16ca, 0x185d, + 0x1a08, 0x1bcc, 0x1dac, 0x1fa7, + 0x21c1, 0x23fa, 0x2655, 0x28d6, + 0x2b7c, 0x2e4a, 0x3141, 0x3464, + 0x37b4, 0x3b35, 0x3ee9, 0x42d3, + 0x46f6, 0x4b53, 0x4ff0, 0x54ce, + 0x59f2, 0x5f5f, 0x6519, 0x6b24, + 0x7183, 0x783c, 0x7f53, 0x86cc, + 0x8ead, 0x96fa, 0x9fba, 0xa8f2, + 0xb2a7, 0xbce1, 0xc7a5, 0xd2fa, + 0xdee8, 0xeb75, 0xf8aa, 0x1068e, + 0x1152a, 0x12487, 0x134ad, 0x145a5, + 0x1577b, 0x16a37, 0x17df5, 0x192bd, + 0x1a890, 0x1bf7b, 0x1d78d, 0x1f0d1, + 0x20b55, 0x22727, 0x24456, 0x262f2, + 0x2830b +}; + +static uint tas3001c_mixer_tab[]={ + 0x0, 0x748, 0x9be, 0xbaf, + 0xda4, 0xfb1, 0x11de, 0x1431, + 0x16ad, 0x1959, 0x1c37, 0x1f4b, + 0x2298, 0x2628, 0x29fb, 0x2e12, + 0x327d, 0x3734, 0x3c47, 0x41b4, + 0x4787, 0x4dbe, 0x546d, 0x5b86, + 0x632e, 0x6b52, 0x7400, 0x7d54, + 0x873b, 0x91c6, 0x9d1a, 0xa920, + 0xb5e5, 0xc38c, 0xd21b, 0xe18f, + 0xf1f5, 0x1036a, 0x1160f, 0x129d6, + 0x13ed0, 0x1550c, 0x16ca0, 0x185c9, + 0x1a07b, 0x1bcc3, 0x1dab9, 0x1fa75, + 0x21c0f, 0x23fa3, 0x26552, 0x28d64, + 0x2b7c9, 0x2e4a2, 0x31411, 0x3463b, + 0x37b44, 0x3b353, 0x3ee94, 0x42d30, + 0x46f55, 0x4b533, 0x4fefc, 0x54ce5, + 0x59f25, 0x5f5f6, 0x65193, 0x6b23c, + 0x71835, 0x783c3, 0x7f52c, 0x86cc0, + 0x8eacc, 0x96fa5, 0x9fba0, 0xa8f1a, + 0xb2a71, 0xbce0a, 0xc7a4a, 0xd2fa0, + 0xdee7b, 0xeb752, 0xf8a9f, 0x1068e4, + 0x1152a3, 0x12486a, 0x134ac8, 0x145a55, + 0x1577ac, 0x16a370, 0x17df51, 0x192bc2, + 0x1a88f8, 0x1bf7b7, 0x1d78c9, 0x1f0d04, + 0x20b542, 0x227268, 0x244564, 0x262f26, + 0x2830af +}; + +static uint tas3001c_treble_tab[]={ + 0x96, 0x95, 0x95, 0x94, + 0x93, 0x92, 0x92, 0x91, + 0x90, 0x90, 0x8f, 0x8e, + 0x8d, 0x8d, 0x8c, 0x8b, + 0x8a, 0x8a, 0x89, 0x88, + 0x88, 0x87, 0x86, 0x85, + 0x85, 0x84, 0x83, 0x83, + 0x82, 0x81, 0x80, 0x80, + 0x7f, 0x7e, 0x7e, 0x7d, + 0x7c, 0x7b, 0x7b, 0x7a, + 0x79, 0x78, 0x78, 0x77, + 0x76, 0x76, 0x75, 0x74, + 0x73, 0x73, 0x72, 0x71, + 0x71, 0x70, 0x6e, 0x6d, + 0x6d, 0x6c, 0x6b, 0x6a, + 0x69, 0x68, 0x67, 0x66, + 0x65, 0x63, 0x62, 0x62, + 0x60, 0x5f, 0x5d, 0x5c, + 0x5a, 0x58, 0x56, 0x55, + 0x53, 0x51, 0x4f, 0x4c, + 0x4a, 0x48, 0x45, 0x43, + 0x40, 0x3d, 0x3a, 0x37, + 0x35, 0x32, 0x2e, 0x2a, + 0x27, 0x22, 0x1e, 0x1a, + 0x15, 0x11, 0xc, 0x7, + 0x1 +}; + +static uint tas3001c_bass_tab[]={ + 0x86, 0x83, 0x81, 0x7f, + 0x7d, 0x7b, 0x79, 0x78, + 0x76, 0x75, 0x74, 0x72, + 0x71, 0x6f, 0x6e, 0x6d, + 0x6c, 0x6b, 0x69, 0x67, + 0x65, 0x64, 0x61, 0x60, + 0x5e, 0x5d, 0x5c, 0x5b, + 0x5a, 0x59, 0x58, 0x57, + 0x56, 0x55, 0x55, 0x54, + 0x53, 0x52, 0x50, 0x4f, + 0x4d, 0x4c, 0x4b, 0x49, + 0x47, 0x45, 0x44, 0x42, + 0x41, 0x3f, 0x3e, 0x3d, + 0x3c, 0x3b, 0x39, 0x38, + 0x37, 0x36, 0x35, 0x34, + 0x33, 0x31, 0x30, 0x2f, + 0x2e, 0x2c, 0x2b, 0x2b, + 0x29, 0x28, 0x27, 0x26, + 0x25, 0x24, 0x22, 0x21, + 0x20, 0x1e, 0x1c, 0x19, + 0x18, 0x18, 0x17, 0x16, + 0x15, 0x14, 0x13, 0x12, + 0x11, 0x10, 0xf, 0xe, + 0xd, 0xb, 0xa, 0x9, + 0x8, 0x6, 0x4, 0x2, + 0x1 +}; + +struct tas_gain_t tas3001c_gain = { + master: tas3001c_master_tab, + treble: tas3001c_treble_tab, + bass: tas3001c_bass_tab, + mixer: tas3001c_mixer_tab +}; + +struct tas_eq_pref_t *tas3001c_eq_prefs[]={ + &eqp_0e_2_1, + &eqp_10_1_0, + &eqp_15_2_1, + &eqp_15_1_0, + &eqp_0f_2_1, + &eqp_0f_1_0, + NULL +}; diff -Nru a/sound/oss/dmasound/tas3004.c b/sound/oss/dmasound/tas3004.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sound/oss/dmasound/tas3004.c Thu Sep 11 23:03:14 2003 @@ -0,0 +1,1124 @@ +/* + * Driver for the i2c/i2s based TA3004 sound chip used + * on some Apple hardware. Also known as "snapper". + * + * Tobias Sargeant + * Based upon tas3001c.c by Christopher C. Chimelis : + * + * TODO: + * ----- + * * Enable control over input line 2 (is this connected?) + * * Implement sleep support (at least mute everything and + * * set gains to minimum during sleep) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "dmasound.h" +#include "tas_common.h" +#include "tas3004.h" + +#include "tas_ioctl.h" + +/* #define DEBUG_DRCE */ + +#define TAS3004_BIQUAD_FILTER_COUNT 7 +#define TAS3004_BIQUAD_CHANNEL_COUNT 2 + +#define VOL_DEFAULT (100 * 4 / 5) +#define INPUT_DEFAULT (100 * 4 / 5) +#define BASS_DEFAULT (100 / 2) +#define TREBLE_DEFAULT (100 / 2) + +struct tas3004_data_t { + struct tas_data_t super; + int device_id; + int output_id; + int speaker_id; + struct tas_drce_t drce_state; +}; + +#define MAKE_TIME(sec,usec) (((sec)<<12) + (50000+(usec/10)*(1<<12))/100000) + +#define MAKE_RATIO(i,f) (((i)<<8) + ((500+(f)*(1<<8))/1000)) + + +static const union tas_biquad_t tas3004_eq_unity = { + .buf = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 }, +}; + + +static const struct tas_drce_t tas3004_drce_min = { + .enable = 1, + .above = { .val = MAKE_RATIO(16,0), .expand = 0 }, + .below = { .val = MAKE_RATIO(2,0), .expand = 0 }, + .threshold = -0x59a0, + .energy = MAKE_TIME(0, 1700), + .attack = MAKE_TIME(0, 1700), + .decay = MAKE_TIME(0, 1700), +}; + + +static const struct tas_drce_t tas3004_drce_max = { + .enable = 1, + .above = { .val = MAKE_RATIO(1,500), .expand = 1 }, + .below = { .val = MAKE_RATIO(2,0), .expand = 1 }, + .threshold = -0x0, + .energy = MAKE_TIME(2,400000), + .attack = MAKE_TIME(2,400000), + .decay = MAKE_TIME(2,400000), +}; + + +static const unsigned short time_constants[]={ + MAKE_TIME(0, 1700), + MAKE_TIME(0, 3500), + MAKE_TIME(0, 6700), + MAKE_TIME(0, 13000), + MAKE_TIME(0, 26000), + MAKE_TIME(0, 53000), + MAKE_TIME(0,106000), + MAKE_TIME(0,212000), + MAKE_TIME(0,425000), + MAKE_TIME(0,850000), + MAKE_TIME(1,700000), + MAKE_TIME(2,400000), +}; + +static const unsigned short above_threshold_compression_ratio[]={ + MAKE_RATIO( 1, 70), + MAKE_RATIO( 1,140), + MAKE_RATIO( 1,230), + MAKE_RATIO( 1,330), + MAKE_RATIO( 1,450), + MAKE_RATIO( 1,600), + MAKE_RATIO( 1,780), + MAKE_RATIO( 2, 0), + MAKE_RATIO( 2,290), + MAKE_RATIO( 2,670), + MAKE_RATIO( 3,200), + MAKE_RATIO( 4, 0), + MAKE_RATIO( 5,330), + MAKE_RATIO( 8, 0), + MAKE_RATIO(16, 0), +}; + +static const unsigned short above_threshold_expansion_ratio[]={ + MAKE_RATIO(1, 60), + MAKE_RATIO(1,130), + MAKE_RATIO(1,190), + MAKE_RATIO(1,250), + MAKE_RATIO(1,310), + MAKE_RATIO(1,380), + MAKE_RATIO(1,440), + MAKE_RATIO(1,500) +}; + +static const unsigned short below_threshold_compression_ratio[]={ + MAKE_RATIO(1, 70), + MAKE_RATIO(1,140), + MAKE_RATIO(1,230), + MAKE_RATIO(1,330), + MAKE_RATIO(1,450), + MAKE_RATIO(1,600), + MAKE_RATIO(1,780), + MAKE_RATIO(2, 0) +}; + +static const unsigned short below_threshold_expansion_ratio[]={ + MAKE_RATIO(1, 60), + MAKE_RATIO(1,130), + MAKE_RATIO(1,190), + MAKE_RATIO(1,250), + MAKE_RATIO(1,310), + MAKE_RATIO(1,380), + MAKE_RATIO(1,440), + MAKE_RATIO(1,500), + MAKE_RATIO(1,560), + MAKE_RATIO(1,630), + MAKE_RATIO(1,690), + MAKE_RATIO(1,750), + MAKE_RATIO(1,810), + MAKE_RATIO(1,880), + MAKE_RATIO(1,940), + MAKE_RATIO(2, 0) +}; + +static inline int +search( unsigned short val, + const unsigned short *arr, + const int arrsize) { + /* + * This could be a binary search, but for small tables, + * a linear search is likely to be faster + */ + + int i; + + for (i=0; i < arrsize; i++) + if (arr[i] >= val) + goto _1; + return arrsize-1; + _1: + if (i == 0) + return 0; + return (arr[i]-val < val-arr[i-1]) ? i : i-1; +} + +#define SEARCH(a, b) search(a, b, ARRAY_SIZE(b)) + +static inline int +time_index(unsigned short time) +{ + return SEARCH(time, time_constants); +} + + +static inline int +above_threshold_compression_index(unsigned short ratio) +{ + return SEARCH(ratio, above_threshold_compression_ratio); +} + + +static inline int +above_threshold_expansion_index(unsigned short ratio) +{ + return SEARCH(ratio, above_threshold_expansion_ratio); +} + + +static inline int +below_threshold_compression_index(unsigned short ratio) +{ + return SEARCH(ratio, below_threshold_compression_ratio); +} + + +static inline int +below_threshold_expansion_index(unsigned short ratio) +{ + return SEARCH(ratio, below_threshold_expansion_ratio); +} + +static inline unsigned char db_to_regval(short db) { + int r=0; + + r=(db+0x59a0) / 0x60; + + if (r < 0x91) return 0x91; + if (r > 0xef) return 0xef; + return r; +} + +static inline short quantize_db(short db) +{ + return db_to_regval(db) * 0x60 - 0x59a0; +} + +static inline int +register_width(enum tas3004_reg_t r) +{ + switch(r) { + case TAS3004_REG_MCR: + case TAS3004_REG_TREBLE: + case TAS3004_REG_BASS: + case TAS3004_REG_ANALOG_CTRL: + case TAS3004_REG_TEST1: + case TAS3004_REG_TEST2: + case TAS3004_REG_MCR2: + return 1; + + case TAS3004_REG_LEFT_LOUD_BIQUAD_GAIN: + case TAS3004_REG_RIGHT_LOUD_BIQUAD_GAIN: + return 3; + + case TAS3004_REG_DRC: + case TAS3004_REG_VOLUME: + return 6; + + case TAS3004_REG_LEFT_MIXER: + case TAS3004_REG_RIGHT_MIXER: + return 9; + + case TAS3004_REG_TEST: + return 10; + + case TAS3004_REG_LEFT_BIQUAD0: + case TAS3004_REG_LEFT_BIQUAD1: + case TAS3004_REG_LEFT_BIQUAD2: + case TAS3004_REG_LEFT_BIQUAD3: + case TAS3004_REG_LEFT_BIQUAD4: + case TAS3004_REG_LEFT_BIQUAD5: + case TAS3004_REG_LEFT_BIQUAD6: + + case TAS3004_REG_RIGHT_BIQUAD0: + case TAS3004_REG_RIGHT_BIQUAD1: + case TAS3004_REG_RIGHT_BIQUAD2: + case TAS3004_REG_RIGHT_BIQUAD3: + case TAS3004_REG_RIGHT_BIQUAD4: + case TAS3004_REG_RIGHT_BIQUAD5: + case TAS3004_REG_RIGHT_BIQUAD6: + + case TAS3004_REG_LEFT_LOUD_BIQUAD: + case TAS3004_REG_RIGHT_LOUD_BIQUAD: + return 15; + + default: + return 0; + } +} + +static int +tas3004_write_register( struct tas3004_data_t *self, + enum tas3004_reg_t reg_num, + char *data, + uint write_mode) +{ + if (reg_num==TAS3004_REG_MCR || + reg_num==TAS3004_REG_BASS || + reg_num==TAS3004_REG_TREBLE) { + return tas_write_byte_register(&self->super, + (uint)reg_num, + *data, + write_mode); + } else { + return tas_write_register(&self->super, + (uint)reg_num, + register_width(reg_num), + data, + write_mode); + } +} + +static int +tas3004_sync_register( struct tas3004_data_t *self, + enum tas3004_reg_t reg_num) +{ + if (reg_num==TAS3004_REG_MCR || + reg_num==TAS3004_REG_BASS || + reg_num==TAS3004_REG_TREBLE) { + return tas_sync_byte_register(&self->super, + (uint)reg_num, + register_width(reg_num)); + } else { + return tas_sync_register(&self->super, + (uint)reg_num, + register_width(reg_num)); + } +} + +static int +tas3004_read_register( struct tas3004_data_t *self, + enum tas3004_reg_t reg_num, + char *data, + uint write_mode) +{ + return tas_read_register(&self->super, + (uint)reg_num, + register_width(reg_num), + data); +} + +static inline int +tas3004_fast_load(struct tas3004_data_t *self, int fast) +{ + if (fast) + self->super.shadow[TAS3004_REG_MCR][0] |= 0x80; + else + self->super.shadow[TAS3004_REG_MCR][0] &= 0x7f; + return tas3004_sync_register(self,TAS3004_REG_MCR); +} + +static uint +tas3004_supported_mixers(struct tas3004_data_t *self) +{ + return SOUND_MASK_VOLUME | + SOUND_MASK_PCM | + SOUND_MASK_ALTPCM | + SOUND_MASK_IMIX | + SOUND_MASK_TREBLE | + SOUND_MASK_BASS; +} + +static int +tas3004_mixer_is_stereo(struct tas3004_data_t *self, int mixer) +{ + switch(mixer) { + case SOUND_MIXER_VOLUME: + case SOUND_MIXER_PCM: + case SOUND_MIXER_ALTPCM: + case SOUND_MIXER_IMIX: + return 1; + default: + return 0; + } +} + +static uint +tas3004_stereo_mixers(struct tas3004_data_t *self) +{ + uint r = tas3004_supported_mixers(self); + uint i; + + for (i=1; isuper.mixer[mixer]; + + return 0; +} + +static int +tas3004_set_mixer_level(struct tas3004_data_t *self, int mixer, uint level) +{ + int rc; + tas_shadow_t *shadow; + uint temp; + uint offset=0; + + if (!self) + return -1; + + shadow = self->super.shadow; + + if (!tas3004_mixer_is_stereo(self,mixer)) + level = tas_mono_to_stereo(level); + switch(mixer) { + case SOUND_MIXER_VOLUME: + temp = tas3004_gain.master[level&0xff]; + SET_4_20(shadow[TAS3004_REG_VOLUME], 0, temp); + temp = tas3004_gain.master[(level>>8)&0xff]; + SET_4_20(shadow[TAS3004_REG_VOLUME], 3, temp); + rc = tas3004_sync_register(self,TAS3004_REG_VOLUME); + break; + case SOUND_MIXER_IMIX: + offset += 3; + case SOUND_MIXER_ALTPCM: + offset += 3; + case SOUND_MIXER_PCM: + /* + * Don't load these in fast mode. The documentation + * says it can be done in either mode, but testing it + * shows that fast mode produces ugly clicking. + */ + /* tas3004_fast_load(self,1); */ + temp = tas3004_gain.mixer[level&0xff]; + SET_4_20(shadow[TAS3004_REG_LEFT_MIXER], offset, temp); + temp = tas3004_gain.mixer[(level>>8)&0xff]; + SET_4_20(shadow[TAS3004_REG_RIGHT_MIXER], offset, temp); + rc = tas3004_sync_register(self,TAS3004_REG_LEFT_MIXER); + if (rc == 0) + rc=tas3004_sync_register(self,TAS3004_REG_RIGHT_MIXER); + /* tas3004_fast_load(self,0); */ + break; + case SOUND_MIXER_TREBLE: + temp = tas3004_gain.treble[level&0xff]; + shadow[TAS3004_REG_TREBLE][0]=temp&0xff; + rc = tas3004_sync_register(self,TAS3004_REG_TREBLE); + break; + case SOUND_MIXER_BASS: + temp = tas3004_gain.bass[level&0xff]; + shadow[TAS3004_REG_BASS][0]=temp&0xff; + rc = tas3004_sync_register(self,TAS3004_REG_BASS); + break; + default: + rc = -1; + break; + } + if (rc < 0) + return rc; + self->super.mixer[mixer] = level; + + return 0; +} + +static int +tas3004_leave_sleep(struct tas3004_data_t *self) +{ + unsigned char mcr = (1<<6)+(2<<4)+(2<<2); + + if (!self) + return -1; + + /* Make sure something answers on the i2c bus */ + if (tas3004_write_register(self, TAS3004_REG_MCR, &mcr, + WRITE_NORMAL | FORCE_WRITE) < 0) + return -1; + + tas3004_fast_load(self, 1); + + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD0); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD1); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD2); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD3); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD4); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD5); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD6); + + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD0); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD1); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD2); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD3); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD4); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD5); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD6); + + tas3004_fast_load(self, 0); + + (void)tas3004_sync_register(self,TAS3004_REG_VOLUME); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_MIXER); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_MIXER); + (void)tas3004_sync_register(self,TAS3004_REG_TREBLE); + (void)tas3004_sync_register(self,TAS3004_REG_BASS); + + return 0; +} + +static int +tas3004_enter_sleep(struct tas3004_data_t *self) +{ + if (!self) + return -1; + return 0; +} + +static int +tas3004_sync_biquad( struct tas3004_data_t *self, + u_int channel, + u_int filter) +{ + enum tas3004_reg_t reg; + + if (channel >= TAS3004_BIQUAD_CHANNEL_COUNT || + filter >= TAS3004_BIQUAD_FILTER_COUNT) return -EINVAL; + + reg=( channel ? TAS3004_REG_RIGHT_BIQUAD0 : TAS3004_REG_LEFT_BIQUAD0 ) + filter; + + return tas3004_sync_register(self,reg); +} + +static int +tas3004_write_biquad_shadow( struct tas3004_data_t *self, + u_int channel, + u_int filter, + const union tas_biquad_t *biquad) +{ + tas_shadow_t *shadow=self->super.shadow; + enum tas3004_reg_t reg; + + if (channel >= TAS3004_BIQUAD_CHANNEL_COUNT || + filter >= TAS3004_BIQUAD_FILTER_COUNT) return -EINVAL; + + reg=( channel ? TAS3004_REG_RIGHT_BIQUAD0 : TAS3004_REG_LEFT_BIQUAD0 ) + filter; + + SET_4_20(shadow[reg], 0,biquad->coeff.b0); + SET_4_20(shadow[reg], 3,biquad->coeff.b1); + SET_4_20(shadow[reg], 6,biquad->coeff.b2); + SET_4_20(shadow[reg], 9,biquad->coeff.a1); + SET_4_20(shadow[reg],12,biquad->coeff.a2); + + return 0; +} + +static int +tas3004_write_biquad( struct tas3004_data_t *self, + u_int channel, + u_int filter, + const union tas_biquad_t *biquad) +{ + int rc; + + rc=tas3004_write_biquad_shadow(self, channel, filter, biquad); + if (rc < 0) return rc; + + return tas3004_sync_biquad(self, channel, filter); +} + +static int +tas3004_write_biquad_list( struct tas3004_data_t *self, + u_int filter_count, + u_int flags, + struct tas_biquad_ctrl_t *biquads) +{ + int i; + int rc; + + if (flags & TAS_BIQUAD_FAST_LOAD) tas3004_fast_load(self,1); + + for (i=0; isuper.shadow; + enum tas3004_reg_t reg; + + if (channel >= TAS3004_BIQUAD_CHANNEL_COUNT || + filter >= TAS3004_BIQUAD_FILTER_COUNT) return -EINVAL; + + reg=( channel ? TAS3004_REG_RIGHT_BIQUAD0 : TAS3004_REG_LEFT_BIQUAD0 ) + filter; + + biquad->coeff.b0=GET_4_20(shadow[reg], 0); + biquad->coeff.b1=GET_4_20(shadow[reg], 3); + biquad->coeff.b2=GET_4_20(shadow[reg], 6); + biquad->coeff.a1=GET_4_20(shadow[reg], 9); + biquad->coeff.a2=GET_4_20(shadow[reg],12); + + return 0; +} + +static int +tas3004_eq_rw( struct tas3004_data_t *self, + u_int cmd, + u_long arg) +{ + int rc; + struct tas_biquad_ctrl_t biquad; + + if (copy_from_user((void *)&biquad, (const void *)arg, sizeof(struct tas_biquad_ctrl_t))) { + return -EFAULT; + } + + if (cmd & SIOC_IN) { + rc=tas3004_write_biquad(self, biquad.channel, biquad.filter, &biquad.data); + if (rc != 0) return rc; + } + + if (cmd & SIOC_OUT) { + rc=tas3004_read_biquad(self, biquad.channel, biquad.filter, &biquad.data); + if (rc != 0) return rc; + + if (copy_to_user((void *)arg, (const void *)&biquad, sizeof(struct tas_biquad_ctrl_t))) { + return -EFAULT; + } + + } + return 0; +} + +static int +tas3004_eq_list_rw( struct tas3004_data_t *self, + u_int cmd, + u_long arg) +{ + int rc = 0; + int filter_count; + int flags; + int i,j; + char sync_required[TAS3004_BIQUAD_CHANNEL_COUNT][TAS3004_BIQUAD_FILTER_COUNT]; + struct tas_biquad_ctrl_t biquad; + + memset(sync_required,0,sizeof(sync_required)); + + if (copy_from_user((void *)&filter_count, + (const void *)arg + offsetof(struct tas_biquad_ctrl_list_t,filter_count), + sizeof(int))) { + return -EFAULT; + } + + if (copy_from_user((void *)&flags, + (const void *)arg + offsetof(struct tas_biquad_ctrl_list_t,flags), + sizeof(int))) { + return -EFAULT; + } + + if (cmd & SIOC_IN) { + } + + for (i=0; i < filter_count; i++) { + if (copy_from_user((void *)&biquad, + (const void *)arg + offsetof(struct tas_biquad_ctrl_list_t, biquads[i]), + sizeof(struct tas_biquad_ctrl_t))) { + return -EFAULT; + } + + if (cmd & SIOC_IN) { + sync_required[biquad.channel][biquad.filter]=1; + rc=tas3004_write_biquad_shadow(self, biquad.channel, biquad.filter, &biquad.data); + if (rc != 0) return rc; + } + + if (cmd & SIOC_OUT) { + rc=tas3004_read_biquad(self, biquad.channel, biquad.filter, &biquad.data); + if (rc != 0) return rc; + + if (copy_to_user((void *)arg + offsetof(struct tas_biquad_ctrl_list_t, biquads[i]), + (const void *)&biquad, + sizeof(struct tas_biquad_ctrl_t))) { + return -EFAULT; + } + } + } + + if (cmd & SIOC_IN) { + /* + * This is OK for the tas3004. For the + * tas3001c, going into fast load mode causes + * the treble and bass to be reset to 0dB, and + * volume controls to be muted. + */ + if (flags & TAS_BIQUAD_FAST_LOAD) tas3004_fast_load(self,1); + for (i=0; isuper.shadow; + + if (flags & TAS_DRCE_ABOVE_RATIO) { + self->drce_state.above.expand = drce->above.expand; + if (drce->above.val == (1<<8)) { + self->drce_state.above.val = 1<<8; + shadow[TAS3004_REG_DRC][0] = 0x02; + + } else if (drce->above.expand) { + i=above_threshold_expansion_index(drce->above.val); + self->drce_state.above.val=above_threshold_expansion_ratio[i]; + shadow[TAS3004_REG_DRC][0] = 0x0a + (i<<3); + } else { + i=above_threshold_compression_index(drce->above.val); + self->drce_state.above.val=above_threshold_compression_ratio[i]; + shadow[TAS3004_REG_DRC][0] = 0x08 + (i<<3); + } + } + + if (flags & TAS_DRCE_BELOW_RATIO) { + self->drce_state.below.expand = drce->below.expand; + if (drce->below.val == (1<<8)) { + self->drce_state.below.val = 1<<8; + shadow[TAS3004_REG_DRC][1] = 0x02; + + } else if (drce->below.expand) { + i=below_threshold_expansion_index(drce->below.val); + self->drce_state.below.val=below_threshold_expansion_ratio[i]; + shadow[TAS3004_REG_DRC][1] = 0x08 + (i<<3); + } else { + i=below_threshold_compression_index(drce->below.val); + self->drce_state.below.val=below_threshold_compression_ratio[i]; + shadow[TAS3004_REG_DRC][1] = 0x0a + (i<<3); + } + } + + if (flags & TAS_DRCE_THRESHOLD) { + self->drce_state.threshold=quantize_db(drce->threshold); + shadow[TAS3004_REG_DRC][2] = db_to_regval(self->drce_state.threshold); + } + + if (flags & TAS_DRCE_ENERGY) { + i=time_index(drce->energy); + self->drce_state.energy=time_constants[i]; + shadow[TAS3004_REG_DRC][3] = 0x40 + (i<<4); + } + + if (flags & TAS_DRCE_ATTACK) { + i=time_index(drce->attack); + self->drce_state.attack=time_constants[i]; + shadow[TAS3004_REG_DRC][4] = 0x40 + (i<<4); + } + + if (flags & TAS_DRCE_DECAY) { + i=time_index(drce->decay); + self->drce_state.decay=time_constants[i]; + shadow[TAS3004_REG_DRC][5] = 0x40 + (i<<4); + } + + if (flags & TAS_DRCE_ENABLE) { + self->drce_state.enable = drce->enable; + } + + if (!self->drce_state.enable) { + shadow[TAS3004_REG_DRC][0] |= 0x01; + } + +#ifdef DEBUG_DRCE + printk("DRCE: set [ ENABLE:%x ABOVE:%x/%x BELOW:%x/%x THRESH:%x ENERGY:%x ATTACK:%x DECAY:%x\n", + self->drce_state.enable, + self->drce_state.above.expand,self->drce_state.above.val, + self->drce_state.below.expand,self->drce_state.below.val, + self->drce_state.threshold, + self->drce_state.energy, + self->drce_state.attack, + self->drce_state.decay); + + printk("DRCE: reg [ %02x %02x %02x %02x %02x %02x ]\n", + (unsigned char)shadow[TAS3004_REG_DRC][0], + (unsigned char)shadow[TAS3004_REG_DRC][1], + (unsigned char)shadow[TAS3004_REG_DRC][2], + (unsigned char)shadow[TAS3004_REG_DRC][3], + (unsigned char)shadow[TAS3004_REG_DRC][4], + (unsigned char)shadow[TAS3004_REG_DRC][5]); +#endif + + return tas3004_sync_register(self, TAS3004_REG_DRC); +} + +static int +tas3004_drce_rw( struct tas3004_data_t *self, + u_int cmd, + u_long arg) +{ + int rc; + struct tas_drce_ctrl_t drce_ctrl; + + if (copy_from_user((void *)&drce_ctrl, + (const void *)arg, + sizeof(struct tas_drce_ctrl_t))) { + return -EFAULT; + } + +#ifdef DEBUG_DRCE + printk("DRCE: input [ FLAGS:%x ENABLE:%x ABOVE:%x/%x BELOW:%x/%x THRESH:%x ENERGY:%x ATTACK:%x DECAY:%x\n", + drce_ctrl.flags, + drce_ctrl.data.enable, + drce_ctrl.data.above.expand,drce_ctrl.data.above.val, + drce_ctrl.data.below.expand,drce_ctrl.data.below.val, + drce_ctrl.data.threshold, + drce_ctrl.data.energy, + drce_ctrl.data.attack, + drce_ctrl.data.decay); +#endif + + if (cmd & SIOC_IN) { + rc = tas3004_update_drce(self, drce_ctrl.flags, &drce_ctrl.data); + if (rc < 0) return rc; + } + + if (cmd & SIOC_OUT) { + if (drce_ctrl.flags & TAS_DRCE_ENABLE) + drce_ctrl.data.enable = self->drce_state.enable; + if (drce_ctrl.flags & TAS_DRCE_ABOVE_RATIO) + drce_ctrl.data.above = self->drce_state.above; + if (drce_ctrl.flags & TAS_DRCE_BELOW_RATIO) + drce_ctrl.data.below = self->drce_state.below; + if (drce_ctrl.flags & TAS_DRCE_THRESHOLD) + drce_ctrl.data.threshold = self->drce_state.threshold; + if (drce_ctrl.flags & TAS_DRCE_ENERGY) + drce_ctrl.data.energy = self->drce_state.energy; + if (drce_ctrl.flags & TAS_DRCE_ATTACK) + drce_ctrl.data.attack = self->drce_state.attack; + if (drce_ctrl.flags & TAS_DRCE_DECAY) + drce_ctrl.data.decay = self->drce_state.decay; + + if (copy_to_user((void *)arg, + (const void *)&drce_ctrl, + sizeof(struct tas_drce_ctrl_t))) { + return -EFAULT; + } + } + + return 0; +} + +static void +tas3004_update_device_parameters(struct tas3004_data_t *self) +{ + char data; + int i; + + if (!self) return; + + if (self->output_id == TAS_OUTPUT_HEADPHONES) { + /* turn on allPass when headphones are plugged in */ + data = 0x02; + } else { + data = 0x00; + } + + tas3004_write_register(self, TAS3004_REG_MCR2, &data, WRITE_NORMAL | FORCE_WRITE); + + for (i=0; tas3004_eq_prefs[i]; i++) { + struct tas_eq_pref_t *eq = tas3004_eq_prefs[i]; + + if (eq->device_id == self->device_id && + (eq->output_id == 0 || eq->output_id == self->output_id) && + (eq->speaker_id == 0 || eq->speaker_id == self->speaker_id)) { + + tas3004_update_drce(self, TAS_DRCE_ALL, eq->drce); + tas3004_write_biquad_list(self, eq->filter_count, TAS_BIQUAD_FAST_LOAD, eq->biquads); + + break; + } + } +} + +static void +tas3004_device_change_handler(void *self) +{ + if (!self) return; + + tas3004_update_device_parameters((struct tas3004_data_t *)self); +} + +static struct work_struct device_change; + +static int +tas3004_output_device_change( struct tas3004_data_t *self, + int device_id, + int output_id, + int speaker_id) +{ + self->device_id=device_id; + self->output_id=output_id; + self->speaker_id=speaker_id; + + schedule_work(&device_change); + + return 0; +} + +static int +tas3004_device_ioctl( struct tas3004_data_t *self, + u_int cmd, + u_long arg) +{ + switch (cmd) { + case TAS_READ_EQ: + case TAS_WRITE_EQ: + return tas3004_eq_rw(self, cmd, arg); + + case TAS_READ_EQ_LIST: + case TAS_WRITE_EQ_LIST: + return tas3004_eq_list_rw(self, cmd, arg); + + case TAS_READ_EQ_FILTER_COUNT: + put_user(TAS3004_BIQUAD_FILTER_COUNT, (uint *)(arg)); + return 0; + + case TAS_READ_EQ_CHANNEL_COUNT: + put_user(TAS3004_BIQUAD_CHANNEL_COUNT, (uint *)(arg)); + return 0; + + case TAS_READ_DRCE: + case TAS_WRITE_DRCE: + return tas3004_drce_rw(self, cmd, arg); + + case TAS_READ_DRCE_CAPS: + put_user(TAS_DRCE_ENABLE | + TAS_DRCE_ABOVE_RATIO | + TAS_DRCE_BELOW_RATIO | + TAS_DRCE_THRESHOLD | + TAS_DRCE_ENERGY | + TAS_DRCE_ATTACK | + TAS_DRCE_DECAY, + (uint *)(arg)); + return 0; + + case TAS_READ_DRCE_MIN: + case TAS_READ_DRCE_MAX: { + struct tas_drce_ctrl_t drce_ctrl; + const struct tas_drce_t *drce_copy; + + if (copy_from_user((void *)&drce_ctrl, + (const void *)arg, + sizeof(struct tas_drce_ctrl_t))) { + return -EFAULT; + } + + if (cmd == TAS_READ_DRCE_MIN) { + drce_copy=&tas3004_drce_min; + } else { + drce_copy=&tas3004_drce_max; + } + + if (drce_ctrl.flags & TAS_DRCE_ABOVE_RATIO) { + drce_ctrl.data.above=drce_copy->above; + } + if (drce_ctrl.flags & TAS_DRCE_BELOW_RATIO) { + drce_ctrl.data.below=drce_copy->below; + } + if (drce_ctrl.flags & TAS_DRCE_THRESHOLD) { + drce_ctrl.data.threshold=drce_copy->threshold; + } + if (drce_ctrl.flags & TAS_DRCE_ENERGY) { + drce_ctrl.data.energy=drce_copy->energy; + } + if (drce_ctrl.flags & TAS_DRCE_ATTACK) { + drce_ctrl.data.attack=drce_copy->attack; + } + if (drce_ctrl.flags & TAS_DRCE_DECAY) { + drce_ctrl.data.decay=drce_copy->decay; + } + + if (copy_to_user((void *)arg, + (const void *)&drce_ctrl, + sizeof(struct tas_drce_ctrl_t))) { + return -EFAULT; + } + } + } + + return -EINVAL; +} + +static int +tas3004_init_mixer(struct tas3004_data_t *self) +{ + unsigned char mcr = (1<<6)+(2<<4)+(2<<2); + + /* Make sure something answers on the i2c bus */ + if (tas3004_write_register(self, TAS3004_REG_MCR, &mcr, + WRITE_NORMAL | FORCE_WRITE) < 0) + return -1; + + tas3004_fast_load(self, 1); + + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD0); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD1); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD2); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD3); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD4); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD5); + (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD6); + + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD0); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD1); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD2); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD3); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD4); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD5); + (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD6); + + tas3004_sync_register(self, TAS3004_REG_DRC); + + tas3004_sync_register(self, TAS3004_REG_MCR2); + + tas3004_fast_load(self, 0); + + tas3004_set_mixer_level(self, SOUND_MIXER_VOLUME, VOL_DEFAULT<<8 | VOL_DEFAULT); + tas3004_set_mixer_level(self, SOUND_MIXER_PCM, INPUT_DEFAULT<<8 | INPUT_DEFAULT); + tas3004_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0); + tas3004_set_mixer_level(self, SOUND_MIXER_IMIX, 0); + + tas3004_set_mixer_level(self, SOUND_MIXER_BASS, BASS_DEFAULT); + tas3004_set_mixer_level(self, SOUND_MIXER_TREBLE, TREBLE_DEFAULT); + + return 0; +} + +static int +tas3004_uninit_mixer(struct tas3004_data_t *self) +{ + tas3004_set_mixer_level(self, SOUND_MIXER_VOLUME, 0); + tas3004_set_mixer_level(self, SOUND_MIXER_PCM, 0); + tas3004_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0); + tas3004_set_mixer_level(self, SOUND_MIXER_IMIX, 0); + + tas3004_set_mixer_level(self, SOUND_MIXER_BASS, 0); + tas3004_set_mixer_level(self, SOUND_MIXER_TREBLE, 0); + + return 0; +} + +static int +tas3004_init(struct i2c_client *client) +{ + struct tas3004_data_t *self; + size_t sz = sizeof(*self) + (TAS3004_REG_MAX*sizeof(tas_shadow_t)); + char drce_init[] = { 0x69, 0x22, 0x9f, 0xb0, 0x60, 0xa0 }; + char mcr2 = 0; + int i, j; + + self = kmalloc(sz, GFP_KERNEL); + if (!self) + return -ENOMEM; + memset(self, 0, sz); + + self->super.client = client; + self->super.shadow = (tas_shadow_t *)(self+1); + self->output_id = TAS_OUTPUT_HEADPHONES; + + dev_set_drvdata(&client->dev, self); + + for (i = 0; i < TAS3004_BIQUAD_CHANNEL_COUNT; i++) + for (j = 0; j + */ + +#ifndef _TAS3004_H_ +#define _TAS3004_H_ + +#include + +#include "tas_common.h" +#include "tas_eq_prefs.h" + +/* + * Macros that correspond to the registers that we write to + * when setting the various values. + */ + +#define TAS3004_VERSION "0.3" +#define TAS3004_DATE "20011214" + +#define I2C_DRIVERNAME_TAS3004 "TAS3004 driver V " TAS3004_VERSION +#define I2C_DRIVERID_TAS3004 (I2C_DRIVERID_TAS_BASE+1) + +extern struct tas_driver_hooks_t tas3004_hooks; +extern struct tas_gain_t tas3004_gain; +extern struct tas_eq_pref_t *tas3004_eq_prefs[]; + +enum tas3004_reg_t { + TAS3004_REG_MCR = 0x01, + TAS3004_REG_DRC = 0x02, + + TAS3004_REG_VOLUME = 0x04, + TAS3004_REG_TREBLE = 0x05, + TAS3004_REG_BASS = 0x06, + TAS3004_REG_LEFT_MIXER = 0x07, + TAS3004_REG_RIGHT_MIXER = 0x08, + + TAS3004_REG_LEFT_BIQUAD0 = 0x0a, + TAS3004_REG_LEFT_BIQUAD1 = 0x0b, + TAS3004_REG_LEFT_BIQUAD2 = 0x0c, + TAS3004_REG_LEFT_BIQUAD3 = 0x0d, + TAS3004_REG_LEFT_BIQUAD4 = 0x0e, + TAS3004_REG_LEFT_BIQUAD5 = 0x0f, + TAS3004_REG_LEFT_BIQUAD6 = 0x10, + + TAS3004_REG_RIGHT_BIQUAD0 = 0x13, + TAS3004_REG_RIGHT_BIQUAD1 = 0x14, + TAS3004_REG_RIGHT_BIQUAD2 = 0x15, + TAS3004_REG_RIGHT_BIQUAD3 = 0x16, + TAS3004_REG_RIGHT_BIQUAD4 = 0x17, + TAS3004_REG_RIGHT_BIQUAD5 = 0x18, + TAS3004_REG_RIGHT_BIQUAD6 = 0x19, + + TAS3004_REG_LEFT_LOUD_BIQUAD = 0x21, + TAS3004_REG_RIGHT_LOUD_BIQUAD = 0x22, + + TAS3004_REG_LEFT_LOUD_BIQUAD_GAIN = 0x23, + TAS3004_REG_RIGHT_LOUD_BIQUAD_GAIN = 0x24, + + TAS3004_REG_TEST = 0x29, + + TAS3004_REG_ANALOG_CTRL = 0x40, + TAS3004_REG_TEST1 = 0x41, + TAS3004_REG_TEST2 = 0x42, + TAS3004_REG_MCR2 = 0x43, + + TAS3004_REG_MAX = 0x44 +}; + +#endif /* _TAS3004_H_ */ diff -Nru a/sound/oss/dmasound/tas3004_tables.c b/sound/oss/dmasound/tas3004_tables.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sound/oss/dmasound/tas3004_tables.c Thu Sep 11 23:03:14 2003 @@ -0,0 +1,301 @@ +#include "tas3004.h" +#include "tas_eq_prefs.h" + +static struct tas_drce_t eqp_17_1_0_drce={ + enable: 1, + above: { val: 3.0 * (1<<8), expand: 0 }, + below: { val: 1.0 * (1<<8), expand: 0 }, + threshold: -19.12 * (1<<8), + energy: 2.4 * (1<<12), + attack: 0.013 * (1<<12), + decay: 0.212 * (1<<12), +}; + +static struct tas_biquad_ctrl_t eqp_17_1_0_biquads[]={ + { channel: 0, filter: 0, data: { coeff: { 0x0fd0d4, 0xe05e56, 0x0fd0d4, 0xe05ee1, 0x0fa234 } } }, + { channel: 0, filter: 1, data: { coeff: { 0x0910d7, 0x088e1a, 0x030651, 0x01dcb1, 0x02c892 } } }, + { channel: 0, filter: 2, data: { coeff: { 0x0ff895, 0xe0970b, 0x0f7f00, 0xe0970b, 0x0f7795 } } }, + { channel: 0, filter: 3, data: { coeff: { 0x0fd1c4, 0xe1ac22, 0x0ec8cf, 0xe1ac22, 0x0e9a94 } } }, + { channel: 0, filter: 4, data: { coeff: { 0x0f7c1c, 0xe3cc03, 0x0df786, 0xe3cc03, 0x0d73a2 } } }, + { channel: 0, filter: 5, data: { coeff: { 0x11fb92, 0xf5a1a0, 0x073cd2, 0xf5a1a0, 0x093865 } } }, + { channel: 0, filter: 6, data: { coeff: { 0x0e17a9, 0x068b6c, 0x08a0e5, 0x068b6c, 0x06b88e } } }, + + { channel: 1, filter: 0, data: { coeff: { 0x0fd0d4, 0xe05e56, 0x0fd0d4, 0xe05ee1, 0x0fa234 } } }, + { channel: 1, filter: 1, data: { coeff: { 0x0910d7, 0x088e1a, 0x030651, 0x01dcb1, 0x02c892 } } }, + { channel: 1, filter: 2, data: { coeff: { 0x0ff895, 0xe0970b, 0x0f7f00, 0xe0970b, 0x0f7795 } } }, + { channel: 1, filter: 3, data: { coeff: { 0x0fd1c4, 0xe1ac22, 0x0ec8cf, 0xe1ac22, 0x0e9a94 } } }, + { channel: 1, filter: 4, data: { coeff: { 0x0f7c1c, 0xe3cc03, 0x0df786, 0xe3cc03, 0x0d73a2 } } }, + { channel: 1, filter: 5, data: { coeff: { 0x11fb92, 0xf5a1a0, 0x073cd2, 0xf5a1a0, 0x093865 } } }, + { channel: 1, filter: 6, data: { coeff: { 0x0e17a9, 0x068b6c, 0x08a0e5, 0x068b6c, 0x06b88e } } } +}; + +static struct tas_eq_pref_t eqp_17_1_0 = { + sample_rate: 44100, + device_id: 0x17, + output_id: TAS_OUTPUT_INTERNAL_SPKR, + speaker_id: 0x00, + + drce: &eqp_17_1_0_drce, + + filter_count: 14, + biquads: eqp_17_1_0_biquads +}; + +/* ======================================================================== */ + +static struct tas_drce_t eqp_18_1_0_drce={ + enable: 1, + above: { val: 3.0 * (1<<8), expand: 0 }, + below: { val: 1.0 * (1<<8), expand: 0 }, + threshold: -13.14 * (1<<8), + energy: 2.4 * (1<<12), + attack: 0.013 * (1<<12), + decay: 0.212 * (1<<12), +}; + +static struct tas_biquad_ctrl_t eqp_18_1_0_biquads[]={ + { channel: 0, filter: 0, data: { coeff: { 0x0f5514, 0xe155d7, 0x0f5514, 0xe15cfa, 0x0eb14b } } }, + { channel: 0, filter: 1, data: { coeff: { 0x06ec33, 0x02abe3, 0x015eef, 0xf764d9, 0x03922d } } }, + { channel: 0, filter: 2, data: { coeff: { 0x0ef5f2, 0xe67d1f, 0x0bcf37, 0xe67d1f, 0x0ac529 } } }, + { channel: 0, filter: 3, data: { coeff: { 0x0db050, 0xe5be4d, 0x0d0c78, 0xe5be4d, 0x0abcc8 } } }, + { channel: 0, filter: 4, data: { coeff: { 0x0f1298, 0xe64ec6, 0x0cc03e, 0xe64ec6, 0x0bd2d7 } } }, + { channel: 0, filter: 5, data: { coeff: { 0x0c641a, 0x06537a, 0x08d155, 0x06537a, 0x053570 } } }, + { channel: 0, filter: 6, data: { coeff: { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } }, + + { channel: 1, filter: 0, data: { coeff: { 0x0f5514, 0xe155d7, 0x0f5514, 0xe15cfa, 0x0eb14b } } }, + { channel: 1, filter: 1, data: { coeff: { 0x06ec33, 0x02abe3, 0x015eef, 0xf764d9, 0x03922d } } }, + { channel: 1, filter: 2, data: { coeff: { 0x0ef5f2, 0xe67d1f, 0x0bcf37, 0xe67d1f, 0x0ac529 } } }, + { channel: 1, filter: 3, data: { coeff: { 0x0db050, 0xe5be4d, 0x0d0c78, 0xe5be4d, 0x0abcc8 } } }, + { channel: 1, filter: 4, data: { coeff: { 0x0f1298, 0xe64ec6, 0x0cc03e, 0xe64ec6, 0x0bd2d7 } } }, + { channel: 1, filter: 5, data: { coeff: { 0x0c641a, 0x06537a, 0x08d155, 0x06537a, 0x053570 } } }, + { channel: 1, filter: 6, data: { coeff: { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } } +}; + +static struct tas_eq_pref_t eqp_18_1_0 = { + sample_rate: 44100, + device_id: 0x18, + output_id: TAS_OUTPUT_INTERNAL_SPKR, + speaker_id: 0x00, + + drce: &eqp_18_1_0_drce, + + filter_count: 14, + biquads: eqp_18_1_0_biquads +}; + +/* ======================================================================== */ + +static struct tas_drce_t eqp_1a_1_0_drce={ + enable: 1, + above: { val: 3.0 * (1<<8), expand: 0 }, + below: { val: 1.0 * (1<<8), expand: 0 }, + threshold: -10.75 * (1<<8), + energy: 2.4 * (1<<12), + attack: 0.013 * (1<<12), + decay: 0.212 * (1<<12), +}; + +static struct tas_biquad_ctrl_t eqp_1a_1_0_biquads[]={ + { channel: 0, filter: 0, data: { coeff: { 0x0fb8fd, 0xe08e04, 0x0fb8fd, 0xe08f40, 0x0f7336 } } }, + { channel: 0, filter: 1, data: { coeff: { 0x06371d, 0x0c6e3a, 0x06371d, 0x05bfd3, 0x031ca2 } } }, + { channel: 0, filter: 2, data: { coeff: { 0x0fa1c0, 0xe18692, 0x0f030e, 0xe18692, 0x0ea4ce } } }, + { channel: 0, filter: 3, data: { coeff: { 0x0fe495, 0xe17eff, 0x0f0452, 0xe17eff, 0x0ee8e7 } } }, + { channel: 0, filter: 4, data: { coeff: { 0x100857, 0xe7e71c, 0x0e9599, 0xe7e71c, 0x0e9df1 } } }, + { channel: 0, filter: 5, data: { coeff: { 0x0fb26e, 0x06a82c, 0x0db2b4, 0x06a82c, 0x0d6522 } } }, + { channel: 0, filter: 6, data: { coeff: { 0x11419d, 0xf06cbf, 0x0a4f6e, 0xf06cbf, 0x0b910c } } }, + + { channel: 1, filter: 0, data: { coeff: { 0x0fb8fd, 0xe08e04, 0x0fb8fd, 0xe08f40, 0x0f7336 } } }, + { channel: 1, filter: 1, data: { coeff: { 0x06371d, 0x0c6e3a, 0x06371d, 0x05bfd3, 0x031ca2 } } }, + { channel: 1, filter: 2, data: { coeff: { 0x0fa1c0, 0xe18692, 0x0f030e, 0xe18692, 0x0ea4ce } } }, + { channel: 1, filter: 3, data: { coeff: { 0x0fe495, 0xe17eff, 0x0f0452, 0xe17eff, 0x0ee8e7 } } }, + { channel: 1, filter: 4, data: { coeff: { 0x100857, 0xe7e71c, 0x0e9599, 0xe7e71c, 0x0e9df1 } } }, + { channel: 1, filter: 5, data: { coeff: { 0x0fb26e, 0x06a82c, 0x0db2b4, 0x06a82c, 0x0d6522 } } }, + { channel: 1, filter: 6, data: { coeff: { 0x11419d, 0xf06cbf, 0x0a4f6e, 0xf06cbf, 0x0b910c } } } +}; + +static struct tas_eq_pref_t eqp_1a_1_0 = { + sample_rate: 44100, + device_id: 0x1a, + output_id: TAS_OUTPUT_INTERNAL_SPKR, + speaker_id: 0x00, + + drce: &eqp_1a_1_0_drce, + + filter_count: 14, + biquads: eqp_1a_1_0_biquads +}; + +/* ======================================================================== */ + +static struct tas_drce_t eqp_1c_1_0_drce={ + enable: 1, + above: { val: 3.0 * (1<<8), expand: 0 }, + below: { val: 1.0 * (1<<8), expand: 0 }, + threshold: -14.34 * (1<<8), + energy: 2.4 * (1<<12), + attack: 0.013 * (1<<12), + decay: 0.212 * (1<<12), +}; + +static struct tas_biquad_ctrl_t eqp_1c_1_0_biquads[]={ + { channel: 0, filter: 0, data: { coeff: { 0x0f4f95, 0xe160d4, 0x0f4f95, 0xe1686e, 0x0ea6c5 } } }, + { channel: 0, filter: 1, data: { coeff: { 0x066b92, 0x0290d4, 0x0148a0, 0xf6853f, 0x03bfc7 } } }, + { channel: 0, filter: 2, data: { coeff: { 0x0f57dc, 0xe51c91, 0x0dd1cb, 0xe51c91, 0x0d29a8 } } }, + { channel: 0, filter: 3, data: { coeff: { 0x0df1cb, 0xe4fa84, 0x0d7cdc, 0xe4fa84, 0x0b6ea7 } } }, + { channel: 0, filter: 4, data: { coeff: { 0x0eba36, 0xe6aa48, 0x0b9f52, 0xe6aa48, 0x0a5989 } } }, + { channel: 0, filter: 5, data: { coeff: { 0x0caf02, 0x05ef9d, 0x084beb, 0x05ef9d, 0x04faee } } }, + { channel: 0, filter: 6, data: { coeff: { 0x0fc686, 0xe22947, 0x0e4b5d, 0xe22947, 0x0e11e4 } } }, + + { channel: 1, filter: 0, data: { coeff: { 0x0f4f95, 0xe160d4, 0x0f4f95, 0xe1686e, 0x0ea6c5 } } }, + { channel: 1, filter: 1, data: { coeff: { 0x066b92, 0x0290d4, 0x0148a0, 0xf6853f, 0x03bfc7 } } }, + { channel: 1, filter: 2, data: { coeff: { 0x0f57dc, 0xe51c91, 0x0dd1cb, 0xe51c91, 0x0d29a8 } } }, + { channel: 1, filter: 3, data: { coeff: { 0x0df1cb, 0xe4fa84, 0x0d7cdc, 0xe4fa84, 0x0b6ea7 } } }, + { channel: 1, filter: 4, data: { coeff: { 0x0eba36, 0xe6aa48, 0x0b9f52, 0xe6aa48, 0x0a5989 } } }, + { channel: 1, filter: 5, data: { coeff: { 0x0caf02, 0x05ef9d, 0x084beb, 0x05ef9d, 0x04faee } } }, + { channel: 1, filter: 6, data: { coeff: { 0x0fc686, 0xe22947, 0x0e4b5d, 0xe22947, 0x0e11e4 } } } +}; + +static struct tas_eq_pref_t eqp_1c_1_0 = { + sample_rate: 44100, + device_id: 0x1c, + output_id: TAS_OUTPUT_INTERNAL_SPKR, + speaker_id: 0x00, + + drce: &eqp_1c_1_0_drce, + + filter_count: 14, + biquads: eqp_1c_1_0_biquads +}; + +/* ======================================================================== */ + +static uint tas3004_master_tab[]={ + 0x0, 0x75, 0x9c, 0xbb, + 0xdb, 0xfb, 0x11e, 0x143, + 0x16b, 0x196, 0x1c3, 0x1f5, + 0x229, 0x263, 0x29f, 0x2e1, + 0x328, 0x373, 0x3c5, 0x41b, + 0x478, 0x4dc, 0x547, 0x5b8, + 0x633, 0x6b5, 0x740, 0x7d5, + 0x873, 0x91c, 0x9d2, 0xa92, + 0xb5e, 0xc39, 0xd22, 0xe19, + 0xf20, 0x1037, 0x1161, 0x129e, + 0x13ed, 0x1551, 0x16ca, 0x185d, + 0x1a08, 0x1bcc, 0x1dac, 0x1fa7, + 0x21c1, 0x23fa, 0x2655, 0x28d6, + 0x2b7c, 0x2e4a, 0x3141, 0x3464, + 0x37b4, 0x3b35, 0x3ee9, 0x42d3, + 0x46f6, 0x4b53, 0x4ff0, 0x54ce, + 0x59f2, 0x5f5f, 0x6519, 0x6b24, + 0x7183, 0x783c, 0x7f53, 0x86cc, + 0x8ead, 0x96fa, 0x9fba, 0xa8f2, + 0xb2a7, 0xbce1, 0xc7a5, 0xd2fa, + 0xdee8, 0xeb75, 0xf8aa, 0x1068e, + 0x1152a, 0x12487, 0x134ad, 0x145a5, + 0x1577b, 0x16a37, 0x17df5, 0x192bd, + 0x1a890, 0x1bf7b, 0x1d78d, 0x1f0d1, + 0x20b55, 0x22727, 0x24456, 0x262f2, + 0x2830b +}; + +static uint tas3004_mixer_tab[]={ + 0x0, 0x748, 0x9be, 0xbaf, + 0xda4, 0xfb1, 0x11de, 0x1431, + 0x16ad, 0x1959, 0x1c37, 0x1f4b, + 0x2298, 0x2628, 0x29fb, 0x2e12, + 0x327d, 0x3734, 0x3c47, 0x41b4, + 0x4787, 0x4dbe, 0x546d, 0x5b86, + 0x632e, 0x6b52, 0x7400, 0x7d54, + 0x873b, 0x91c6, 0x9d1a, 0xa920, + 0xb5e5, 0xc38c, 0xd21b, 0xe18f, + 0xf1f5, 0x1036a, 0x1160f, 0x129d6, + 0x13ed0, 0x1550c, 0x16ca0, 0x185c9, + 0x1a07b, 0x1bcc3, 0x1dab9, 0x1fa75, + 0x21c0f, 0x23fa3, 0x26552, 0x28d64, + 0x2b7c9, 0x2e4a2, 0x31411, 0x3463b, + 0x37b44, 0x3b353, 0x3ee94, 0x42d30, + 0x46f55, 0x4b533, 0x4fefc, 0x54ce5, + 0x59f25, 0x5f5f6, 0x65193, 0x6b23c, + 0x71835, 0x783c3, 0x7f52c, 0x86cc0, + 0x8eacc, 0x96fa5, 0x9fba0, 0xa8f1a, + 0xb2a71, 0xbce0a, 0xc7a4a, 0xd2fa0, + 0xdee7b, 0xeb752, 0xf8a9f, 0x1068e4, + 0x1152a3, 0x12486a, 0x134ac8, 0x145a55, + 0x1577ac, 0x16a370, 0x17df51, 0x192bc2, + 0x1a88f8, 0x1bf7b7, 0x1d78c9, 0x1f0d04, + 0x20b542, 0x227268, 0x244564, 0x262f26, + 0x2830af +}; + +static uint tas3004_treble_tab[]={ + 0x96, 0x95, 0x95, 0x94, + 0x93, 0x92, 0x92, 0x91, + 0x90, 0x90, 0x8f, 0x8e, + 0x8d, 0x8d, 0x8c, 0x8b, + 0x8a, 0x8a, 0x89, 0x88, + 0x88, 0x87, 0x86, 0x85, + 0x85, 0x84, 0x83, 0x83, + 0x82, 0x81, 0x80, 0x80, + 0x7f, 0x7e, 0x7e, 0x7d, + 0x7c, 0x7b, 0x7b, 0x7a, + 0x79, 0x78, 0x78, 0x77, + 0x76, 0x76, 0x75, 0x74, + 0x73, 0x73, 0x72, 0x71, + 0x71, 0x68, 0x45, 0x5b, + 0x6d, 0x6c, 0x6b, 0x6a, + 0x69, 0x68, 0x67, 0x66, + 0x65, 0x63, 0x62, 0x62, + 0x60, 0x5e, 0x5c, 0x5b, + 0x59, 0x57, 0x55, 0x53, + 0x52, 0x4f, 0x4d, 0x4a, + 0x48, 0x46, 0x43, 0x40, + 0x3d, 0x3a, 0x36, 0x33, + 0x2f, 0x2c, 0x27, 0x23, + 0x1f, 0x1a, 0x15, 0xf, + 0x8, 0x5, 0x2, 0x1, + 0x1 +}; + +static uint tas3004_bass_tab[]={ + 0x96, 0x95, 0x95, 0x94, + 0x93, 0x92, 0x92, 0x91, + 0x90, 0x90, 0x8f, 0x8e, + 0x8d, 0x8d, 0x8c, 0x8b, + 0x8a, 0x8a, 0x89, 0x88, + 0x88, 0x87, 0x86, 0x85, + 0x85, 0x84, 0x83, 0x83, + 0x82, 0x81, 0x80, 0x80, + 0x7f, 0x7e, 0x7e, 0x7d, + 0x7c, 0x7b, 0x7b, 0x7a, + 0x79, 0x78, 0x78, 0x77, + 0x76, 0x76, 0x75, 0x74, + 0x73, 0x73, 0x72, 0x71, + 0x70, 0x6f, 0x6e, 0x6d, + 0x6c, 0x6b, 0x6a, 0x6a, + 0x69, 0x67, 0x66, 0x66, + 0x65, 0x63, 0x62, 0x62, + 0x61, 0x60, 0x5e, 0x5d, + 0x5b, 0x59, 0x57, 0x55, + 0x53, 0x51, 0x4f, 0x4c, + 0x4a, 0x48, 0x46, 0x44, + 0x41, 0x3e, 0x3b, 0x38, + 0x36, 0x33, 0x2f, 0x2b, + 0x28, 0x24, 0x20, 0x1c, + 0x17, 0x12, 0xd, 0x7, + 0x1 +}; + +struct tas_gain_t tas3004_gain={ + master: tas3004_master_tab, + treble: tas3004_treble_tab, + bass: tas3004_bass_tab, + mixer: tas3004_mixer_tab +}; + +struct tas_eq_pref_t *tas3004_eq_prefs[]={ + &eqp_17_1_0, + &eqp_18_1_0, + &eqp_1a_1_0, + &eqp_1c_1_0, + NULL +}; diff -Nru a/sound/oss/dmasound/tas_common.c b/sound/oss/dmasound/tas_common.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sound/oss/dmasound/tas_common.c Thu Sep 11 23:03:14 2003 @@ -0,0 +1,212 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tas_common.h" + +#define CALL0(proc) \ + do { \ + struct tas_data_t *self; \ + if (!tas_client || driver_hooks == NULL) \ + return -1; \ + self = dev_get_drvdata(&tas_client->dev); \ + if (driver_hooks->proc) \ + return driver_hooks->proc(self); \ + else \ + return -EINVAL; \ + } while (0) + +#define CALL(proc,arg...) \ + do { \ + struct tas_data_t *self; \ + if (!tas_client || driver_hooks == NULL) \ + return -1; \ + self = dev_get_drvdata(&tas_client->dev); \ + if (driver_hooks->proc) \ + return driver_hooks->proc(self, ## arg); \ + else \ + return -EINVAL; \ + } while (0) + + +static u8 tas_i2c_address = 0x34; +static struct i2c_client *tas_client; +static struct device_node* tas_node; + +static int tas_attach_adapter(struct i2c_adapter *); +static int tas_detach_client(struct i2c_client *); + +struct i2c_driver tas_driver = { + .owner = THIS_MODULE, + .name = "tas", + .flags = I2C_DF_NOTIFY, + .attach_adapter = tas_attach_adapter, + .detach_client = tas_detach_client, +}; + +struct tas_driver_hooks_t *driver_hooks; + +int +tas_register_driver(struct tas_driver_hooks_t *hooks) +{ + driver_hooks = hooks; + return 0; +} + +int +tas_get_mixer_level(int mixer, uint *level) +{ + CALL(get_mixer_level,mixer,level); +} + +int +tas_set_mixer_level(int mixer,uint level) +{ + CALL(set_mixer_level,mixer,level); +} + +int +tas_enter_sleep(void) +{ + CALL0(enter_sleep); +} + +int +tas_leave_sleep(void) +{ + CALL0(leave_sleep); +} + +int +tas_supported_mixers(void) +{ + CALL0(supported_mixers); +} + +int +tas_mixer_is_stereo(int mixer) +{ + CALL(mixer_is_stereo,mixer); +} + +int +tas_stereo_mixers(void) +{ + CALL0(stereo_mixers); +} + +int +tas_output_device_change(int device_id,int layout_id,int speaker_id) +{ + CALL(output_device_change,device_id,layout_id,speaker_id); +} + +int +tas_device_ioctl(u_int cmd, u_long arg) +{ + CALL(device_ioctl,cmd,arg); +} + +int +tas_post_init(void) +{ + CALL0(post_init); +} + +static int +tas_detect_client(struct i2c_adapter *adapter, int address) +{ + static const char *client_name = "tas Digital Equalizer"; + struct i2c_client *new_client; + int rc = -ENODEV; + + if (!driver_hooks) { + printk(KERN_ERR "tas_detect_client called with no hooks !\n"); + return -ENODEV; + } + + new_client = kmalloc(sizeof(*new_client), GFP_KERNEL); + if (!new_client) + return -ENOMEM; + memset(new_client, 0, sizeof(*new_client)); + + new_client->addr = address; + new_client->adapter = adapter; + new_client->driver = &tas_driver; + strlcpy(new_client->name, client_name, DEVICE_NAME_SIZE); + + if (driver_hooks->init(new_client)) + goto bail; + + /* Tell the i2c layer a new client has arrived */ + if (i2c_attach_client(new_client)) { + driver_hooks->uninit(dev_get_drvdata(&new_client->dev)); + goto bail; + } + + tas_client = new_client; + return 0; + bail: + tas_client = NULL; + kfree(new_client); + return rc; +} + +static int +tas_attach_adapter(struct i2c_adapter *adapter) +{ + if (!strncmp(adapter->name, "mac-io", 6)) + return tas_detect_client(adapter, tas_i2c_address); + return 0; +} + +static int +tas_detach_client(struct i2c_client *client) +{ + if (client == tas_client) { + driver_hooks->uninit(dev_get_drvdata(&client->dev)); + + i2c_detach_client(client); + kfree(client); + } + return 0; +} + +void +tas_cleanup(void) +{ + i2c_del_driver(&tas_driver); +} + +int __init +tas_init(int driver_id, const char *driver_name) +{ + u32* paddr; + + printk(KERN_INFO "tas driver [%s])\n", driver_name); + + tas_node = find_devices("deq"); + if (tas_node == NULL) + return -ENODEV; + paddr = (u32 *)get_property(tas_node, "i2c-address", NULL); + if (paddr) { + tas_i2c_address = (*paddr) >> 1; + printk(KERN_INFO "using i2c address: 0x%x from device-tree\n", + tas_i2c_address); + } else + printk(KERN_INFO "using i2c address: 0x%x (default)\n", + tas_i2c_address); + + return i2c_add_driver(&tas_driver); +} diff -Nru a/sound/oss/dmasound/tas_common.h b/sound/oss/dmasound/tas_common.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sound/oss/dmasound/tas_common.h Thu Sep 11 23:03:14 2003 @@ -0,0 +1,284 @@ +#ifndef _TAS_COMMON_H_ +#define _TAS_COMMON_H_ + +#include +#include +#include + +#define I2C_DRIVERID_TAS_BASE (0xFEBA) + +#define SET_4_20(shadow, offset, val) \ + do { \ + (shadow)[(offset)+0] = ((val) >> 16) & 0xff; \ + (shadow)[(offset)+1] = ((val) >> 8) & 0xff; \ + (shadow)[(offset)+2] = ((val) >> 0) & 0xff; \ + } while (0) + +#define GET_4_20(shadow, offset) \ + (((u_int)((shadow)[(offset)+0]) << 16) | \ + ((u_int)((shadow)[(offset)+1]) << 8) | \ + ((u_int)((shadow)[(offset)+2]) << 0)) + + +#define TAS_BIQUAD_FAST_LOAD 0x01 + +#define TAS_DRCE_ENABLE 0x01 +#define TAS_DRCE_ABOVE_RATIO 0x02 +#define TAS_DRCE_BELOW_RATIO 0x04 +#define TAS_DRCE_THRESHOLD 0x08 +#define TAS_DRCE_ENERGY 0x10 +#define TAS_DRCE_ATTACK 0x20 +#define TAS_DRCE_DECAY 0x40 + +#define TAS_DRCE_ALL 0x7f + + +#define TAS_OUTPUT_HEADPHONES 0x00 +#define TAS_OUTPUT_INTERNAL_SPKR 0x01 +#define TAS_OUTPUT_EXTERNAL_SPKR 0x02 + + +union tas_biquad_t { + struct { + int b0,b1,b2,a1,a2; + } coeff; + int buf[5]; +}; + +struct tas_biquad_ctrl_t { + u_int channel:4; + u_int filter:4; + + union tas_biquad_t data; +}; + +struct tas_biquad_ctrl_list_t { + int flags; + int filter_count; + struct tas_biquad_ctrl_t biquads[0]; +}; + +struct tas_ratio_t { + unsigned short val; /* 8.8 */ + unsigned short expand; /* 0 = compress, !0 = expand. */ +}; + +struct tas_drce_t { + unsigned short enable; + struct tas_ratio_t above; + struct tas_ratio_t below; + short threshold; /* dB, 8.8 signed */ + unsigned short energy; /* seconds, 4.12 unsigned */ + unsigned short attack; /* seconds, 4.12 unsigned */ + unsigned short decay; /* seconds, 4.12 unsigned */ +}; + +struct tas_drce_ctrl_t { + uint flags; + + struct tas_drce_t data; +}; + +struct tas_gain_t +{ + unsigned int *master; + unsigned int *treble; + unsigned int *bass; + unsigned int *mixer; +}; + +typedef char tas_shadow_t[16]; + +struct tas_data_t +{ + struct i2c_client *client; + tas_shadow_t *shadow; + uint mixer[SOUND_MIXER_NRDEVICES]; +}; + +typedef int (*tas_hook_init_t)(struct i2c_client *); +typedef int (*tas_hook_post_init_t)(struct tas_data_t *); +typedef void (*tas_hook_uninit_t)(struct tas_data_t *); + +typedef int (*tas_hook_get_mixer_level_t)(struct tas_data_t *,int,uint *); +typedef int (*tas_hook_set_mixer_level_t)(struct tas_data_t *,int,uint); + +typedef int (*tas_hook_enter_sleep_t)(struct tas_data_t *); +typedef int (*tas_hook_leave_sleep_t)(struct tas_data_t *); + +typedef int (*tas_hook_supported_mixers_t)(struct tas_data_t *); +typedef int (*tas_hook_mixer_is_stereo_t)(struct tas_data_t *,int); +typedef int (*tas_hook_stereo_mixers_t)(struct tas_data_t *); + +typedef int (*tas_hook_output_device_change_t)(struct tas_data_t *,int,int,int); +typedef int (*tas_hook_device_ioctl_t)(struct tas_data_t *,u_int,u_long); + +struct tas_driver_hooks_t { + /* + * All hardware initialisation must be performed in + * post_init(), as tas_dmasound_init() does a hardware reset. + * + * init() is called before tas_dmasound_init() so that + * ouput_device_change() is always called after i2c driver + * initialisation. The implication is that + * output_device_change() must cope with the fact that it + * may be called before post_init(). + */ + + tas_hook_init_t init; + tas_hook_post_init_t post_init; + tas_hook_uninit_t uninit; + + tas_hook_get_mixer_level_t get_mixer_level; + tas_hook_set_mixer_level_t set_mixer_level; + + tas_hook_enter_sleep_t enter_sleep; + tas_hook_leave_sleep_t leave_sleep; + + tas_hook_supported_mixers_t supported_mixers; + tas_hook_mixer_is_stereo_t mixer_is_stereo; + tas_hook_stereo_mixers_t stereo_mixers; + + tas_hook_output_device_change_t output_device_change; + tas_hook_device_ioctl_t device_ioctl; +}; + +enum tas_write_mode_t { + WRITE_HW = 0x01, + WRITE_SHADOW = 0x02, + WRITE_NORMAL = 0x03, + FORCE_WRITE = 0x04 +}; + +static inline uint +tas_mono_to_stereo(uint mono) +{ + mono &=0xff; + return mono | (mono<<8); +} + +/* + * Todo: make these functions a bit more efficient ! + */ +static inline int +tas_write_register( struct tas_data_t *self, + uint reg_num, + uint reg_width, + char *data, + uint write_mode) +{ + int rc; + + if (reg_width==0 || data==NULL || self==NULL) + return -EINVAL; + if (!(write_mode & FORCE_WRITE) && + !memcmp(data,self->shadow[reg_num],reg_width)) + return 0; + + if (write_mode & WRITE_SHADOW) + memcpy(self->shadow[reg_num],data,reg_width); + if (write_mode & WRITE_HW) { + rc=i2c_smbus_write_block_data(self->client, + reg_num, + reg_width, + data); + if (rc < 0) { + printk("tas: I2C block write failed \n"); + return rc; + } + } + return 0; +} + +static inline int +tas_sync_register( struct tas_data_t *self, + uint reg_num, + uint reg_width) +{ + int rc; + + if (reg_width==0 || self==NULL) + return -EINVAL; + rc=i2c_smbus_write_block_data(self->client, + reg_num, + reg_width, + self->shadow[reg_num]); + if (rc < 0) { + printk("tas: I2C block write failed \n"); + return rc; + } + return 0; +} + +static inline int +tas_write_byte_register( struct tas_data_t *self, + uint reg_num, + char data, + uint write_mode) +{ + if (self==NULL) + return -1; + if (!(write_mode & FORCE_WRITE) && data != self->shadow[reg_num][0]) + return 0; + if (write_mode & WRITE_SHADOW) + self->shadow[reg_num][0]=data; + if (write_mode & WRITE_HW) { + if (i2c_smbus_write_byte_data(self->client, reg_num, data) < 0) { + printk("tas: I2C byte write failed \n"); + return -1; + } + } + return 0; +} + +static inline int +tas_sync_byte_register( struct tas_data_t *self, + uint reg_num, + uint reg_width) +{ + if (reg_width==0 || self==NULL) + return -1; + if (i2c_smbus_write_byte_data( + self->client, reg_num, self->shadow[reg_num][0]) < 0) { + printk("tas: I2C byte write failed \n"); + return -1; + } + return 0; +} + +static inline int +tas_read_register( struct tas_data_t *self, + uint reg_num, + uint reg_width, + char *data) +{ + if (reg_width==0 || data==NULL || self==NULL) + return -1; + memcpy(data,self->shadow[reg_num],reg_width); + return 0; +} + +extern int tas_register_driver(struct tas_driver_hooks_t *hooks); + +extern int tas_get_mixer_level(int mixer,uint *level); +extern int tas_set_mixer_level(int mixer,uint level); +extern int tas_enter_sleep(void); +extern int tas_leave_sleep(void); +extern int tas_supported_mixers(void); +extern int tas_mixer_is_stereo(int mixer); +extern int tas_stereo_mixers(void); +extern int tas_output_device_change(int,int,int); +extern int tas_device_ioctl(u_int, u_long); + +extern void tas_cleanup(void); +extern int tas_init(int driver_id,const char *driver_name); +extern int tas_post_init(void); + +#endif /* _TAS_COMMON_H_ */ +/* + * Local Variables: + * tab-width: 8 + * indent-tabs-mode: t + * c-basic-offset: 8 + * End: + */ diff -Nru a/sound/oss/dmasound/tas_eq_prefs.h b/sound/oss/dmasound/tas_eq_prefs.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sound/oss/dmasound/tas_eq_prefs.h Thu Sep 11 23:03:14 2003 @@ -0,0 +1,24 @@ +#ifndef _TAS_EQ_PREFS_H_ +#define _TAS_EQ_PREFS_H_ + +struct tas_eq_pref_t { + u_int sample_rate; + u_int device_id; + u_int output_id; + u_int speaker_id; + + struct tas_drce_t *drce; + + u_int filter_count; + struct tas_biquad_ctrl_t *biquads; +}; + +#endif /* _TAS_EQ_PREFS_H_ */ + +/* + * Local Variables: + * tab-width: 8 + * indent-tabs-mode: t + * c-basic-offset: 8 + * End: + */ diff -Nru a/sound/oss/dmasound/tas_ioctl.h b/sound/oss/dmasound/tas_ioctl.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sound/oss/dmasound/tas_ioctl.h Thu Sep 11 23:03:14 2003 @@ -0,0 +1,24 @@ +#ifndef _TAS_IOCTL_H_ +#define _TAS_IOCTL_H_ + +#include +#include + + +#define TAS_READ_EQ _SIOR('t',0,struct tas_biquad_ctrl_t) +#define TAS_WRITE_EQ _SIOW('t',0,struct tas_biquad_ctrl_t) + +#define TAS_READ_EQ_LIST _SIOR('t',1,struct tas_biquad_ctrl_t) +#define TAS_WRITE_EQ_LIST _SIOW('t',1,struct tas_biquad_ctrl_t) + +#define TAS_READ_EQ_FILTER_COUNT _SIOR('t',2,int) +#define TAS_READ_EQ_CHANNEL_COUNT _SIOR('t',3,int) + +#define TAS_READ_DRCE _SIOR('t',4,struct tas_drce_ctrl_t) +#define TAS_WRITE_DRCE _SIOW('t',4,struct tas_drce_ctrl_t) + +#define TAS_READ_DRCE_CAPS _SIOR('t',5,int) +#define TAS_READ_DRCE_MIN _SIOR('t',6,int) +#define TAS_READ_DRCE_MAX _SIOR('t',7,int) + +#endif diff -Nru a/sound/oss/dmasound/trans_16.c b/sound/oss/dmasound/trans_16.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/sound/oss/dmasound/trans_16.c Thu Sep 11 23:03:14 2003 @@ -0,0 +1,679 @@ +/* + * linux/drivers/sound/dmasound/trans_16.c + * + * 16 bit translation routines. Only used by Power mac at present. + * + * See linux/drivers/sound/dmasound/dmasound_core.c for copyright and + * history prior to 08/02/2001. + * + * 08/02/2001 Iain Sandoe + * split from dmasound_awacs.c + */ + +#include +#include +#include "dmasound.h" + +static short dmasound_alaw2dma16[] ; +static short dmasound_ulaw2dma16[] ; + +static ssize_t pmac_ct_law(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t pmac_ct_s8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t pmac_ct_u8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t pmac_ct_s16(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t pmac_ct_u16(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); + +static ssize_t pmac_ctx_law(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t pmac_ctx_s8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t pmac_ctx_u8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t pmac_ctx_s16(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t pmac_ctx_u16(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); + +static ssize_t pmac_ct_s16_read(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); +static ssize_t pmac_ct_u16_read(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft); + +/*** Translations ************************************************************/ + +extern int expand_bal; /* Balance factor for expanding (not volume!) */ +static int expand_data; /* Data for expanding */ + +static ssize_t pmac_ct_law(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + short *table = dmasound.soft.format == AFMT_MU_LAW + ? dmasound_ulaw2dma16 : dmasound_alaw2dma16; + ssize_t count, used; + short *p = (short *) &frame[*frameUsed]; + int val, stereo = dmasound.soft.stereo; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + used = count = min_t(unsigned long, userCount, frameLeft); + while (count > 0) { + u_char data; + if (get_user(data, userPtr++)) + return -EFAULT; + val = table[data]; + *p++ = val; + if (stereo) { + if (get_user(data, userPtr++)) + return -EFAULT; + val = table[data]; + } + *p++ = val; + count--; + } + *frameUsed += used * 4; + return stereo? used * 2: used; +} + + +static ssize_t pmac_ct_s8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + short *p = (short *) &frame[*frameUsed]; + int val, stereo = dmasound.soft.stereo; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + used = count = min_t(unsigned long, userCount, frameLeft); + while (count > 0) { + u_char data; + if (get_user(data, userPtr++)) + return -EFAULT; + val = data << 8; + *p++ = val; + if (stereo) { + if (get_user(data, userPtr++)) + return -EFAULT; + val = data << 8; + } + *p++ = val; + count--; + } + *frameUsed += used * 4; + return stereo? used * 2: used; +} + + +static ssize_t pmac_ct_u8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + short *p = (short *) &frame[*frameUsed]; + int val, stereo = dmasound.soft.stereo; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + used = count = min_t(unsigned long, userCount, frameLeft); + while (count > 0) { + u_char data; + if (get_user(data, userPtr++)) + return -EFAULT; + val = (data ^ 0x80) << 8; + *p++ = val; + if (stereo) { + if (get_user(data, userPtr++)) + return -EFAULT; + val = (data ^ 0x80) << 8; + } + *p++ = val; + count--; + } + *frameUsed += used * 4; + return stereo? used * 2: used; +} + + +static ssize_t pmac_ct_s16(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + int stereo = dmasound.soft.stereo; + short *fp = (short *) &frame[*frameUsed]; + + frameLeft >>= 2; + userCount >>= (stereo? 2: 1); + used = count = min_t(unsigned long, userCount, frameLeft); + if (!stereo) { + short *up = (short *) userPtr; + while (count > 0) { + short data; + if (get_user(data, up++)) + return -EFAULT; + *fp++ = data; + *fp++ = data; + count--; + } + } else { + if (copy_from_user(fp, userPtr, count * 4)) + return -EFAULT; + } + *frameUsed += used * 4; + return stereo? used * 4: used * 2; +} + +static ssize_t pmac_ct_u16(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); + int stereo = dmasound.soft.stereo; + short *fp = (short *) &frame[*frameUsed]; + short *up = (short *) userPtr; + + frameLeft >>= 2; + userCount >>= (stereo? 2: 1); + used = count = min_t(unsigned long, userCount, frameLeft); + while (count > 0) { + short data; + if (get_user(data, up++)) + return -EFAULT; + data ^= mask; + *fp++ = data; + if (stereo) { + if (get_user(data, up++)) + return -EFAULT; + data ^= mask; + } + *fp++ = data; + count--; + } + *frameUsed += used * 4; + return stereo? used * 4: used * 2; +} + + +static ssize_t pmac_ctx_law(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + unsigned short *table = (unsigned short *) + (dmasound.soft.format == AFMT_MU_LAW + ? dmasound_ulaw2dma16 : dmasound_alaw2dma16); + unsigned int data = expand_data; + unsigned int *p = (unsigned int *) &frame[*frameUsed]; + int bal = expand_bal; + int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; + int utotal, ftotal; + int stereo = dmasound.soft.stereo; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + ftotal = frameLeft; + utotal = userCount; + while (frameLeft) { + u_char c; + if (bal < 0) { + if (userCount == 0) + break; + if (get_user(c, userPtr++)) + return -EFAULT; + data = table[c]; + if (stereo) { + if (get_user(c, userPtr++)) + return -EFAULT; + data = (data << 16) + table[c]; + } else + data = (data << 16) + data; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + expand_bal = bal; + expand_data = data; + *frameUsed += (ftotal - frameLeft) * 4; + utotal -= userCount; + return stereo? utotal * 2: utotal; +} + +static ssize_t pmac_ctx_s8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + unsigned int *p = (unsigned int *) &frame[*frameUsed]; + unsigned int data = expand_data; + int bal = expand_bal; + int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; + int stereo = dmasound.soft.stereo; + int utotal, ftotal; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + ftotal = frameLeft; + utotal = userCount; + while (frameLeft) { + u_char c; + if (bal < 0) { + if (userCount == 0) + break; + if (get_user(c, userPtr++)) + return -EFAULT; + data = c << 8; + if (stereo) { + if (get_user(c, userPtr++)) + return -EFAULT; + data = (data << 16) + (c << 8); + } else + data = (data << 16) + data; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + expand_bal = bal; + expand_data = data; + *frameUsed += (ftotal - frameLeft) * 4; + utotal -= userCount; + return stereo? utotal * 2: utotal; +} + + +static ssize_t pmac_ctx_u8(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + unsigned int *p = (unsigned int *) &frame[*frameUsed]; + unsigned int data = expand_data; + int bal = expand_bal; + int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; + int stereo = dmasound.soft.stereo; + int utotal, ftotal; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + ftotal = frameLeft; + utotal = userCount; + while (frameLeft) { + u_char c; + if (bal < 0) { + if (userCount == 0) + break; + if (get_user(c, userPtr++)) + return -EFAULT; + data = (c ^ 0x80) << 8; + if (stereo) { + if (get_user(c, userPtr++)) + return -EFAULT; + data = (data << 16) + ((c ^ 0x80) << 8); + } else + data = (data << 16) + data; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + expand_bal = bal; + expand_data = data; + *frameUsed += (ftotal - frameLeft) * 4; + utotal -= userCount; + return stereo? utotal * 2: utotal; +} + + +static ssize_t pmac_ctx_s16(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + unsigned int *p = (unsigned int *) &frame[*frameUsed]; + unsigned int data = expand_data; + unsigned short *up = (unsigned short *) userPtr; + int bal = expand_bal; + int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; + int stereo = dmasound.soft.stereo; + int utotal, ftotal; + + frameLeft >>= 2; + userCount >>= (stereo? 2: 1); + ftotal = frameLeft; + utotal = userCount; + while (frameLeft) { + unsigned short c; + if (bal < 0) { + if (userCount == 0) + break; + if (get_user(data, up++)) + return -EFAULT; + if (stereo) { + if (get_user(c, up++)) + return -EFAULT; + data = (data << 16) + c; + } else + data = (data << 16) + data; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + expand_bal = bal; + expand_data = data; + *frameUsed += (ftotal - frameLeft) * 4; + utotal -= userCount; + return stereo? utotal * 4: utotal * 2; +} + + +static ssize_t pmac_ctx_u16(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); + unsigned int *p = (unsigned int *) &frame[*frameUsed]; + unsigned int data = expand_data; + unsigned short *up = (unsigned short *) userPtr; + int bal = expand_bal; + int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; + int stereo = dmasound.soft.stereo; + int utotal, ftotal; + + frameLeft >>= 2; + userCount >>= (stereo? 2: 1); + ftotal = frameLeft; + utotal = userCount; + while (frameLeft) { + unsigned short c; + if (bal < 0) { + if (userCount == 0) + break; + if (get_user(data, up++)) + return -EFAULT; + data ^= mask; + if (stereo) { + if (get_user(c, up++)) + return -EFAULT; + data = (data << 16) + (c ^ mask); + } else + data = (data << 16) + data; + userCount--; + bal += hSpeed; + } + *p++ = data; + frameLeft--; + bal -= sSpeed; + } + expand_bal = bal; + expand_data = data; + *frameUsed += (ftotal - frameLeft) * 4; + utotal -= userCount; + return stereo? utotal * 4: utotal * 2; +} + +/* data in routines... */ + +static ssize_t pmac_ct_s8_read(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + short *p = (short *) &frame[*frameUsed]; + int val, stereo = dmasound.soft.stereo; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + used = count = min_t(unsigned long, userCount, frameLeft); + while (count > 0) { + u_char data; + + val = *p++; + data = val >> 8; + if (put_user(data, (u_char *)userPtr++)) + return -EFAULT; + if (stereo) { + val = *p; + data = val >> 8; + if (put_user(data, (u_char *)userPtr++)) + return -EFAULT; + } + p++; + count--; + } + *frameUsed += used * 4; + return stereo? used * 2: used; +} + + +static ssize_t pmac_ct_u8_read(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + short *p = (short *) &frame[*frameUsed]; + int val, stereo = dmasound.soft.stereo; + + frameLeft >>= 2; + if (stereo) + userCount >>= 1; + used = count = min_t(unsigned long, userCount, frameLeft); + while (count > 0) { + u_char data; + + val = *p++; + data = (val >> 8) ^ 0x80; + if (put_user(data, (u_char *)userPtr++)) + return -EFAULT; + if (stereo) { + val = *p; + data = (val >> 8) ^ 0x80; + if (put_user(data, (u_char *)userPtr++)) + return -EFAULT; + } + p++; + count--; + } + *frameUsed += used * 4; + return stereo? used * 2: used; +} + +static ssize_t pmac_ct_s16_read(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + int stereo = dmasound.soft.stereo; + short *fp = (short *) &frame[*frameUsed]; + + frameLeft >>= 2; + userCount >>= (stereo? 2: 1); + used = count = min_t(unsigned long, userCount, frameLeft); + if (!stereo) { + short *up = (short *) userPtr; + while (count > 0) { + short data; + data = *fp; + if (put_user(data, up++)) + return -EFAULT; + fp+=2; + count--; + } + } else { + if (copy_to_user((u_char *)userPtr, fp, count * 4)) + return -EFAULT; + } + *frameUsed += used * 4; + return stereo? used * 4: used * 2; +} + +static ssize_t pmac_ct_u16_read(const u_char *userPtr, size_t userCount, + u_char frame[], ssize_t *frameUsed, + ssize_t frameLeft) +{ + ssize_t count, used; + int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); + int stereo = dmasound.soft.stereo; + short *fp = (short *) &frame[*frameUsed]; + short *up = (short *) userPtr; + + frameLeft >>= 2; + userCount >>= (stereo? 2: 1); + used = count = min_t(unsigned long, userCount, frameLeft); + while (count > 0) { + int data; + + data = *fp++; + data ^= mask; + if (put_user(data, up++)) + return -EFAULT; + if (stereo) { + data = *fp; + data ^= mask; + if (put_user(data, up++)) + return -EFAULT; + } + fp++; + count--; + } + *frameUsed += used * 4; + return stereo? used * 4: used * 2; +} + +TRANS transAwacsNormal = { + ct_ulaw: pmac_ct_law, + ct_alaw: pmac_ct_law, + ct_s8: pmac_ct_s8, + ct_u8: pmac_ct_u8, + ct_s16be: pmac_ct_s16, + ct_u16be: pmac_ct_u16, + ct_s16le: pmac_ct_s16, + ct_u16le: pmac_ct_u16, +}; + +TRANS transAwacsExpand = { + ct_ulaw: pmac_ctx_law, + ct_alaw: pmac_ctx_law, + ct_s8: pmac_ctx_s8, + ct_u8: pmac_ctx_u8, + ct_s16be: pmac_ctx_s16, + ct_u16be: pmac_ctx_u16, + ct_s16le: pmac_ctx_s16, + ct_u16le: pmac_ctx_u16, +}; + +TRANS transAwacsNormalRead = { + ct_s8: pmac_ct_s8_read, + ct_u8: pmac_ct_u8_read, + ct_s16be: pmac_ct_s16_read, + ct_u16be: pmac_ct_u16_read, + ct_s16le: pmac_ct_s16_read, + ct_u16le: pmac_ct_u16_read, +}; + +/* translation tables */ +/* 16 bit mu-law */ + +static short dmasound_ulaw2dma16[] = { + -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, + -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, + -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, + -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, + -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, + -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, + -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, + -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, + -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, + -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, + -876, -844, -812, -780, -748, -716, -684, -652, + -620, -588, -556, -524, -492, -460, -428, -396, + -372, -356, -340, -324, -308, -292, -276, -260, + -244, -228, -212, -196, -180, -164, -148, -132, + -120, -112, -104, -96, -88, -80, -72, -64, + -56, -48, -40, -32, -24, -16, -8, 0, + 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, + 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, + 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, + 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, + 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, + 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, + 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, + 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, + 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, + 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, + 876, 844, 812, 780, 748, 716, 684, 652, + 620, 588, 556, 524, 492, 460, 428, 396, + 372, 356, 340, 324, 308, 292, 276, 260, + 244, 228, 212, 196, 180, 164, 148, 132, + 120, 112, 104, 96, 88, 80, 72, 64, + 56, 48, 40, 32, 24, 16, 8, 0, +}; + +/* 16 bit A-law */ + +static short dmasound_alaw2dma16[] = { + -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, + -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, + -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, + -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, + -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944, + -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, + -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472, + -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, + -344, -328, -376, -360, -280, -264, -312, -296, + -472, -456, -504, -488, -408, -392, -440, -424, + -88, -72, -120, -104, -24, -8, -56, -40, + -216, -200, -248, -232, -152, -136, -184, -168, + -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, + -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, + -688, -656, -752, -720, -560, -528, -624, -592, + -944, -912, -1008, -976, -816, -784, -880, -848, + 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, + 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, + 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, + 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, + 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, + 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, + 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, + 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, + 344, 328, 376, 360, 280, 264, 312, 296, + 472, 456, 504, 488, 408, 392, 440, 424, + 88, 72, 120, 104, 24, 8, 56, 40, + 216, 200, 248, 232, 152, 136, 184, 168, + 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, + 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, + 688, 656, 752, 720, 560, 528, 624, 592, + 944, 912, 1008, 976, 816, 784, 880, 848, +}; diff -Nru a/sound/oss/forte.c b/sound/oss/forte.c --- a/sound/oss/forte.c Thu Sep 11 23:03:12 2003 +++ b/sound/oss/forte.c Thu Sep 11 23:03:12 2003 @@ -37,7 +37,6 @@ #include #include -#include #include #include diff -Nru a/sound/oss/nec_vrc5477.c b/sound/oss/nec_vrc5477.c --- a/sound/oss/nec_vrc5477.c Thu Sep 11 23:03:13 2003 +++ b/sound/oss/nec_vrc5477.c Thu Sep 11 23:03:13 2003 @@ -96,7 +96,6 @@ #endif #if defined(VRC5477_AC97_DEBUG) -#include #define ASSERT(x) if (!(x)) { \ panic("assertion failed at %s:%d: %s\n", __FILE__, __LINE__, #x); } #else diff -Nru a/sound/oss/rme96xx.c b/sound/oss/rme96xx.c --- a/sound/oss/rme96xx.c Thu Sep 11 23:03:12 2003 +++ b/sound/oss/rme96xx.c Thu Sep 11 23:03:12 2003 @@ -54,7 +54,6 @@ #include #include #include -#include #include #include #include diff -Nru a/sound/oss/vwsnd.c b/sound/oss/vwsnd.c --- a/sound/oss/vwsnd.c Thu Sep 11 23:03:12 2003 +++ b/sound/oss/vwsnd.c Thu Sep 11 23:03:12 2003 @@ -158,8 +158,6 @@ #ifdef VWSND_DEBUG -#include /* for in_interrupt() */ - static int shut_up = 1; /* diff -Nru a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c --- a/usr/gen_init_cpio.c Thu Sep 11 23:03:13 2003 +++ b/usr/gen_init_cpio.c Thu Sep 11 23:03:13 2003 @@ -212,7 +212,7 @@ int main (int argc, char *argv[]) { - cpio_mkdir("/dev", 0700, 0, 0); + cpio_mkdir("/dev", 0755, 0, 0); cpio_mknod("/dev/console", 0600, 0, 0, 'c', 5, 1); cpio_mkdir("/root", 0700, 0, 0); cpio_trailer();