# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet v2.5.69 -> 1.1225 # fs/xfs/linux/xfs_lrw.c 1.22 -> 1.23 # net/core/link_watch.c 1.2 -> 1.4 # drivers/video/fbmem.c 1.74 -> 1.76 # drivers/i2c/chips/w83781d.c 1.5 -> 1.6 # include/asm-x86_64/irq.h 1.2 -> 1.3 # drivers/hotplug/cpqphp_core.c 1.15.1.1 -> 1.17 # drivers/net/8139too.c 1.52 -> 1.55 # arch/sparc/Kconfig 1.12 -> 1.13 # arch/i386/kernel/process.c 1.49 -> 1.51 # include/acpi/acglobal.h 1.22 -> 1.24 # drivers/net/am79c961a.h 1.1 -> 1.2 drivers/net/arm/am79c961a.h (moved) # arch/alpha/kernel/entry.S 1.28 -> 1.29 # drivers/isdn/hardware/avm/b1pcmcia.c 1.22 -> 1.23 # net/ipv4/netfilter/ip_conntrack_core.c 1.28 -> 1.29 # net/bridge/br_device.c 1.7 -> 1.8 # drivers/char/drm/drm_agpsupport.h 1.18 -> 1.19 # drivers/char/ipmi/ipmi_kcs_intf.c 1.7 -> 1.8 # arch/ia64/lib/io.c 1.3 -> 1.5 # arch/arm/kernel/irq.c 1.27 -> 1.28 # drivers/scsi/inia100.h 1.14 -> 1.15 # drivers/acorn/scsi/oak.c 1.15 -> 1.18 drivers/scsi/arm/oak.c (moved) # include/asm-alpha/agp_backend.h 1.1 -> 1.2 # include/asm-i386/mpspec.h 1.11 -> 1.12 # drivers/net/defxx.c 1.16 -> 1.17 # drivers/scsi/megaraid.c 1.43 -> 1.45 # drivers/pcmcia/cs_internal.h 1.12 -> 1.13 # drivers/net/3c59x.c 1.34 -> 1.37 # Documentation/DocBook/kernel-api.tmpl 1.23.1.2 -> 1.25 # include/linux/file.h 1.9 -> 1.10 # include/acpi/acpixf.h 1.22 -> 1.23 # net/ipv4/netfilter/ipt_pkttype.c 1.2 -> 1.3 # net/irda/irproc.c 1.4 -> 1.5 # arch/ppc64/kernel/signal.c 1.26 -> 1.27 # kernel/intermodule.c 1.3 -> 1.4 # include/linux/proc_fs.h 1.15 -> 1.17 # fs/xfs/xfs_mount.h 1.13 -> 1.15 # drivers/net/irda/nsc-ircc.c 1.20 -> 1.22 # fs/cifs/file.c 1.15 -> 1.16 # drivers/i2c/chips/lm75.c 1.14 -> 1.15 # include/linux/kernel.h 1.35 -> 1.37 # drivers/scsi/aic7xxx/aic79xx_core.c 1.17 -> 1.24 # include/asm-i386/mmu_context.h 1.15 -> 1.16 # arch/i386/kernel/timers/Makefile 1.6 -> 1.7 # drivers/scsi/dpti.h 1.8 -> 1.9 # drivers/isdn/hardware/eicon/maintidi.c 1.1 -> 1.2 # drivers/atm/horizon.c 1.10 -> 1.11 # drivers/media/video/tda9887.c 1.5 -> 1.8 # drivers/ide/pci/via82cxxx.c 1.11 -> 1.12 # drivers/scsi/imm.h 1.7 -> 1.8 # drivers/scsi/in2000.h 1.9 -> 1.10 # drivers/isdn/isdnloop/isdnloop.c 1.18 -> 1.19 # include/linux/netfilter_ipv4/ip_nat_core.h 1.1 -> 1.3 # drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped 1.8 -> 1.10 # drivers/block/acsi_slm.c 1.11 -> 1.12 # drivers/media/video/saa7134/saa7134-tvaudio.c 1.5 -> 1.6 # arch/i386/mm/fault.c 1.24 -> 1.26 # drivers/scsi/qlogicisp.h 1.5 -> 1.6 # include/asm-ppc/hardirq.h 1.18 -> 1.19 # include/asm-ppc/elf.h 1.8 -> 1.9 # fs/xfs/linux/xfs_sysctl.h 1.7 -> 1.8 # drivers/char/esp.c 1.18 -> 1.19 # sound/oss/opl3sa2.c 1.20 -> 1.21 # arch/sparc/kernel/module.c 1.10 -> 1.11 # arch/i386/lib/usercopy.c 1.11 -> 1.13 # drivers/acpi/namespace/nsdumpdv.c 1.8 -> 1.9 # arch/ppc/boot/simple/Makefile 1.14 -> 1.15 # ipc/msg.c 1.13 -> 1.14 # net/ipv4/syncookies.c 1.12 -> 1.13 # net/llc/af_llc.c 1.39 -> 1.41 # fs/xfs/linux/xfs_vfs.c 1.6 -> 1.8 # drivers/scsi/ips.c 1.52 -> 1.57 # include/net/dn_dev.h 1.4 -> 1.5 # drivers/usb/misc/usblcd.c 1.7 -> 1.8 # include/asm-i386/system.h 1.27.1.1 -> 1.29 # net/bluetooth/rfcomm/core.c 1.17 -> 1.21 # drivers/scsi/scsi_error.c 1.48 -> 1.54 # drivers/usb/misc/uss720.c 1.13 -> 1.14 # net/ipx/ipx_proc.c 1.2 -> 1.6 # drivers/net/irda/toshoboe.c 1.15 -> 1.17 # arch/ia64/hp/sim/simscsi.h 1.6 -> 1.7 # kernel/rcupdate.c 1.3 -> 1.4 # include/linux/agpgart.h 1.2 -> 1.5 # drivers/media/video/tvaudio.h 1.3 -> 1.4 # include/asm-arm/arch-tbox/time.h 1.5 -> 1.6 # drivers/ide/ide-taskfile.c 1.16 -> 1.18 # fs/libfs.c 1.17 -> 1.18 # drivers/char/vme_scc.c 1.16 -> 1.17 # arch/x86_64/kernel/traps.c 1.19 -> 1.21 # arch/ia64/kernel/palinfo.c 1.13 -> 1.14 # drivers/usb/misc/tiglusb.c 1.17 -> 1.19 # include/acpi/acutils.h 1.25 -> 1.26 # include/asm-ppc64/page.h 1.18 -> 1.19 # drivers/scsi/fcal.h 1.6 -> 1.7 # fs/reiserfs/file.c 1.18 -> 1.19 # drivers/ieee1394/raw1394.c 1.24 -> 1.25 # drivers/media/video/saa7134/saa7134-ts.c 1.5 -> 1.6 # drivers/scsi/pas16.c 1.9 -> 1.10 # drivers/char/lp.c 1.25 -> 1.26 # include/linux/pagemap.h 1.35 -> 1.36 # arch/x86_64/mm/fault.c 1.11 -> 1.12 # arch/alpha/kernel/module.c 1.4 -> 1.5 # drivers/scsi/aic7xxx/aic7xxx_proc.c 1.7 -> 1.10 # net/ipv4/netfilter/ip_nat_proto_tcp.c 1.3 -> 1.4 # kernel/ksyms.c 1.195 -> 1.200 # fs/cifs/inode.c 1.10 -> 1.11 # include/asm-ppc64/unistd.h 1.19 -> 1.20 # drivers/acorn/scsi/Makefile 1.8 -> 1.10 drivers/scsi/arm/Makefile (moved) # net/ipv4/tcp_diag.c 1.5 -> 1.8 # include/linux/if_frad.h 1.2 -> 1.3 # fs/xfs/linux/xfs_vfs.h 1.9 -> 1.11 # drivers/scsi/aic7xxx_old/aic7xxx.h 1.13 -> 1.14 # include/acpi/acpiosxf.h 1.27 -> 1.29 # arch/m68k/kernel/entry.S 1.11 -> 1.12 # include/asm-mips64/elf.h 1.5 -> 1.6 # include/net/sctp/user.h 1.9 -> 1.10 # arch/ppc64/kernel/entry.S 1.24 -> 1.26 # drivers/i2c/chips/adm1021.c 1.15 -> 1.16 # net/ipv4/proc.c 1.11 -> 1.14 # sound/core/seq/oss/seq_oss_synth.c 1.10 -> 1.11 # arch/i386/kernel/cpu/cpufreq/powernow-k7.c 1.9 -> 1.13 # include/linux/sysrq.h 1.4 -> 1.5 # drivers/net/pci-skeleton.c 1.20 -> 1.21 # drivers/net/wan/cosa.c 1.20 -> 1.21 # drivers/scsi/pci2220i.c 1.20 -> 1.21 # drivers/net/tulip/de4x5.c 1.25 -> 1.26 # drivers/acpi/hardware/hwgpe.c 1.19 -> 1.20 # drivers/acpi/dispatcher/dsobject.c 1.25 -> 1.26 # drivers/pci/quirks.c 1.25 -> 1.28 # drivers/isdn/hardware/avm/b1pci.c 1.29 -> 1.30 # include/asm-i386/mach-visws/mach_apic.h 1.1 -> 1.3 # drivers/scsi/g_NCR5380.h 1.7 -> 1.8 # include/asm-arm/bitops.h 1.11 -> 1.13 # fs/select.c 1.19 -> 1.20 # net/xfrm/xfrm_input.c 1.10 -> 1.11 # drivers/sbus/char/bpp.c 1.13 -> 1.14 # net/ipv6/anycast.c 1.1 -> 1.2 # include/asm-ia64/machvec_init.h 1.4 -> 1.6 # drivers/usb/media/dabusb.h 1.5 -> 1.6 # include/linux/elevator.h 1.19 -> 1.21 # drivers/char/isicom.c 1.17 -> 1.18 # drivers/usb/class/usb-midi.c 1.16 -> 1.17 # fs/cifs/cifsproto.h 1.9 -> 1.10 # include/linux/swap.h 1.76 -> 1.77 # drivers/isdn/i4l/isdn_net_lib.c 1.38 -> 1.41 # include/asm-i386/edd.h 1.4 -> 1.5 # drivers/pnp/pnpbios/core.c 1.29 -> 1.30 # arch/x86_64/ia32/ia32_binfmt.c 1.11 -> 1.13 # drivers/net/bmac.c 1.13 -> 1.14 # fs/cifs/AUTHORS 1.2 -> 1.3 # fs/xfs/quota/xfs_qm.c 1.12 -> 1.13 # fs/xfs/pagebuf/page_buf.c 1.50 -> 1.53 # net/sctp/associola.c 1.38.1.1 -> 1.45 # include/net/dn_route.h 1.6 -> 1.7 # net/ipv4/xfrm4_state.c 1.3 -> 1.5 # arch/ia64/Makefile 1.42 -> 1.44 # drivers/atm/Makefile 1.17 -> 1.19 # arch/ia64/kernel/efi.c 1.19 -> 1.20 # arch/m68k/sun3/prom/printf.c 1.1 -> 1.2 # include/asm-i386/processor.h 1.48 -> 1.50 # net/ipv6/exthdrs.c 1.9 -> 1.12 # arch/x86_64/kernel/setup.c 1.13 -> 1.14 # include/linux/mm.h 1.117 -> 1.121 # fs/file_table.c 1.23 -> 1.24 # arch/arm/kernel/module.c 1.6 -> 1.7 # net/core/neighbour.c 1.11 -> 1.13 # include/linux/nfsd/state.h 1.1 -> 1.3 # drivers/char/agp/sis-agp.c 1.15 -> 1.23 # include/asm-x86_64/page.h 1.9 -> 1.10 # drivers/input/serio/rpckbd.c 1.8 -> 1.9 # drivers/scsi/fcal.c 1.9 -> 1.10 # drivers/net/net_init.c 1.10 -> 1.12 # arch/ia64/kernel/fw-emu.c 1.7 -> 1.8 # net/atm/addr.c 1.2 -> 1.3 # include/linux/cycx_cfm.h 1.1 -> 1.3 # arch/i386/kernel/apm.c 1.50 -> 1.53 # drivers/scsi/hosts.c 1.58 -> 1.64 # drivers/net/natsemi.c 1.48 -> 1.51 # arch/x86_64/vmlinux.lds.S 1.15 -> 1.16 # lib/Makefile 1.21 -> 1.22 # fs/open.c 1.38 -> 1.41 # arch/i386/kernel/cpu/cpufreq/longhaul.c 1.17 -> 1.18 # net/ipv4/netfilter/ipt_TOS.c 1.7 -> 1.8 # net/ipv4/netfilter/ipt_limit.c 1.3 -> 1.4 # include/asm-i386/fixmap.h 1.11 -> 1.12 # drivers/ide/pci/amd74xx.h 1.6 -> 1.7 # net/sctp/objcnt.c 1.5 -> 1.7 # drivers/net/skfp/skfddi.c 1.11 -> 1.12 # net/Kconfig 1.11 -> 1.14 # include/asm-ia64/acpi-ext.h 1.1 -> 1.2 # include/asm-ia64/io.h 1.9 -> 1.11 # net/sctp/input.c 1.25 -> 1.28 # arch/ppc/Makefile 1.38 -> 1.39 # include/linux/i2c-id.h 1.10 -> 1.11 # arch/ppc64/kernel/udbg.c 1.7 -> 1.8 # net/ipv6/ip6_output.c 1.20 -> 1.26 # drivers/base/core.c 1.65 -> 1.67 # drivers/net/sb1000.c 1.16 -> 1.19 # drivers/scsi/cpqfcTSinit.c 1.35 -> 1.37 # drivers/ide/pci/serverworks.c 1.17 -> 1.18 # drivers/scsi/aic7xxx/aic7xxx_pci.c 1.12 -> 1.14 # drivers/scsi/aacraid/comminit.c 1.2 -> 1.5 # drivers/acpi/toshiba_acpi.c 1.8 -> 1.9 # drivers/usb/class/Kconfig 1.6 -> 1.7 # sound/core/seq/oss/seq_oss_ioctl.c 1.2 -> 1.3 # drivers/net/ioc3-eth.c 1.17 -> 1.18 # drivers/media/video/mxb.c 1.3 -> 1.4 # drivers/scsi/aic7xxx/aiclib.h 1.6 -> 1.8 # net/ipv4/ip_input.c 1.14 -> 1.15 # drivers/ide/pci/piix.c 1.14 -> 1.15 # drivers/scsi/atp870u.h 1.8 -> 1.9 # drivers/net/sk98lin/skproc.c 1.5 -> 1.6 # net/sctp/sm_statefuns.c 1.41.1.1 -> 1.48 # arch/i386/kernel/irq.c 1.34 -> 1.36 # include/linux/raid/md.h 1.26 -> 1.27 # drivers/scsi/mac53c94.c 1.4 -> 1.5 # include/asm-m68knommu/hardirq.h 1.2 -> 1.3 # drivers/char/watchdog/pcwd.c 1.22 -> 1.23 # drivers/scsi/scsi_proc.c 1.19 -> 1.22 # mm/page_alloc.c 1.154 -> 1.158 # drivers/scsi/aic7xxx/aic7xxx_osm.c 1.28 -> 1.37 # drivers/i2c/busses/Makefile 1.7 -> 1.8 # include/asm-ppc64/processor.h 1.27 -> 1.29 # drivers/isdn/hysdn/hycapi.c 1.17 -> 1.18 # include/acpi/acexcep.h 1.14 -> 1.15 # drivers/scsi/aacraid/README 1.1 -> 1.2 # sound/core/seq/oss/seq_oss_rw.c 1.2 -> 1.3 # drivers/net/wan/comx-proto-lapb.c 1.5 -> 1.6 # drivers/video/vesafb.c 1.31 -> 1.32 # arch/ppc/boot/images/Makefile 1.7 -> 1.8 # include/asm-ia64/spinlock.h 1.9 -> 1.11 # drivers/char/random.c 1.32 -> 1.33 # drivers/acpi/utilities/uteval.c 1.17 -> 1.18 # Documentation/driver-model/class.txt 1.2 -> 1.3 # net/bridge/br_fdb.c 1.5 -> 1.6 # drivers/char/dz.c 1.18 -> 1.20 # drivers/acpi/utilities/utmisc.c 1.24 -> 1.25 # arch/sparc/kernel/sparc_ksyms.c 1.17 -> 1.19 # drivers/input/serio/i8042.c 1.26 -> 1.27 # drivers/usb/host/ohci-hcd.c 1.42 -> 1.43 # arch/i386/kernel/smp.c 1.30 -> 1.31 # drivers/acpi/events/evrgnini.c 1.16 -> 1.18 # fs/ext3/Makefile 1.9 -> 1.10 # include/net/ipx.h 1.6 -> 1.10 # net/llc/llc_proc.c 1.9 -> 1.10 # drivers/net/pcmcia/nmclan_cs.c 1.13 -> 1.14 # arch/alpha/kernel/core_marvel.c 1.9 -> 1.11 # net/ipv6/datagram.c 1.8 -> 1.10 # drivers/acpi/executer/exdump.c 1.19 -> 1.20 # drivers/acorn/scsi/cumana_1.c 1.14 -> 1.17 drivers/scsi/arm/cumana_1.c (moved) # include/asm-arm/arch-cl7500/time.h 1.5 -> 1.6 # drivers/net/wan/comx-hw-comx.c 1.10 -> 1.11 # drivers/scsi/lasi700.c 1.7 -> 1.8 # net/ipv4/netfilter/ipt_mac.c 1.4 -> 1.5 # arch/i386/kernel/head.S 1.26 -> 1.27 # kernel/fork.c 1.118 -> 1.121 # net/sunrpc/svcsock.c 1.43 -> 1.48 # include/linux/sched.h 1.142 -> 1.146 # drivers/ide/ppc/pmac.c 1.10 -> 1.12 # include/asm-ia64/machvec_hpzx1.h 1.6 -> 1.7 # include/linux/ptrace.h 1.8 -> 1.9 # include/asm-ppc64/module.h 1.2 -> 1.3 # drivers/scsi/ibmmca.c 1.17 -> 1.18 # drivers/block/ll_rw_blk.c 1.168 -> 1.170 # arch/i386/kernel/vm86.c 1.25 -> 1.26 # kernel/sysctl.c 1.41 -> 1.42 # drivers/net/Space.c 1.19 -> 1.20 # arch/arm/kernel/ptrace.c 1.18 -> 1.19 # drivers/acpi/namespace/nsparse.c 1.7 -> 1.8 # drivers/acorn/scsi/queue.c 1.8 -> 1.10 drivers/scsi/arm/queue.c (moved) # net/ipv4/xfrm4_tunnel.c 1.4 -> 1.6 # drivers/media/radio/miropcm20-rds.c 1.10 -> 1.11 # drivers/net/wireless/airo.c 1.39 -> 1.40 # drivers/atm/ambassador.c 1.11 -> 1.12 # drivers/i2c/chips/via686a.c 1.6 -> 1.7 # net/ipv4/netfilter/ipt_tcpmss.c 1.3 -> 1.4 # Documentation/video4linux/bttv/CARDLIST 1.8 -> 1.9 # fs/xfs/xfs_log_priv.h 1.5 -> 1.10 # drivers/isdn/hisax/hisax_fcclassic.c 1.4 -> 1.5 # drivers/net/wan/hdlc_generic.c 1.7 -> 1.9 # drivers/media/video/bttv-if.c 1.11 -> 1.13 # drivers/media/video/bt819.c 1.7 -> 1.8 # drivers/acpi/utilities/utglobal.c 1.26 -> 1.27 # include/acpi/acnamesp.h 1.18 -> 1.19 # drivers/isdn/eicon/eicon_mod.c 1.12 -> 1.14 # drivers/net/smc-mca.c 1.8 -> 1.9 # include/net/tcp.h 1.35 -> 1.37 # include/acpi/acobject.h 1.18 -> 1.19 # drivers/acpi/hardware/hwtimer.c 1.15 -> 1.16 # drivers/media/video/bttv.h 1.9 -> 1.10 # drivers/scsi/dtc.h 1.7 -> 1.8 # include/asm-ppc64/ucontext.h 1.2 -> 1.3 # arch/ppc64/kernel/chrp_setup.c 1.21.2.2 -> 1.27 # drivers/serial/amba.c 1.20 -> 1.21 # drivers/media/video/videodev.c 1.19 -> 1.22 # include/net/sctp/ulpevent.h 1.7 -> 1.9 # drivers/net/wan/sdla_ft1.c 1.6 -> 1.7 # include/asm-ia64/page.h 1.15 -> 1.17 # sound/core/seq/seq_clientmgr.c 1.14 -> 1.16 # net/ipv4/protocol.c 1.5 -> 1.7 # drivers/ieee1394/sbp2.c 1.30 -> 1.31 # net/bridge/br_ioctl.c 1.8 -> 1.9 # drivers/net/tlan.c 1.20 -> 1.21 # fs/dcache.c 1.51 -> 1.53 # arch/x86_64/kernel/acpi.c 1.5 -> (deleted) # net/sctp/endpointola.c 1.19 -> 1.23 # arch/arm/kernel/asm-offsets.c 1.2 -> 1.3 # drivers/acpi/utilities/utxface.c 1.16 -> 1.17 # include/asm-arm/arch-rpc/time.h 1.4 -> 1.5 # net/ipv4/af_inet.c 1.44 -> 1.48 # mm/vmscan.c 1.156 -> 1.158 # drivers/isdn/hardware/eicon/divasmain.c 1.8 -> 1.9 # arch/ia64/kernel/setup.c 1.37.1.1 -> 1.41 # arch/um/drivers/mmapper_kern.c 1.4 -> 1.5 # net/ipv6/netfilter/ip6t_ah.c 1.4 -> 1.5 # net/atm/Makefile 1.7 -> 1.10 # drivers/acorn/scsi/Kconfig 1.1 -> 1.2 drivers/scsi/arm/Kconfig (moved) # drivers/isdn/hardware/avm/t1pci.c 1.26 -> 1.27 # drivers/net/hamradio/mkiss.h 1.1 -> 1.2 # drivers/serial/sa1100.c 1.24 -> 1.25 # drivers/scsi/NCR_D700.c 1.7 -> 1.9 # drivers/char/agp/frontend.c 1.31 -> 1.38 # include/net/iw_handler.h 1.5 -> 1.6 # drivers/scsi/lasi700.h 1.4 -> 1.5 # drivers/net/arcnet/com20020-isa.c 1.4 -> 1.5 # include/linux/if_arcnet.h 1.1 -> 1.2 # net/sctp/sm_make_chunk.c 1.34.1.1 -> 1.46 # drivers/scsi/dc395x.c 1.1 -> 1.2 # drivers/scsi/sym53c416.c 1.16 -> 1.17 # arch/sparc/kernel/process.c 1.24 -> 1.26 # fs/proc/task_mmu.c 1.2 -> 1.3 # drivers/acorn/scsi/scsi.h 1.5 -> 1.6 drivers/scsi/arm/scsi.h (moved) # include/asm-arm/arch-pxa/irqs.h 1.2 -> 1.3 # include/asm-v850/hardirq.h 1.2 -> 1.3 # drivers/i2c/i2c-core.c 1.32 -> 1.37 # drivers/net/tulip/xircom_tulip_cb.c 1.20 -> 1.21 # drivers/net/sk98lin/skge.c 1.15 -> 1.17 # drivers/char/agp/generic-3.0.c 1.9 -> (deleted) # arch/x86_64/kernel/apic.c 1.16 -> 1.17 # arch/ia64/hp/common/sba_iommu.c 1.11 -> 1.20 # arch/ppc64/kernel/rtas.c 1.9 -> 1.11 # drivers/ieee1394/video1394.c 1.34 -> 1.35 # arch/i386/Kconfig 1.56 -> 1.57 # drivers/isdn/hisax/elsa.c 1.37 -> 1.38 # net/ipv4/netfilter/ip_nat_core.c 1.22 -> 1.27 # include/asm-i386/uaccess.h 1.23 -> 1.25 # include/linux/nfsd/xdr4.h 1.9 -> 1.11 # drivers/cpufreq/proc_intf.c 1.1 -> 1.2 # include/linux/elf.h 1.22 -> 1.23 # drivers/media/video/saa7134/saa7134-i2c.c 1.7 -> 1.10 # arch/ia64/lib/do_csum.S 1.9 -> 1.10 # fs/reiserfs/do_balan.c 1.16 -> 1.17 # drivers/acpi/events/evxfregn.c 1.15 -> 1.16 # net/ipv4/netfilter/ip_nat_helper.c 1.12 -> 1.14 # include/acpi/acdebug.h 1.20 -> 1.21 # arch/x86_64/kernel/x8664_ksyms.c 1.13 -> 1.14 # drivers/net/arcnet/com20020-pci.c 1.12 -> 1.13 # net/x25/x25_proc.c 1.2 -> 1.3 # include/linux/tpqic02.h 1.3 -> 1.4 # net/ipx/af_ipx.c 1.29 -> 1.34 # drivers/media/video/saa7134/saa7134-video.c 1.6 -> 1.7 # net/ipv4/udp.c 1.35 -> 1.39 # net/sctp/ulpevent.c 1.14 -> 1.18 # net/ipv6/protocol.c 1.3 -> 1.5 # arch/i386/kernel/traps.c 1.51 -> 1.52 # drivers/char/drm/drm_memory.h 1.8 -> 1.9 # drivers/net/wan/cycx_x25.c 1.10 -> 1.18 # fs/devfs/base.c 1.87 -> 1.89 # drivers/net/hamradio/6pack.c 1.11 -> 1.13 # init/main.c 1.98 -> 1.99 # fs/intermezzo/sysctl.c 1.8 -> 1.9 # net/ipv4/netfilter/ipt_multiport.c 1.4 -> 1.5 # include/asm-i386/numnodes.h 1.3 -> 1.4 # drivers/scsi/fd_mcs.h 1.6 -> 1.7 # arch/ppc/kernel/pci-dma.c 1.4 -> 1.5 # arch/ia64/lib/copy_user.S 1.7 -> 1.8 # arch/mips/arc/misc.c 1.3 -> 1.4 # arch/i386/kernel/Makefile 1.39 -> 1.41 # net/ipv4/fib_semantics.c 1.10 -> 1.11 # fs/nfsd/nfsctl.c 1.33 -> 1.34 # drivers/scsi/g_NCR5380.c 1.17 -> 1.18 # include/linux/i2c.h 1.25 -> 1.30 # drivers/scsi/eata.h 1.18 -> 1.19 # net/ipv4/netfilter/ip_nat_proto_udp.c 1.1 -> 1.3 # drivers/usb/class/usblp.c 1.42 -> 1.45 # fs/stat.c 1.18 -> 1.19 # include/linux/signal.h 1.10 -> 1.11 # drivers/usb/Kconfig 1.2 -> 1.3 # include/net/bluetooth/l2cap.h 1.5 -> 1.7 # net/bluetooth/af_bluetooth.c 1.16 -> 1.18 # drivers/ieee1394/sbp2.h 1.17 -> 1.18 # drivers/pcmcia/sa11xx_core.c 1.1 -> 1.2 # drivers/ide/legacy/qd65xx.c 1.5 -> 1.6 # drivers/ide/legacy/umc8672.c 1.6 -> 1.7 # drivers/net/irda/sir_dongle.c 1.3 -> 1.4 # include/asm-i386/mach-summit/mach_ipi.h 1.2 -> 1.3 # drivers/scsi/dc390.h 1.5 -> 1.6 # drivers/char/drm/radeon_cp.c 1.18 -> 1.19 # include/asm-ia64/atomic.h 1.5 -> 1.6 # drivers/ide/legacy/ali14xx.c 1.5 -> 1.6 # fs/xfs/xfs_vfsops.c 1.32 -> 1.33 # arch/i386/vmlinux.lds.S 1.29 -> 1.30 # net/sctp/transport.c 1.16.1.1 -> 1.20 # drivers/scsi/scsi_sysfs.c 1.10 -> 1.16 # drivers/net/ixgb/ixgb_main.c 1.4 -> 1.5 # arch/arm/kernel/sys_arm.c 1.10 -> 1.11 # include/asm-x86_64/hardirq.h 1.3 -> 1.4 # drivers/net/tulip/winbond-840.c 1.31 -> 1.34 # fs/cifs/cifsglob.h 1.7 -> 1.9 # drivers/net/wan/sdla_ppp.c 1.22 -> 1.25 # include/linux/kmod.h 1.3 -> 1.4 # Documentation/video4linux/bttv/Cards 1.5 -> 1.6 # include/linux/cpu.h 1.5 -> 1.6 # drivers/media/dvb/dvb-core/dvbdev.c 1.8 -> 1.10 # mm/swapfile.c 1.77 -> 1.79 # net/sched/sch_teql.c 1.4 -> 1.6 # arch/x86_64/mm/init.c 1.16 -> 1.17 # include/asm-ppc64/sigcontext.h 1.3 -> 1.4 # include/linux/ipv6_route.h 1.1 -> 1.2 # drivers/net/wan/x25_asy.c 1.5 -> 1.6 # net/sctp/output.c 1.23 -> 1.30 # drivers/ide/pci/piix.h 1.6 -> 1.7 # net/sctp/Kconfig 1.3 -> 1.5 # fs/ioctl.c 1.8 -> 1.9 # kernel/cpufreq.c 1.29 -> 1.31 # drivers/video/cyber2000fb.c 1.28 -> 1.29 # drivers/char/cyclades.c 1.21 -> 1.22 # drivers/atm/nicstar.c 1.15 -> 1.17 # arch/ia64/kernel/time.c 1.19 -> 1.21 # include/asm-ia64/mca.h 1.6 -> 1.7 # net/atm/atm_misc.c 1.2 -> 1.3 # security/dummy.c 1.19 -> 1.20 # sound/core/seq/seq_device.c 1.10 -> 1.11 # drivers/net/ne2k-pci.c 1.10 -> 1.11 # include/linux/arcdevice.h 1.1 -> 1.2 # net/bridge/br_stp.c 1.5 -> 1.6 # fs/cifs/cifssmb.c 1.14 -> 1.15 # drivers/atm/eni.c 1.12 -> 1.14 # include/asm-ppc/pgtable.h 1.21 -> 1.22 # net/ipv6/netfilter/ip6t_frag.c 1.4 -> 1.5 # drivers/char/i8k.c 1.6 -> 1.7 # include/linux/blkdev.h 1.102 -> 1.105 # net/bridge/br_private.h 1.12 -> 1.13 # include/net/ip6_route.h 1.7 -> 1.8 # net/ipv6/xfrm6_policy.c 1.4 -> 1.6 # drivers/net/fc/iph5526.c 1.20 -> 1.21 # drivers/isdn/hardware/eicon/capimain.c 1.3 -> 1.4 # drivers/scsi/aacraid/aacraid.h 1.4 -> 1.7 # net/sched/cls_api.c 1.4 -> 1.5 # drivers/atm/zatm.c 1.11 -> 1.12 # drivers/block/cciss_scsi.c 1.12 -> 1.14 # drivers/acpi/tables/tbinstal.c 1.18 -> 1.19 # drivers/acpi/namespace/nsxfname.c 1.15 -> 1.16 # net/decnet/Makefile 1.5 -> 1.6 # drivers/acorn/scsi/acornscsi-io.S 1.1 -> 1.2 drivers/scsi/arm/acornscsi-io.S (moved) # drivers/serial/core.c 1.59 -> 1.60 # net/ipv4/devinet.c 1.14 -> 1.18 # drivers/scsi/3w-xxxx.h 1.20 -> 1.21 # include/asm-arm/mach/dma.h 1.2 -> 1.3 # include/asm-m68k/elf.h 1.2 -> 1.3 # include/media/audiochip.h 1.5 -> 1.6 # arch/x86_64/kernel/ioport.c 1.5 -> 1.6 # arch/i386/kernel/cpu/mtrr/if.c 1.5 -> 1.7 # drivers/scsi/ips.h 1.25 -> 1.29 # drivers/base/bus.c 1.44 -> 1.45 # drivers/net/rrunner.c 1.15 -> 1.16 # include/asm-ppc64/compat.h 1.12 -> 1.13 # net/ipv4/netfilter/ip_tables.c 1.14 -> 1.16 # drivers/usb/core/message.c 1.25 -> 1.27 # include/net/compat.h 1.3 -> 1.4 # include/linux/major.h 1.8 -> 1.9 # include/asm-sparc/smp.h 1.5 -> 1.6 # include/asm-i386/spinlock.h 1.9 -> 1.10 # sound/core/seq/oss/seq_oss_timer.c 1.2 -> 1.3 # net/bluetooth/sco.c 1.15 -> 1.17 # drivers/net/wan/comx-hw-munich.c 1.10 -> 1.11 # drivers/scsi/NCR5380.c 1.16 -> 1.17 # arch/ia64/kernel/smpboot.c 1.28 -> 1.32 # net/key/af_key.c 1.33 -> 1.37 # drivers/scsi/aha1740.c 1.14 -> 1.15 # drivers/net/starfire.c 1.26 -> 1.27 # drivers/scsi/sr.c 1.76 -> 1.78 # drivers/mtd/maps/sa1100-flash.c 1.9 -> 1.10 # arch/ppc64/kernel/LparData.c 1.8 -> 1.9 # net/bridge/br_input.c 1.10 -> 1.12 # drivers/scsi/scsi.h 1.75 -> 1.79 # drivers/net/irda/irtty.c 1.16 -> 1.18 # include/linux/fs.h 1.238 -> 1.244 # drivers/pcmcia/cs.c 1.26 -> 1.27 # drivers/scsi/ini9100u.c 1.14 -> 1.15 # drivers/atm/lanai.c 1.9 -> 1.10 # arch/ia64/kernel/entry.S 1.39 -> 1.40 # arch/i386/mm/ioremap.c 1.17 -> 1.18 # include/asm-ia64/hardirq.h 1.11 -> 1.12 # include/linux/capability.h 1.5 -> 1.6 # net/decnet/dn_table.c 1.5 -> 1.6 # Documentation/networking/3c509.txt 1.2 -> 1.3 # arch/ppc/kernel/module.c 1.7 -> 1.8 # include/linux/netfilter_ipv4/ip_nat_helper.h 1.4 -> 1.5 # drivers/scsi/t128.h 1.6 -> 1.7 # arch/i386/kernel/entry.S 1.61 -> 1.62 # drivers/block/paride/pt.c 1.15 -> 1.16 # Documentation/kobject.txt 1.5 -> 1.6 # fs/cifs/cifs_fs_sb.h 1.2 -> 1.3 # drivers/char/nwbutton.h 1.1 -> 1.2 # fs/xfs/linux/xfs_super.h 1.16 -> 1.19 # include/asm-x86_64/floppy.h 1.2 -> 1.3 # drivers/md/dm-ioctl.c 1.19 -> 1.21 # drivers/sgi/char/sgiserial.c 1.12 -> 1.14 # drivers/usb/image/scanner.c 1.57 -> 1.59 # include/asm-arm/arch-ebsa110/time.h 1.6 -> 1.7 # include/net/sctp/sctp.h 1.30 -> 1.37 # net/ipv6/netfilter/ip6t_rt.c 1.4 -> 1.5 # arch/x86_64/kernel/e820.c 1.4 -> 1.5 # net/bluetooth/hci_proc.c 1.2 -> 1.3 # fs/sysv/dir.c 1.14 -> 1.15 # net/bridge/br_private_timer.h 1.1 -> (deleted) # net/ipv4/tcp.c 1.38 -> 1.40 # drivers/char/ser_a2232.c 1.8 -> 1.9 # drivers/char/n_hdlc.c 1.14 -> 1.15 # drivers/net/pcnet32.c 1.33 -> 1.34 # fs/udf/dir.c 1.12 -> 1.13 # arch/i386/kernel/ptrace.c 1.19 -> 1.20 # Documentation/scsi/aic7xxx.txt 1.6 -> 1.7 # drivers/atm/nicstar.h 1.3 -> 1.5 # arch/sparc/kernel/smp.c 1.9 -> 1.10 # drivers/net/mace.c 1.13 -> 1.14 # include/acpi/actables.h 1.15 -> 1.16 # include/asm-ppc64/types.h 1.2 -> 1.3 # drivers/net/Makefile 1.58 -> 1.60 # arch/alpha/kernel/smp.c 1.34 -> 1.35 # drivers/acpi/events/evxfevnt.c 1.17 -> 1.18 # arch/x86_64/ia32/ptrace32.c 1.6 -> 1.7 # arch/x86_64/kernel/setup64.c 1.12 -> 1.13 # drivers/mtd/chips/cfi_cmdset_0001.c 1.6 -> 1.7 # drivers/char/vc_screen.c 1.9 -> 1.10 # drivers/ide/ide.c 1.59 -> 1.62 # net/ipv4/netfilter/ipt_physdev.c 1.4 -> 1.5 # drivers/md/md.c 1.166 -> 1.168 # arch/alpha/kernel/core_titan.c 1.15 -> 1.16 # include/linux/ip.h 1.8 -> 1.10 # fs/cifs/transport.c 1.7 -> 1.8 # arch/x86_64/ia32/Makefile 1.13 -> 1.14 # net/atm/proc.c 1.9 -> 1.15 # drivers/net/wan/comx-proto-fr.c 1.10 -> 1.11 # net/ipv4/ip_sockglue.c 1.15 -> 1.16 # drivers/scsi/advansys.c 1.31 -> 1.33 # drivers/scsi/ncr53c8xx.c 1.25 -> 1.27 # Documentation/driver-model/overview.txt 1.8 -> 1.9 # fs/cifs/link.c 1.4 -> 1.5 # arch/i386/kernel/reboot.c 1.7 -> 1.8 # drivers/ide/legacy/dtc2278.c 1.5 -> 1.6 # net/ipv6/icmp.c 1.26 -> 1.32 # drivers/scsi/inia100.c 1.21 -> 1.22 # drivers/i2c/busses/i2c-piix4.c 1.8 -> 1.10 # include/net/sctp/ulpqueue.h 1.9 -> 1.10 # kernel/kmod.c 1.25 -> 1.27 # net/ipv6/netfilter/ip6t_LOG.c 1.5 -> 1.6 # net/sunrpc/rpc_pipe.c 1.8 -> 1.10 # drivers/usb/media/se401.c 1.35 -> 1.36 # drivers/acpi/parser/psargs.c 1.17 -> 1.18 # net/atm/pvc.c 1.5 -> 1.8 # include/linux/wanrouter.h 1.5 -> 1.7 # arch/ppc64/kernel/ras.c 1.3 -> 1.4 # arch/ppc/ocp/Makefile 1.2 -> 1.3 # drivers/scsi/u14-34f.c 1.26 -> 1.28 # arch/mips/au1000/common/serial.c 1.15 -> 1.16 # net/ipv4/netfilter/ip_nat_tftp.c 1.2 -> 1.3 # mm/bootmem.c 1.15 -> 1.16 # arch/x86_64/kernel/ptrace.c 1.12 -> 1.13 # include/asm-arm/arch-nexuspci/time.h 1.4 -> 1.5 # arch/arm/kernel/entry-armv.S 1.30 -> 1.31 # arch/i386/kernel/mpparse.c 1.39 -> 1.41 # net/ipv6/reassembly.c 1.11 -> 1.12 # include/asm-ia64/uaccess.h 1.8 -> 1.9 # drivers/scsi/hosts.h 1.59 -> 1.63 # drivers/usb/media/ov511.c 1.43 -> 1.44 # drivers/char/agp/Makefile 1.19 -> 1.25 # arch/x86_64/kernel/mpparse.c 1.8 -> 1.9 # include/asm-ppc64/machdep.h 1.14 -> 1.16 # drivers/net/arcnet/com90io.c 1.6 -> 1.7 # net/ipv4/netfilter/ip_nat_proto_icmp.c 1.1 -> 1.3 # net/sctp/outqueue.c 1.26 -> 1.34 # include/linux/brlvger.h 1.3 -> 1.4 # net/ipv4/tcp_ipv4.c 1.51 -> 1.56 # drivers/media/video/saa7134/saa7134-core.c 1.4 -> 1.5 # drivers/media/video/tvaudio.c 1.17 -> 1.19 # fs/reiserfs/inode.c 1.74 -> 1.76 # arch/ppc/boot/openfirmware/Makefile 1.16 -> 1.17 # fs/xfs/linux/xfs_iops.c 1.22 -> 1.23 # arch/i386/kernel/io_apic.c 1.64 -> 1.67 # drivers/ide/ide-tape.c 1.22 -> 1.23 # fs/char_dev.c 1.13 -> 1.14 # net/8021q/vlanproc.c 1.9 -> 1.11 # drivers/hotplug/acpiphp_glue.c 1.8 -> 1.10 # include/asm-sparc64/elf.h 1.13 -> 1.14 # include/linux/sunrpc/rpc_pipe_fs.h 1.1 -> 1.2 # arch/sparc64/defconfig 1.84 -> 1.85 # drivers/usb/media/vicam.c 1.34 -> 1.36 # drivers/net/sunhme.c 1.32 -> 1.34 # net/decnet/dn_dev.c 1.10 -> 1.15 # include/net/sctp/constants.h 1.12 -> 1.14 # net/ipv4/netfilter/ipt_REDIRECT.c 1.4 -> 1.5 # include/linux/cycx_drv.h 1.1 -> 1.3 # mm/filemap.c 1.191 -> 1.193 # drivers/acpi/acpi_ksyms.c 1.23 -> 1.24 # drivers/scsi/pluto.c 1.10 -> 1.12 # include/linux/ppp_defs.h 1.1 -> 1.2 # net/bridge/netfilter/ebtables.c 1.8 -> 1.9 # drivers/isdn/hisax/hisax_hfcpci.c 1.8 -> 1.9 # net/decnet/dn_nsp_in.c 1.9 -> 1.10 # fs/namei.c 1.71 -> 1.72 # arch/s390/kernel/traps.c 1.17 -> 1.18 # net/ipv4/netfilter/ipt_ULOG.c 1.7 -> 1.8 # drivers/isdn/hisax/avm_pci.c 1.42 -> 1.43 # arch/sparc64/solaris/socksys.c 1.11 -> 1.12 # fs/coda/sysctl.c 1.9 -> 1.10 # fs/xfs/xfs_mount.c 1.27 -> 1.30 # drivers/char/pcmcia/synclink_cs.c 1.15 -> 1.16 # drivers/hotplug/cpqphp_ctrl.c 1.9.1.1 -> 1.11 # arch/s390/math-emu/math.c 1.6 -> 1.7 # drivers/char/agp/generic.c 1.25 -> 1.51 # drivers/isdn/i4l/isdn_common.c 1.73 -> 1.74 # drivers/pci/pci.h 1.2 -> 1.4 # drivers/mtd/chips/chipreg.c 1.4 -> 1.5 # arch/ia64/ia32/ia32_traps.c 1.4 -> 1.5 # arch/i386/Makefile 1.50 -> 1.51 # net/socket.c 1.56 -> 1.62 # drivers/scsi/ncr53c8xx.h 1.11 -> 1.12 # include/asm-ia64/processor.h 1.34 -> 1.36 # arch/x86_64/kernel/entry.S 1.11 -> 1.12 # drivers/isdn/i4l/isdn_x25iface.c 1.4 -> 1.5 # drivers/char/synclink.c 1.34 -> 1.35 # drivers/scsi/gdth.h 1.11 -> 1.12 # drivers/scsi/sgiwd93.h 1.2 -> 1.3 # drivers/ide/pci/serverworks.h 1.4 -> 1.5 # drivers/scsi/aacraid/commctrl.c 1.1 -> 1.2 # net/atm/ipcommon.c 1.1 -> 1.2 # drivers/scsi/aic7xxx/aic7xxx_osm.h 1.34.1.1 -> 1.44 # include/asm-ppc/spinlock.h 1.11 -> 1.12 # drivers/scsi/qlogicfc.h 1.8 -> 1.9 # arch/ia64/hp/zx1/hpzx1_machvec.c 1.3 -> 1.4 # drivers/net/e1000/e1000_main.c 1.64 -> 1.65 # net/xfrm/xfrm_algo.c 1.9 -> 1.10 # arch/arm/mach-pxa/lubbock.c 1.9 -> 1.10 # arch/cris/drivers/eeprom.c 1.10 -> 1.11 # drivers/isdn/hardware/eicon/divasi.c 1.5 -> 1.6 # drivers/char/agp/sworks-agp.c 1.22 -> 1.32 # ipc/sem.c 1.17 -> 1.18 # include/linux/brlock.h 1.8 -> (deleted) # drivers/net/irda/w83977af_ir.c 1.16 -> 1.18 # drivers/base/base.h 1.25 -> 1.26 # drivers/scsi/fd_mcs.c 1.11 -> 1.13 # arch/i386/kernel/dmi_scan.c 1.32 -> 1.34 # drivers/media/video/bttvp.h 1.10 -> 1.11 # include/linux/sysfs.h 1.25 -> 1.26 # net/sctp/proc.c 1.2 -> 1.3 # include/asm-x86_64/pda.h 1.8 -> 1.9 # drivers/net/irda/sa1100_ir.c 1.9 -> 1.12 # crypto/autoload.c 1.6 -> 1.7 # include/linux/ide.h 1.48 -> 1.52 # drivers/scsi/nsp32.c 1.10 -> 1.11 # drivers/char/rio/riotty.c 1.8 -> 1.9 # drivers/net/hp100.c 1.16 -> 1.17 # drivers/net/yellowfin.c 1.21 -> 1.22 # fs/exec.c 1.80 -> 1.82 # include/asm-ia64/machvec_sn2.h 1.7 -> 1.8 # arch/i386/mach-voyager/voyager_smp.c 1.11 -> 1.14 # include/asm-ppc64/proc_fs.h 1.1 -> 1.2 # net/ipv4/netfilter/ip_fw_compat.c 1.15 -> 1.18 # drivers/scsi/aacraid/linit.c 1.15 -> 1.18 # drivers/usb/storage/transport.c 1.68 -> 1.71 # net/sunrpc/clnt.c 1.34 -> 1.37 # drivers/acorn/scsi/fas216.c 1.15 -> 1.19 drivers/scsi/arm/fas216.c (moved) # drivers/net/pcmcia/xirc2ps_cs.c 1.17 -> 1.18 # drivers/char/ftape/zftape/zftape-init.c 1.17 -> 1.18 # net/netlink/netlink_dev.c 1.15 -> 1.17 # drivers/isdn/hisax/niccy.c 1.29 -> 1.30 # fs/nfsd/vfs.c 1.60 -> 1.61 # arch/i386/kernel/suspend_asm.S 1.4 -> 1.6 # net/ipv6/raw.c 1.23 -> 1.29 # arch/ia64/kernel/irq_ia64.c 1.11 -> 1.12 # include/linux/sem.h 1.5 -> 1.6 # drivers/usb/image/scanner.h 1.33 -> 1.35 # kernel/signal.c 1.80 -> 1.83 # drivers/usb/storage/transport.h 1.21 -> 1.23 # drivers/scsi/cpqfcTS.h 1.7 -> 1.8 # include/linux/net.h 1.15 -> 1.16 # drivers/net/irda/ali-ircc.c 1.16 -> 1.18 # drivers/scsi/atp870u.c 1.19 -> 1.20 # net/ipv6/proc.c 1.11 -> 1.14 # drivers/char/keyboard.c 1.30 -> 1.31 # drivers/usb/misc/auerswald.c 1.29 -> 1.31 # arch/um/kernel/mem.c 1.15 -> 1.16 # net/ipv4/netfilter/ip_nat_rule.c 1.9 -> 1.10 # drivers/acpi/tables/tbconvrt.c 1.20 -> 1.22 # drivers/message/fusion/mptscsih.c 1.22 -> 1.23 # include/acpi/acpi_bus.h 1.14 -> 1.15 # net/netsyms.c 1.66 -> 1.75 # net/ipv4/netfilter/ipfwadm_core.c 1.14 -> 1.16 # drivers/char/sx.c 1.28 -> 1.29 # net/ipv6/xfrm6_state.c 1.3 -> 1.6 # drivers/media/video/dpc7146.c 1.1 -> 1.2 # include/asm-i386/mach-bigsmp/mach_ipi.h 1.1 -> 1.2 # include/asm-sparc/io-unit.h 1.1 -> 1.2 # include/linux/pci_ids.h 1.91.1.1 -> 1.101 # drivers/ide/ide-disk.c 1.40 -> 1.44 # drivers/usb/serial/usb-serial.c 1.77 -> 1.78 # drivers/scsi/aic7xxx_old.c 1.48 -> 1.49 # drivers/net/dl2k.c 1.26 -> 1.27 # drivers/scsi/sym53c8xx.h 1.12 -> 1.13 # fs/xattr.c 1.13 -> 1.14 # drivers/acpi/scan.c 1.16 -> 1.18 # include/asm-x86_64/io.h 1.6 -> 1.7 # drivers/hotplug/Kconfig 1.6 -> 1.7 # include/linux/moduleloader.h 1.5 -> 1.6 # include/asm-ia64/system.h 1.34 -> 1.35 # drivers/usb/input/hid-input.c 1.16 -> 1.17 # include/asm-i386/mach-numaq/mach_apic.h 1.14 -> 1.16 # Documentation/driver-model/binding.txt 1.2 -> 1.3 # drivers/acorn/scsi/acornscsi.h 1.4 -> 1.6 drivers/scsi/arm/acornscsi.h (moved) # include/net/protocol.h 1.9 -> 1.10 # arch/arm/kernel/traps.c 1.26 -> 1.27 # include/asm-x86_64/pci.h 1.6 -> 1.7 # drivers/scsi/ultrastor.h 1.5 -> 1.6 # drivers/char/dtlk.c 1.11 -> 1.12 # drivers/usb/input/hiddev.c 1.31 -> 1.33 # arch/ia64/mm/init.c 1.33 -> 1.35 # mm/shmem.c 1.117 -> 1.119 # drivers/char/agp/agp.h 1.49 -> 1.72 # arch/i386/kernel/msr.c 1.11 -> 1.12 # drivers/acpi/utilities/utcopy.c 1.23 -> 1.24 # arch/x86_64/ia32/sys_ia32.c 1.31 -> 1.32 # arch/x86_64/kernel/irq.c 1.13 -> 1.15 # arch/sparc64/kernel/process.c 1.41 -> 1.42 # include/asm-mips/elf.h 1.4 -> 1.5 # drivers/mtd/chips/cfi_cmdset_0002.c 1.7 -> 1.8 # Documentation/networking/ip-sysctl.txt 1.15 -> 1.16 # include/linux/usb.h 1.75 -> 1.77 # drivers/net/hamradio/dmascc.c 1.11 -> 1.13 # drivers/char/serial167.c 1.21 -> 1.22 # drivers/media/video/tda9875.c 1.12 -> 1.14 # drivers/net/sis900.c 1.35 -> 1.36 # include/asm-i386/mach-summit/mach_mpparse.h 1.5 -> 1.6 # arch/x86_64/kernel/pci-gart.c 1.9 -> 1.10 # arch/ppc64/kernel/irq.c 1.23 -> 1.25 # drivers/net/irda/donauboe.c 1.5 -> 1.7 # arch/sparc/mm/init.c 1.19 -> 1.20 # include/linux/input.h 1.29 -> 1.30 # drivers/scsi/aacraid/aachba.c 1.10 -> 1.14 # arch/ia64/hp/zx1/hpzx1_misc.c 1.13 -> (deleted) # net/sched/sch_api.c 1.8 -> 1.9 # drivers/scsi/seagate.c 1.17 -> 1.18 # drivers/input/mouse/rpcmouse.c 1.13 -> 1.14 # drivers/net/wan/comx.c 1.16 -> 1.18 # drivers/isdn/hardware/avm/b1isa.c 1.21 -> 1.22 # arch/x86_64/ia32/ia32entry.S 1.19 -> 1.20 # drivers/ide/ide-cd.c 1.43 -> 1.45 # fs/fat/inode.c 1.63 -> 1.64 # drivers/net/tun.c 1.15 -> 1.17 # fs/super.c 1.100 -> 1.102 # arch/ia64/pci/pci.c 1.26 -> 1.29 # arch/ia64/hp/sim/simscsi.c 1.12 -> 1.13 # drivers/atm/Kconfig 1.3 -> 1.5 # include/asm-ia64/serial.h 1.2 -> 1.3 # fs/binfmt_elf.c 1.44 -> 1.45 # include/net/sctp/sm.h 1.21 -> 1.24 # fs/reiserfs/super.c 1.59 -> 1.60 # net/core/dv.c 1.5 -> 1.6 # arch/i386/kernel/signal.c 1.31 -> 1.32 # mm/memory.c 1.123 -> 1.124 # drivers/scsi/BusLogic.h 1.13 -> 1.14 # drivers/scsi/sg.c 1.52 -> 1.56 # drivers/char/riscom8.c 1.14 -> 1.15 # drivers/usb/serial/pl2303.c 1.39 -> 1.40 # net/sched/sch_atm.c 1.9 -> 1.10 # arch/ia64/kernel/ia64_ksyms.c 1.21 -> 1.23 # drivers/scsi/aic7xxx/aic7xxx_core.c 1.27 -> 1.28 # include/asm-arm/arch-pxa/time.h 1.4 -> 1.5 # fs/sysfs/symlink.c 1.2 -> 1.4 # include/linux/blkpg.h 1.4 -> 1.5 # drivers/scsi/aacraid/dpcsup.c 1.1 -> 1.3 # lib/inflate.c 1.2 -> 1.4 # arch/sparc/kernel/entry.S 1.11 -> 1.13 # drivers/net/epic100.c 1.30 -> 1.31 # drivers/usb/usb-skeleton.c 1.32 -> 1.36 # drivers/usb/serial/ir-usb.c 1.27 -> 1.28 # arch/ia64/kernel/efivars.c 1.10 -> 1.11 # net/core/netfilter.c 1.18 -> 1.20 # drivers/net/8139cp.c 1.37 -> 1.38 # drivers/net/acenic.c 1.28 -> 1.31 # drivers/usb/core/hub.c 1.62 -> 1.63 # arch/ppc64/kernel/rtas-proc.c 1.4 -> 1.6 # drivers/usb/net/catc.c 1.22 -> 1.23 # crypto/md5.c 1.9 -> 1.10 # drivers/net/acenic.h 1.13 -> 1.14 # drivers/net/arcnet/rfc1201.c 1.3 -> 1.5 # drivers/block/genhd.c 1.84 -> 1.85 # net/irda/irda_device.c 1.16 -> 1.17 # arch/ppc64/kernel/setup.c 1.21.1.1 -> 1.24 # drivers/net/e100/e100_main.c 1.61 -> 1.62 # arch/ia64/kernel/mca.c 1.22 -> 1.29 # Documentation/pci.txt 1.8 -> 1.9 # drivers/scsi/aic7xxx/aic79xx_pci.c 1.9 -> 1.10 # include/linux/pci.h 1.71 -> 1.77 # drivers/scsi/aic7xxx/aic79xx_inline.h 1.7 -> 1.10 # arch/ia64/kernel/iosapic.c 1.23 -> 1.27 # arch/i386/kernel/acpi/sleep.c 1.2 -> 1.3 # arch/i386/kernel/ioport.c 1.7 -> 1.8 # arch/um/drivers/net_kern.c 1.9 -> 1.11 # arch/i386/kernel/setup.c 1.79 -> 1.82 # arch/arm/tools/mach-types 1.27 -> 1.28 # drivers/scsi/osst.c 1.42 -> 1.44 # fs/cifs/cifs_debug.c 1.8 -> 1.10 # arch/ia64/kernel/process.c 1.30 -> 1.34 # drivers/scsi/pci2220i.h 1.5 -> 1.6 # net/wanrouter/wanproc.c 1.15 -> 1.19 # fs/ncpfs/ncplib_kernel.c 1.10 -> 1.11 # drivers/atm/idt77252.c 1.10 -> 1.13 # drivers/usb/core/hcd-pci.c 1.13 -> 1.14 # arch/i386/kernel/smpboot.c 1.57 -> 1.61 # net/ipv4/netfilter/ipt_ecn.c 1.2 -> 1.3 # drivers/scsi/scsi_debug.h 1.12 -> 1.15 # arch/ppc/kernel/process.c 1.32 -> 1.34 # include/asm-m68k/hardirq.h 1.3 -> 1.4 # drivers/net/wan/cycx_main.c 1.8 -> 1.14 # arch/i386/kernel/module.c 1.10 -> 1.11 # net/ipv4/fib_hash.c 1.11 -> 1.14 # drivers/acpi/utilities/utdelete.c 1.18 -> 1.19 # drivers/media/video/saa7134/saa7134-oss.c 1.4 -> 1.5 # net/ipv4/ipmr.c 1.17 -> 1.19 # arch/i386/kernel/cpu/cpufreq/gx-suspmod.c 1.7 -> 1.8 # include/asm-arm/processor.h 1.13 -> 1.14 # drivers/scsi/AM53C974.c 1.12 -> 1.13 # drivers/input/serio/sa1111ps2.c 1.7 -> 1.9 # drivers/char/tpqic02.c 1.22 -> 1.23 # arch/ia64/hp/sim/simserial.c 1.15 -> 1.16 # fs/nfs/dir.c 1.54 -> 1.55 # drivers/char/agp/intel-agp.c 1.26 -> 1.42 # arch/ia64/kernel/acpi.c 1.36 -> 1.40 # arch/x86_64/mm/pageattr.c 1.4 -> 1.5 # drivers/acpi/dispatcher/dsmethod.c 1.16 -> 1.17 # include/asm-ppc64/naca.h 1.5 -> 1.6 # drivers/acorn/scsi/msgqueue.c 1.4 -> 1.5 drivers/scsi/arm/msgqueue.c (moved) # arch/ia64/kernel/machvec.c 1.4 -> 1.5 # include/asm-ia64/kmap_types.h 1.4 -> 1.5 # net/econet/af_econet.c 1.17 -> 1.18 # drivers/scsi/scsi_syms.c 1.32 -> 1.36 # drivers/input/joydev.c 1.17 -> 1.18 # drivers/net/wan/sdla_chdlc.c 1.23 -> 1.27 # drivers/net/rclanmtl.h 1.7 -> 1.8 # sound/oss/soundcard.c 1.15 -> 1.17 # drivers/ide/pci/sis5513.c 1.14 -> 1.15 # drivers/i2c/busses/i2c-i801.c 1.8 -> 1.9 # drivers/media/video/video-buf.c 1.9 -> 1.10 # include/linux/spinlock.h 1.22 -> 1.23 # drivers/scsi/scsi_lib.c 1.84 -> 1.90 # include/net/dn_fib.h 1.3 -> 1.6 # fs/sysfs/bin.c 1.4 -> 1.5 # include/linux/tty.h 1.15 -> 1.16 # drivers/acpi/namespace/nsutils.c 1.22 -> 1.24 # drivers/usb/input/xpad.c 1.13 -> 1.14 # net/netlink/af_netlink.c 1.23 -> 1.24 # ipc/shm.c 1.25 -> 1.27 # include/asm-alpha/elf.h 1.4 -> 1.5 # include/asm-i386/mmzone.h 1.11 -> 1.12 # include/asm-arm/arch-anakin/time.h 1.4 -> 1.5 # drivers/net/wan/dlci.c 1.9 -> 1.10 # drivers/ide/arm/icside.c 1.6 -> 1.9 # drivers/scsi/dmx3191d.h 1.5 -> 1.6 # net/sunrpc/pmap_clnt.c 1.6 -> 1.7 # net/core/dev.c 1.68 -> 1.81 # drivers/ide/legacy/pdc4030.c 1.8 -> 1.9 # net/xfrm/xfrm_policy.c 1.24 -> 1.27 # drivers/net/irda/irda-usb.c 1.36 -> 1.38 # include/asm-x86_64/i387.h 1.8 -> 1.9 # drivers/ide/ide-dma.c 1.13 -> 1.15 # arch/x86_64/kernel/io_apic.c 1.8 -> 1.9 # net/ipv6/Kconfig 1.3 -> 1.4 # fs/ext3/hash.c 1.1 -> 1.2 # sound/core/seq/oss/seq_oss_device.h 1.2 -> 1.3 # include/linux/cyclomx.h 1.2 -> 1.8 # drivers/scsi/scsi.c 1.106 -> 1.112 # drivers/char/mem.c 1.35 -> 1.37 # drivers/usb/core/usb.c 1.122 -> 1.123 # drivers/usb/misc/brlvger.c 1.16 -> 1.17 # drivers/i2c/busses/i2c-ali15x3.c 1.7 -> 1.8 # arch/ppc64/kernel/traps.c 1.14 -> 1.16 # drivers/char/dsp56k.c 1.12 -> 1.13 # drivers/block/cciss_scsi.h 1.2 -> 1.3 # net/bridge/br_stp_timer.c 1.3 -> 1.4 # drivers/net/r8169.c 1.9 -> 1.10 # kernel/posix-timers.c 1.15 -> 1.16 # net/ipv4/netfilter/ipt_TCPMSS.c 1.8 -> 1.9 # net/ipv4/netfilter/ipt_esp.c 1.5 -> 1.6 # arch/ppc64/kernel/head.S 1.26 -> 1.31 # drivers/acpi/namespace/nsalloc.c 1.16 -> 1.17 # include/linux/reiserfs_fs_sb.h 1.20 -> 1.21 # drivers/net/depca.c 1.18 -> 1.19 # drivers/usb/host/ohci-sa1111.c 1.14 -> 1.15 # arch/sparc/kernel/traps.c 1.5 -> 1.6 # arch/arm/lib/copy_page.S 1.3 -> 1.4 # arch/ia64/mm/hugetlbpage.c 1.10 -> 1.11 # drivers/isdn/hardware/eicon/divamnt.c 1.5 -> 1.6 # Documentation/driver-model/device.txt 1.2 -> 1.3 # Documentation/driver-model/interface.txt 1.2 -> 1.3 # include/asm-ppc64/xics.h 1.4 -> 1.5 # drivers/scsi/pluto.h 1.6 -> 1.7 # drivers/scsi/aha1542.c 1.25 -> 1.27 # drivers/s390/char/tubio.h 1.11 -> 1.12 # drivers/acorn/scsi/acornscsi.c 1.25 -> 1.30 drivers/scsi/arm/acornscsi.c (moved) # Documentation/driver-model/driver.txt 1.4 -> 1.5 # drivers/acorn/scsi/arxescsi.c 1.16 -> 1.19 drivers/scsi/arm/arxescsi.c (moved) # fs/nfs/symlink.c 1.7 -> 1.8 # net/ipv4/netfilter/ip_nat_proto_unknown.c 1.2 -> 1.3 # arch/ia64/dig/machvec.c 1.1 -> 1.2 # drivers/pci/pci.ids 1.43 -> 1.44 # net/decnet/af_decnet.c 1.24 -> 1.25 # arch/x86_64/ia32/ia32_ioctl.c 1.22 -> 1.24 # drivers/scsi/ultrastor.c 1.16 -> 1.18 # sound/pci/emu10k1/emufx.c 1.18 -> 1.19 # drivers/scsi/ini9100u.h 1.9 -> 1.10 # sound/core/seq/oss/seq_oss_timer.h 1.1 -> 1.2 # drivers/scsi/pcmcia/qlogic_stub.c 1.14 -> 1.15 # drivers/char/serial_tx3912.c 1.12 -> 1.13 # drivers/scsi/megaraid.h 1.17 -> 1.18 # drivers/acpi/events/evgpeblk.c 1.5 -> 1.7 # net/ipv4/netfilter/ipt_MARK.c 1.3 -> 1.4 # include/asm-parisc/kmap_types.h 1.2 -> 1.3 # crypto/md4.c 1.6 -> 1.7 # drivers/net/pcmcia/ibmtr_cs.c 1.12 -> 1.13 # drivers/scsi/aic7xxx/aiclib.c 1.4 -> 1.5 # fs/ext3/dir.c 1.10 -> 1.14 # arch/i386/mm/highmem.c 1.3 -> 1.4 # include/asm-x86_64/suspend.h 1.4 -> 1.5 # include/media/video-buf.h 1.7 -> 1.8 # arch/ia64/sn/kernel/machvec.c 1.4 -> 1.5 # drivers/acorn/scsi/queue.h 1.3 -> 1.4 drivers/scsi/arm/queue.h (moved) # drivers/scsi/aic7xxx/aic7xxx.h 1.12 -> 1.13 # include/linux/msg.h 1.3 -> 1.4 # include/linux/netfilter_ipv4/ip_tables.h 1.4 -> 1.5 # fs/xfs/xfs_log_recover.c 1.17 -> 1.23 # drivers/usb/net/usbnet.c 1.51 -> 1.52 # net/bluetooth/rfcomm/tty.c 1.19 -> 1.20 # drivers/usb/image/mdc800.c 1.29 -> 1.30 # include/asm-h8300/hardirq.h 1.1 -> 1.2 # include/asm-ia64/machvec.h 1.13 -> 1.14 # include/asm-ia64/intrinsics.h 1.5 -> 1.7 # fs/ext2/dir.c 1.21 -> 1.22 # include/linux/nfsd/export.h 1.28 -> 1.29 # include/asm-ia64/unwind.h 1.4 -> 1.5 # drivers/scsi/NCR_D700.h 1.2 -> 1.3 # fs/pipe.c 1.24 -> 1.26 # include/linux/wait.h 1.12 -> 1.13 # net/sunrpc/sched.c 1.25 -> 1.26 # include/linux/sunrpc/svc.h 1.19 -> 1.20 # include/asm-i386/apicdef.h 1.7 -> 1.8 # arch/x86_64/kernel/asm-offsets.c 1.2 -> 1.3 # fs/lockd/host.c 1.5 -> 1.6 # drivers/input/input.c 1.30 -> 1.31 # include/acpi/acmacros.h 1.21 -> 1.22 # fs/cifs/cifsfs.c 1.11 -> 1.14 # drivers/acpi/ec.c 1.23 -> 1.24 # drivers/media/video/v4l1-compat.c 1.1 -> 1.2 # arch/ia64/hp/sim/hpsim_machvec.c 1.2 -> 1.3 # include/linux/netfilter_ipv4/ip_nat_protocol.h 1.1 -> 1.2 # include/linux/sysctl.h 1.43 -> 1.44 # drivers/isdn/hardware/avm/c4.c 1.34 -> 1.35 # arch/ppc64/kernel/xics.c 1.19 -> 1.22 # arch/ia64/ia32/ia32_entry.S 1.23 -> 1.24 # drivers/net/tg3.c 1.68 -> 1.69 # include/linux/smp.h 1.22 -> 1.23 # fs/reiserfs/dir.c 1.18 -> 1.19 # include/linux/list.h 1.28 -> 1.29 # net/bridge/br_private_stp.h 1.3 -> 1.4 # drivers/scsi/aic7xxx/aic79xx_osm.c 1.29 -> 1.42 # arch/x86_64/kernel/process.c 1.16 -> 1.17 # net/ipv4/raw.c 1.30 -> 1.31 # drivers/i2c/busses/i2c-isa.c 1.2 -> 1.3 # fs/nfsd/nfssvc.c 1.34 -> 1.36 # include/linux/mmzone.h 1.36 -> 1.37 # arch/v850/kernel/module.c 1.4 -> 1.5 # Documentation/BK-usage/bk-kernel-howto.txt 1.5 -> 1.6 # net/ipv6/tcp_ipv6.c 1.52 -> 1.55 # net/ipv6/af_inet6.c 1.32 -> 1.42 # drivers/char/ipmi/ipmi_msghandler.c 1.4 -> 1.6 # drivers/sbus/char/vfc_dev.c 1.10 -> 1.11 # include/asm-ia64/iosapic.h 1.9 -> 1.10 # drivers/net/sungem.h 1.10 -> 1.11 # arch/ppc/kernel/l2cr.S 1.7 -> 1.8 # drivers/net/wireless/wavelan_cs.c 1.20 -> 1.22 # drivers/net/slip.h 1.2 -> 1.3 # fs/ext3/xattr.c 1.14 -> 1.15 # include/asm-ia64/perfmon.h 1.12 -> 1.13 # kernel/pid.c 1.8 -> 1.9 # net/sched/sch_csz.c 1.10 -> 1.11 # drivers/char/mwave/mwavedd.h 1.3 -> 1.4 # fs/Kconfig 1.23 -> 1.25 # net/sunrpc/cache.c 1.13 -> 1.14 # drivers/mtd/chips/sharp.c 1.5 -> 1.6 # drivers/net/amd8111e.c 1.3 -> 1.4 # net/xfrm/xfrm_user.c 1.19 -> 1.20 # drivers/usb/media/dabusb.c 1.27 -> 1.28 # arch/i386/oprofile/init.c 1.5 -> 1.6 # fs/buffer.c 1.198 -> 1.200 # arch/sparc/mm/srmmu.c 1.32 -> 1.33 # drivers/block/loop.c 1.86 -> 1.87 # mm/vmalloc.c 1.24 -> 1.26 # drivers/pnp/resource.c 1.11 -> 1.12 # drivers/char/agp/Kconfig 1.15 -> 1.21 # arch/ia64/kernel/signal.c 1.22 -> 1.24 # include/asm-arm/arch-arc/time.h 1.4 -> 1.5 # net/ipv4/esp.c 1.28 -> 1.29 # drivers/usb/input/hid-core.c 1.54 -> 1.56 # arch/ppc/syslib/open_pic.c 1.24 -> 1.25 # drivers/scsi/dmx3191d.c 1.11 -> 1.12 # drivers/ide/ide-probe.c 1.41 -> 1.46 # drivers/usb/core/hcd.c 1.61 -> 1.63 # drivers/video/logo/logo.c 1.5 -> 1.6 # fs/nfsd/export.c 1.79 -> 1.80 # drivers/acpi/events/evxface.c 1.20 -> 1.21 # drivers/scsi/aacraid/sa.c 1.3 -> 1.4 # drivers/usb/serial/belkin_sa.c 1.34 -> 1.35 # include/acpi/actypes.h 1.25 -> 1.27 # drivers/acpi/events/evmisc.c 1.22 -> 1.23 # include/acpi/acevents.h 1.17 -> 1.18 # fs/ext3/namei.c 1.37 -> 1.38 # arch/ppc64/kernel/htab.c 1.32 -> 1.33 # arch/ppc64/mm/init.c 1.40 -> 1.42 # arch/ppc64/kernel/open_pic.c 1.11 -> 1.13 # drivers/scsi/aha1740.h 1.5 -> 1.6 # drivers/net/wan/cycx_drv.c 1.3 -> 1.7 # drivers/scsi/ppa.c 1.20 -> 1.21 # drivers/acpi/events/evgpe.c 1.12 -> 1.13 # include/linux/skbuff.h 1.22 -> 1.23 # include/linux/ext3_fs.h 1.23 -> 1.24 # drivers/acorn/net/ether1.c 1.9 -> 1.12 drivers/net/arm/ether1.c (moved) # include/asm-i386/smp.h 1.23 -> 1.24 # include/asm-i386/types.h 1.4 -> 1.5 # drivers/char/tty_io.c 1.90 -> 1.95 # drivers/scsi/pcmcia/fdomain_stub.c 1.15 -> 1.16 # drivers/isdn/hardware/avm/t1isa.c 1.27 -> 1.28 # drivers/char/agp/i460-agp.c 1.16 -> 1.25 # drivers/net/tulip/tulip_core.c 1.41 -> 1.43 # arch/x86_64/pci/irq.c 1.7 -> 1.8 # include/asm-arm/arch-shark/time.h 1.7 -> 1.8 # drivers/acpi/executer/exconfig.c 1.17 -> 1.18 # net/ipv6/ndisc.c 1.33 -> 1.38 # fs/bio.c 1.42 -> 1.43 # drivers/char/pcxx.c 1.10 -> 1.11 # include/acpi/achware.h 1.14 -> 1.15 # arch/ppc64/kernel/process.c 1.30 -> 1.32 # arch/ppc/boot/Makefile 1.15 -> 1.16 # net/rxrpc/proc.c 1.2 -> 1.4 # drivers/ieee1394/amdtp.c 1.12 -> 1.13 # net/sctp/ipv6.c 1.29.1.6 -> 1.41 # net/sctp/protocol.c 1.40.1.2 -> 1.48 # MAINTAINERS 1.136 -> 1.139 # drivers/net/sundance.c 1.41 -> 1.42 # drivers/s390/char/tubfs.c 1.16 -> 1.17 # drivers/usb/net/rtl8150.c 1.22 -> 1.24 # arch/x86_64/lib/copy_user.S 1.3 -> 1.4 # fs/jffs/inode-v23.c 1.44 -> 1.45 # include/asm-arm/arch-l7200/time.h 1.5 -> 1.6 # net/core/dst.c 1.10 -> 1.12 # net/ipv6/netfilter/ip6t_esp.c 1.4 -> 1.5 # net/ipv4/netfilter/ipt_unclean.c 1.9 -> 1.10 # arch/ppc64/kernel/pci_dma.c 1.11 -> 1.14 # include/asm-generic/rmap.h 1.4 -> 1.5 # Documentation/driver-model/bus.txt 1.3 -> 1.4 # kernel/exec_domain.c 1.13 -> 1.14 # net/irda/irlap_event.c 1.20 -> 1.21 # drivers/scsi/scsi_debug.c 1.32 -> 1.37 # include/linux/cpufreq.h 1.23 -> 1.24 # drivers/char/rio/rio_linux.c 1.19 -> 1.20 # arch/ia64/ia32/sys_ia32.c 1.49.1.1 -> 1.55 # net/compat.c 1.7 -> 1.9 # fs/reiserfs/prints.c 1.21 -> 1.22 # include/linux/if_ether.h 1.5 -> 1.6 # drivers/media/video/msp3400.c 1.17 -> 1.19 # drivers/char/istallion.c 1.20 -> 1.22 # net/atm/lec.c 1.17 -> 1.22 # include/acpi/aclocal.h 1.29 -> 1.31 # drivers/scsi/aic7xxx/aic79xx_osm.h 1.22 -> 1.29 # drivers/char/raw.c 1.31 -> 1.32 # net/ipv4/netfilter/ipt_MASQUERADE.c 1.7 -> 1.8 # drivers/ieee1394/eth1394.c 1.12 -> 1.13 # mm/mmap.c 1.79 -> 1.81 # arch/s390/kernel/s390_ksyms.c 1.11 -> 1.12 # fs/proc/base.c 1.42 -> 1.43 # arch/ia64/hp/sim/simeth.c 1.5 -> 1.7 # fs/nls/nls_base.c 1.9 -> 1.10 # drivers/telephony/phonedev.c 1.5 -> 1.6 # fs/xfs/linux/xfs_globals.c 1.13 -> 1.14 # drivers/scsi/gdth.c 1.26 -> 1.27 # include/asm-sparc64/compat.h 1.13 -> 1.14 # fs/ext2/xattr.c 1.12 -> 1.13 # drivers/acorn/net/Makefile 1.5 -> 1.7 drivers/net/arm/Makefile (moved) # net/unix/af_unix.c 1.42 -> 1.44 # drivers/message/i2o/i2o_core.c 1.19 -> 1.20 # include/linux/time.h 1.13 -> 1.14 # fs/read_write.c 1.30 -> 1.31 # fs/coda/psdev.c 1.16 -> 1.17 # scripts/ver_linux 1.8 -> 1.9 # include/asm-alpha/spinlock.h 1.6 -> 1.7 # net/ipv6/esp6.c 1.14 -> 1.16 # drivers/net/typhoon.c 1.4 -> 1.5 # arch/x86_64/ia32/syscall32.c 1.3 -> 1.4 # net/ipv4/netfilter/ipt_ah.c 1.5 -> 1.6 # drivers/usb/class/cdc-acm.c 1.38 -> 1.40 # drivers/usb/misc/rio500.c 1.20 -> 1.21 # arch/sparc64/kernel/module.c 1.12 -> 1.14 # include/asm-i386/mach-summit/mach_apic.h 1.22 -> 1.25 # drivers/usb/input/hid-tmff.c 1.1 -> 1.2 # net/sctp/command.c 1.6 -> 1.7 # include/asm-alpha/hardirq.h 1.7 -> 1.8 # drivers/net/arcnet/rfc1051.c 1.3 -> 1.4 # net/bluetooth/rfcomm/sock.c 1.15 -> 1.17 # drivers/scsi/st.c 1.60 -> 1.62 # include/linux/if_wanpipe_common.h 1.4 -> 1.5 # drivers/scsi/ide-scsi.c 1.23 -> 1.24 # fs/cifs/md5.c 1.2 -> 1.3 # arch/sparc/kernel/asm-offsets.c 1.1 -> 1.2 # fs/qnx4/dir.c 1.6 -> 1.7 # arch/ppc64/kernel/open_pic_defs.h 1.1 -> 1.2 # drivers/scsi/eata_pio.c 1.16 -> 1.17 # drivers/acpi/tables/tbget.c 1.18 -> 1.19 # include/asm-i386/unistd.h 1.24 -> 1.25 # include/linux/futex.h 1.6 -> 1.7 # fs/reiserfs/bitmap.c 1.25 -> 1.26 # drivers/net/eepro100.c 1.60 -> 1.61 # fs/namespace.c 1.39 -> 1.43 # net/atm/svc.c 1.5 -> 1.9 # drivers/char/agp/ali-agp.c 1.15 -> 1.25 # include/linux/wanpipe.h 1.6 -> 1.8 # drivers/char/agp/alpha-agp.c 1.3 -> 1.8 # include/linux/wireless.h 1.7 -> 1.8 # drivers/acorn/scsi/powertec.c 1.21 -> 1.25 drivers/scsi/arm/powertec.c (moved) # drivers/atm/atmtcp.c 1.6 -> 1.7 # drivers/usb/host/ehci-hcd.c 1.47 -> 1.49 # fs/nfs/file.c 1.27 -> 1.28 # drivers/scsi/mesh.c 1.7 -> 1.8 # drivers/acpi/utilities/utobject.c 1.17 -> 1.18 # include/asm-ia64/ptrace.h 1.9 -> 1.10 # arch/x86_64/kernel/sys_x86_64.c 1.7 -> 1.8 # include/asm-x86_64/calling.h 1.4 -> 1.5 # drivers/net/wan/comx-hw-locomx.c 1.6 -> 1.7 # sound/oss/cs4281/cs4281pm-24.c 1.3 -> 1.4 # net/sctp/sm_sideeffect.c 1.36.1.1 -> 1.43 # drivers/scsi/pci2000.c 1.15 -> 1.16 # arch/x86_64/kernel/head.S 1.11 -> 1.12 # net/atm/pppoatm.c 1.5 -> 1.6 # drivers/input/serio/ambakmi.c 1.3 -> 1.5 # arch/ppc64/kernel/asm-offsets.c 1.12 -> 1.13 # include/net/ax25.h 1.9 -> 1.10 # Makefile 1.405 -> 1.406 # drivers/acpi/events/evregion.c 1.17 -> 1.19 # fs/fcntl.c 1.25 -> 1.26 # fs/ext2/xattr.h 1.5 -> 1.7 # include/asm-x86_64/e820.h 1.4 -> 1.5 # include/asm-ia64/pal.h 1.5 -> 1.6 # include/asm-ia64/machvec_sn1.h 1.8 -> 1.9 # arch/ia64/kernel/head.S 1.9 -> 1.10 # net/packet/af_packet.c 1.23 -> 1.26 # drivers/net/pcmcia/fmvj18x_cs.c 1.19 -> 1.20 # drivers/scsi/sym53c8xx.c 1.33 -> 1.34 # drivers/net/irda/irport.c 1.15 -> 1.17 # drivers/char/agp/amd-k8-agp.c 1.30 -> 1.41 # drivers/scsi/aic7xxx/aic79xx.h 1.10 -> 1.11 # drivers/scsi/ibmmca.h 1.7 -> 1.8 # arch/mips64/arc/misc.c 1.2 -> 1.3 # drivers/net/pcmcia/smc91c92_cs.c 1.17 -> 1.18 # sound/core/sound.c 1.25 -> 1.27 # fs/dquot.c 1.60 -> 1.61 # mm/page-writeback.c 1.62 -> 1.64 # net/sunrpc/xprt.c 1.53 -> 1.59 # include/asm-ppc64/mmu.h 1.6 -> 1.7 # net/ipv6/ah6.c 1.14 -> 1.17 # include/asm-i386/elf.h 1.8 -> 1.9 # include/net/ip.h 1.17 -> 1.21 # net/bluetooth/bnep/core.c 1.16 -> 1.17 # net/core/pktgen.c 1.3 -> 1.4 # drivers/scsi/psi240i.c 1.9 -> 1.10 # drivers/char/mxser.c 1.21 -> 1.22 # net/decnet/dn_neigh.c 1.5 -> 1.7 # drivers/i2c/i2c-keywest.c 1.1 -> 1.2 # drivers/net/arcnet/arcnet.c 1.9 -> 1.11 # arch/x86_64/defconfig 1.19 -> 1.20 # arch/ppc64/mm/numa.c 1.2 -> 1.4 # net/bluetooth/l2cap.c 1.24 -> 1.28 # arch/x86_64/kernel/acpi/wakeup.S 1.1 -> 1.2 # include/asm-x86_64/debugreg.h 1.2 -> 1.3 # drivers/mtd/mtdchar.c 1.12 -> 1.13 # net/ipv4/netfilter/ipt_dscp.c 1.2 -> 1.3 # Documentation/driver-model/porting.txt 1.1 -> 1.2 # drivers/scsi/pas16.h 1.6 -> 1.7 # drivers/char/rocket.c 1.19 -> 1.20 # drivers/video/console/fbcon.c 1.100 -> 1.101 # drivers/acpi/resources/rsxface.c 1.15 -> 1.16 # include/net/sctp/tsnmap.h 1.6 -> 1.7 # net/sctp/inqueue.c 1.6 -> 1.9 # drivers/scsi/aha1542.h 1.7 -> 1.8 # net/wanrouter/wanmain.c 1.12 -> 1.15 # arch/x86_64/kernel/signal.c 1.16 -> 1.17 # drivers/char/agp/backend.c 1.72 -> 1.83 # drivers/net/wan/sdla_x25.c 1.21 -> 1.24 # arch/ppc64/kernel/syscalls.c 1.9 -> 1.10 # include/linux/netfilter_ipv4/compat_firewall.h 1.1 -> 1.2 # include/asm-x86_64/thread_info.h 1.10 -> 1.11 # arch/i386/kernel/ldt.c 1.12 -> 1.13 # lib/brlock.c 1.6 -> (deleted) # include/asm-ppc64/ptrace.h 1.1 -> 1.2 # drivers/char/rio/rio_linux.h 1.3 -> 1.4 # fs/xfs/Makefile 1.12 -> 1.15 # drivers/media/video/cpia.c 1.24 -> 1.25 # drivers/net/fealnx.c 1.25 -> 1.26 # arch/ppc64/kernel/sys_ppc32.c 1.53.1.5 -> 1.59 # include/linux/ipv6.h 1.6 -> 1.8 # drivers/char/vt_ioctl.c 1.22 -> 1.24 # net/sunrpc/xdr.c 1.13 -> 1.14 # drivers/pci/pci-driver.c 1.21 -> 1.26 # drivers/net/arcnet/com90xx.c 1.6 -> 1.7 # drivers/video/riva/fbdev.c 1.45 -> 1.46 # drivers/isdn/sc/init.c 1.6 -> 1.7 # net/decnet/TODO 1.4 -> 1.5 # CREDITS 1.81 -> 1.83 # drivers/pci/probe.c 1.38 -> 1.39 # include/media/tuner.h 1.8 -> 1.9 # include/asm-sparc64/hardirq.h 1.13 -> 1.15 # drivers/isdn/tpam/tpam_main.c 1.8 -> 1.9 # drivers/media/video/tda7432.c 1.10 -> 1.12 # drivers/net/wireless/wavelan.p.h 1.11 -> 1.12 # fs/nfsd/nfs4state.c 1.1 -> 1.3 # fs/seq_file.c 1.9 -> 1.11 # drivers/scsi/aacraid/commsup.c 1.3 -> 1.5 # net/ipv4/netfilter/ip_fw_compat_redir.c 1.5 -> 1.6 # fs/xfs/xfs_ag.h 1.3 -> 1.4 # include/asm-x86_64/compat.h 1.11 -> 1.13 # drivers/video/console/fbcon.h 1.30 -> 1.31 # fs/lockd/mon.c 1.8 -> 1.9 # net/ipv6/ipv6_syms.c 1.12 -> 1.13 # drivers/scsi/dtc.c 1.9 -> 1.10 # drivers/usb/net/kaweth.c 1.39 -> 1.40 # arch/ppc64/kernel/prom.c 1.22 -> 1.25 # drivers/char/tipar.c 1.6 -> 1.7 # include/asm-i386/kmap_types.h 1.13 -> 1.14 # drivers/acorn/scsi/cumana_2.c 1.22 -> 1.27 drivers/scsi/arm/cumana_2.c (moved) # kernel/module.c 1.80 -> 1.82 # net/core/skbuff.c 1.25 -> 1.26 # net/xfrm/xfrm_state.c 1.23 -> 1.26 # include/asm-x86_64/pgtable.h 1.18 -> 1.19 # include/linux/security.h 1.16 -> 1.18 # drivers/acpi/parser/pswalk.c 1.12 -> 1.13 # arch/ia64/kernel/salinfo.c 1.2 -> 1.3 # drivers/isdn/pcbit/drv.c 1.10 -> 1.12 # drivers/isdn/act2000/module.c 1.9 -> 1.10 # drivers/media/video/saa7134/saa7134-reg.h 1.1 -> 1.2 # drivers/ieee1394/dv1394.c 1.30 -> 1.31 # include/net/sock.h 1.37 -> 1.39 # fs/xfs/xfs_inode.h 1.14 -> 1.15 # drivers/input/evdev.c 1.24 -> 1.25 # drivers/scsi/in2000.c 1.18 -> 1.19 # drivers/i2c/busses/i2c-viapro.c 1.2 -> 1.3 # drivers/scsi/qlogicfc.c 1.31 -> 1.32 # arch/ppc64/kernel/iSeries_setup.c 1.10.1.1 -> 1.12 # include/asm-ppc64/elf.h 1.9 -> 1.10 # include/asm-ia64/dma-mapping.h 1.1 -> 1.2 # net/core/sock.c 1.24 -> 1.25 # drivers/net/wan/sdlamain.c 1.16 -> 1.18 # arch/ia64/lib/swiotlb.c 1.14 -> 1.16 # net/ipv4/sysctl_net_ipv4.c 1.9 -> 1.10 # include/asm-ppc/pci.h 1.15 -> 1.16 # include/asm-parisc/elf.h 1.4 -> 1.5 # drivers/media/video/saa7134/saa7134.h 1.4 -> 1.5 # arch/ia64/kernel/perfmon_mckinley.h 1.5 -> 1.6 # Documentation/scsi/aic79xx.txt 1.7 -> 1.8 # include/linux/sunrpc/xprt.h 1.23 -> 1.24 # include/linux/shm.h 1.4 -> 1.5 # include/linux/cycx_x25.h 1.1 -> 1.2 # include/linux/devfs_fs_kernel.h 1.44 -> 1.46 # drivers/char/drm/drmP.h 1.23 -> 1.24 # include/asm-arm/bugs.h 1.2 -> 1.3 # arch/ppc64/kernel/smp.c 1.31.2.1 -> 1.35 # net/atm/common.h 1.3 -> 1.4 # net/ipv6/ip6_input.c 1.11 -> 1.12 # fs/nfs/write.c 1.39 -> 1.40 # arch/x86_64/kernel/Makefile 1.19 -> 1.20 # net/ipv4/netfilter/ipt_helper.c 1.3 -> 1.4 # drivers/media/video/bt832.c 1.2 -> 1.3 # fs/ext2/Makefile 1.8 -> 1.9 # net/ipx/Makefile 1.9 -> 1.10 # include/asm-ia64/sn/addrs.h 1.4 -> 1.5 # arch/ia64/ia32/ia32_ioctl.c 1.8 -> 1.9 # net/ipv4/ip_gre.c 1.24 -> 1.25 # include/net/ip6_fib.h 1.3 -> 1.5 # arch/sparc/defconfig 1.16 -> 1.17 # drivers/char/stallion.c 1.21 -> 1.23 # drivers/serial/21285.c 1.18 -> 1.19 # drivers/media/video/saa5249.c 1.14 -> 1.15 # drivers/usb/class/bluetty.c 1.40 -> 1.41 # net/ipv6/route.c 1.26 -> 1.40 # drivers/isdn/hisax/hisax_fcpcipnp.c 1.17 -> 1.18 # include/acpi/acconfig.h 1.36 -> 1.39 # drivers/scsi/sym53c416.h 1.6 -> 1.7 # drivers/acpi/tables/tbgetall.c 1.10 -> 1.11 # net/ipv4/netfilter/ipt_length.c 1.2 -> 1.3 # include/asm-ia64/percpu.h 1.6 -> 1.7 # include/linux/nfs.h 1.3 -> 1.4 # net/decnet/dn_rules.c 1.5 -> 1.6 # drivers/scsi/sd.c 1.108 -> 1.113 # arch/ppc64/mm/fault.c 1.9 -> 1.10 # arch/i386/mm/init.c 1.47 -> 1.48 # net/ipv4/tcp_minisocks.c 1.27 -> 1.31 # include/asm-i386/i387.h 1.11 -> 1.12 # fs/minix/dir.c 1.13 -> 1.14 # include/asm-arm/arch-integrator/time.h 1.5 -> 1.6 # sound/oss/i810_audio.c 1.37 -> 1.38 # drivers/bluetooth/hci_ldisc.c 1.9 -> 1.10 # net/ipv6/Makefile 1.12 -> 1.13 # drivers/sgi/char/shmiq.c 1.9 -> 1.10 # drivers/usb/input/hid-lgff.c 1.3 -> 1.4 # arch/ppc64/kernel/pacaData.c 1.5 -> 1.6 # drivers/block/DAC960.c 1.57 -> 1.59 # drivers/block/DAC960.h 1.20 -> 1.21 # drivers/net/am79c961a.c 1.10 -> 1.11 drivers/net/arm/am79c961a.c (moved) # net/ipv4/Kconfig 1.6 -> 1.7 # drivers/scsi/aic7xxx/aic79xx_proc.c 1.6 -> 1.9 # drivers/usb/host/uhci-hcd.h 1.8 -> 1.9 # drivers/usb/storage/unusual_devs.h 1.33 -> 1.38 # drivers/i2c/chips/it87.c 1.3 -> 1.10 # drivers/i2c/i2c-dev.c 1.27 -> 1.30 # net/atm/signaling.c 1.5 -> 1.8 # arch/ia64/kernel/brl_emu.c 1.5 -> 1.6 # include/linux/module.h 1.62 -> 1.63 # net/sched/sch_ingress.c 1.12 -> 1.13 # net/core/wireless.c 1.9 -> 1.12 # net/ipv4/netfilter/ip_conntrack_ftp.c 1.11 -> 1.12 # arch/alpha/kernel/irq.c 1.20 -> 1.21 # drivers/net/tulip/xircom_cb.c 1.12 -> 1.13 # mm/slab.c 1.75 -> 1.80 # net/ipv4/netfilter/arp_tables.c 1.6 -> 1.7 # arch/i386/kernel/suspend.c 1.14 -> 1.16 # fs/nfs/inode.c 1.76 -> 1.77 # include/linux/bio.h 1.28 -> 1.29 # include/linux/socket.h 1.8 -> 1.9 # drivers/block/elevator.c 1.40 -> 1.42 # net/atm/mpoa_proc.c 1.5 -> 1.6 # fs/xfs/xfsidbg.c 1.26 -> 1.27 # net/ipv4/netfilter/ip_nat_standalone.c 1.22 -> 1.24 # include/net/bluetooth/rfcomm.h 1.6 -> 1.8 # arch/arm/mm/consistent.c 1.10 -> 1.11 # drivers/acpi/tables/tbutils.c 1.18 -> 1.19 # fs/filesystems.c 1.14 -> 1.16 # drivers/scsi/scsi_scan.c 1.80 -> 1.85 # arch/x86_64/Kconfig 1.18 -> 1.19 # include/linux/rtnetlink.h 1.10 -> 1.15 # include/linux/msdos_fs.h 1.22 -> 1.23 # net/ipv4/netfilter/ip_fw_compat_masq.c 1.7 -> 1.10 # kernel/sched.c 1.180 -> 1.185 # drivers/net/rcpci45.c 1.20 -> 1.21 # include/linux/agp_backend.h 1.27 -> 1.37 # drivers/scsi/seagate.h 1.5 -> 1.6 # include/asm-sparc/elf.h 1.6 -> 1.7 # include/linux/smp_lock.h 1.5 -> 1.6 # net/8021q/vlan.c 1.15 -> 1.17 # net/sctp/adler32.c 1.6.1.1 -> 1.8 # drivers/char/agp/hp-agp.c 1.16 -> 1.24 # crypto/tcrypt.c 1.22 -> 1.23 # drivers/block/deadline-iosched.c 1.17 -> 1.20 # drivers/Makefile 1.32 -> 1.33 # net/atm/resources.h 1.2 -> 1.3 # drivers/acpi/parser/psxface.c 1.16 -> 1.17 # drivers/ide/arm/rapide.c 1.4 -> 1.5 # net/ipv6/ip6_fib.c 1.11 -> 1.18 # drivers/scsi/Makefile 1.41 -> 1.43 # drivers/net/tulip/de2104x.c 1.16 -> 1.19 # drivers/usb/host/ehci-q.c 1.45 -> 1.47 # drivers/ide/legacy/ht6560b.c 1.5 -> 1.6 # net/sctp/ssnmap.c 1.1 -> 1.2 # include/linux/netfilter_ipv4/ipfwadm_core.h 1.1 -> 1.2 # drivers/s390/char/tubtty.c 1.10 -> 1.11 # drivers/acpi/osl.c 1.34 -> 1.36 # drivers/net/cs89x0.c 1.16 -> 1.17 # init/Kconfig 1.13 -> 1.14 # include/asm-x86_64/elf.h 1.5 -> 1.6 # drivers/usb/storage/sddr09.c 1.23 -> 1.24 # include/linux/divert.h 1.1 -> 1.2 # include/net/ipv6.h 1.11 -> 1.14 # drivers/ieee1394/iso.c 1.4 -> 1.5 # scripts/Makefile.build 1.34 -> 1.36 # arch/um/kernel/irq.c 1.7 -> 1.8 # drivers/scsi/sim710.c 1.11 -> 1.12 # arch/ia64/kernel/gate.S 1.14 -> 1.15 # net/sctp/crc32c.c 1.5 -> 1.6 # net/atm/mpc.c 1.10 -> 1.15 # drivers/s390/char/tuball.c 1.11 -> 1.12 # drivers/ide/ide-io.c 1.8 -> 1.11 # drivers/scsi/dpt_i2o.c 1.27 -> 1.29 # fs/ufs/dir.c 1.13 -> 1.14 # drivers/net/wireless/wavelan_cs.p.h 1.6 -> 1.8 # net/ipv6/udp.c 1.28 -> 1.35 # drivers/char/drm/drm_drv.h 1.17 -> 1.18 # drivers/hotplug/cpqphp.h 1.6.1.1 -> 1.9 # arch/x86_64/mm/numa.c 1.2 -> 1.3 # drivers/i2c/busses/i2c-amd8111.c 1.7 -> 1.8 # include/linux/atmdev.h 1.8 -> 1.13 # arch/sparc64/kernel/sparc64_ksyms.c 1.47 -> 1.48 # net/ipv4/netfilter/ipt_REJECT.c 1.14 -> 1.15 # include/asm-x86_64/system.h 1.14 -> 1.15 # drivers/usb/serial/console.c 1.2 -> 1.4 # drivers/acpi/dispatcher/dsopcode.c 1.19 -> 1.20 # include/net/xfrm.h 1.34 -> 1.39 # arch/ia64/hp/sim/hpsim_console.c 1.6 -> 1.7 # kernel/timer.c 1.52 -> 1.53 # fs/nfsd/nfs4xdr.c 1.14 -> 1.15 # arch/x86_64/kernel/reboot.c 1.3 -> 1.5 # drivers/usb/serial/visor.h 1.19 -> 1.20 # include/asm-i386/suspend.h 1.8 -> 1.9 # drivers/media/video/tuner.c 1.17 -> 1.20 # drivers/char/agp/via-agp.c 1.33 -> 1.44 # Documentation/driver-model/platform.txt 1.2 -> 1.3 # arch/um/kernel/sys_call_table.c 1.19 -> 1.20 # include/linux/netfilter_ipv4.h 1.4 -> 1.5 # drivers/tc/zs.c 1.14 -> 1.16 # drivers/char/ipmi/ipmi_devintf.c 1.7 -> 1.8 # drivers/acpi/hardware/hwregs.c 1.22 -> 1.23 # drivers/block/paride/pg.c 1.15 -> 1.16 # include/linux/pfkeyv2.h 1.5 -> 1.6 # net/sctp/bind_addr.c 1.14 -> 1.16 # arch/m68knommu/platform/5249/MOTOROLA/crt0_ram.S 1.1 -> 1.2 # include/asm-i386/mach-default/mach_mpparse.h 1.3 -> 1.4 # fs/cifs/cifspdu.h 1.5 -> 1.6 # drivers/scsi/aic7xxx/aic79xx.seq 1.8 -> 1.10 # drivers/media/video/saa7134/saa7134-cards.c 1.4 -> 1.5 # net/ipv4/netfilter/ipchains_core.c 1.13 -> 1.15 # drivers/scsi/ppa.h 1.7 -> 1.8 # drivers/scsi/aacraid/Makefile 1.5 -> 1.7 # arch/ppc/boot/utils/Makefile 1.5 -> (deleted) # arch/ppc/boot/common/dummy.c 1.2 -> (deleted) # drivers/ieee1394/ohci1394.c 1.34 -> 1.36 # drivers/char/hvc_console.c 1.13.1.4 -> 1.17 # drivers/char/vt.c 1.43 -> 1.45 # drivers/i2c/busses/i2c-amd756.c 1.6 -> 1.7 # drivers/usb/host/ehci.h 1.19 -> 1.20 # drivers/scsi/AM53C974.h 1.3 -> 1.4 # fs/fat/misc.c 1.13 -> 1.14 # include/net/atmclip.h 1.1 -> 1.2 # drivers/net/Kconfig 1.25 -> 1.27 # drivers/i2c/busses/Kconfig 1.10 -> 1.11 # arch/ppc64/kernel/pci.c 1.29 -> 1.30 # arch/ppc64/xmon/xmon.c 1.24 -> 1.26 # drivers/char/sysrq.c 1.26 -> 1.27 # net/ipv4/ipcomp.c 1.4 -> 1.10 # net/ipv6/mcast.c 1.18 -> 1.20 # drivers/scsi/eata.c 1.30 -> 1.31 # drivers/char/drm/Kconfig 1.4 -> 1.5 # net/ipv4/arp.c 1.19 -> 1.24 # drivers/isdn/hisax/config.c 1.46 -> 1.47 # drivers/acorn/net/etherh.c 1.13 -> 1.15 drivers/net/arm/etherh.c (moved) # include/asm-i386/ipc.h 1.2 -> 1.3 # include/asm-x86_64/user.h 1.4 -> 1.5 # arch/ppc64/kernel/misc.S 1.52.2.3 -> 1.57 # net/ipv4/netfilter/ipt_LOG.c 1.6 -> 1.7 # arch/ia64/kernel/mca_asm.S 1.6 -> 1.8 # fs/cifs/CHANGES 1.14 -> 1.16 # arch/s390/kernel/compat_exec.c 1.1 -> 1.2 # kernel/exit.c 1.100 -> 1.101 # arch/ia64/kernel/irq.c 1.20 -> 1.23 # arch/alpha/kernel/process.c 1.26 -> 1.27 # include/net/flow.h 1.5 -> 1.7 # net/sched/Kconfig 1.3 -> 1.4 # arch/x86_64/Makefile 1.25 -> 1.26 # include/asm-x86_64/apic.h 1.5 -> 1.6 # arch/arm/mach-pxa/irq.c 1.6 -> 1.7 # arch/ppc/kernel/entry.S 1.26 -> 1.27 # drivers/ieee1394/iso.h 1.2 -> 1.3 # drivers/usb/input/pid.c 1.6 -> 1.7 # drivers/scsi/psi240i.h 1.4 -> 1.5 # net/netrom/nr_loopback.c 1.3 -> 1.4 # drivers/usb/host/uhci-hcd.c 1.33 -> 1.35 # drivers/char/specialix.c 1.14 -> 1.15 # arch/sparc64/kernel/power.c 1.12 -> 1.13 # arch/s390/kernel/module.c 1.7 -> 1.8 # net/ipv6/netfilter/ip6_tables.c 1.17 -> 1.18 # include/linux/reiserfs_fs.h 1.46 -> 1.47 # net/bridge/br_stp_if.c 1.6 -> 1.7 # drivers/net/tulip/dmfe.c 1.30 -> 1.31 # include/asm-sparc/bitops.h 1.10 -> 1.11 # arch/x86_64/kernel/bluesmoke.c 1.9 -> 1.10 # include/asm-arm/mach/arch.h 1.7 -> 1.8 # include/asm-x86_64/ia32.h 1.13 -> 1.14 # arch/alpha/kernel/ptrace.c 1.13 -> 1.14 # include/asm-i386/mach-default/mach_ipi.h 1.1 -> 1.2 # arch/sparc/kernel/sclow.S 1.4 -> 1.5 # fs/bfs/dir.c 1.18 -> 1.19 # arch/sparc64/kernel/ioctl32.c 1.61 -> 1.62 # net/bridge/netfilter/ebtable_filter.c 1.5 -> 1.6 # drivers/scsi/pcmcia/aha152x_stub.c 1.14 -> 1.15 # arch/ppc/kernel/Makefile 1.36 -> 1.37 # drivers/media/video/tvmixer.c 1.13 -> 1.16 # fs/hugetlbfs/inode.c 1.22 -> 1.23 # arch/x86_64/kernel/module.c 1.7 -> 1.9 # net/appletalk/atalk_proc.c 1.2 -> 1.3 # arch/m68k/sun3/prom/init.c 1.1 -> 1.2 # fs/ext3/super.c 1.60 -> 1.61 # drivers/scsi/Kconfig 1.20 -> 1.21 # drivers/scsi/t128.c 1.10 -> 1.11 # include/asm-ia64/bitops.h 1.12 -> 1.13 # arch/ppc/boot/prep/Makefile 1.16 -> 1.18 # scripts/kconfig/menu.c 1.4 -> 1.5 # arch/ia64/tools/print_offsets.c 1.16 -> 1.17 # drivers/acpi/tables/tbxface.c 1.16 -> 1.17 # arch/ia64/kernel/unaligned.c 1.11 -> 1.12 # drivers/scsi/u14-34f.h 1.15 -> 1.16 # fs/ntfs/inode.c 1.104 -> 1.105 # include/linux/device.h 1.86.1.1 -> 1.91 # include/asm-arm/elf.h 1.5 -> 1.6 # drivers/net/wireless/wavelan.c 1.15 -> 1.17 # include/asm-s390/elf.h 1.5 -> 1.6 # fs/cifs/connect.c 1.14 -> 1.16 # include/net/ip_fib.h 1.8 -> 1.10 # arch/parisc/hpux/wrappers.S 1.2 -> 1.3 # net/ipv4/netfilter/ipt_conntrack.c 1.4 -> 1.5 # arch/ppc/kernel/ppc_ksyms.c 1.38 -> 1.39 # lib/kobject.c 1.19.1.1 -> 1.21 # drivers/pci/Makefile 1.25.1.1 -> 1.28 # arch/i386/kernel/cpu/cpufreq/p4-clockmod.c 1.15 -> 1.16 # drivers/usb/serial/cyberjack.c 1.26 -> 1.27 # arch/ppc64/kernel/signal32.c 1.38 -> 1.39 # scripts/kconfig/conf.c 1.4 -> 1.5 # drivers/acorn/net/Kconfig 1.1 -> 1.3 drivers/net/arm/Kconfig (moved) # include/linux/ipx.h 1.2 -> 1.3 # fs/partitions/check.c 1.109 -> 1.112 # drivers/net/ppp_deflate.c 1.9 -> 1.10 # drivers/input/mousedev.c 1.24 -> 1.25 # arch/arm/common/sa1111.c 1.24 -> 1.25 # arch/ppc/kernel/misc.S 1.42 -> 1.43 # drivers/scsi/pci2000.h 1.6 -> 1.7 # fs/xfs/linux/xfs_super.c 1.40 -> 1.44 # include/asm-ia64/pci.h 1.14 -> 1.16 # drivers/pci/hotplug.c 1.12 -> 1.14 # arch/alpha/kernel/sys_titan.c 1.10 -> 1.11 # arch/i386/mm/hugetlbpage.c 1.35 -> 1.36 # Documentation/Changes 1.33 -> 1.34 # drivers/scsi/aic7xxx/aic79xx.reg 1.8 -> 1.10 # drivers/acpi/namespace/nsload.c 1.18 -> 1.19 # drivers/net/setup.c 1.6 -> 1.12 # arch/ppc64/kernel/rtas_flash.c 1.4 -> 1.5 # include/asm-parisc/hardirq.h 1.2 -> 1.3 # arch/i386/kernel/i8259.c 1.22 -> 1.23 # net/ipv6/sit.c 1.23 -> 1.24 # arch/x86_64/kernel/ldt.c 1.8 -> 1.9 # arch/x86_64/kernel/pci-dma.c 1.5 -> 1.6 # drivers/acpi/dispatcher/dsinit.c 1.8 -> 1.9 # drivers/acorn/char/pcf8583.c 1.7 -> 1.8 # arch/ia64/ia32/binfmt_elf32.c 1.11 -> 1.12 # drivers/isdn/eicon/eicon_pci.c 1.4 -> 1.5 # drivers/char/misc.c 1.18 -> 1.20 # net/irda/irlap.c 1.18 -> 1.19 # net/sched/sch_sfq.c 1.9 -> 1.10 # fs/intermezzo/methods.c 1.8 -> 1.9 # include/asm-x86_64/segment.h 1.7 -> 1.8 # net/atm/raw.c 1.2 -> 1.3 # net/ipv6/addrconf.c 1.38 -> 1.45 # drivers/bluetooth/hci_usb.c 1.26 -> 1.28 # drivers/scsi/3w-xxxx.c 1.31 -> 1.32 # arch/ia64/kernel/perfmon.c 1.41 -> 1.43 # drivers/char/moxa.c 1.17 -> 1.18 # net/ipv4/netfilter/ipt_owner.c 1.6 -> 1.8 # crypto/Kconfig 1.12 -> 1.14 # drivers/hotplug/cpqphp_pci.c 1.16 -> 1.18 # drivers/acorn/net/ether3.h 1.1 -> 1.2 drivers/net/arm/ether3.h (moved) # drivers/net/ppp_generic.c 1.24 -> 1.30 # drivers/isdn/hisax/diva.c 1.41 -> 1.42 # include/asm-ia64/compat.h 1.11 -> 1.12 # net/core/Makefile 1.13 -> 1.15 # arch/x86_64/mm/ioremap.c 1.9 -> 1.10 # net/sctp/ulpqueue.c 1.17.1.1 -> 1.22 # drivers/media/video/saa7134/saa7134-vbi.c 1.4 -> 1.5 # fs/locks.c 1.40 -> 1.41 # include/asm-i386/mach-bigsmp/mach_apic.h 1.8 -> 1.11 # net/ipv4/icmp.c 1.27 -> 1.29 # include/linux/efi.h 1.1 -> 1.2 # arch/ppc/kernel/smp.c 1.32 -> 1.34 # drivers/usb/Makefile 1.41 -> 1.43 # net/atm/resources.c 1.8 -> 1.9 # include/linux/netdevice.h 1.33 -> 1.37 # drivers/macintosh/apm_emu.c 1.5 -> 1.6 # fs/ext3/xattr.h 1.6 -> 1.8 # drivers/isdn/hisax/st5481_init.c 1.7 -> 1.8 # drivers/net/pcmcia/3c589_cs.c 1.16 -> 1.17 # drivers/scsi/BusLogic.c 1.17 -> 1.19 # arch/ia64/Kconfig 1.20 -> 1.21 # drivers/scsi/sgiwd93.c 1.7 -> 1.8 # kernel/panic.c 1.10 -> 1.12 # mm/truncate.c 1.9 -> 1.10 # include/asm-ia64/sal.h 1.15 -> 1.16 # include/asm-ppc64/mmzone.h 1.9 -> 1.10 # net/decnet/dn_route.c 1.15 -> 1.16 # drivers/atm/iphase.c 1.18 -> 1.21 # drivers/isdn/capi/capi.c 1.40 -> 1.42 # drivers/usb/misc/usbtest.c 1.14 -> 1.15 # net/ipv4/netfilter/ipt_DSCP.c 1.2 -> 1.3 # net/ipv4/netfilter/ipt_tos.c 1.3 -> 1.4 # include/asm-ppc64/io.h 1.7 -> 1.8 # drivers/acorn/scsi/ecoscsi.c 1.14 -> 1.16 drivers/scsi/arm/ecoscsi.c (moved) # drivers/usb/input/usbkbd.c 1.28 -> 1.29 # drivers/input/tsdev.c 1.10 -> 1.11 # drivers/char/sh-sci.c 1.18 -> 1.19 # drivers/pci/bus.c 1.3 -> 1.4 # sound/core/info.c 1.24 -> 1.26 # arch/i386/kernel/timers/timer.c 1.6 -> 1.7 # fs/cifs/TODO 1.4 -> 1.5 # drivers/net/sungem.c 1.34 -> 1.36 # arch/ia64/kernel/traps.c 1.28 -> 1.29 # include/sound/seq_kernel.h 1.5 -> 1.6 # drivers/acpi/namespace/nssearch.c 1.18 -> 1.19 # arch/ia64/kernel/sal.c 1.5 -> 1.6 # drivers/net/arcnet/arc-rawmode.c 1.3 -> 1.4 # net/bridge/br_netfilter.c 1.9 -> 1.10 # drivers/scsi/scsi_ioctl.c 1.16 -> 1.17 # include/net/if_inet6.h 1.6 -> 1.7 # drivers/video/radeonfb.c 1.26 -> 1.27 # drivers/net/ns83820.c 1.21 -> 1.25 # arch/ia64/mm/fault.c 1.13 -> 1.14 # fs/xfs/xfs_buf.h 1.11 -> 1.12 # fs/xfs/xfs_iget.c 1.14 -> 1.15 # fs/xfs/xfs_inode.c 1.21 -> 1.23 # drivers/net/wan/comx-hw-mixcom.c 1.9 -> 1.10 # drivers/macintosh/macserial.c 1.20 -> 1.21 # drivers/usb/serial/io_ti.c 1.16 -> 1.17 # sound/sound_core.c 1.17 -> 1.19 # crypto/deflate.c 1.3 -> 1.4 # drivers/isdn/hardware/eicon/i4lididrv.c 1.6 -> 1.7 # include/asm-ppc/highmem.h 1.11 -> 1.12 # drivers/net/wireless/netwave_cs.c 1.15 -> 1.16 # drivers/net/hamradio/mkiss.c 1.9 -> 1.10 # arch/x86_64/ia32/ia32_signal.c 1.13 -> 1.14 # arch/i386/kernel/sys_i386.c 1.12 -> 1.13 # drivers/char/ppdev.c 1.20 -> 1.21 # net/sctp/tsnmap.c 1.8 -> 1.9 # drivers/char/nwbutton.c 1.4 -> 1.5 # drivers/net/via-rhine.c 1.40 -> 1.41 # drivers/isdn/hisax/sedlbauer.c 1.35 -> 1.36 # include/linux/nfsd/nfsd.h 1.16 -> 1.18 # include/asm-ppc64/topology.h 1.6 -> 1.7 # net/atm/clip.c 1.7 -> 1.12 # net/wanrouter/af_wanpipe.c 1.22 -> 1.23 # include/asm-x86_64/processor.h 1.15 -> 1.16 # net/decnet/dn_nsp_out.c 1.7 -> 1.8 # drivers/acpi/dispatcher/dswexec.c 1.19 -> 1.20 # sound/core/memalloc.c 1.4 -> 1.5 # fs/ext3/fsync.c 1.7 -> 1.8 # drivers/ide/pci/pdc202xx_old.c 1.13 -> 1.15 # arch/ppc64/kernel/Makefile 1.22 -> 1.23 # include/linux/if_wanpipe.h 1.4 -> 1.5 # drivers/acorn/net/ether3.c 1.13 -> 1.15 drivers/net/arm/ether3.c (moved) # arch/ppc64/kernel/module.c 1.2 -> 1.5 # arch/ia64/hp/zx1/Makefile 1.6 -> 1.7 # drivers/scsi/qlogicisp.c 1.19 -> 1.20 # drivers/char/ipmi/ipmi_watchdog.c 1.2 -> 1.3 # arch/x86_64/mm/k8topology.c 1.3 -> 1.4 # net/ipv4/ip_output.c 1.34 -> 1.36 # drivers/scsi/pcmcia/nsp_cs.c 1.20 -> 1.21 # net/ipv4/igmp.c 1.22 -> 1.24 # drivers/scsi/esp.c 1.24 -> 1.26 # arch/ppc/Kconfig 1.20 -> 1.21 # drivers/acpi/namespace/nsxfeval.c 1.11 -> 1.12 # drivers/scsi/aic7xxx/aic79xx_seq.h_shipped 1.8 -> 1.10 # net/ipv4/netfilter/ipt_ECN.c 1.4 -> 1.5 # arch/ia64/kernel/ptrace.c 1.20 -> 1.22 # include/asm-ppc64/rtas.h 1.5 -> 1.6 # drivers/md/dm-target.c 1.6 -> 1.8 # drivers/scsi/aic7xxx/Makefile 1.20 -> 1.21 # mm/mincore.c 1.3 -> 1.4 # net/bridge/netfilter/ebtable_nat.c 1.5 -> 1.6 # drivers/scsi/wd7000.c 1.22 -> 1.24 # drivers/net/wan/sdla_fr.c 1.24 -> 1.27 # include/scsi/scsi.h 1.9 -> 1.11 # drivers/scsi/advansys.h 1.9 -> 1.10 # net/netrom/nr_route.c 1.4 -> 1.5 # net/bridge/br_if.c 1.11 -> 1.14 # include/asm-ia64/ia32.h 1.20 -> 1.21 # net/nonet.c 1.1 -> 1.3 # arch/ia64/kernel/smp.c 1.23 -> 1.24 # include/net/sctp/command.h 1.12 -> 1.13 # drivers/acorn/scsi/eesox.c 1.22 -> 1.27 drivers/scsi/arm/eesox.c (moved) # net/decnet/Kconfig 1.1 -> 1.2 # net/ipv4/route.c 1.52 -> 1.60 # drivers/base/class.c 1.26 -> 1.28 # sound/oss/cs4281/cs4281m.c 1.21 -> 1.22 # drivers/scsi/aic7xxx/aic79xx_reg.h_shipped 1.8 -> 1.10 # drivers/scsi/imm.c 1.19 -> 1.20 # drivers/scsi/aic7xxx/aic7770.c 1.9 -> 1.10 # drivers/acorn/scsi/fas216.h 1.4 -> 1.7 drivers/scsi/arm/fas216.h (moved) # include/linux/slab.h 1.20 -> 1.21 # drivers/atm/fore200e.c 1.13 -> 1.14 # arch/i386/kernel/i386_ksyms.c 1.51 -> 1.52 # arch/ia64/kernel/Makefile 1.16 -> 1.17 # include/net/sctp/structs.h 1.47 -> 1.60 # arch/ppc64/kernel/align.c 1.6 -> 1.8 # arch/sparc/kernel/ptrace.c 1.14 -> 1.15 # arch/arm/mach-rpc/dma.c 1.9 -> 1.11 # arch/i386/kernel/sysenter.c 1.13 -> 1.14 # drivers/block/scsi_ioctl.c 1.24 -> 1.27 # drivers/scsi/qla1280.h 1.14 -> 1.15 # drivers/usb/storage/freecom.c 1.24 -> 1.25 # drivers/ide/ide-tcq.c 1.2 -> 1.5 # net/ipv4/fib_frontend.c 1.10 -> 1.13 # arch/ppc/mm/cachemap.c 1.7 -> 1.8 # include/asm-arm/arch-epxa10db/time.h 1.4 -> 1.5 # net/appletalk/ddp.c 1.20 -> 1.23 # drivers/scsi/sym53c8xx_2/sym53c8xx.h 1.8 -> 1.9 # net/ipv4/netfilter/ipt_MIRROR.c 1.5 -> 1.6 # net/sctp/Makefile 1.7 -> 1.9 # drivers/net/hamachi.c 1.24 -> 1.25 # fs/nfsd/nfs4proc.c 1.9 -> 1.12 # drivers/ide/pci/amd74xx.c 1.16 -> 1.17 # arch/arm/kernel/pm.c 1.1 -> 1.2 # include/asm-alpha/kmap_types.h 1.4 -> 1.5 # include/linux/seq_file.h 1.4 -> 1.7 # arch/ppc64/kernel/ioctl32.c 1.25.1.2 -> 1.31 # drivers/char/amiserial.c 1.19 -> 1.20 # drivers/usb/core/file.c 1.7 -> 1.10 # drivers/scsi/qla1280.c 1.32 -> 1.33 # include/asm-s390/hardirq.h 1.7 -> 1.8 # arch/ppc64/kernel/pSeries_lpar.c 1.20 -> 1.21 # net/ipv4/netfilter/ipt_ttl.c 1.2 -> 1.3 # drivers/message/fusion/mptscsih.h 1.15 -> 1.16 # include/linux/sunrpc/xdr.h 1.11 -> 1.12 # include/asm-arm/arch-clps711x/time.h 1.2 -> 1.3 # fs/xfs/linux/xfs_vnode.h 1.16 -> 1.17 # drivers/usb/misc/speedtch.c 1.80 -> 1.93 # net/ipv4/netfilter/ipt_state.c 1.4 -> 1.5 # include/asm-i386/mach-default/mach_apic.h 1.22 -> 1.24 # drivers/net/wan/wanpipe_multppp.c 1.12 -> 1.14 # drivers/scsi/aic7xxx/aic7xxx_inline.h 1.8 -> 1.10 # fs/xfs/xfs_log.c 1.13 -> 1.16 # drivers/net/wan/sdla.c 1.9 -> 1.10 # drivers/char/tty_ioctl.c 1.8 -> 1.9 # drivers/macintosh/adb.c 1.18 -> 1.19 # drivers/acorn/char/i2c.c 1.7 -> 1.8 # net/sctp/primitive.c 1.9 -> 1.10 # drivers/isdn/icn/icn.c 1.13 -> 1.14 # arch/ia64/kernel/acpi-ext.c 1.1 -> 1.3 # arch/x86_64/kernel/smpboot.c 1.16 -> 1.17 # include/asm-sparc/bug.h 1.1 -> 1.2 # drivers/net/wan/comx-proto-ppp.c 1.4 -> 1.5 # fs/fs-writeback.c 1.34 -> 1.35 # arch/arm/mach-footbridge/dc21285.c 1.7 -> 1.9 # include/net/transp_v6.h 1.2 -> 1.3 # net/ipv6/netfilter/ip6t_ipv6header.c 1.4 -> 1.5 # include/asm-arm/arch-sa1100/time.h 1.7 -> 1.8 # drivers/acorn/scsi/msgqueue.h 1.1 -> 1.2 drivers/scsi/arm/msgqueue.h (moved) # fs/xfs/xfs_vnodeops.c 1.26 -> 1.28 # drivers/usb/serial/bus.c 1.7 -> 1.8 # drivers/net/slip.c 1.13 -> 1.16 # net/decnet/dn_fib.c 1.4 -> 1.6 # drivers/char/agp/amd-k7-agp.c 1.19 -> 1.31 # drivers/hotplug/ibmphp_core.c 1.24 -> 1.26 # arch/arm/kernel/calls.S 1.11 -> 1.12 # drivers/acorn/net/ether1.h 1.1 -> 1.2 drivers/net/arm/ether1.h (moved) # fs/block_dev.c 1.131 -> 1.132 # drivers/char/ip2main.c 1.28 -> 1.31 # include/linux/nfs_fs_sb.h 1.9 -> 1.10 # Documentation/video4linux/bttv/Sound-FAQ 1.7 -> 1.8 # include/asm-sparc/hardirq.h 1.10 -> 1.12 # arch/arm/mach-integrator/mm.c 1.3 -> 1.4 # arch/i386/mm/pgtable.c 1.11 -> 1.12 # net/bluetooth/bnep/sock.c 1.9 -> 1.10 # net/core/rtnetlink.c 1.10 -> 1.14 # arch/ia64/kernel/unwind.c 1.19 -> 1.22 # arch/parisc/kernel/module.c 1.3 -> 1.4 # include/asm-arm/arch-ebsa285/time.h 1.6 -> 1.7 # fs/reiserfs/tail_conversion.c 1.23 -> 1.24 # fs/xfs/linux/xfs_sysctl.c 1.9 -> 1.10 # fs/xfs/xfs_log.h 1.5 -> 1.6 # fs/xfs/support/kmem.h 1.2 -> 1.3 # drivers/usb/serial/usb-serial.h 1.29 -> 1.31 # net/sctp/socket.c 1.48.1.1 -> 1.69 # drivers/scsi/tmscsim.c 1.18 -> 1.19 # drivers/scsi/sym53c8xx_2/sym_glue.c 1.18 -> 1.20 # net/atm/common.c 1.15 -> 1.25 # net/ipv4/netfilter/ipt_mark.c 1.3 -> 1.4 # include/asm-um/pgtable.h 1.10 -> 1.11 # (new) -> 1.1 include/asm-i386/mach-generic/mach_mpparse.h # (new) -> 1.1 include/asm-arm/traps.h # (new) -> 1.1 drivers/scsi/scsi_devinfo.h # (new) -> 1.2 net/core/flow.c # (new) -> 1.1 arch/i386/mach-generic/probe.c # (new) -> 1.1 arch/i386/mach-generic/default.c # (new) -> 1.1 drivers/scsi/scsi_logging.h # (new) -> 1.9 drivers/usb/gadget/net2280.c # (new) -> 1.1 arch/x86_64/kernel/warmreboot.S # (new) -> 1.1 include/linux/atm_he.h # (new) -> 1.1 drivers/usb/gadget/Makefile # (new) -> 1.7 drivers/atm/he.c # (new) -> 1.1 include/net/ipcomp.h # (new) -> 1.1 arch/x86_64/ia32/vsyscall.lds # (new) -> 1.10 drivers/char/agp/nvidia-agp.c # (new) -> 1.1 arch/i386/mach-generic/bigsmp.c # (new) -> 1.1 drivers/net/sungem_phy.c # (new) -> 1.1 drivers/i2c/busses/i2c-sis96x.c # (new) -> 1.4 drivers/usb/gadget/Kconfig # (new) -> 1.1 drivers/scsi/scsi_devinfo.c # (new) -> 1.2 include/asm-i386/mach-generic/mach_apic.h # (new) -> 1.1 include/linux/atmbr2684.h # (new) -> 1.2 net/atm/br2684.c # (new) -> 1.1 net/ipv4/netfilter/ip_fw_compat.h # (new) -> 1.5 drivers/usb/gadget/zero.c # (new) -> 1.2 include/linux/usb_gadget.h # (new) -> 1.1 include/asm-ppc/agp.h # (new) -> 1.3 drivers/atm/he.h # (new) -> 1.1 net/ipx/ipx_route.c # (new) -> 1.1 arch/x86_64/ia32/vsyscall.S # (new) -> 1.1 arch/ppc/boot/prep/dummy.c # (new) -> 1.1 fs/ext3/xattr_security.c # (new) -> 1.3 net/ipv6/ipcomp6.c # (new) -> 1.2 net/decnet/netfilter/dn_rtmsg.c # (new) -> 1.1 fs/ext2/xattr_security.c # (new) -> 1.1 include/asm-ppc64/systemcfg.h # (new) -> 1.1 include/acpi/acdisasm.h # (new) -> 1.5 drivers/char/agp/uninorth-agp.c # (new) -> 1.1 arch/i386/mach-generic/Makefile # (new) -> 1.1 net/decnet/netfilter/Makefile # (new) -> 1.2 include/asm-i386/genapic.h # (new) -> 1.1 include/asm-x86_64/vsyscall32.h # (new) -> 1.2 drivers/usb/gadget/usbstring.c # (new) -> 1.6 drivers/scsi/scsi_priv.h # (new) -> 1.1 arch/ppc64/kernel/proc_ppc64.c # (new) -> 1.2 drivers/usb/gadget/net2280.h # (new) -> 1.1 drivers/net/sungem_phy.h # (new) -> 1.1 arch/ppc/boot/simple/dummy.c # (new) -> 1.2 include/linux/pci-dynids.h # (new) -> 1.1 arch/x86_64/kernel/vsyscall.S # (new) -> 1.5 net/sctp/chunk.c # (new) -> 1.1 arch/ppc/boot/openfirmware/dummy.c # (new) -> 1.1 include/asm-i386/mach-generic/mach_ipi.h # (new) -> 1.1 net/decnet/netfilter/Kconfig # (new) -> 1.2 fs/xfs/linux/xfs_syncd.c # (new) -> 1.1 net/core/net-sysfs.c # (new) -> 1.7 drivers/char/agp/isoch.c # (new) -> 1.1 include/acpi/amlresrc.h # (new) -> 1.1 arch/i386/mach-generic/summit.c # (new) -> 1.4 drivers/usb/gadget/ether.c # (new) -> 1.1 drivers/net/arm/ether00.c # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/05/04 torvalds@home.transmeta.com 1.1042.124.10 # Linux 2.5.69 # -------------------------------------------- # 03/05/04 cifs.adm@hostme.bitkeeper.com 1.1042.124.11 # Merge bk://linux.bkbits.net/linux-2.5 # into hostme.bitkeeper.com:/ua/repos/c/cifs/linux-2.5cifs # -------------------------------------------- # 03/05/05 anton@samba.org 1.1057.2.13 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/tmp3 # -------------------------------------------- # 03/05/04 davem@nuts.ninka.net 1.1042.1.183 # [ATM]: mpc.c warning fixes. # -------------------------------------------- # 03/05/04 davem@nuts.ninka.net 1.1042.1.184 # [NETFILTER IPV6]: Fix warnings. # -------------------------------------------- # 03/05/04 davem@nuts.ninka.net 1.1042.1.185 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/05 davej@tetrachloride.(none) 1.1042.125.1 # Merge tetrachloride.(none):/mnt/raid/src/kernel/2.5/bk-linus # into tetrachloride.(none):/mnt/raid/src/kernel/2.5/agpgart # -------------------------------------------- # 03/05/05 davej@codemonkey.org.uk 1.1042.125.2 # [AGPGART] Disable debugging printk's again. # With the 'AGP bug' solved, we don't need this noise for a while... # -------------------------------------------- # 03/05/05 davej@tetrachloride.(none) 1.1042.126.1 # Merge tetrachloride.(none):/mnt/raid/src/kernel/2.5/bk-linus # into tetrachloride.(none):/mnt/raid/src/kernel/2.5/cpufreq # -------------------------------------------- # 03/05/05 anton@samba.org 1.1062 # Merge samba.org:/scratch/anton/tmp3 # into samba.org:/scratch/anton/linux-2.5_ppc64 # -------------------------------------------- # 03/05/05 anton@samba.org 1.1057.2.14 # Merge samba.org:/scratch/anton/tmp3 # into samba.org:/scratch/anton/linux-2.5_ppc64drivers # -------------------------------------------- # 03/05/04 torvalds@home.transmeta.com 1.1063 # Merge http://ppc.bkbits.net/for-linus-ppc64drivers # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/05 acme@conectiva.com.br 1.1042.121.2 # o list.h: implement list_for_each_entry_safe # -------------------------------------------- # 03/05/05 acme@conectiva.com.br 1.1042.121.3 # o ipx: convert ipx_interface handling to use list_head # -------------------------------------------- # 03/05/05 jgrimm@touki.austin.ibm.com 1.1042.127.1 # [SCTP] Use put_user() in get_peer_addr_params (reported by yjf@standford.edu) # # Standford Checker reported direct touch of user space. # -------------------------------------------- # 03/05/05 davej@codemonkey.org.uk 1.1042.125.3 # [AGPGART] Skip devices with no AGP headers sooner. # -------------------------------------------- # 03/05/05 jgrimm@touki.austin.ibm.com 1.1042.25.17 # Merge http://linux-lksctp.bkbits.net/lksctp-2.5.work # into touki.austin.ibm.com:/home/jgrimm/bk/lksctp-2.5.work # -------------------------------------------- # 03/05/05 jejb@raven.il.steeleye.com 1.1064 # Merge raven.il.steeleye.com:/home/jejb/BK/linux-2.5.69 # into raven.il.steeleye.com:/home/jejb/BK/scsi-misc-2.5 # -------------------------------------------- # 03/05/05 Matt_Domsch@dell.com 1.1042.119.2 # Shrink dynids feature set # # Per recommendation from GregKH: # Remove directory 'dynamic_id' # Remove exporting dynamic_id/0 files # Remove probe_it driver attribute # Move new_id into driver directory as a driver attribute. Make it # probe when new IDs are added. # Move attribute existance test into pci-driver.c completely. # # -------------------------------------------- # 03/05/05 Matt_Domsch@dell.com 1.1063.1.1 # Merge dell.com:/home/mdomsch/bk/linux-2.5 # into dell.com:/home/mdomsch/bk/dynids/linux-2.5-dynids-smaller # -------------------------------------------- # 03/05/05 davej@codemonkey.org.uk 1.1042.125.4 # [AGPGART] Store agp revision in agp_bridge struct. # There are a few places we do spec revision compliance checks, this cset # generalises that function, and removes some duplicated functionality. # -------------------------------------------- # 03/05/05 davej@codemonkey.org.uk 1.1042.125.5 # [AGPGART] Work around AMD 8151 errata. # Some revisions incorrectly report they support v3.5 of the AGP spec, when # they are actually only 3.0 compliant. # -------------------------------------------- # 03/05/05 bunk@fs.tum.de 1.1042.108.3 # [PATCH] USB: kill the last occurances of usb_serial_get_by_minor # # I got an error at the final linking of 2.5.68-bk11. It seems the patch # below is needed. # -------------------------------------------- # 03/05/05 geert@linux-m68k.org 1.1042.108.4 # [PATCH] USB: Big endian RTL8150 # # The RTL8150 USB Ethernet driver doesn't work on big endian machines. Here are # patches (for both 2.4.x and 2.5.x) to fix that. The fix was tested on the # 2.4.20 and 2.4.21-rc1 version of the driver on big endian MIPS. # # Changes: # - Fix endianness of rx_creg (from Dimitri Torfs ) # - Kill unused last parameter of async_set_registers() # -------------------------------------------- # 03/05/05 davem@redhat.com 1.1042.108.5 # [PATCH] USB speedtouch fix # # Missing header file. Please apply. # -------------------------------------------- # 03/05/05 philipp@void.at 1.1042.108.6 # [PATCH] USB: unusual_devs.h patch # -------------------------------------------- # 03/05/05 Matt_Domsch@dell.com 1.1063.1.2 # PCI dynids - documentation fixes, id_table NULL check # -------------------------------------------- # 03/05/05 greg@kroah.com 1.1063.2.1 # Merge kroah.com:/home/greg/linux/BK/bleed-2.5 # into kroah.com:/home/greg/linux/BK/gregkh-2.5 # -------------------------------------------- # 03/05/05 hch@lst.de 1.1065 # [PATCH] move all host templates into .c files # # Oookay - I really got upset by that tmeplates in headers crap when # grepping for certain methods. The patch below moves all templates # from the headers into the actual implementation files and removes # the ifdef mess for unmaintained drivers - for maintained support # gazillion kernel releases drivers like gdth I've kept them. # # This means a driver works fine without any problems for all modular # builds and builtin kernel >= 2.4.0. If you want certain drivers # to work with 2.0/2.2 statyic builds too I can hack something up for # you, but I'd prefer not supporting stuff like that anymore. # # Tested by compiling all drivers with make -k and not getting more # warnings than before :) # -------------------------------------------- # 03/05/05 nicolas@dupeux.net 1.1063.2.2 # [PATCH] USB: UNUSUAL_DEV for aiptek pocketcam # # Here is the unusual_dev entry i'm using to get my digital camera. # # # diff -cr linux/drivers/usb/storage/unusual_devs.h linux_vaxvms/drivers/usb/storage/unusual_devs.h # *** linux/drivers/usb/storage/unusual_devs.h 2003-03-14 21:32:46.000000000 +0100 # -------------------------------------------- # 03/05/05 andmike@us.ibm.com 1.1064.1.1 # [PATCH] scsi host sysfs support again [1/4] # # -andmike # -- # Michael Anderson # andmike@us.ibm.com # # DESC # This patch removes the shost_devclass device class support that was # previously added, but incomplete. # EDESC # # # drivers/acorn/scsi/acornscsi.c | 1 - # drivers/acorn/scsi/arxescsi.c | 1 - # drivers/acorn/scsi/cumana_1.c | 1 - # drivers/acorn/scsi/cumana_2.c | 1 - # drivers/acorn/scsi/eesox.c | 1 - # drivers/acorn/scsi/oak.c | 1 - # drivers/acorn/scsi/powertec.c | 1 - # drivers/scsi/scsi_sysfs.c | 23 ----------------------- # 8 files changed, 30 deletions(-) # -------------------------------------------- # 03/05/05 andmike@us.ibm.com 1.1064.1.2 # [PATCH] scsi host sysfs support again [2/4] # # -andmike # -- # Michael Anderson # andmike@us.ibm.com # # # DESC # This patch changes the structure of sdebug_host_info and changes the # method / order of driver model cleanup. # EDESC # # # drivers/scsi/scsi_debug.c | 215 ++++++++++++++++++++++++---------------------- # drivers/scsi/scsi_debug.h | 2 # 2 files changed, 115 insertions(+), 102 deletions(-) # -------------------------------------------- # 03/05/05 andmike@us.ibm.com 1.1064.1.3 # [PATCH] scsi host sysfs support again [3/4] # # -andmike # -- # Michael Anderson # andmike@us.ibm.com # # # DESC # Change scsi host to class device model. Change scsi host and scsi device # to release when ref count goes to zero. # EDESC # # # drivers/scsi/hosts.c | 23 +++++------------------ # drivers/scsi/hosts.h | 20 ++++++++++++++------ # drivers/scsi/scsi_scan.c | 4 +--- # 3 files changed, 20 insertions(+), 27 deletions(-) # -------------------------------------------- # 03/05/05 andmike@us.ibm.com 1.1064.1.4 # [PATCH] scsi host sysfs support again [4/4] # # -andmike # -- # Michael Anderson # andmike@us.ibm.com # # # DESC # Change scsi sysfs to support scsi host class device and call release # functions when ref count goes to zero. # EDESC # # # drivers/scsi/scsi_sysfs.c | 111 +++++++++++++++++++++++++++++++++++++++------- # 1 files changed, 96 insertions(+), 15 deletions(-) # -------------------------------------------- # 03/05/05 Matt_Domsch@dell.com 1.1063.1.3 # pci.h whitespace cleanups # -------------------------------------------- # 03/05/05 jgrimm@touki.austin.ibm.com 1.1042.25.18 # [SCTP] Support SCTP ECN on ipv6. # -------------------------------------------- # 03/05/05 acme@conectiva.com.br 1.1042.121.4 # o ipx: convert ipx_route to use list_head # -------------------------------------------- # 03/05/05 davem@nuts.ninka.net 1.1063.3.1 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.3.2 # [IPSEC]: Fix SADB_EALG_{3,}DESCBC values. # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.3.3 # Merge bk://kernel.bkbits.net/acme/ipx-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.3.4 # [ATM]: Fix some CPP pasting in ambassador driver. # -------------------------------------------- # 03/05/06 chas@locutus.cmf.nrl.navy.mil 1.1063.3.5 # [ATM]: Fix excessive stack usage in iphase driver. # -------------------------------------------- # 03/05/06 chas@locutus.cmf.nrl.navy.mil 1.1063.3.6 # [ATM]: svcs possible race with sigd. # -------------------------------------------- # 03/05/06 steve@gw.chygwyn.com 1.1063.3.7 # [FS]: Add seq_release_private and proc_net_fops_create helpers. # -------------------------------------------- # 03/05/06 steve@gw.chygwyn.com 1.1063.3.8 # [DECNET]: seq file conversions and fixes. # o Removed blksize from decnet device parameters - use the device mtu like we # ought to. # o Removed /proc/net/decnet_route file - I don't think anybody ever used it # and it was lacking a full enough description of the routes to be useful. # ip -D route list is much better :-) # o Added rt_local_src entry to decnet routes so that we get the local source # address right when forwarding. # o Added correct proto argument to struct flowi for routing # o MSG_MORE in sendmsg (ignored, but accepted whereas before we'd error) # o /proc/net/decnet converted to seq_file # o /proc/net/decnet_dev converted to seq_file # o /proc/net/decnet_cache converted to seq_file # o Use pskb_may_pull() and add code to linearize skbs on the input path # except for those containing data. # o Fixed returned packet code (mostly - some left to do) # o update_pmtu() method for decnet dst entries (ip_gre device assumes this # method exists - well I think it does :-) # o Fixed bug in forwarding to get IE bit set correctly # o Fixed compile bugs with CONFIG_DECNET_ROUTE_FWMARK pointed out by Adrian # Bunk # o Fixed zero dest code to grab an address from loopback # o Fixed local routes in dn_route_output_slow() # o Fixed error case in dn_route_input/output_slow() pointed out by Rusty # -------------------------------------------- # 03/05/06 rusty@rustcorp.com.au 1.1063.3.9 # [NETFILTER]: Fix Module Usage in ipchains and ipfwadm. # Gets rid of some warnings. Manipulating our own module count inside the # sockopt is safe, because unregistering that sockopt will block. # -------------------------------------------- # 03/05/06 rusty@rustcorp.com.au 1.1063.3.10 # [NETFILTER]: Make NAT code handle non-linear skbs. # Makes the NAT code and all NAT helpers handle non-linear skbs. # Main trick is to introduce skb_ip_make_writable which handles all # the decloning, linearizing, etc. # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.3.11 # [NETFILTER]: ip_nat_proto_{icmp,udp}.c need ip_nat_core.h # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.3.12 # [IPV6]: Kill spurious module_{get,put}(). # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.3.13 # [BLUETOOTH]: Fix hci_usb build. # -------------------------------------------- # 03/05/06 yoshfuji@linux-ipv6.org 1.1063.3.14 # [IPV6]: Fix offset in ICMPV6_HDR_FIELD messages. # -------------------------------------------- # 03/05/06 yoshfuji@linux-ipv6.org 1.1063.3.15 # [IPV^]: Use correct icmp6 type in ip6_pkt_discard. # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.4.1 # [SPARC64]: Only use power interrupt when button property exists. # -------------------------------------------- # 03/05/06 chas@cmf.nrl.navy.mil 1.1063.3.16 # [ATM]: Fix foul up in lec driver. # -------------------------------------------- # 03/05/06 torvalds@home.transmeta.com 1.1063.5.1 # Merge bk://kernel.bkbits.net/davem/sparc-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/06 Matt_Domsch@dell.com 1.1063.1.4 # dynids: call driver_attach() when new IDs are added # # This causes the driver to create proper device symlinks in sysfs when # new IDs are added and thus new devices found by the driver. # # drivers/base/bus.c # make driver_attach non-static # drivers/pci/pci-driver.c # delete probe_each_pci_dev, call driver_attach instead. # Whitespace cleanups. # include/linux/device.h # add declaration of driver_attach. # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.3.17 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/06 jejb@raven.il.steeleye.com 1.1066 # Merge hch/andmike changes # -------------------------------------------- # 03/05/06 davidm@tiger.hpl.hp.com 1.971.102.22 # ia64: Improve spinlock code to handle contention in shared routine called # with a special convention. Various minor fixes for gcc-pre3.4. # -------------------------------------------- # 03/05/06 jejb@raven.il.steeleye.com 1.1067 # Add .release template method to scsi_debug.c # # Lost in the hch/andmike merge # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.3.18 # [IPV6]: Remove illogical bug check in fib6_del. # -------------------------------------------- # 03/05/06 davej@codemonkey.org.uk 1.1042.125.6 # [AGPGART] Only enable isochronous transfers on AGP3.5 chipsets. # The standard says that 3.0 chipsets don't support these extensions. # Move the isoch stuff out into isoch.c leaving behind a shell for basic # AGP3.0 enabling (to be written). # -------------------------------------------- # 03/05/06 davej@codemonkey.org.uk 1.1042.125.7 # [AGPGART] Remove unneeded exports. # These functions should only be called indirectly from agp_generic_enable() # -------------------------------------------- # 03/05/06 jejb@raven.il.steeleye.com 1.1068 # Fix aic merge error # -------------------------------------------- # 03/05/06 arun.sharma@intel.com 1.971.102.23 # [PATCH] ia64: fix ia32 emulation of rlimit et al # # -------------------------------------------- # 03/05/06 eranian@hpl.hp.com 1.971.102.24 # [PATCH] ia64: perfmon update # # Please apply the following patch on top of 2.5.6x. This patch does the # following: # # - repair broken system-wide overflow notification # - repair broken per-process notification # - fix a problem in the resrved bitmask for opcode # matcher8,9 for McKinley as reported by UIUC. # - forcing of bit2 for pmc8/pmc9 now part of reserved bitmask # - add the unsecure option to perfmon # - update to perfmon 1.4 (similar to 2.4) # -------------------------------------------- # 03/05/06 elenstev@mesatop.com 1.971.102.25 # [PATCH] ia64: spelling fixes # # -------------------------------------------- # 03/05/06 davidm@tiger.hpl.hp.com 1.971.102.26 # ia64: Manual merge of Steve's spelling fixes. # -------------------------------------------- # 03/05/06 alex_williamson@hp.com 1.971.102.27 # [PATCH] ia64: fix timer interrupts getting lost # # This patch fixes the issue of some CPUs not showing timer interrupts # going off. Seems during the process of sync'ing the itc, we jumped over # the next timer value. This patch is against 2.5.67 + ia64. I haven't # seen the problem on 2.4, but a quick looks seems like it's potentially # an issue there too. # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.5.2 # Merge gregkh@kernel.bkbits.net:/home/gregkh/linux/i2c-2.5 # into kroah.com:/home/greg/linux/BK/i2c-2.5 # -------------------------------------------- # 03/05/06 alex_williamson@hp.com 1.971.102.28 # [PATCH] ia64: interrupt fixes/cleanup # # Here's some cleanups/fixes/changes for interrupts on 2.5.67 + ia64. # Specifically: # # - Cleanup some ugliness with polarity/trigger setup. # # - Add iosapic_enable_intr() to set_rte on an interupt when the # device is enabled. IMHO, we really only want to unmask RTEs # for PRTs we might actually use. This moves the interrupt # distribution here too. # # - When changing a vector from edge to level, call register_intr() # to do it so all the data structures get set correctly. If we # have to guess how to setup an interupt and get it wrong, this # should close some holes in changing it back to the correct type. # # - Register the HCDP interrupt in 8250_hcdp - this is where we have # to guess the polarity/trigger. The real handler will get fixed # up via PCI setup or ACPI namespace serial support, this gets it # associated w/ the port at setup. This should allow interrupts # to work when using builtin UARTs as console on HP Itanium2 boxes. # -------------------------------------------- # 03/05/06 bjorn_helgaas@hp.com 1.971.102.29 # [PATCH] ia64: multi-ioport space support # # This has been in my 2.4 BK tree for a while, but I should have # posted it in case there's feedback from other people working # on large machines. So here it is, in four parts: # # 1 enhance __ia64_mk_io_addr(port) # 2 enhance pcibios_scan_root to get multiple mem & io windows # from ACPI _CRS, and fixup all the resources # 3 add support for /proc/iomem and /proc/ioports # 4 trivial (whitespace, copyright, and move pcibios_fixup_device_resources # closer to related code) # # The current scheme is that IO ports are 64 bits, with the low 24 # bits being the port number within an IO port space, and the upper # bits identifying the space. There is currently a limit of 16 # spaces. # -------------------------------------------- # 03/05/06 bjorn_helgaas@hp.com 1.971.102.30 # [PATCH] ia64: multi-ioport space support (part 2 of 4) # # enhance pcibios_scan_root to get multiple mem & io windows from ACPI _CRS, # and fixup all the resources # -------------------------------------------- # 03/05/06 bjorn_helgaas@hp.com 1.971.102.31 # [PATCH] ia64: multi-ioport space support (part 3 of 4) # # add support for /proc/iomem and /proc/ioports # -------------------------------------------- # 03/05/06 bjorn_helgaas@hp.com 1.971.102.32 # [PATCH] ia64: multi-ioport space support (part 3 of 4) # # trivial (whitespace, copyright, and move pcibios_fixup_device_resources # closer to related code) # -------------------------------------------- # 03/05/06 bjorn_helgaas@hp.com 1.971.102.33 # [PATCH] ia64: new IOC recognition # # This is a trivial patch that makes sba_iommu recognize a new IOC. # Only change is that it will print # # IOC: sx1000 0.1 HPA 0xf8120002000 IOVA space 1024Mb at 0x80000000 # # instead of # # IOC: Unknown (103c:127c) 0.1 HPA 0xf8120002000 IOVA space 1024Mb # at 0x80000000 # -------------------------------------------- # 03/05/06 bjorn_helgaas@hp.com 1.971.102.34 # [PATCH] ia64: vendor-specific ACPI resource cleanup # # This is to # # - handle _CRS with multiple vendor-specific resources # - use acpi_walk_resources() instead of doing it by hand # - make lookup of vendor resource by GUID generic # - cleanup now-unused helper functions # # (This depends on the previous IO port space patches, because # they removed the last of acpi_get_addr_space()). # # My hope is that acpi_vendor_resource_match() and # acpi_find_vendor_resource() can someday move into ACPI, # but that probably depends on getting the idea of labelling # vendor resources with a GUID into the spec. HP does this # and I think is working on putting it in the spec. # -------------------------------------------- # 03/05/06 petrides@redhat.com 1.971.102.35 # [PATCH] ia64: fixes for semtimedop() ia32-compat handling # # Here are two fixes for the ia32-compatibility mode handling # for the new semtimedop() system call for the ia64 architecture. # # The first problem was that treatment of user-mode calls to semtimedop() # with a NULL 4th (struct timespec *) parameter was inconsistent with the # behavior of the same executable on i386 and also with a natively compiled # ia64 binary. A NULL 4th arg to semtimedop() should result in no timeout # being used (like a straight semop() call) rather than in an EFAULT error. # # The second problem was that a legitimate semtimedop() with a timeout was # also resulting in an EFAULT because the fetch of the internal timespec # strucure by sys_semtimedop() from semtimedop32()'s kernel stack was # treated as an invalid user-data reference. This requires temporarily # switching the addressing limit with set_fs(), further requiring that # appropriate parameter checking by performed prior to the switch. # # The const qualifier was removed from the (struct compat_timespec *) arg # to semtimedop32() so that the call to get_compat_timespec() wouldn't # generate a compilation warning. # -------------------------------------------- # 03/05/06 davidm@tiger.hpl.hp.com 1.971.102.36 # ia64: Manual merge of Bjorn Helgaas' sba_iommu patch to make it use seq_file. # -------------------------------------------- # 03/05/06 jejb@raven.il.steeleye.com 1.1067.1.1 # fix syntax error in ncr53c8xx from hch conversion # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.6.1 # Merge gregkh@kernel.bkbits.net:/home/gregkh/linux/pci-2.5 # into kroah.com:/home/greg/linux/BK/pci-2.5 # -------------------------------------------- # 03/05/06 jejb@raven.il.steeleye.com 1.1067.1.2 # fix missed conversion of to_scsi_host -> dev_to_shost in sim710 # -------------------------------------------- # 03/05/06 jejb@raven.il.steeleye.com 1.1067.1.3 # add missing asm/io.h to scsi/dc395x.c # -------------------------------------------- # 03/05/06 jejb@raven.il.steeleye.com 1.1069 # Merge raven.il.steeleye.com:/home/jejb/BK/scsi-aic-2.5 # into raven.il.steeleye.com:/home/jejb/BK/scsi-misc-2.5 # -------------------------------------------- # 03/05/06 roland@frob.com 1.1063.7.1 # [PATCH] core dump psinfo.pr_sname letter fix # # This patch makes the state letter in the pr_sname field in core dumps # correct for stopped and zombie threads. The order needed to be changed when # the TASK_* values changed. This matches the letters used in sched.c:show_task. # -------------------------------------------- # 03/05/06 davidm@tiger.hpl.hp.com 1.1063.8.1 # Merge tiger.hpl.hp.com:/data1/bk/vanilla/linux-2.5 # into tiger.hpl.hp.com:/data1/bk/lia64/to-linus-2.5 # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.6.2 # [PATCH] PCI Hotplug: fix up the compaq driver to work properly again. # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.6.3 # [PATCH] PCI Hotplug: fix up the ibm driver to work properly again. # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.6.4 # [PATCH] PCI Hotplug: fix compiler warning in ibm driver. # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.6.5 # [PATCH] PCI Hotplug: fix up the acpi driver to work properly again. # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.6.6 # [PATCH] PCI Hotplug: fix dependancies for CONFIG_HOTPLUG_PCI_ACPI # # Thanks to Adrian Bunk for pointing this out. # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.6.7 # PCI Hotplug: export the acpi_resource_to_address64 function, as the acpi pci hotplug driver needs it. # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.5.3 # Merge kroah.com:/home/greg/linux/BK/bleed-2.5 # into kroah.com:/home/greg/linux/BK/i2c-2.5 # -------------------------------------------- # 03/05/06 davidm@tiger.hpl.hp.com 1.1063.8.2 # mca.c: # (show_min_state): Fix typo r11 -> r12. # -------------------------------------------- # 03/05/06 sri@us.ibm.com 1.1042.128.1 # Manual merge. # -------------------------------------------- # 03/05/06 kraxel@bytesex.org 1.1063.5.4 # [PATCH] i2c #1/3: listify i2c core # # This is the first of tree patches for i2c. Trying to get the i2c # cleanups finshed before 2.6.x, so we (hopefully) don't have a # ever-changing i2c subsystem in 2.7.x again (which is very annonying for # driver maintainance). # # Changes: # # * listify i2c-core, i.e. make it use instead of # statically-sized arrays, removed lots of ugly code :) # * added i2c_(get|put)_adapter, changed i2c-dev.c to use these # functions instead maintaining is own adapter list. # * killed the I2C_DF_DUMMY flag which had the strange semantics to # make the i2c subsystem call driver->attach_adapter on detaches. # Added a detach_adapter() callback instead. # * some other minor cleanups along the way ... # -------------------------------------------- # 03/05/06 kraxel@bytesex.org 1.1063.5.5 # [PATCH] i2c #2/3: add i2c_clients_command # # Changes: # # * adds a i2c_clients_command() function to i2c-core which calls # the ->command() callback of all clients attached to a adapter. # * make bttv + saa7134 drivers use that function instead of mucking # with the i2c_adapter struct themself. # -------------------------------------------- # 03/05/06 kraxel@bytesex.org 1.1063.5.6 # [PATCH] i2c #3/3: add class field to i2c_adapter # # This is the last of three patches for i2c. It introduces a new field # to i2c_adapter which classifies the kind of hardware a i2c adapter # belongs to (analog tv card / dvb card / smbus / gfx card ...). i2c chip # drivers can use this infomation to decide whenever they want to look for # hardware on that adapter or not. It doesn't make sense to probe for a # tv tuner on a smbus for example ... # -------------------------------------------- # 03/05/06 torvalds@home.transmeta.com 1.1063.6.8 # Merge bk://kernel.bkbits.net/gregkh/linux/pci-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.5.7 # [PATCH] i2c: fix compile error due to previous patches. # -------------------------------------------- # 03/05/06 warp@mercury.d2dc.net 1.1063.5.8 # [PATCH] i2c: it87 patch. # # More or less straight forward patch. # # Fix a typo in the comments at the top. # Show all 9 voltage inputs. # Show all 3 fan inputs. # Allow you to select the temp sensor type from the sysfs interface, # instead of just with the temp_type module option. # (1 = diode, 2 = thermistor, 0 = disabled). # # I'm still trying to figure out the registers for PWM fan controller # support. # -------------------------------------------- # 03/05/06 sri@us.ibm.com 1.1063.7.2 # o net/socket: fix bug in sys_accept # # module_put() gets called twice on error. Once via the explicit module_put and # the second via sock_release(). Also i think we should do a __module_get() with # newsock's owner(although same as the original listening sock). # -------------------------------------------- # 03/05/06 torvalds@home.transmeta.com 1.1063.5.9 # Merge bk://kernel.bkbits.net/gregkh/linux/i2c-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/06 paulkf@microgate.com 1.1063.5.10 # [PATCH] synclink update # # - Add support for hardware version 2 (universal PCI) of synclink adapter # - Use mod_timer() function # -------------------------------------------- # 03/05/06 paulkf@microgate.com 1.1063.5.11 # [PATCH] n_hdlc update # # - Use C99 initializers # -------------------------------------------- # 03/05/06 arun.sharma@intel.com 1.1063.8.3 # [PATCH] ia64: fix sys32_select() # # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.3.19 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.3.20 # Merge bk://kernel.bkbits.net/acme/unix-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.3.21 # [IPV4/IPV6]: Set owner field in family ops. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.2.3 # [PATCH] USB: add usb class support for usb drivers that use the USB major # # This also consolodates the devfs calls for the USB drivers. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.2.4 # [PATCH] USB: converted usblp over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.2.5 # [PATCH] USB: converted mdc800 over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.2.6 # [PATCH] USB: converted scanner over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.2.7 # [PATCH] USB: converted dabusb over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.2.8 # [PATCH] USB: converted auerswald over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.2.9 # [PATCH] USB: converted brlvger over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.2.10 # [PATCH] USB: converted rio500 over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.2.11 # [PATCH] USB: converted usblcd over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.2.12 # [PATCH] USB: converted usb-skeleton over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.2.13 # [PATCH] USB: remove #include from some drivers that do not need it. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.2.14 # USB: converted hiddev over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 rddunlap@osdl.org 1.1063.3.22 # [NET]: Spelling/typo fixes in rtnetlink.h # -------------------------------------------- # 03/05/07 rddunlap@osdl.org 1.1063.3.23 # [IPV6]: Convert /proc/net/rt6_stats to seq_file. # -------------------------------------------- # 03/05/07 bdschuym@pandora.be 1.1063.3.24 # [BRIDGE]: Change pkt_type to PACKET_HOST earlier. # -------------------------------------------- # 03/05/07 shemminger@osdl.org 1.1063.3.25 # [IPV4]: Replace explicit dev->refcount bumps with dev_hold. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.3.26 # [NET]: Remove duplicated alloc_skb debug check. # -------------------------------------------- # 03/05/07 chas@cmf.nrl.navy.mil 1.1063.3.27 # [ATM]: Add Forerunner HE support. # -------------------------------------------- # 03/05/07 chas@cmf.nrl.navy.mil 1.1063.3.28 # [ATM]: Forward port br2864 to 2.5.x # -------------------------------------------- # 03/05/07 chas@cmf.nrl.navy.mil 1.1063.3.29 # [ATM]: Clip locking and more atmvcc cleanup. # -------------------------------------------- # 03/05/07 rddunlap@osdl.org 1.1063.3.30 # [IPV6]: Fix typos in ip6_fib.c # -------------------------------------------- # 03/05/07 rddunlap@osdl.org 1.1063.3.31 # [IPV6]: Use time_after() etc. for comparing jiffies. # -------------------------------------------- # 03/05/07 olof@austin.ibm.com 1.1063.3.32 # [TCP]: tcp_twkill leaves death row list in inconsistent state over tcp_timewait_kill. # -------------------------------------------- # 03/05/07 davem@nuts.ninka.net 1.1063.3.33 # [ATM]: Fix build of HE driver. # -------------------------------------------- # 03/05/07 trond.myklebust@fys.uio.no 1.1063.5.12 # Decrement the nr_unstable page state after the COMMIT RPC call # completes instead of before. This ensures that writeback # WB_SYNC_ALL does wait on completion. # # Don't overreport the number of pages we wrote out. It is safer to # underreport. # # Fix missing NFSv3 unstable write accounting in fs/fs-writeback.c # and mm/page-writeback.c # -------------------------------------------- # 03/05/07 trond.myklebust@fys.uio.no 1.1063.5.13 # Fix typos in close-to-open cache consistency checking. # -------------------------------------------- # 03/05/07 trond.myklebust@fys.uio.no 1.1063.5.14 # Fix a TCP race: check whether or not the socket has been disconnected # before we allow an RPC request to wait on a reply. # -------------------------------------------- # 03/05/07 trond.myklebust@fys.uio.no 1.1063.5.15 # Don't use an RPC child process when reconnecting to a TCP server. # This is more efficient, and also fixes an existing deadlock # situation in which the child could be waiting for an xprt_write_lock # that was being held by the parent. # -------------------------------------------- # 03/05/07 trond.myklebust@fys.uio.no 1.1063.5.16 # Ensure that if we need to reconnect the socket, we also resend # the entire RPC message # # Assorted TCP reconnection fixes. # # Temporarily raise the necessary CAP_NET_BIND_SERVICE capability # if we need to bind the socket to a reserved port during a TCP # reconnection. Check for CAP_NET_BIND_SERVICE at mount time. # -------------------------------------------- # 03/05/07 trond.myklebust@fys.uio.no 1.1063.5.17 # Add the sk->callback_lock spinlocks to the RPC socket callbacks # in order to protect the socket from being released by one # CPU while the other is in a soft interrupt. # -------------------------------------------- # 03/05/07 cel@citi.umich.edu 1.1063.5.18 # the recently-applied patch to fix the rpc_show_tasks() Oops is incomplete. # this applies over 2.5.68 and should address all of the issues in # rpc_show_tasks(). # -------------------------------------------- # 03/05/07 trond.myklebust@fys.uio.no 1.1063.5.19 # Ensure that Lockd and the NSM (statd) clients always use privileged # ports. Remove the existing code to temporarily raise privileges in # fs/lockd/host.c, and use the new code in net/sunrpc/xprt.c # # There should no longer be a need to temporarily change the fsuid. # Remove this feature. # -------------------------------------------- # 03/05/07 trond.myklebust@fys.uio.no 1.1063.5.20 # UDP and TCP zero copy code for the NFS client. The main interest # of this patch is to eliminate the use of xdr_kmap() and xdr_unmap() # by replacing them with MSG_MORE. xdr_kmap() is deadlock-prone # due to the fact that it has to kmap() several pages at the same time. # -------------------------------------------- # 03/05/07 acme@conectiva.com.br 1.1063.9.1 # o ipx: ipx_interfaces outlives struct sock/socket # # And thus have to do module refcounting... # -------------------------------------------- # 03/05/07 davem@nuts.ninka.net 1.1063.3.34 # Merge bk://kernel.bkbits.net/acme/ipx-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/07 torvalds@penguin.transmeta.com 1.1063.10.1 # Whee. Fix ancient mailing address. # -------------------------------------------- # 03/05/07 torvalds@penguin.transmeta.com 1.1063.11.1 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into penguin.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.2.15 # Merge kroah.com:/home/greg/linux/BK/bleed-2.5 # into kroah.com:/home/greg/linux/BK/gregkh-2.5 # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.2.16 # [PATCH] USB: update my copyrights in a few locations. # -------------------------------------------- # 03/05/07 torvalds@penguin.transmeta.com 1.1063.12.1 # Merge bk://kernel.bkbits.net/gregkh/linux/linus-2.5 # into penguin.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/07 chas@cmf.nrl.navy.mil 1.1063.3.35 # [ATM]: assorted atm patches # -------------------------------------------- # 03/05/07 chas@cmf.nrl.navy.mil 1.1063.3.36 # [ATM] remove iovcnt from atm_skb # skbs has (and has had for a while) scatter/gather support # making the scatter gather in atm redundant. the current iovcnt # schme really isnt being used anyway typically. the atm # layer will need a little more work in the future to take # advantage of the skb scatter/gather support. this patch # removes the iovcnt dependencies and gets the check for # non linear skbs right. # -------------------------------------------- # 03/05/07 davem@nuts.ninka.net 1.1063.3.37 # [IPV4]: Use time_{before,after}() and proper jiffies types in route.c # -------------------------------------------- # 03/05/07 davem@nuts.ninka.net 1.1063.3.38 # [IPV4]: Two minor errors in jiffies changes. # -------------------------------------------- # 03/05/07 shemminger@osdl.org 1.1063.3.39 # [NET]: Kill more direct references to netdev->refcnt. # -------------------------------------------- # 03/05/07 kuznet@ms2.inr.ac.ru 1.1063.3.40 # [ACENIC]: Comment out netif_wake_queue from acenic watchdog. # -------------------------------------------- # 03/05/07 David_Jeffery@adaptec.com 1.1070 # [PATCH] ips 2.5 driver update [1/4] irq return update # # This is the proper way to report if the interrupt # was from a serveraid or not. # # David Jeffery # # ips.c | 29 ++++++++++++++++------------- # ips.h | 6 +++++- # 2 files changed, 21 insertions(+), 14 deletions(-) # -------------------------------------------- # 03/05/07 davem@nuts.ninka.net 1.1063.3.41 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/07 David_Jeffery@adaptec.com 1.1071 # [PATCH] ips 2.5 driver update [2/4] missing kfree and static init s # # This patch adds a missing kfree on an error path # and removes some cases where static variables # were being explicitly initiated to 0. # # ips.c | 13 ++++++------- # 1 files changed, 6 insertions(+), 7 deletions(-) # -------------------------------------------- # 03/05/07 David_Jeffery@adaptec.com 1.1072 # [PATCH] ips 2.5 driver update [3/4]: misc cleanups # # This patch checks the return code of # pci_set_dma_mask for a 32bit mask, adds a break # to quiet some compilers, and adds some 2.4 compat. # code. # # ips.c | 8 ++++++-- # ips.h | 4 +++- # 2 files changed, 9 insertions(+), 3 deletions(-) # -------------------------------------------- # 03/05/07 David_Jeffery@adaptec.com 1.1073 # [PATCH] ips 2.5 driver update [4/4]: use dev_printk # # Use the new dev_printk. # # Thanks go to Mike Christie who originally # created this patch. # # ips.c | 135 +++++++++++++++++++++++++++--------------------------------------- # ips.h | 5 ++ # 2 files changed, 62 insertions(+), 78 deletions(-) # -------------------------------------------- # 03/05/07 hch@lst.de 1.1074 # [PATCH] remove scsi_slave_attach/scsi_slave_detach # # I added those two to factor out common code from the upper drivers # a long time ago, but after Doug & Lubens nice work there's nothing # left but incrementing/decrementing a counter in struct scsi_device # that's never used except in the case were we not it must be NULL # because we just walked the chain of drivers to detach every single # one.. # -------------------------------------------- # 03/05/07 hch@lst.de 1.1075 # [PATCH] first batch of shost sysfs fixes # # (a) scsi_check_device_busy() is unused now, kill it. Btw, although I # love to see this this really means we need to imply a # scsi_set_device_offline (or even better scsi_set_host_offline) # in scsi_remove_host now.. # (b) make shost_class static to scsi_sysfs.c, with the new device model # changes no LLDD needs this anymore # (c) move private prototypes where they belong. # # BTW, Mike, did I miss something or will your changes make every driver # converted to scsi_add_host & co OOPS on removal now? # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.1 # [PATCH] tc_zs tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.2 # [PATCH] specialix tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.3 # [PATCH] stallion tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.4 # [PATCH] serial_tx3912 tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.5 # [PATCH] sh-sci tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.6 # [PATCH] ser_a2232 tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.7 # [PATCH] serial167 tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.8 # [PATCH] rocket tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.9 # [PATCH] sgi/char/sgiserial tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.10 # [PATCH] rio tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.11 # [PATCH] riscom8 tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.12 # [PATCH] pcxx tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.13 # [PATCH] mxser tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.14 # [PATCH] istallion tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.15 # [PATCH] moxa tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.16 # [PATCH] ip2main tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.17 # [PATCH] isicom tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.18 # [PATCH] esp tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.19 # [PATCH] hvc_console tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.20 # [PATCH] dz tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.21 # [PATCH] cyclades tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.22 # [PATCH] amiserial tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.23 # [PATCH] macintosh/macserial tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.24 # [PATCH] isdn/capi tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.13.25 # [PATCH] vme_scc tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 davem@nuts.ninka.net 1.1063.3.42 # [PKT_SCHED]: Kill iovcnt reference from sch_atm.c # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.13.26 # TTY: add tty class support for all tty devices. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.13.27 # TTY: changes based on tty_register_device() paramater change. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.13.28 # TTY: remove usb-serial sysfs dev file as it is now redundant. # -------------------------------------------- # 03/05/07 torvalds@home.transmeta.com 1.1063.12.2 # Make lib/inflate.c look remotely like ANSI C, so that it can be # properly checked with the rest of the kernel. # -------------------------------------------- # 03/05/07 torvalds@home.transmeta.com 1.1063.12.3 # Avoid using undefined preprocessor symbols: check CONFIG_MK7 with # "defined()" rather than using it as a value. # -------------------------------------------- # 03/05/07 jejb@mulgrave.(none) 1.1076 # Update aacraid to last drop on 2.4 from Alan Cox # -------------------------------------------- # 03/05/07 jejb@mulgrave.(none) 1.1077 # Update aacraid from 2.4->2.5 semantics # # - stanford checker fixes (randy.dunlap) # - updated io_request_lock to correct 2.5 lock # - spelling fixes # - torvalds daemonize changes # - updated templates etc # - update scsicmd-> to scsicmd->device-> for new command alloc code # - update biosparam and add slave_configure # - gendisk name changes # - fix compile warnings # -------------------------------------------- # 03/05/07 markh@osdl.org 1.1078 # [PATCH] New aacraid driver fixed. # # I have the new aacraid driver working on my system now. The patch is # against the 2.5.66 updates that you gave me. I made the following # changes: # # aachba.c aac_scsi_cmd() # There was a race accessing the scsicmd pointer accessing the host_lock. # I made a local pointer to the Scsi_Host so the spin_lock_irq after # aac_read wouldn't panic. I think that sometimes the I/O would be done # and the memory freed before returning invalidating the scsicmd pointer. # I made the same change in aac_io_done in case scsi_done had freed the # scsicmd memory before returning. # # comminit.c aac_alloc_comm() # AdapterFibsVirtualAddress was set to the virtual address of base. I # changed it to set it to the phys address. I compared this to code # pointed to by matt domsch on the aacraid devel list on the 5th. Its # aac_alloc_comm sets this variable to the phys address. This fixed the # probelem where the entry->addr was bad. Another was to fix it I guess # would be to leave this change alone and not try to convert the address # in aac_command_normal. # # dpcsup.c aac_response_normal() # Changed the bus_to_virt to the calculation we talked about last month. # dpcsup.c aac_command_normal() # Changed the bus_to_virt to the calculation. # -------------------------------------------- # 03/05/07 maxk@qualcomm.com 1.1063.12.4 # Merge bk://linux-bt.bkbits.net/marcel-2.5 # into qualcomm.com:/home/kernel/bt-2.5 # -------------------------------------------- # 03/05/07 torvalds@home.transmeta.com 1.1063.14.1 # Use "__attribute__" consistently. # -------------------------------------------- # 03/05/07 torvalds@home.transmeta.com 1.1063.14.2 # Allow external checkers to overrid the "cond_syscall()" macro. # -------------------------------------------- # 03/05/07 torvalds@home.transmeta.com 1.1063.14.3 # Support a "checking" mode for kernel builds, that runs a # user-supplied source checker on all C files before compiling # them. # # I'll release the actual checker once I've cleaned it up a # bit more (yay, all the copyright paperwork completed!) # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.4 # [PATCH] generic subarchitecture for ia32 # # From: Andi Kleen # # This patch adds an generic x86 subarchitecture. It is intended to provide # an dynamic interface for APIC drivers. There are already three subarchitectures # (bigsmp, summit, default) that only differ in how they drive the local APIC. # A fourth - Unisys ES7000 - is scheduled to be merged soon. # # The subarchitecture concept separated this nicely, but it has the big # drawback that they are compile time options. A Linux vendor cannot # ship own binary kernel rpms for all of these machines. Runtime probing # is needed instead. # # This patch adds a new "generic" subarchitecture that just acts as a # dynamic switching layer for APIC drivers. It only tries to virtualize # the APICs, no attempt is made to cover further incompatiblities. # This means machines like the Visual Workstation, pc9800 or # Voyager are not covered; but these are unlikely to be supported by # binary distributions anyways. # # The generic arch reuses the existing interface in mach_ipi / mach_mpparse.h / # mach_apic.h and just pulls it using some macros into an "struct genapic" # object. The main APIC code does not recognize it, it is all hidden # in the mach-generic include files. # # Auto detection of APIC types is supported in the usual way used by # existing ports like Summit - checking ACPI or mptables for specific # signatures - or it can be specified by the user using a new "apic=" # boot option. I also moved the DMI scan to before the generic # subarchitecture probe, so DMI could be used in future too to probe # specific machines. # # Some minor hacks were needed to avoid circular declaration of a few # symbols, but overall it's fairly clean. # # The patch has been tested on a Summit machine, an generic 4 virtual CPUs # Xeon and on an ES7000. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.5 # [PATCH] Fix .altinstructions linking failures # # From: Andi Kleen # # Some configs didn't link anymore because they got references from # .altinstructions to __exit functions. Fixing it at the linker level is not # easily possible. This patch just discards .text.exit at runtime instead of # link time to avoid this. # # It will also fix a related problem with .eh_frame in modern gcc (so far only # observed on x86-64, but could happen on i386 too) # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.6 # [PATCH] cpia driver __exit fix # # From: Andi Kleen # # This driver was bogusly relying on the dropping of the __exit section at link # time. cpia_exit() is calling proc_cpia_destroy(), which doesn't even exist # if !CONFIG_MODULE. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.7 # [PATCH] fix OSS opl3sa2 compilation # # From: Zwane Mwaikambo # # There was a 2.4 merge from Alan Cox, but a few #ifdef's got shuffled around # in the process, resulting in a broken build for !CONFIG_PM # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.8 # [PATCH] misc fixes # # - ifdef fix in kmap_types.h (Oleg Drokin) # # - remove redundant ext3 inclusions (Burton Windle) # # - Fix misidentified warning printk in vmalloc.c # # - radeon_cp printk warning fix (Randy Dunlap) # # - Update minimum binutils version for the ".incbin" thing in vsyscall.S # # - update raw driver to recent module API. # # - update my email address # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.9 # [PATCH] mwave build fix # # From: Michael Buesch and Paul Schroeder. # # mwavedd.h needs and smapi.h # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.10 # [PATCH] drm timer initialisation fix # # The timer is being initialised too late (in ->open()). If modprobe fails we # get an uninitialised timer warning. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.11 # [PATCH] slab: initialisation cleanup and oops fix # # From: Manfred Spraul # # attached is the promised cleanup/bugfix patch for the slab bootstrap: # # - kmem_cache_init & kmem_cache_sizes_init merged into one function, # called after mem_init(). It's impossible to bring slab to an operational # state without working gfp, thus the early partial initialization is not # necessary. # # - g_cpucache_up set to FULL at the end of kmem_cache_init instead of the # module init call. This is a bugfix: slab was completely initialized, # just the update of the state was missing. # # - some documentation for the bootstrap added. # # The minimal fix for the bug is a two-liner: move g_cpucache_up=FULL from # cpucache_init to kmem_cache_sizes_init, but I want to get rid of # kmem_cache_sizes_init, too. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.12 # [PATCH] sysrq-S, sysrq-U cleanups # # From: Christoph Hellwig # # Change sysrq sync/remount from a magic bdflush hook to proper pdflush # operations. The sync operation reuses most of the regular sys_sync path now # instead of implementing it's own superblock walking and (broken) local disk # detection, the remount implementation has been moved to super.c, cleaned up # and updated for the last two years locking changes. It also shares some code # with the regular remount path now. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.13 # [PATCH] s/UPDATE_ATIME/update_atime/ cleanup # # From: Stewart Smith # # Remove the UPDATE_ATIME() macro, use update_atime() directly. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.14 # [PATCH] irqreturn_t for drivers/net/pcmcia # # From: Zwane Mwaikambo # # update pcmcia drivers for new IRQ API # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.15 # [PATCH] keyboard.c Fix CONFIG_MAGIC_SYSRQ+PrintScreen # # From: Chris Heath # # This patch fixes the PrintScreen key when CONFIG_MAGIC_SYSRQ is enabled. It # allows you to use that key normally when Alt is not being pressed. Patch is # against kernel 2.5.68. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.16 # [PATCH] Don't use devfs names in disk_name() # # From: Christoph Hellwig # # disk_name() (and hence bdevname()) are now returning devfs-style device names # when devfs is enabled. # # This is nice, but these names are very long, and they overflow the 32-char # buffers which these functions use. # # The choices are: # # a) Use a bigger buffer (increase BDEVNAME_SIZE). # # This might be practical. But how big? # # b) return the name in kmalloced memory, make caller free it up. Yuk. # # c) Add a print_bdevname() thing and intersperse that amongst the printk's. # This would work. # # d) Just print the non-devfs device name. That's what this patch does. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.17 # [PATCH] devfs: API changes # # From: Christoph Hellwig # # Some people may already have noticed that I've been revamping the devfs API # recently. The worst offender still left is devfs_register, it's prototype # is: # # devfs_handle_t devfs_register(devfs_handle_t dir, # const char *name, unsigned int flags, # unsigned int major, unsigned int minor, # umode_t mode, void *ops, void *info) # # Of these: # # - dir and flags are always zero # - the return value is never used # - info is only used in one driver which doesn't even need it for # operation # - umode_t always describes a character device # - name very often comes from a stack buffer we sprintf'ed into # # so obviously we really want a much simpler API instead. My first draft for # this was: # # int devfs_mk_cdev(dev_t dev, umode_t mode, # struct file_operations *fops, void *info, # const char *fmt, ...) # # this removes the unused argumens, switches to a proper dev_t for the device # number and allows to directly use a printf-like expression as name, getting # rid of the temporary buffers. # # Now Al has reappeared and put the first steps of his CIDR for charater device # on public ftp and we'll soon have a similar lookup object + fops mechanism in # generic code as we already habe for blockdevices, i.e. the devfs code to # assign fops from an entry will become superflous as generic code already does # it. That means the fops and info arguments are obsolete before they were # introduced, so I'd like to propose the following API instead: # # int devfs_mk_cdev(dev_t dev, umode_t mode, const char *fmt, ...) # # which is much nicer anyway. The educated reader will notice that this is # exactly the same prototype devfs_mk_bdev has so I'll probably get suggestions # to merge those two into some kind of devfs_mk_node soon. Personally I don't # like that as character and blockdevices are two really separate entinities # and I'll like to keep them as separate as possible. # # Example patch that introduces the API and converts drivers/input attached. # # Every driver which calls devfs_mk_cdev (about 50) needs conversion. Note # that the transition can happen in pieces - devfs_register continues to work # after this patch, it's just the plan to get rid of it in the end. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.18 # [PATCH] remove partition_name() # # From: Christoph Hellwig # # partition_name() is a variant of __bdevname() that caches results and # returns a pointrer to kmalloc()ed data instead of printing into a buffer. # Due to it's caching it gets utterly confused when the name for a dev_t # changes (can happen easily now with device mapper and probably in the # future with dynamic dev_t users). # # It's only used by the raid code and most calls are through a wrapper, # bdev_partition_name() which takes a struct block_device * that maybe be # NULL. # # The patch below changes the bdev_partition_name() to call bdevname() if # possible and the other calls where we really have nothing more than a dev_t # to __bdevname. # # Btw, it would be nice if someone who knows the md code a bit better than me # could remove bdev_partition_name() in favour of direct calls to bdevname() # where possible - that would also get rid of the returns pointer to string # on stack issue that this patch can't fix yet. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.19 # [PATCH] switch most remaining drivers over to devfs_mk_bdev # # From: Christoph Hellwig # # This is a pretty huge patch, but splitting it doesn't make a lot # of sense.. # # (USB may still need work) # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.20 # [PATCH] dvbdev fixes # # From: Monchi Abbad # # I found a mistake in the dvbdev.c file when creating the dvb /devfs files, # it created /dev/dvb/adapter0device0 instead of /dev/dvb/adapter0/device0. # But here is a simple fix. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.21 # [PATCH] access_ok() race fix for 80386. # # From: Manfred Spraul # # Real 80386 cpus ignore the write protected bit in the page tables when # running in supervisory mode. Thus the write protected bit must be checked by # software. The current implementation does that check during access_ok(). # This can result in data corruptions, if kswapd starts a swap-out between the # access_ok and the actual write operation. # # To fix this, the patch moves the check from access_ok() into # __copy_to_user_ll(), and redirects all user space writes into # __copy_to_user_ll(). The patch only affects kernels build for 80386 cpus. # Additionally, the patch removes the dead prototypes for __put_user_{1,2,4,8}. # # Due to the uninlining of access_ok, the .text segment is now ~ 8 kB shorter. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.22 # [PATCH] hold i_sem on swapfiles # # If a swapfile is ftruncated while in use, subsequent swapout will scribble on # the filesystem. # # This is a case of root-shoot-foot, but wrecking the fs is a fairly rude # response. And it's easy to fix: hold i_sem across the life of the swapon. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.23 # [PATCH] remove unnecessary PAE pgd set # # From: Dave Hansen , Bill Irwin # # With PAE on, there are only 4 PGD entries. The kernel ones never change, # so there is no need to copy them when a vmalloc fault occurs. This was # this was causing problems with the split pmd patches, but it is still # correct for mainline. # # Tested with and without PAE. I ran it in a loop turning on and off 10 swap # partitions, which is what excited the original bug. # http://bugme.osdl.org/show_bug.cgi?id=640 # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.24 # [PATCH] account for slab reclaim in try_to_free_pages() # # try_to_free_pages() currently fails to notice that it successfully freed slab # pages via shrink_slab(). So it can keep looping and eventually call # out_of_memory(), even though there's a lot of memory now free. # # And even if it doesn't do that, it can free too much memory. # # The patch changes try_to_free_pages() so that it will notice freed slab pages # and will return when enough memory has been freed via shrink_slab(). # # Many options were considered, but must of them were unacceptably inaccurate, # intrusive or sleazy. I ended up putting the accounting into a stack-local # structure which is pointed to by current->reclaim_state. # # One reason for this is that we can cleanly resurrect the current->local_pages # pool by putting it into struct reclaim_state. # # (current->local_pages was removed because the per-cpu page pools in the page # allocator largely duplicate its function. But it is still possible for # interrupt-time allocations to steal just-freed pages, so we might want to put # it back some time.) # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.25 # [PATCH] slab: additional debug checks # # From: Manfred Spraul # # below is the promised patch for better slab debugging, against 2.5.68-mm4: # # Changes: # # - enable redzoning and last user accounting even for large objects, if # that doesn't waste too much memory # # - document why FORCED_DEBUG doesn't enable redzoning&last user accounting # for some caches. # # - check the validity of the bufctl chains in a slab in __free_blocks. # This detects double-free error for the caches without redzoning. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.26 # [PATCH] reduced overheads in fget/fput # # From: Dipankar Sarma # # # fget() shows up on profiles, especially on SMP. Dipankar's patch # special-cases the situation wherein there are no sharers of current->files. # # In this situation we know that no other process can close this file, so it # is not necessary to increment the file's refcount. # # It's ugly as sin, but makes a substantial difference. # # The test is # # dd if=/dev/zero of=foo bs=1 count=1M # # On 4CPU P3 xeon with 1MB L2 cache and 512MB ram: # # kernel sys time std-dev # ------------ -------- ------- # # UP - vanilla 2.104 0.028 # UP - file 1.867 0.019 # # SMP - vanilla 2.976 0.023 # SMP - file 2.719 0.026 # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.27 # [PATCH] allow i8042 interrupt sharing # # Ed Tomlinson has a machine on which some other device grabs IRQ12 first, and # the 8042 doesn't work. Enabling shared iRQs in the 8042 driver fixes it up. # Alan has confirmed that this is OK. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.28 # [PATCH] select() speedup # # From: Christoph Hellwig # # Originally by David Mosberger, testing by Roger Luethi. From the ia64 tree. # # Basically, it avoids going to memory all the time. What this does is make # life a lot easier for gcc, so it can actually do a decent amount of # optimization. The restructuring clearly is less important for out-of-order # CPUs, but even there it gives some benefits. # # More specifically, the loop is now structured to operate one "unsigned long" # at a time, rather than one bit at a time. Of course, you still need to # process all the bits, but most of the relevant state in the inner loop can be # kept in registers. # # Roger Luethi measured the routine on a bunch of different machines (mostly # x86, IIRC: P5, P6, Crusoe, Athlons) and performance improved there, too (and # it should definitely improve performance on any RISC-like architecture). # # # Roger's benchmarking results (vs number of fd's): # # File TCP # Numbfer of fd's: 10 250 500 10 250 500 # # UP, Pentium MMX 233MHz original 8.2 108.5 212.8 11.0 180.0 356.5 # UP, Pentium MMX 233MHz w/patch 7.4 87.6 171.1 10.4 163.6 323.4 # # MP, Pentium MMX 233MHz original 15.7 283.8 562.8 18.9 354.4 705.5 # MP, Pentium MMX 233MHz w/patch 14.6 255.6 506.5 17.8 332.8 664.1 # # UP, Athlon 1394 MHz original 1.3 13.4 26.1 1.9 24.7 48.6 # UP, Athlon 1394 MHz w/patch 1.2 11.0 21.5 1.6 22.3 43.8 # # MP, Athlon 1394 MHz original 1.6 22.4 44.6 1.9 30.9 60.5 # MP, Athlon 1394 MHz w/patch 1.5 21.2 41.7 1.9 30.2 59.6 # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.29 # [PATCH] Move security_d_instantiate hook calls # # From: Stephen Smalley # # This patch moves the security_d_instantiate hook calls in d_instantiate and # d_splice_alias after the inode has been attached to the dentry. This # change is necessary so that security modules can internally call the # getxattr inode operation (which takes a dentry parameter) from this hook to # obtain the inode security label. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.30 # [PATCH] ext3 xattr handler for security modules # # From: Stephen Smalley # # This patch against 2.5.68 implements an xattr handler for ext3 to support the # use of extended attributes by security modules for storing file security # labels. As per the earlier discussion of extended attributes for security # modules, this handler uses a "security." prefix and allows for per-module # attribute names. Security checking for userspace access to these attributes # can be performed by the security module using the LSM hooks in fs/xattr.c, # and the security module is free to internally use the inode operations # without restriction for managing its security labels. Unlike the trusted # namespace, these labels are used internally for access control purposes by # the security modules, and controls over userspace access to them require # finer granularity than capable() supports. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.31 # [PATCH] ext2 xattr handler for security modules # # From: Stephen Smalley # # This patch against 2.5.68 implements an xattr handler for ext2 to support the # use of extended attributes by security modules for storing file security # labels. As per the earlier discussion of extended attributes for security # modules, this handler uses a "security." prefix and allows for per-module # attribute names. Security checking on userspace access to these attributes # can be performed by the security module using the LSM hooks in fs/xattr.c, # and the security module is free to internally use the inode operations # without restriction for managing its security labels. Unlike the trusted # namespace, these labels are used internally for access control purposes by # the security module, and controls over userspace access to them require finer # granularity than capable() supports. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.32 # [PATCH] Change LSM hooks in setxattr # # From: Stephen Smalley # # This patch against 2.5.69 adds a security_inode_post_setxattr hook so that # security modules can update the inode security structure after a successful # setxattr, and it moves the existing security_inode_setxattr hook call after # the taking the inode semaphore so that atomicity is provided for the # security check and the update to the inode security structure. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.14.33 # [PATCH] Work around include/linux/sunrpc/svc.h compilation # # From: Grzegorz Jaskiewicz # # gcc-2.94 fails to compile this code, alleging an invalid lvalue. # An equivalent transformation fixes it up. # -------------------------------------------- # 03/05/07 torvalds@home.transmeta.com 1.1063.14.34 # Merge conflicting tty devfs cleanups # -------------------------------------------- # 03/05/08 greg@kroah.com 1.1063.14.35 # TTY: fix up lost devfs_mk_cdev change. # -------------------------------------------- # 03/05/08 greg@kroah.com 1.1063.14.36 # USB: change core to use devfs_mk_cdev() instead of devfs_register() # -------------------------------------------- # 03/05/08 greg@kroah.com 1.1063.14.37 # USB: fix up compile error in tiglusb driver due to devfs_mk_cdev() changes. # -------------------------------------------- # 03/05/08 greg@kroah.com 1.1063.2.17 # Merge gregkh@kernel.bkbits.net:/home/gregkh/linux/linus-2.5 # into kroah.com:/home/linux/linux/BK/gregkh-2.5 # -------------------------------------------- # 03/05/08 greg@kroah.com 1.1063.2.18 # TTY: add lock to tty_dev_list, and handle tty names with more than one '/' # # Thanks to Al Viro for pointing out these problems. # -------------------------------------------- # 03/05/08 davem@nuts.ninka.net 1.1063.15.1 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/08 chas@locutus.cmf.nrl.navy.mil 1.1063.15.2 # [ATM]: Kill stray ATM_PDU_OVHD reference in lec.c # -------------------------------------------- # 03/05/08 mk@linux-ipv6.org 1.1063.15.3 # [IPSEC]: Fix ipcomp header handling in ipv4 IPCOMP. # -------------------------------------------- # 03/05/08 hch@lst.de 1.1079 # [PATCH] rationalize scsi_queue_next & friends # # (1) second arg to scsi_queue_next_request() is only ever non-NULL # inside scsi_lib.c and only used in the first conditional inside # that function - ripped out of scsi_queue_next_request() and # put into a new helper scsi_requeue_command(). # (2) Most remaining callers of are in the form # scsi_put_command(cmd); # scsi_queue_next_request(q, NULL); # add a new helper, scsi_next_command() for them. # (2b) many callers of that still contain a repeated codepath, namely # everything from scsi_release_request except the final kfree. # New helper __scsi_release_request() for those. # (3) All remaining callers loop over the devices of a host and call # scsi_queue_next_request() on them - new helper # scsi_run_host_queues(). # (4) scsi_queue_next_request() renamed to scsi_run_queue(), second # arg is gone and it's static to scsi_lib.c now. # -------------------------------------------- # 03/05/08 rddunlap@osdl.org 1.1063.15.4 # [IPV6]: Remove incorrect comment in ip6_fib.c # -------------------------------------------- # 03/05/08 shemminger@osdl.org 1.1063.15.5 # [SYSKONNECT]: /proc module handling fixup. # -------------------------------------------- # 03/05/08 shemminger@osdl.org 1.1063.15.6 # [PKTGEN]: Module and dev cleanup. # -------------------------------------------- # 03/05/08 steve@gw.chygwyn.com 1.1063.15.7 # [DECNET]: Decnet not obeying netdev locking (from shemminger@osdl.org). # -------------------------------------------- # 03/05/08 hch@lst.de 1.1063.15.8 # [SLIP]: Move over to initcalls. # -------------------------------------------- # 03/05/08 davem@nuts.ninka.net 1.1063.16.1 # Merge http://linux-lksctp.bkbits.net/lksctp-2.5 # into nuts.ninka.net:/home/davem/src/BK/sctp-2.5 # -------------------------------------------- # 03/05/08 davem@nuts.ninka.net 1.1063.15.9 # Merge nuts.ninka.net:/home/davem/src/BK/sctp-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/08 davem@nuts.ninka.net 1.1063.15.10 # [IPV4]: Fix expiration test in rt_check_expire. # -------------------------------------------- # 03/05/08 rusty@rustcorp.com.au 1.1063.15.11 # [NETFILTER]: Fix skb_checksum args in ip_nat_core.c # -------------------------------------------- # 03/05/08 davem@kernel.bkbits.net 1.1063.2.19 # Merge davem@nuts.ninka.net:/home/davem/src/BK/net-2.5 # into kernel.bkbits.net:/home/davem/net-2.5 # -------------------------------------------- # 03/05/08 david-b@pacbell.net 1.1063.17.1 # [PATCH] USB Gadget API (1/6) # # This patch createss , the gadget API # and inlined implementation. # # There's additional kerneldoc, which I won't submit at # this time, available. # -------------------------------------------- # 03/05/08 david-b@pacbell.net 1.1063.17.2 # [PATCH] Net2280 driver (2/6) # # This patch creates drivers/usb/gadget/net2280.[hc], # providing a driver for NetChip's "Net2280 PCI USB 2.0 # High Speed Peripheral Controller". # # It implements the API included in the first patch. # # The driver has behaved well with chiprev 0100 under # stress tests with Gadget Zero and the ethernet model # driver, and has passed sanity tests for chiprev 0110. # -------------------------------------------- # 03/05/08 david-b@pacbell.net 1.1063.17.3 # [PATCH] USB "Gadget Zero" driver (3/6) # # This patch adds "Gadget Zero" (drivers/usb/gadget/zero.c). # # Gadget Zero is a simple gadget driver that's useful for # testing controller drivers, and as an example to be used # for clone/modify style development. # # This driver implements two configurations, and needs only # two bulk endpoints (in addition to ep0) ... so pretty much # any USB device controller should be usable with it in # one configuration or another. It (optionally) supports # high speed devices, and has passed the USB-IF "chapter 9" # device model conformance tests. # # It's worth noticing the kinds of hardware differences that # gadget drivers need to cope with. Endpoints differ, in # ways that must be reflected various ways in descriptors. # And sometimes chip errata cause interoperability problems; # for example, an sa1100 can't change configurations after # enumerating. # -------------------------------------------- # 03/05/08 david-b@pacbell.net 1.1063.17.4 # [PATCH] USB Ethernet Gadget (4/6) # # This patch adds an "Ethernet Gadget" driver, implementing # the CDC Ethernet model (drivers/usb/gadget/ether.c). # # It interops with the current CDC Ether drivers on Linux, # both 2.4 (CDCEther, using Marcelo's latest) and 2.5 # (cdc-ether with recent patches, or on 2.5.68 "usbnet") # # On a net2280, this has successfully streamed dozens of # megabytes per second using "ttcp" (high speed, and using # "usbnet" on the host side), for days at a time. And no # problems using SSH/NFS/etc in lighter duty testing. # # It's possible this will need tweaking to cope with UDC # bugs on Intel's pxa25x controllers, presenting itself # as a non-CDC device. (I'm told altsettings are even # more broken than originally specified to be.) # -------------------------------------------- # 03/05/08 david-b@pacbell.net 1.1063.17.5 # [PATCH] USB Gadget string utility (5/6) # # This adds utility code that gadget drivers can use to manage # string descriptors (drivers/usb/gadget/usbstring.c) in the # common case that the ISO-8859/1 character set is in use. # # Both "Gadget Zero" and the Ethernet gadget code use this. # -------------------------------------------- # 03/05/08 david-b@pacbell.net 1.1063.17.6 # [PATCH] kbuild/kbuild for USB Gadgets (6/6) # # This patch adds kconfig/kbuild support for the preceding # code, so that an EXPERIMENTAL option appears in the # USB part of the config menus. # # Once a USB device controller driver is configured (which # just now means net2280, but sa11x0 and pxa25x options # are just waiting for updates!), gadget driver options # are also available. # -------------------------------------------- # 03/05/08 david-b@pacbell.net 1.1063.17.7 # [PATCH] USB: gadget cleanup of #ifdefs # # > can you get rid of all of the #ifdef HAVE_DRIVER_MODEL stuff? # # Done. Now this code "knows" it's running in a 2.5 # environment, and needs modifications to run on 2.4. # # I also changed the file modes in the module_parm() # calls so the parameters will be writable when they # eventually show up in sysfs; and fixed a typo. # # Compile-tested with and without DEBUG enabled. # -------------------------------------------- # 03/05/08 david-b@pacbell.net 1.1063.17.8 # [PATCH] USB: gadget zero, loopback config fix # # If the host writes OUT packets using URB_ZERO_PACKET # (or its analogue on other USB host systems), then the # loopback configuration should set req->zero, to use that # same transfer termination policy when it writes the # response back IN to the host. # -------------------------------------------- # 03/05/08 david-b@pacbell.net 1.1063.17.9 # [PATCH] USB gadget: net2280: dmachain off, zlp pio ok # # This patch has two small fixes for issues that people # reported to me yesterday: # # - One of the out-of-tree drivers sees odd things # happening when dma chaining is enabled. (The # in-tree drivers seem fine with it.) So disable # for now; it's easily enabled if needed. # # - Zero Length Packets (ZLPs): # # * Should now read/write ok with PIO. # # * On DMA endpoints, explicit ZLPs need PIO. # Until they do, don't allow queuing zero length # buffers onto DMA endpoints. # -------------------------------------------- # 03/05/08 torvalds@penguin.transmeta.com 1.1063.2.20 # Use the right CFLAGS for source checking. Fix grammar. # -------------------------------------------- # 03/05/08 greg@kroah.com 1.1063.18.1 # Merge kroah.com:/home/linux/linux/BK/bleed-2.5 # into kroah.com:/home/linux/linux/BK/gadget-2.5 # -------------------------------------------- # 03/05/08 davem@nuts.ninka.net 1.1063.15.12 # [MPLS]: Add ethernet protocol numbers. # -------------------------------------------- # 03/05/08 davem@nuts.ninka.net 1.1063.15.13 # [NETFILTER]: Fix icmp_reply_translation args. # -------------------------------------------- # 03/05/08 davem@nuts.ninka.net 1.1063.15.14 # [MPLS]: Add MPLS support to PPP. # -------------------------------------------- # 03/05/08 maxk@qualcomm.com 1.1063.12.5 # [Bluetooth] Add required infrastructure for socket module refcounting. # Initialize ->owner fields in Bluetooth protocols and drivers. # -------------------------------------------- # 03/05/08 maxk@qualcomm.com 1.1063.19.1 # Merge bk://linux.bkbits.net/linux-2.5 # into qualcomm.com:/home/kernel/bt-2.5 # -------------------------------------------- # 03/05/08 agrover@groveronline.com 1.1063.20.1 # Merge groveronline.com:/root/bk/linux-2.5 # into groveronline.com:/root/bk/linux-acpi # -------------------------------------------- # 03/05/08 davem@nuts.ninka.net 1.1063.15.15 # [SKFDDI]: Use SET_MODULE_OWNER. # -------------------------------------------- # 03/05/08 davem@nuts.ninka.net 1.1063.15.16 # [IPV6]: Pass route attributes all the way down. # -------------------------------------------- # 03/05/08 davidm@tiger.hpl.hp.com 1.1063.8.4 # ia64: Patch from Asit K. Mallick: fix a few places where last_fph_cpu # wasn't updated and one place in the sigreturn path where # the fph-owner wasn't set. # -------------------------------------------- # 03/05/08 jmorris@intercode.com.au 1.1063.15.17 # [IPSEC]: Use xfrm_state_put in pfkey_msg2xfrm_state. # -------------------------------------------- # 03/05/08 chas@cmf.nrl.navy.mil 1.1063.15.18 # [ATM]: Make he driver code more palatable. # -------------------------------------------- # 03/05/08 davem@nuts.ninka.net 1.1063.15.19 # [NETFILTER]: Fix ip_nat_core.c:manip_pkt return value checks. # -------------------------------------------- # 03/05/08 willy@debian.org 1.1063.15.20 # [DLCI]: Use module_init and fix ioctl handling. # -------------------------------------------- # 03/05/08 ak@muc.de 1.1063.15.21 # [NET]: Clean up socket filter compat handling. # -------------------------------------------- # 03/05/09 nfsclient.adm@hostme.bitkeeper.com 1.1063.2.21 # Merge bk://linux.bkbits.net/linux-2.5 # into hostme.bitkeeper.com:/ua/repos/n/nfsclient/linux-2.5 # -------------------------------------------- # 03/05/09 davej@codemonkey.org.uk 1.1042.125.8 # [AGPGART] Remove duplicate copying of ->chipset in agp_copy_info() # -------------------------------------------- # 03/05/09 davem@nuts.ninka.net 1.1063.21.1 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/09 yoshfuji@linux-ipv6.org 1.1063.21.2 # [MAINTAINERS/CREDITS]: Add entries for USAGI hackers. # -------------------------------------------- # 03/05/09 jmorris@intercode.com.au 1.1063.21.3 # [XFRM]: Make use of xfrm_state_hold(). # -------------------------------------------- # 03/05/09 jmorris@intercode.com.au 1.1063.21.4 # [XFRM]: Use xfrm_pol_hold(). # -------------------------------------------- # 03/05/09 hch@lst.de 1.1063.21.5 # [NET]: Switch x25_asy over to initcalls. # -------------------------------------------- # 03/05/09 davem@nuts.ninka.net 1.1063.21.6 # [XFRM]: Fix typos in xfrm_state_put() changes. # -------------------------------------------- # 03/05/09 marcel@holtmann.org 1.1042.48.4 # [Bluetooth] Send the correct values in RPN response # # This patch fixes a bug in rfcomm_recv_rpn(), which do not set # the correct values for xon_char, xoff_char and flow_ctrl. # -------------------------------------------- # 03/05/09 marcel@holtmann.org 1.1042.48.5 # [Bluetooth] Handle priority bits in parameter negotiation # # The PN response have to return the same value for the priority # bits as in the request. The priority value is now also stored # in the rfcomm_dlc structure and the default value is 7. # -------------------------------------------- # 03/05/09 torvalds@home.transmeta.com 1.1063.22.1 # Make aic7xxx driver use ANSI prototypes. My checker tool refuses # to touch K&R C. # -------------------------------------------- # 03/05/09 torvalds@penguin.transmeta.com 1.1063.21.7 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into penguin.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/09 agrover@groveronline.com 1.1063.23.1 # Merge groveronline.com:/root/bk/linux-2.5 # into groveronline.com:/root/bk/linux-acpi # -------------------------------------------- # 03/05/09 maxk@qualcomm.com 1.1063.19.2 # [Bluetooth] L2CAP config req/rsp fixes. # We have to set continuation flag in config rsp if it was set in req. # -------------------------------------------- # 03/05/09 greg@kroah.com 1.1063.24.1 # [PATCH] i2c: add i2c_adapter class support # -------------------------------------------- # 03/05/09 mark@alpha.dyndns.org 1.1063.24.2 # [PATCH] I2C: add more classes # # Add I2C classes for analog and digital cameras, and fix a typo. # -------------------------------------------- # 03/05/09 torvalds@penguin.transmeta.com 1.1063.21.8 # Annotate LDT system calls with user pointer annotations. # -------------------------------------------- # 03/05/09 torvalds@penguin.transmeta.com 1.1063.21.9 # Annotate x86 system calls with user pointer annotations. # -------------------------------------------- # 03/05/09 torvalds@penguin.transmeta.com 1.1063.21.10 # Fix mismatch between i387 user copy function declaration and # definition. # -------------------------------------------- # 03/05/09 torvalds@penguin.transmeta.com 1.1063.21.11 # Annotate IPC system calls with user pointer annotations # -------------------------------------------- # 03/05/09 torvalds@penguin.transmeta.com 1.1063.21.12 # Annotate vm86_info as a pointer to user space. # -------------------------------------------- # 03/05/09 warp@mercury.d2dc.net 1.1063.24.3 # [PATCH] I2C: Another it87 patch. # # This is against my last. # # While the old code most definitely did /something/ to the register for # setting the fan div, the 'what' is a more interesting question. # # To be honest I could not figure out what it was trying to do, because # the way it was inserting values disagreed with not only the data sheet, # but how it parsed the very same register. # # This corrects the issue, and allows one to properly control the divisor # on all 3 fans, including the (much more limited) 3rd fan. # -------------------------------------------- # 03/05/09 warp@mercury.d2dc.net 1.1063.24.4 # [PATCH] I2C: Yet another it87 patch. # # Ok, after writing up something in the way of a perl script to make some # sense of the data for voltages, and finding that there is no sense to # make, I took a longer look at things. # # The it87 driver in 2.5.x is doing some, down right /odd/ math on the # numbers for the in_input* readings, and the 2.4.x driver is doing # something quite different. # # And while it might be possible to get sane numbers out of the 2.5.x # driver, people /expect/ to get the numbers that they were getting from # 2.4.x. # # So this patch puts things back to the simpler calculations done by the # 2.4.x lm-sensors drivers, and my script confirms that the numbers come # out right. # -------------------------------------------- # 03/05/09 warp@mercury.d2dc.net 1.1063.24.5 # [PATCH] I2C: And another it87 patch. # # Don't provide min/max for in8, which allowed one to scribble on # registers one should not be messing with. (My fault, oops.) # # The setting of the temp high/low registers was off by one, not mine this # time. While I was at it, I reordered a few other register accesses to # be base 0 instead of base 1. # # The temp interface was slightly incorrect, degrees * 100 instead of # degrees * 1000, also fixed. # # And lastly, when changing the fan count divisor, fix up the min setting # to still be roughly the same. (Previously the meaning of the value in # the register changed, but not the value itself, resulting in, undesired # surprises.) # -------------------------------------------- # 03/05/09 greg@kroah.com 1.1063.24.6 # [PATCH] i2c: register the i2c_adapter_driver so things link up properly in sysfs # -------------------------------------------- # 03/05/09 greg@kroah.com 1.1063.21.13 # Merge kroah.com:/home/greg/linux/BK/bleed-2.5 # into kroah.com:/home/greg/linux/BK/i2c-2.5 # -------------------------------------------- # 03/05/09 rohit.seth@intel.com 1.1063.8.5 # [PATCH] ia64: enable 1G hugepage size for Mckinley # # -------------------------------------------- # 03/05/09 corbet@lwn.net 1.1063.25.1 # [PATCH] cpufreq class fix # -------------------------------------------- # 03/05/09 greg@kroah.com 1.1063.25.2 # [PATCH] driver core: Add driver symlink to class devices in sysfs. # # Thanks to Mike Anderson for the idea for this. # -------------------------------------------- # 03/05/09 greg@kroah.com 1.1063.25.3 # [PATCH] driver core: remove unneeded line in class code. # # Thanks to Jonathan Corbet for pointing this out. # -------------------------------------------- # 03/05/09 maxk@qualcomm.com 1.1063.19.3 # [Bluetooth] Detect and log error condition when first L2CAP fragment is too long. # -------------------------------------------- # 03/05/09 vandrove@vc.cvut.cz 1.1063.26.1 # [PATCH] Fix potential runqueue deadlock # # send_sig_info() has been broken since 2.5.60. # # The function can be invoked from a the time interrupt (timer_interrpt -> # do_timer -> update_process_times -> -> update_one_process -> ( # do_process_times, do_it_prof, do_it_virt ) -> -> send_sig -> # send_sig_info) but it uses spin_unlock_irq instead of the correct # spin_unlock_irqrestore. # # This enables interrupts, and later scheduler_tick() locks runqueue # (without disabling interrupts). And if we are unlucky, a new interrupt # comes at this point. And if this interrupt tries to do wake_up() (like # RTC interrupt does), we will deadlock on runqueue lock :-( # # The bug was introduced by signal-fixes-2.5.59-A4, which split the # original send_sig_info into two functions, and in one branch it started # using these unsafe spinlock variants (while the "group" variant uses # irqsave/restore correctly). # -------------------------------------------- # 03/05/09 maxk@qualcomm.com 1.1063.19.4 # Merge bk://linux-bt.bkbits.net/marcel-2.5 # into qualcomm.com:/home/kernel/bt-2.5 # -------------------------------------------- # 03/05/09 maxk@qualcomm.com 1.1063.19.5 # [Bluetooth] RFCOMM must wait for MSC exchange to complete before sending data. # -------------------------------------------- # 03/05/09 greg@kroah.com 1.1063.21.14 # Merge greg@deskfan:linux/BK/i2c-2.5 # into kroah.com:/home/greg/linux/BK/i2c-2.5 # -------------------------------------------- # 03/05/09 greg@kroah.com 1.1063.25.4 # Merge greg@deskfan:linux/BK/class-2.5 # into kroah.com:/home/greg/linux/BK/class-2.5 # -------------------------------------------- # 03/05/09 greg@kroah.com 1.1063.26.2 # Merge greg@desk:linux/BK/gadget-2.5 # into kroah.com:/home/greg/linux/BK/gadget-2.5 # -------------------------------------------- # 03/05/10 davej@codemonkey.org.uk 1.1042.125.9 # [AGPGART] death of generic-3.0.c = folded into generic.c # -------------------------------------------- # 03/05/10 davej@codemonkey.org.uk 1.1042.125.10 # [AGPGART] Add proper AGP3 initialisation routine. # -------------------------------------------- # 03/05/10 davej@codemonkey.org.uk 1.1042.125.11 # [AGPGART] Make sure we don't poke reserved bits when enabling agp v3 # -------------------------------------------- # 03/05/10 davej@codemonkey.org.uk 1.1042.125.12 # [AGPGART] Add missing #defines from last checkin. # -------------------------------------------- # 03/05/10 davej@codemonkey.org.uk 1.1042.125.13 # [AGPGART] Use symbolic defines for isoch registers in isoch code. # -------------------------------------------- # 03/05/10 davej@codemonkey.org.uk 1.1042.125.14 # [AGPGART] CodingStyle nitpicks for isoch.c # -------------------------------------------- # 03/05/10 davidm@tiger.hpl.hp.com 1.1063.8.6 # ia64: Prepare for GCC v3.4. Sync with 2.5.69. # -------------------------------------------- # 03/05/10 davidm@tiger.hpl.hp.com 1.1063.8.7 # ia64: Patch by John Marvin: Add virtual mem-map support. # -------------------------------------------- # 03/05/10 davem@nuts.ninka.net 1.1063.27.1 # [TCP]: NULL out newsk->owner in tcp_create_openreq_child(). # -------------------------------------------- # 03/05/10 jgarzik@redhat.com 1.1063.27.2 # [SCTP]: Fix missing Kconfig dependency. # -------------------------------------------- # 03/05/10 shemminger@osdl.org 1.1063.27.3 # [IPV4/IPV6]: inetsw using RCU. # -------------------------------------------- # 03/05/10 yoshfuji@linux-ipv6.org 1.1063.27.4 # [IPV6]: Convert /proc/net/raw6 to seq_file. # -------------------------------------------- # 03/05/10 davej@codemonkey.org.uk 1.1042.125.15 # [AGPGART] Make the agp 3.5 use the agp3 code for enabling, leaving just the isoch stuff in isoch.c # -------------------------------------------- # 03/05/10 James.Bottomley@steeleye.com 1.1080 # [PATCH] sd.c spinup code can go into a wild loop # # This problem was reported against 2.4 by Eddie.Williams@SteelEye.com # # There's a problem in the sd spinup code in that if the unit returns NOT # READY, we begin to spin it up, but thereafter if it returns anything # other than NOT READY or success, the while loop in the spinup code will # be executed *without* the 1s delay that's in the NOT READY case. # # The problem was seen with a real device: Compaq multi-path storage # arrays return NOT READY to probes down inactive paths, but when the # start unit is sent to activate the path, they can then respond back with # error conditions. # # The fix is to terminate the while loop for any unexpected return. # -------------------------------------------- # 03/05/10 hch@lst.de 1.1081 # [PATCH] some warning fixes # -------------------------------------------- # 03/05/10 hch@lst.de 1.1082 # [PATCH] fix the aacraid merge a bit more # -------------------------------------------- # 03/05/10 hch@lst.de 1.1083 # [PATCH] scsi_report_device_reset # # aic7xxx/79xx wants a variant of scsi_report_bus_reset that operates # only on a single device. Implement it to get rid of shost->my_devices # traversals in drivers. (and move both to scsi_error.c) # -------------------------------------------- # 03/05/10 andmike@us.ibm.com 1.1084 # [PATCH] scsi_host sysfs updates scsi-misc-2.5 [1/2] # # -andmike # -- # Michael Anderson # andmike@us.ibm.com # # # DESC # scsi_debug cleanups for scsi-misc-2.5 # - Remove release function. # - Remove scsi_debug wrapper driver register / unregister functions. # - Douglas's target == this_id fix. # - Remove some old cleanups that where incorrect. # - Move code back into sdebug_driver_remove. # EDESC # # # drivers/scsi/scsi_debug.c | 78 ++++++++++++++-------------------------------- # drivers/scsi/scsi_debug.h | 1 # 2 files changed, 25 insertions(+), 54 deletions(-) # -------------------------------------------- # 03/05/10 andmike@us.ibm.com 1.1085 # [PATCH] scsi_host sysfs updates scsi-misc-2.5 [2/2] # # Here is an update of the patch with the externs in scsi_priv.h # # -andmike # -- # Michael Anderson # andmike@us.ibm.com # # DESC # scsi shost sysfs cleanups for scsi-misc-2.5 # - Add LLDD short name to scsi_host struct device. # - scsi_host_release now calls scsi_free_shost. # - Switched from device_register / device_unregister and class_register # / class_register to initialize, add, del, put pairs. # - Moved some function from scsi_register and scsi_unregister. # - Filled in scsi_host_put and scsi_host_get. # # Rev 2 move externs to scsi_priv.h # EDESC # # # drivers/scsi/hosts.c | 33 ++++++++++++++++++++++++++++----- # drivers/scsi/scsi_priv.h | 2 ++ # drivers/scsi/scsi_sysfs.c | 19 +++++++++++-------- # 3 files changed, 41 insertions(+), 13 deletions(-) # -------------------------------------------- # 03/05/10 hch@lst.de 1.1086 # [PATCH] consolidate devlist handling in a single file # # Currently it's spread all over the scsi midlayer but having this # nicely separate out to a file of it's own without exposing the # data structures sounds like a good idea. # -------------------------------------------- # 03/05/10 chas@cmf.nrl.navy.mil 1.1063.27.5 # [ATM]: HE and IPHASE driver fixes. # -------------------------------------------- # 03/05/10 yoshfuji@linux-ipv6.org 1.1063.27.6 # [NET]: Set file_operations->owner as appropriate. # -------------------------------------------- # 03/05/10 davem@nuts.ninka.net 1.1063.27.7 # [VLAN]: vlanproc.c needs module.h # -------------------------------------------- # 03/05/10 torvalds@home.transmeta.com 1.1063.21.15 # Merge master.kernel.org:/home/gregkh/BK/i2c-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/10 torvalds@home.transmeta.com 1.1063.21.16 # Merge master.kernel.org:/home/gregkh/BK/gadget-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/10 torvalds@home.transmeta.com 1.1063.21.17 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/10 axboe@suse.de 1.1063.21.18 # [PATCH] bio_endio() increments bio->bi_sector # # increment bi_sector in bio_endio() so make_request_fn drivers don't # have to do this accounting themselves. # -------------------------------------------- # 03/05/10 axboe@suse.de 1.1063.21.19 # [PATCH] make MO drive work with ide-floppy/ide-cd # # Resend of the ide-cd buggy debug check removal. # # From der.eremit@email.de. # -------------------------------------------- # 03/05/10 axboe@suse.de 1.1063.21.20 # [PATCH] shrink deadline hash size # # Limit deadline hash to 32 entries instead of 1024. This has been benched # and profiled extensively and shows no increased system time. # # Also, move "hot" entries to the front of the list. # -------------------------------------------- # 03/05/10 axboe@suse.de 1.1063.21.21 # [PATCH] dynamic request allocation # # This patch adds dynamic allocation of request structures. Right now we # are reserving 256 requests per initialized queue, which adds up to quite # a lot of memory for even a modest number of queues. For the quoted 4000 # disk systems, it's a disaster. # # Instead, we mempool 4 requests per queue and put an upper limit on the # number of requests that we will put in-flight as well. I've kept the 128 # read/write max in-flight limit for now. It is trivial to experiement # with larger queue sizes now, but I want to change one thing at the time # (the truncate scenario doesn't look all that good with a huge number of # requests, for instance). # # Patch has been in -mm for a while, I'm running it here against stock 2.5 # as well. Additionally, it actually kills quite a bit of code as well # -------------------------------------------- # 03/05/10 nfsclient.adm@hostme.bitkeeper.com 1.1063.2.22 # Merge bk://linux.bkbits.net/linux-2.5 # into hostme.bitkeeper.com:/ua/repos/n/nfsclient/linux-2.5 # -------------------------------------------- # 03/05/11 James.Bottomley@steeleye.com 1.1087 # [PATCH] Correct typo in linux/scsi/scsi.h and introduce new # # I notice we seem to have a typo in the SAM_ status codes (they say # IMMEDIATE where they mean INTERMEDIATE). # # I've also introduced a new macro who's job is to return true if any of # the possible good return codes is found. This means # # SAM_STAT_GOOD # SAM_STAT_INTERMEDIATE # SAM_STAT_INTERMEDIATE_CONDITION_MET # # and for now # # SAM_STAT_COMMAND_TERMINATED # # By and large, this is currently irrelevant to us, since we don't use # linked commands and I've never met a device using COMMAND TERMINATED, # but it may help us in the future. # -------------------------------------------- # 03/05/11 hch@lst.de 1.1063.21.22 # [PATCH] switch sb1000 to new style net init & pnp # # This cleans up the driver big time and gets rid of a big ugly wart # in setup.c. Note that I don't have the hardware so this is only # compile-tested. # -------------------------------------------- # 03/05/11 jt@bougret.hpl.hp.com 1.1063.21.23 # [PATCH] irq fixes for wavelan_cs/netwave_cs # # This patch for 2.5.68-bk11 will fix the irq handler of some # obsolete wireless drivers (wavelan, wavelan_cs and netwave_cs) plus # assorted fixes. All those drivers have been tested on a SMP box. # -------------------------------------------- # 03/05/11 jt@bougret.hpl.hp.com 1.1063.21.24 # [PATCH] Wireless Extension 16 # # This patch for 2.5.68-bk11 will update Wireless Extension to # version 16 : # o increase bitrate and frequency number for 802.11g/802.11a # o enhanced iwspy support # o minor tweaks and cleanups # # This patch is only for the core of WE. The patches for the # individual drivers have been sent to their respective maintainers. # Compared to the previous version I sent you a few weeks ago, # I've just updated to the latest kernel. # -------------------------------------------- # 03/05/11 jt@bougret.hpl.hp.com 1.1063.21.25 # [PATCH] WE-16 for Wavelan ISA driver # # This update the Wavelan ISA driver for Wireless Extension 16 # (going with my previous patch). # -------------------------------------------- # 03/05/11 jt@bougret.hpl.hp.com 1.1063.21.26 # [PATCH] WE-16 for Wavelan Pcmcia driver # # This patch update the Wavelan Pcmcia driver for Wireless # Extensions 16, and also remove all the backward compatibility cruft # that is broken anyway. # -------------------------------------------- # 03/05/11 paulus@samba.org 1.1063.21.27 # [PATCH] Update mac ethernet drivers # # This patch updates the bmac and mace ethernet drivers so that their # interrupt routines return an irqreturn_t, and updates the bmac driver # to use a spinlock rather than global cli/sti. # -------------------------------------------- # 03/05/11 dean@arctic.org 1.1063.21.28 # [PATCH] better ali1563 integrated ethernet support # # it turns out the tulip driver is a much better driver for the integrated # ali1563 ethernet than the dmfe driver... the dmfe driver gets tx timeouts # every ~15s and can't receive over 5MB/s. but with the small tulip patch # below i'm seeing 11MB/s+ in both directions without problems. # -------------------------------------------- # 03/05/11 mzyngier@freesurf.fr 1.1063.21.29 # [PATCH] depca update (was Re: [Patch] DMA mapping API for Alpha) # # this patch has been sleeping # in Alan tree for quite some time. It updates the depca driver to the # EISA/sysfs API, gets rid of check_region, and properly reserve memory # region. Patch is against latest BK. # -------------------------------------------- # 03/05/11 jgarzik@redhat.com 1.1063.28.1 # [bk] add useful tip to bk kernel howto # # Kudos to Wayne Scott @ BitMover for this. # -------------------------------------------- # 03/05/11 axboe@suse.de 1.1063.21.30 # [PATCH] Proper 48-bit lba support # -------------------------------------------- # 03/05/11 torvalds@home.transmeta.com 1.1063.21.31 # Merge bk://kernel.bkbits.net/jgarzik/misc-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/11 torvalds@home.transmeta.com 1.1063.21.32 # Merge bk://linux-dj.bkbits.net/cpufreq # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/11 torvalds@home.transmeta.com 1.1063.21.33 # Merge bk://linux-dj.bkbits.net/agpgart # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/11 mikpe@csd.uu.se 1.1063.21.34 # [PATCH] restore sysenter MSRs at APM resume # # This changes apm.c to invoke suspend.c's save and restore processor # state procedures around suspends, which fixes the SYSENTER MSR problem. # # The patch also decouples sysenter.c from SOFTWARE_SUSPEND: the variables # used (only!) in suspend_asm.S are moved there, and the include file now # declares the procedures called from apm.c (previously they were only # called from suspend_asm.S). # -------------------------------------------- # 03/05/11 torvalds@home.transmeta.com 1.1063.2.23 # Merge http://nfsclient.bkbits.net/linux-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/11 B.Zolnierkiewicz@elka.pw.edu.pl 1.1063.2.24 # [PATCH] fix lost IDE interrupt problem # # Alan and I were investigating this, but we don't know why the problem # occurs. # # This reverts the previous handling of masked_irq, and fixes the problem. # -------------------------------------------- # 03/05/11 jejb@raven.il.steeleye.com 1.1088 # Fix thinko introduced into include/scsi/scsi.h # # SAM_STAT_* are return codes, not bitmaps # -------------------------------------------- # 03/05/11 rth@kanga.twiddle.net 1.1063.29.1 # [ALPHA] Fix titan_intr_nop for 2.5 irq api changes. # -------------------------------------------- # 03/05/11 davem@nuts.ninka.net 1.1063.30.1 # [IPV4/IPV6]; Missing schedule_net() in inet{,6}_del_protocol. # -------------------------------------------- # 03/05/11 davem@nuts.ninka.net 1.1063.30.2 # [NETFILTER]: Fix stale skb data pointer usage in ipv4 NAT. # -------------------------------------------- # 03/05/11 davem@kernel.bkbits.net 1.1063.2.25 # Merge davem@nuts.ninka.net:/home/davem/src/BK/net-2.5 # into kernel.bkbits.net:/home/davem/net-2.5 # -------------------------------------------- # 03/05/11 davej@codemonkey.org.uk 1.1042.125.16 # [AGPGART] add checks to agp_copy_info() before dereferencing. # Spotted by Andi Kleen with AGPless IOMMU setup. # -------------------------------------------- # 03/05/11 davej@tetrachloride.(none) 1.1063.31.1 # Merge tetrachloride.(none):/mnt/raid/src/kernel/2.5/bk-linus # into tetrachloride.(none):/mnt/raid/src/kernel/2.5/agpgart # -------------------------------------------- # 03/05/11 rmk@flint.arm.linux.org.uk 1.1063.32.1 # Merge flint.arm.linux.org.uk:/usr/src/linux-bk-2.5/linux-2.5 # into flint.arm.linux.org.uk:/usr/src/linux-bk-2.5/linux-2.5-rmk # -------------------------------------------- # 03/05/11 davem@nuts.ninka.net 1.1063.30.3 # [IPV6]: Missing sk->family check in UDPv6 multicast handling. # -------------------------------------------- # 03/05/11 davem@kernel.bkbits.net 1.1063.2.26 # Merge davem@nuts.ninka.net:/home/davem/src/BK/net-2.5 # into kernel.bkbits.net:/home/davem/net-2.5 # -------------------------------------------- # 03/05/11 torvalds@home.transmeta.com 1.1063.2.27 # Bartlomiej says: 'Please revert this patch, it is unfinished.' # We'll do it *after* IDE taskfile IO is done # Cset exclude: axboe@suse.de|ChangeSet|20030511184946|49736 # -------------------------------------------- # 03/05/11 torvalds@home.transmeta.com 1.1063.2.28 # Merge bk://are.twiddle.net/axp-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/11 torvalds@home.transmeta.com 1.1063.2.29 # Merge http://lia64.bkbits.net/to-linus-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/11 david-b@pacbell.net 1.1063.2.30 # [PATCH] more kbuild tweaks] # # This fixes a typo reported by Geert, and more significantly # fixes static linking so that it works even when only the # device side of USB is enabled, and the host side (CONFIG_USB) # isn't. # -------------------------------------------- # 03/05/11 david-b@pacbell.net 1.1063.2.31 # [PATCH] Fix big-endian USB gadget build # # Initializers must be constant expressions, and thus we can't use the # complex expression "cpu_to_le*()" - the end result of which may have a # constant _value_ but the expression itself isn't a constant expression. # # So use the explicitly constant "__constant_cpu_to_*()" expression # instead. # -------------------------------------------- # 03/05/11 rusty@rustcorp.com.au 1.1063.33.1 # [NETFILTER]: Move ip_fw declarations into header file. # -------------------------------------------- # 03/05/11 zaitcev@redhat.com 1.1063.34.1 # [SPARC]: Fix shadowing of global max_pfn, kill BOOTMEM_DEBUG. # -------------------------------------------- # 03/05/11 zaitcev@redhat.com 1.1063.34.2 # [SPARC]: Allow esp to use highmem_io on sparc32. # -------------------------------------------- # 03/05/11 zaitcev@redhat.com 1.1063.34.3 # [SPARC]: New compact show_regs format. # -------------------------------------------- # 03/05/12 hch@lst.de 1.1089 # [PATCH] two more templates in headers # # I missed aic7xxx_old and cciss_scsi. For the first it's the trivial # move, for the second it's the patch to move to scsi_add_host & friend # as already ACKed by Steve when he still was cciss maintainer. # -------------------------------------------- # 03/05/12 bgerst@didntduck.org 1.1063.2.32 # [PATCH] Fix ioperm bitmap # # This makes sure that the ioperm bitmap in the TSS is correctly set up # during the first ioperm() call. Without this the TSS bitmap contains # random garbage until the next context switch. # -------------------------------------------- # 03/05/12 agrover@groveronline.com 1.1063.23.2 # ACPI: kobject fix (Greg KH) # Here's a small patch that fixes the logic of the kobject creation and # registration in the acpi code (since we use kobject_init(), we need to # use kobject_add(), not kobject_register() to add the kobject to the # kernel systems). # -------------------------------------------- # 03/05/12 agrover@groveronline.com 1.1063.23.3 # ACPI: Allow ":" in OS override string (Ducrot Bruno) # -------------------------------------------- # 03/05/12 agrover@groveronline.com 1.1063.23.4 # ACPI: Interpreter update to 20030509 # Changed the subsystem initialization sequence to hold off installation of # address space handlers until the hardware has been initialized and the # system has entered ACPI mode. This is because the installation of space # handlers can cause _REG methods to be run. Previously, the _REG methods # could potentially be run before ACPI mode was enabled. # # Fixed some memory leak issues related to address space handler and notify # handler installation. There were some problems with the reference count # mechanism caused by the fact that the handler objects are shared across # several namespace objects. # # Fixed a reported problem where reference counts within the namespace were # not properly updated when named objects created by method execution were # deleted. # # Fixed a reported problem where multiple SSDTs caused a deletion issue # during subsystem termination. Restructured the table data structures # to simplify the linked lists and the related code. # # Fixed a problem where the table ID associated with secondary tables (SSDTs) # was not being propagated into the namespace objects created by those # tables. This would only present a problem for tables that are unloaded # at run-time, however. # # Updated AcpiOsReadable and AcpiOsWritable to use the ACPI_SIZE type as # the length parameter (instead of UINT32). # # Solved a long-standing problem where an ALREADY_EXISTS error appears on # various systems. This problem could happen when there are multiple # PCI_Config operation regions under a single PCI root bus. This doesnt # happen very frequently, but there are some systems that do this in the # ASL. # # Fixed a reported problem where the internal DeleteNode function was # incorrectly handling the case where a namespace node was the first in # the parents child list, and had additional peers (not the only child, # but first in the list of children.) # -------------------------------------------- # 03/05/12 davej@codemonkey.org.uk 1.1063.31.2 # [DRM] Intel i8xx DRM modules are dependant on their AGP counterparts. # Closes bugzilla #646 # -------------------------------------------- # 03/05/12 davej@tetrachloride.(none) 1.1063.35.1 # Merge tetrachloride.(none):/mnt/raid/src/kernel/2.5/bk-linus # into tetrachloride.(none):/mnt/raid/src/kernel/2.5/agpgart # -------------------------------------------- # 03/05/12 torvalds@penguin.transmeta.com 1.1063.2.33 # Use '#ifdef' to test for CONFIG_xxx variables, instead of depending # on undefined preprocessor symbols evaluating to zero. # # Make smpboot.c look like ANSI C with proper function declarations. # -------------------------------------------- # 03/05/12 torvalds@penguin.transmeta.com 1.1063.2.34 # Add user pointer annotations. # -------------------------------------------- # 03/05/12 agrover@groveronline.com 1.1063.36.1 # Merge groveronline.com:/root/bk/linux-2.5 # into groveronline.com:/root/bk/linux-acpi # -------------------------------------------- # 03/05/12 torvalds@penguin.transmeta.com 1.1063.2.35 # Use '#ifdef' to test for CONFIG_xxx variables, instead of # depending on undefined preprocessor symbols evaluating to zero. # # Make panic.c use proper function prototypes. # -------------------------------------------- # 03/05/12 torvalds@penguin.transmeta.com 1.1063.2.36 # Add user pointer annotations to core sysctl files. # -------------------------------------------- # 03/05/12 maxk@qualcomm.com 1.1063.37.1 # Merge bk://linux.bkbits.net/linux-2.5 # into qualcomm.com:/home/kernel/bt-2.5 # -------------------------------------------- # 03/05/12 davem@nuts.ninka.net 1.1063.38.1 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/12 shemminger@osdl.org 1.1063.38.2 # [BRIDGE]: Bridge timer performance enhancement. # -------------------------------------------- # 03/05/12 shemminger@osdl.org 1.1063.38.3 # [NET]: Network packet type using RCU. # * packet type converted from linked list to list_macro # * writer lock replaced with spin lock, readers use RCU # * add __dev_remove_pack for callers that cant sleep. # * af_packet changes to handle and sleeping requirements, and possible # races that could cause. # -------------------------------------------- # 03/05/12 shemminger@osdl.org 1.1063.38.4 # [BRLOCK]: Kill big reader locks, no longer used. # -------------------------------------------- # 03/05/12 shemminger@osdl.org 1.1063.38.5 # [IPV4/IPV6]: synchronize_kernel --> synchronize_net. # -------------------------------------------- # 03/05/12 davem@nuts.ninka.net 1.1063.38.6 # [BRLOCK]: Kill stray brlock.h references in sparc/sparc64 headers. # -------------------------------------------- # 03/05/12 jmorris@intercode.com.au 1.1063.38.7 # [IPSEC]: Implement proper IPIP tunnel handling for IPcomp. # -------------------------------------------- # 03/05/12 jmorris@intercode.com.au 1.1063.38.8 # [CRYPTO]: Fix config dependencies. # -------------------------------------------- # 03/05/12 kazunori@miyazawa.org 1.1063.38.9 # [IPV4]: Introduce ip6_append_data. # -------------------------------------------- # 03/05/12 torvalds@penguin.transmeta.com 1.1063.2.37 # Add user pointer annotations to socket, file IO and signal # handling. # # This pointed out a bug in x86 sys_rt_sigreturn(), btw. # -------------------------------------------- # 03/05/12 davidm@napali.hpl.hp.com 1.1063.2.38 # [PATCH] Add ia64 relocation types to elf.h and clean up # # There is a _lot_ of stuff in linux/elf.h that shouldn't be there. # # This moves the arch-specific stuff in linux/elf.h into the corresponding # asm header files. # -------------------------------------------- # 03/05/12 davem@nuts.ninka.net 1.1063.38.10 # [IPV6]: Fix two bugs in ip6_append_data changes. # - Export ip_generic_getfrag # - In udp6 increment v6 udp statistics not v4 one # -------------------------------------------- # 03/05/12 davem@kernel.bkbits.net 1.1063.2.39 # Merge davem@nuts.ninka.net:/home/davem/src/BK/sparc-2.5 # into kernel.bkbits.net:/home/davem/sparc-2.5 # -------------------------------------------- # 03/05/12 mochel@osdl.org 1.1042.8.4 # kobject: Update Documentation # # From Geert Uytterhoeven. # -------------------------------------------- # 03/05/12 bunk@fs.tum.de 1.1063.38.11 # [NET]: wireless.c needs module.h # -------------------------------------------- # 03/05/12 mochel@osdl.org 1.1063.39.1 # Merge osdl.org:/home/mochel/src/kernel/devel/linux-2.5-virgin # into osdl.org:/home/mochel/src/kernel/devel/linux-2.5-core # -------------------------------------------- # 03/05/12 davem@nuts.ninka.net 1.1063.38.12 # [NETFILTER]: ip_ct_gather_frags no longer needs to linearize. # -------------------------------------------- # 03/05/12 davem@nuts.ninka.net 1.1063.38.13 # [PKT_SCHED]: sch_ingress.c does not need to linearize SKBs. # -------------------------------------------- # 03/05/12 rmk@flint.arm.linux.org.uk 1.1063.40.1 # [PCMCIA] Add per-socket thread to process socket events. # # Add a per-socket kernel thread, which is responsible for processing # insertion, removal, battery status and ready status changes. We # also add a semaphore to prevent multiple threads trying to change # the socket suspend/present state. # # This will allows us to eliminate the per-socket work queues, and # will allow us to handle the card insertion without resources # cleanly. # -------------------------------------------- # 03/05/12 andmike@us.ibm.com 1.1090 # [PATCH] scsi_host sysfs updates fix release behaviour # # Fix scsi sysfs init so that a scsi_unregister can be called anytime after # a scsi_register. # - Create scsi_sysfs_init_host function and call from # scsi_register. # # drivers/scsi/hosts.c | 4 ++-- # drivers/scsi/scsi_priv.h | 1 + # drivers/scsi/scsi_sysfs.c | 25 ++++++++++++++++--------- # 3 files changed, 19 insertions(+), 11 deletions(-) # -------------------------------------------- # 03/05/12 jejb@raven.il.steeleye.com 1.1091 # Fix use after free in scsi_host_put # # put_device will call release and free the host structure (which # contains both the generic device and the host class). We must do # the class_device_put() *before* the put_device(). # -------------------------------------------- # 03/05/12 davem@nuts.ninka.net 1.1063.41.1 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/12 mochel@osdl.org 1.1063.39.2 # driver model: Set device's kset before calling kobject_add(). # # Suggested by James Bottomley, and technically correct. We want the kset of # the kobjects to be set before we call kobject_add() so we can access the # kset's release method when the object is deleted. # # -------------------------------------------- # 03/05/13 rmk@flint.arm.linux.org.uk 1.1063.32.2 # [ARM] Update a variety of ARM drivers to use irqreturn_t. # -------------------------------------------- # 03/05/12 torvalds@home.transmeta.com 1.1063.42.1 # Add user pointer annotations to mtrr driver. # -------------------------------------------- # 03/05/12 torvalds@home.transmeta.com 1.1063.42.2 # Fix do_utimes() user pointer annotations. # -------------------------------------------- # 03/05/12 torvalds@home.transmeta.com 1.1063.42.3 # Make sys_open() declaration match definition. # -------------------------------------------- # 03/05/12 torvalds@home.transmeta.com 1.1063.42.4 # Don't use undefined preprocessor symbols in expressions. # -------------------------------------------- # 03/05/12 torvalds@home.transmeta.com 1.1063.41.2 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/12 torvalds@home.transmeta.com 1.1063.2.40 # Merge bk://kernel.bkbits.net/davem/sparc-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/12 acme@conectiva.com.br 1.1063.2.41 # o wanrouter: add missing include module.h # -------------------------------------------- # 03/05/12 elenstev@mesatop.com 1.1063.43.1 # [PATCH] Use '#ifdef' to test for CONFIG_xxx variables # # Don't depend on undefined preprocessor symbols evaluating to zero. # -------------------------------------------- # 03/05/12 jejb@raven.il.steeleye.com 1.1092 # Merge raven.il.steeleye.com:/home/jejb/BK/scsi-misc-2.5 # into raven.il.steeleye.com:/home/jejb/BK/scsi-for-linus-2.5 # -------------------------------------------- # 03/05/12 chris@wirex.com 1.1063.43.2 # [RXRPC]: Put file_operations THIS_OWNER in correct place. # -------------------------------------------- # 03/05/12 davem@nuts.ninka.net 1.1063.2.42 # Merge bk://kernel.bkbits.net/acme/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/12 yoshfuji@linux-ipv6.org 1.1063.2.43 # [NET]: nonet.c needs module.h # -------------------------------------------- # 03/05/12 acme@conectiva.com.br 1.1063.2.44 # [IPV4/IPV6]: Consolidate saddr resetting into inet_reset_saddr(). # -------------------------------------------- # 03/05/12 kaber@trash.net 1.1063.2.45 # [XFRM]: Fix typo in __xfrm4_find_acq. # -------------------------------------------- # 03/05/12 elenstev@mesatop.com 1.1063.44.1 # [PATCH] more potentially undefined preprocessor symbols # # Here are three more fixes which I missed in the previous patch. # -------------------------------------------- # 03/05/12 torvalds@home.transmeta.com 1.1063.44.2 # Remove extraneous NO_MATCH # -------------------------------------------- # 03/05/12 torvalds@home.transmeta.com 1.1063.44.3 # Fix broken aic7xxx preprocessor conditional (that's not how # C preprocessor expressions work, guys!) # -------------------------------------------- # 03/05/12 torvalds@home.transmeta.com 1.1063.2.46 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.47 # [PATCH] enable slab debugging for larger objects # # Some of the fancier slab debugging options are disabled for caches whose # objects are larger than PAGE_SIZE/8, for speed/fragmentation reasons. # # But this patch turns up bugs in the size-2048 slab, so it was a bad idea. # Enable the debugging for slabs up to 4096 bytes. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.48 # [PATCH] Remove __verify_write leftovers # # From: Taral # # Looks like the recent access_ok fixes broke building of i386. # __verify_write is still referenced in a couple places. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.49 # [PATCH] hrtimers: fix timer_create(2) && SIGEV_NONE # # From: george anzinger # # - Fix the sig_notify filtering code for the timer_create system call to # properly check for the signal number being small enought, but only if # SIG_NONE is not specified. # # - Eliminate useless test of sig_notify. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.50 # [PATCH] implement module_arch_cleanup() in all architectures # # From: Rusty Russell , David Mosberger # # The patch below updates the other platforms with module_arch_cleanup(). # Also, I added more debug output to kernel/module.c since I found it useful # to be able to see the final section layout. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.51 # [PATCH] remove devfs_register # # From: Christoph Hellwig # # Whee! devfs_register isn't used anymore in the whole tree and with # it some other devfs crap. Kill it for good. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.52 # [PATCH] fix pnp_test_handler return # # It looks like I guessed wrong on this one. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.53 # [PATCH] fat cluster search speedup # # From: Bjorn Stenberg # OGAWA Hirofumi # # This simple patch makes the linux fat filesystem driver use the # next_cluster field in the fat_boot_fsinfo structure. This field is a hint # where to start looking for free clusters. # # Using this field makes a big difference for disks connected over slow links # such as USB 1.1. Finding the first free cluster on a 40gig fat-formatted # usb disk can today take several minutes. This patch cuts it down to a # fraction of a second. # # Also, commit the next_cluster search hint toand from the superblock in # write_super/fill_super. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.54 # [PATCH] Fix for vma merging refcounting bug # # From: "Stephen C. Tweedie" # # When a new vma can be merged simultaneously with its two immediate # neighbours in both directions, vma_merge() extends the predecessor vma and # deletes the successor. However, if the vma maps a file, it fails to fput() # when doing the delete, leaving the file's refcount inconsistent. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.55 # [PATCH] Commented out printk causes change in program flow in # # From: Zwane Mwaikambo # # Commented out printk causes change in program flow in cpufreq/p4-clockmod.c # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.56 # [PATCH] small cleanup for __rmqueue # # From: Zwane Mwaikambo # # Removes an extra initialisation and general nitpicking. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.57 # [PATCH] export cpufreq_driver to fix oops in proc interface # # From: Zwane Mwaikambo # # The proc interface has no way of telling wether there is an active cpufreq # driver or not. This means that if you don't have a cpufreq supported # processor, this will oops in various possible places. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.58 # [PATCH] Quota write transaction size fix # # From: Jan Kara # # I'm sending a patch which changes numbers of blocks reserved for quota writes # to more appropriate values (with current values ext3 asserts can be # triggered). # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.59 # [PATCH] dquot_transfer() fix # # From: Jan Kara # # I'm sending a fix which fixes potential problems (dropping references which # were not acquired) when dquot_transfer() fails. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.60 # [PATCH] Bump module ref during init. # # From: Rusty Russell # # __module_get is theoretically allowed on module inside init, since we # already hold an implicit reference. Currently this BUG()s: make the # reference count explicit, which also simplifies delete path. Also cleans # up unload path, such that it only drops semaphore when it's actually # sleeping for rmmod --wait. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.61 # [PATCH] exit_mmap() TASK_SIZE fix # # exit_mmap() currently assumes that the exitting task used virtual address # span TASK_SIZE. # # But on some platforms, TASK_SIZE is variable, based on current->mm. # # But exit_mmap() can be called from (say) procfs's call to mmput. In which # case current->mm has nothing to do with the mm which is being put in # mmput(). # # So rather than assuming that the mm which is being put is current->mm, we # need to calculate the virtual span of the mm. Add a new per-arch macro # MM_VM_SIZE() for that. # # Some platforms can currently go BUG over this (where?). sparc64 is safe # because our TASK_SIZE is constant. # # Platforms such as ia64 should stick the VM extent inside of mm_struct, I'd # suggest adding it to mm_context_t. # # 1) TASK_SIZE means what is valid for mmap()'s in the processes # address space # # 2) MM_VM_SIZE means where things might be mapped for a MM, including # private implementation-specific areas created by the kernel # which the user cannot access # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.62 # [PATCH] semop race fix # # From: Mingming Cao # # Basically, freeary() is called with the spinlock for that semaphore set # hold. But after the semaphore set is removed from the ID array by # calling sem_rmid(), there is no lock to protect the waiting queue for # that semaphore set. So, if a waiter is woken up by a signal (not by the # wakeup from freeary()), it will check the q->status and q->prev fields. # At that moment, freeary() may not have a chance to update those fields # yet. # # static void freeary (int id) # { # ....... # sma = sem_rmid(id); # # ...... # /* Wake up all pending processes and let them fail with EIDRM.*/ # for (q = sma->sem_pending; q; q = q->next) { # q->status = -EIDRM; # q->prev = NULL; # wake_up_process(q->sleeper); /* doesn't sleep */ # } # sem_unlock(sma); # ...... # } # # So I propose move sem_rmid() after the loop of waking up every waiters. # That could gurantee that when the waiters are woke up, the updates for # q->status and q->prev have already done. Similar thing in message queue # case. The patch is attached below. Comments are very welcomed. # # I have tested this patch on 2.5.68 kernel with LTP tests, seems fine to # me. Paul, could you test this on DOTS test again? Thanks! # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.63 # [PATCH] visws: fix penguin with sgi logo # # From: Andrey Panin # # attached patch fixes penguin with sgi framebuffer logo for # visws subarch. It was broken in 2.5.68 IIRC. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.64 # [PATCH] fix for clusterd io_apics # # From: Keith Mannthey # # The following is a patch to fix inconsistent use of the function # set_ioapic_affinity. In the current kernel it is unclear as to weather the # value being passed to the function is a cpu mask or valid apic id. In # irq_affinity_write_proc the kernel passes on a cpu mask but the kirqd thread # passes on logical apic ids. In flat apic mode this is not an issue because a # cpu mask represents the apic value. However in clustered apic mode the cpu # mask is very different from the logical apic id. # # This is an attempt to do the right thing for clustered apics. I clarify that # the value being passed to set_ioapic_affinity is a cpu mask not a apicid. # Set_ioapic_affinity will do the conversion to logical apic ids. Since many # cpu masks don't map to valid apicids in clustered apic mode TARGET_CPUS is # used as a default value when such a situation occurs. I think this is a good # step in making irq_affinity clustered apic safe. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.65 # [PATCH] provide user feedback for emergency sync and remount # # People like to see when the emergency sync and emergency remount operations # have completed. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.66 # [PATCH] copy_process return value fix # # Rather than assuming that all the things which copy_process() calls want to # return -ENOMEM, correctly propagate the return values. # # This turns out to be a no-op at present. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.67 # [PATCH] de_thread memory corruption fix # # From: Manfred Spraul # # de_thread calls list_del(¤t->tasks), but current->tasks was never # added to the task list. The structure contains stale values from the parent. # # switch_exec_pid() transforms a normal thread to a thread group leader. # Thread group leaders are included in the init_task.tasks linked list, # non-leaders are not in that list. The patch adds the new thread group # leader to the linked list, otherwise de_thread corrupts the task list. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.68 # [PATCH] vmalloc race fix # # From: William Lee Irwin III # # The new vmalloc() semantics from 2.5.32 had a race window. As things stand, # the presence of a vm_area in the vmlist protects from allocators other than # the owner examining the ptes in that area. This puts an ordering constraint # on unmapping, so that allocators are required to unmap areas before removing # them from the list or otherwise dropping the lock. # # Currently, unmap_vm_area() is done outside the lock and after the area is # removed, which as we've seen from Felix von Leitner's test is oopsable. # # The following patch folds calls to unmap_vm_area() into remove_vm_area() to # reinstate what are essentially the 2.4.x semantics of vfree(). This renders # a number of unmap_vm_area() calls unnecessary (and in fact oopsable since # they wipe ptes from later allocations). It's an open question as to whether # this is sufficiently performant, but it is the minimally invasive approach. # The more performant alternative is to provide the right API hooks to wipe the # vmalloc() area clean before removing them from the list, using the ownership # of the area to eliminate holding the vmlist_lock for the duration of the # unmapping. If it proves to be necessary wli is on standby to implement it. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.69 # [PATCH] Reserve the ext2/ext3 EAs for the Lustre filesystem # # From: Andreas Dilger # # Below are the patches which reserve the Lustre EA index. The rest of the # code is part of the Lustre tree, which isn't working with 2.5 yet. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.70 # [PATCH] Fix arch/i386/oprofile/init.c build error # # From: John M Flinchbaugh # # this patch makes arch/i386/oprofile/init.c build. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.71 # [PATCH] Fix ext3 htree / NFS compatibility problems # # Patch from "Theodore Ts'o" # # The following patch should (in theory) fix the htree/NFS readdir problems # that people have reported. Specifically, it should fix the NFS looping on # EOF problem with readdir, as well as the problems caused by coverting a # directory to HTREE while an NFS readdir is in progress problem. # # I'd appreciate it if people who can easily replicate these NFS/htree problems # could give this patch (against BK-recent / 2.5.63) a whirl. Thanks!! # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.72 # [PATCH] htree nfs fix # # Patch from "Theodore Ts'o" # # We now use 0x7ffffff as the EOF cookie, because Linux NFS stupidly interprets # the cookie (which is supposed to be a bag of bits without necessarily any # semantic value) as a signed 64 bit integer, and then converts it to a # unsigned integer, and then blows up if it cannot be expressed be expressed as # a 32-bit value!! # # In order to do this, we have to fold the hash value 0x7ffffff into the hash # value 0x7ffffffe. This is relatively safe; the only time we will lose if the # directory contains filenames that hash to both 0x7ffffffe and 0x7fffffff # (under the original hash), and the last directory entry which hashes to # 0x7ffffffe is at the end of a leaf block, and the first directory entry which # hashes to 0x7fffffff is at the beginning of a leaf block. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.2.73 # [PATCH] ext3: htree memory leak fix # # From Alex Tomas # # We started using ext3_dx_readdir() for all dir_index filesystems, because # we want to return entries in hash order always, so that readdir with a # partial read + new entry added before next readdir won't be crazy. # # So we now need to free the structure at filp->pricate_data even against # non-indexed directories. # -------------------------------------------- # 03/05/12 torvalds@home.transmeta.com 1.1093 # Merge http://linux-scsi.bkbits.net/scsi-for-linus-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/13 acme@conectiva.com.br 1.1094 # o ipv4/ipv6: use ipv6_addr_copy where appropriate # -------------------------------------------- # 03/05/13 rmk@flint.arm.linux.org.uk 1.1063.32.3 # [ARM] Allow CONFIG_PM to be enabled on all ARM platforms # -------------------------------------------- # 03/05/13 nico@org.rmk.(none) 1.1063.32.4 # [ARM PATCH] 1533/1: fix count when no preload support in copy_page # # Patch from Nicolas Pitre # # Of course, the PLD macro is always defined even if it's empty. # Without this fix anything below ARMv5 is broken. # -------------------------------------------- # 03/05/13 rmk@flint.arm.linux.org.uk 1.1063.32.5 # [ARM PATCH] 1530/1: PXA2xx IRQ handling updates # # From: Nicolas Pitre. # # (manual entry since bk openlogging crapped out again) # -------------------------------------------- # 03/05/13 nico@org.rmk.(none) 1.1063.32.6 # [ARM PATCH] 1531/1: optimized ffs/ffz/fls for ARMv5 # # Patch from Nicolas Pitre # # -------------------------------------------- # 03/05/13 rmk@flint.arm.linux.org.uk 1.1063.32.7 # [ARM] Fix timer interrupts to use irqreturn_t # # Also remove uninitialised variable warning and update mach-types. # -------------------------------------------- # 03/05/13 rmk@flint.arm.linux.org.uk 1.1063.32.8 # [ARM] Add prefetch support for ARMv5. # -------------------------------------------- # 03/05/13 rmk@flint.arm.linux.org.uk 1.1063.32.9 # [ARM] Fix test_bit to return 0 or 1. # -------------------------------------------- # 03/05/13 rmk@flint.arm.linux.org.uk 1.1063.32.10 # [ARM] Remove static mappings for Integrator PS/2 ports. # # Request the memory region used for the keyboard and mouse ports, # and ioremap. # -------------------------------------------- # 03/05/13 rmk@flint.arm.linux.org.uk 1.1063.32.11 # [ARM] switch ptrace to use an undefined instruction # # This avoids a problem with the original ptrace code using a system # call (SWI) to implement single stepping; programs such as ltrace # do not expect to receive system call trace traps when breakpoints # are hit. # -------------------------------------------- # 03/05/13 stevef@steveft21.ltcsamba 1.1042.71.2 # Fix readlink of dfs junctions # -------------------------------------------- # 03/05/13 stevef@steveft21.ltcsamba 1.1042.124.12 # Merge http://cifs.bkbits.net/linux-2.5cifs # into steveft21.ltcsamba:/usr/src/bk/linux-2.5cifs # -------------------------------------------- # 03/05/13 torvalds@penguin.transmeta.com 1.1093.1.1 # Don't make the intel-AGP driver require a AGP capabilities # pointer. The integrated graphics AGP things don't have one. # -------------------------------------------- # 03/05/13 rmk@flint.arm.linux.org.uk 1.1063.32.12 # [ARM] Convert more structure initialisers to C99 syntax. # -------------------------------------------- # 03/05/13 greg@kroah.com 1.1093.2.1 # [PATCH] i2c: piix4 driver: turn common error message to a debug level and rename the sysfs driver name. # -------------------------------------------- # 03/05/13 greg@kroah.com 1.1093.3.1 # [PATCH] USB: fix jiffies warning in uss720.c # -------------------------------------------- # 03/05/13 davem@nuts.ninka.net 1.1095 # Merge bk://kernel.bkbits.net/acme/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/13 romieu@fr.zoreil.com 1.1093.3.2 # [PATCH] USB: patch to fix up coding style violations # -------------------------------------------- # 03/05/13 david-b@pacbell.net 1.1093.3.3 # [PATCH] USB: rm debug printks in ehci and ohci # # These two debug messages weren't supposed to be left in, # they're just noise. # -------------------------------------------- # 03/05/13 smb@smbnet.de 1.1093.3.4 # [PATCH] USB: another usb storage addition # -------------------------------------------- # 03/05/13 david-b@pacbell.net 1.1093.3.5 # [PATCH] USB: fix for multiple definition of `usb_gadget_get_string' # -------------------------------------------- # 03/05/13 david-b@pacbell.net 1.1093.3.6 # [PATCH] USB: net2280 minor updates # # This patch: # # - Lets cleanup happen after devices disconnect # - Creates/uses a module "fifo_mode" option # - Handles the fifo_status request a bit better # -------------------------------------------- # 03/05/13 david-b@pacbell.net 1.1093.3.7 # [PATCH] USB: net2280, PPC fixes # # Minutes after I sent the previous patch, Gordon Strachan # sent me some big-endian fixes (for PPC). # -------------------------------------------- # 03/05/13 greg@kroah.com 1.1093.3.8 # [PATCH] USB: fix break control for pl2303 driver # # Thanks to Martin Evans for pointing this out. # -------------------------------------------- # 03/05/13 davem@nuts.ninka.net 1.1096 # [NETFILTER]: Teach ip_fw_compat and modules to handle non-linear SKBs. # # Much help provided by Rusty Russell in fixing device leak # and TOS modification handling bugs. # -------------------------------------------- # 03/05/13 bcollins@debian.org 1.1093.3.9 # [PATCH] USB: Happ UGCI added as BADPAD for workaround # # Greg, I sent these patches to Vojtech, and haven't heard anything back, # but they are straight forward. One simply backports the BADPAD handling # to 2.4, and both patches add Happ UGCI joysticks under the BADPAD # workaround. # -------------------------------------------- # 03/05/13 torvalds@penguin.transmeta.com 1.1093.1.2 # Add user pointer annotations to core filesystem routines. # -------------------------------------------- # 03/05/13 davem@nuts.ninka.net 1.1097 # [IPV6]: Check output fragmentation using dst_pmtu not dev->mtu. # -------------------------------------------- # 03/05/13 mhoffman@lightlink.com 1.1093.2.2 # [PATCH] i2c: Add SiS96x I2C/SMBus driver # # This patch adds support for the SMBus of SiS96x south # bridges. It is based on i2c-sis645.c from the lm sensors # project, which never made it into an official kernel and # was anyway mis-named. # # This driver works on my SiS 645/961 board vs w83781d. # -------------------------------------------- # 03/05/13 davem@nuts.ninka.net 1.1098 # [AIC7XXX]: Only build in biosparam function if actually used. # -------------------------------------------- # 03/05/13 davem@nuts.ninka.net 1.1099 # [IPV6]: Fix ipv6_addr_copy warning in ah6.c. # -------------------------------------------- # 03/05/13 torvalds@penguin.transmeta.com 1.1093.1.3 # Make x86 user-copy have user pointer annotations to match # declarations. # -------------------------------------------- # 03/05/13 torvalds@penguin.transmeta.com 1.1093.1.4 # Add a few initial user pointer annotations to sound driver. # # Quite a few suspicious places here that pass kernel pointers # to the internal ioctl engine. # -------------------------------------------- # 03/05/14 davej@tetrachloride.(none) 1.1093.4.1 # Merge tetrachloride.(none):/mnt/raid/src/kernel/2.5/bk-linus # into tetrachloride.(none):/mnt/raid/src/kernel/2.5/agpgart # -------------------------------------------- # 03/05/13 mochel@osdl.org 1.1063.39.3 # driver model: Define BUS_ID_SIZE based on KOBJ_NAME_LEN # # From Ben Collins. # -------------------------------------------- # 03/05/13 mochel@osdl.org 1.1063.39.4 # driver model: Remove device_sem # # This was only used to add/remove device from parent's list of children, # which we can easily replace with a write lock on the device subsys's rwsem. # -------------------------------------------- # 03/05/13 vojtech@suse.cz 1.1093.3.10 # [PATCH] USB: Fix Kconfig for usb printers # # On Sun, May 11, 2003 at 09:55:04PM +0200, Kronos wrote: # > Hi, # > the USB printer module is 'usblp', not 'printer': # > # -------------------------------------------- # 03/05/13 daniel@osdl.org 1.1100 # [IPV6]: Missing kmem_cache_destroy calls. # -------------------------------------------- # 03/05/13 chas@cmf.nrl.navy.mil 1.1101 # [ATM]: Make clip modular. # -------------------------------------------- # 03/05/13 akpm@digeo.com 1.1102 # [NET]: netif_receive_skb() warning fix. # -------------------------------------------- # 03/05/13 akpm@digeo.com 1.1103 # [ATM]: Fix macro pasting in HE driver. # -------------------------------------------- # 03/05/13 davem@nuts.ninka.net 1.1104 # [SPARC64]: Update defconfig. # -------------------------------------------- # 03/05/13 davem@kernel.bkbits.net 1.1105 # Merge davem@nuts.ninka.net:/home/davem/src/BK/net-2.5 # into kernel.bkbits.net:/home/davem/net-2.5 # -------------------------------------------- # 03/05/13 cifs.adm@hostme.bitkeeper.com 1.1093.5.1 # Merge bk://linux.bkbits.net/linux-2.5 # into hostme.bitkeeper.com:/ua/repos/c/cifs/linux-2.5cifs # -------------------------------------------- # 03/05/13 davem@nuts.ninka.net 1.1093.6.1 # Merge bk://linux-bt.bkbits.net/bt-2.5 # into nuts.ninka.net:/home/davem/src/BK/bluetooth-2.5 # -------------------------------------------- # 03/05/13 torvalds@home.transmeta.com 1.1093.1.5 # Merge bk://linux-dj.bkbits.net/agpgart # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/13 torvalds@home.transmeta.com 1.1106 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/13 torvalds@home.transmeta.com 1.1107 # Merge bk://linux-bt.bkbits.net/bt-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/13 torvalds@home.transmeta.com 1.1108 # Merge bk://kernel.bkbits.net/davem/bluetooth-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1093.7.1 # [CPUFREQ] missing export compile fix for powernow-k7 # -------------------------------------------- # 03/05/13 torvalds@home.transmeta.com 1.1109 # Merge bk://linux-dj.bkbits.net/cpufreq # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/13 jsimmons@infradead.org 1.1110 # [PATCH] Console font size fix # # The font size needs to be set for all terminals. # # This was the bug that was causing dual head (vga and mda) to lock up. # -------------------------------------------- # 03/05/13 jsimmons@infradead.org 1.1111 # [PATCH] Remove EDID parsing # # This removes EDID support for VESA. The EDID code needs more # developement which can be done on the side. # # The results where mixed. It worked for some but not for others. # -------------------------------------------- # 03/05/13 jsimmons@infradead.org 1.1112 # [PATCH] Riva Framebuffer update. # # This kills off warnings about unused variables. # -------------------------------------------- # 03/05/13 jsimmons@infradead.org 1.1113 # [PATCH] Framebuffer console fix # # This fixes a oops that happens when we map a framebuffer device to a # non-existant console. # # set_con2fb_map wasn't testing to see the VC we where mapping to actually # exist. Now it does. # # I also added code to fbcon_cursor to reset the hotspot if it was changed # by userland. # -------------------------------------------- # 03/05/14 acme@conectiva.com.br 1.1114 # o ipv4/ipv6: call tcp_timewait_kill in tcp_tw_deschedule # # After all calls to tcp_tw_deschedule we had a call to tcp_timewait_kill, # move it to the end of tcp_tw_deschedule and unexport tcp_timewait_kill, # making it static. # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1093.1.6 # [AGPGART] PPC Uninorth support. # By Paul Mackerras and BenH # -------------------------------------------- # 03/05/14 davej@tetrachloride.(none) 1.1113.1.1 # Merge tetrachloride.(none):/mnt/raid/src/kernel/2.5/bk-linus # into tetrachloride.(none):/mnt/raid/src/kernel/2.5/agpgart # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.1.2 # [AGPGART] Move AGP PM to individual drivers. # From Christoph Hellwig. # This is a lot cleaner by using the proper PCI PM infrastructure and also # fixes the breakage with the non-PCIish bridges on alpha and ia64 # -------------------------------------------- # 03/05/14 cifs.adm@hostme.bitkeeper.com 1.1113.2.1 # Merge bk://linux.bkbits.net/linux-2.5 # into hostme.bitkeeper.com:/ua/repos/c/cifs/linux-2.5cifs # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.1.3 # [AGPGART] Add printk's to error paths of agp_add_bridge # -------------------------------------------- # 03/05/14 torvalds@penguin.transmeta.com 1.1113.3.1 # Merge bk://bk.arm.linux.org.uk/linux-2.5-pcmcia # into penguin.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/14 torvalds@penguin.transmeta.com 1.1113.3.2 # Merge bk://bk.arm.linux.org.uk/linux-2.5-rmk # into penguin.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/14 axboe@suse.de 1.1113.4.1 # [PATCH] bio walking code # # Add bio traversal functionality. This is a prereq for doing ide # multiwrites safely and sanely. Patch was originally done by Suparna, # Bartlomiej picked it up and changed the design somewhat. From Bart: # # Main idea is now reversed - instead of introducing rq->hard_bio as # pointer for bio to be completed and using rq->bio as pointer for bio # to be submitted, rq->cbio is introduced for submissions and rq->bio # is used for completions # # This minimizes changes to block layer and assures that all existing # block users are not affected by this patch. # -------------------------------------------- # 03/05/14 axboe@suse.de 1.1113.4.2 # [PATCH] ide minimum 48-bit support # # This is the small patch that we all agreed on. With this patch, we do # nice big writes/reads on ide disks that support 48-bit lba. # -------------------------------------------- # 03/05/14 axboe@suse.de 1.1113.4.3 # [PATCH] remove ide-cd chatty errors # # Quiet down the TEST_UNIT_READY commands, we know these may fail (that's # the whole purpose of the command :-). # -------------------------------------------- # 03/05/14 axboe@suse.de 1.1113.4.4 # [PATCH] Fix scsi_ioctl command direction bits # # With the dynamic request allocation, we get the direction bits set for # us. This breaks the scsi_ioctl stuff, since we always pass in WRITE # there. So actually pass in the right direction instead. # -------------------------------------------- # 03/05/14 torvalds@penguin.transmeta.com 1.1113.3.3 # Merge home:v2.5/linux # into penguin.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/14 axboe@suse.de 1.1113.3.4 # [PATCH] ide tcq fixes # # This fixes a few problems with ide tcq, I don't know of any other known # ones (and it is solid here, survives ours of beating on it). Basically: # # - Don't enable tcq if the drive isn't alone on the channel. This raises # all sorts of fun that really requires hardware support (auto poll), or # it's going to _suck_. I never wanted to do that, and no hardware I # know of supports auto-poll. # # - Introduce a drive blacklist so we don't enable tcq on known broken # drives. Or enable with restrictions on some models. # # - Add a check for pdc4030, apparently tcq doesn't work there (hell knows # who would be crazy enough to pull such a stunt). # -------------------------------------------- # 03/05/14 akpm@digeo.com 1.1093.3.11 # [PATCH] USB: net2280 writel fix # # This driver is doing a writel to some random u32, rather than to a device # register. # -------------------------------------------- # 03/05/14 greg@kroah.com 1.1113.5.1 # Merge kroah.com:/home/linux/linux/BK/bleed-2.5 # into kroah.com:/home/linux/linux/BK/gregkh-2.5 # -------------------------------------------- # 03/05/14 davem@nuts.ninka.net 1.1113.6.1 # [AF_KEY]: Force km.state to XFRM_STATE_DEAD in pfkey_msg2xfrm_state. # -------------------------------------------- # 03/05/14 kaber@trash.net 1.1113.6.2 # [NET]: Fix two bogus kfree(skb). # -------------------------------------------- # 03/05/15 davej@tetrachloride.(none) 1.1113.1.4 # Merge tetrachloride.(none):/mnt/raid/src/kernel/2.5/bk-linus # into tetrachloride.(none):/mnt/raid/src/kernel/2.5/agpgart # -------------------------------------------- # 03/05/15 davej@codemonkey.org.uk 1.1113.1.5 # [AGPGART] Remove duplicated masking routines, replace with agp_generic_mask_memory() # -------------------------------------------- # 03/05/15 davej@codemonkey.org.uk 1.1113.1.6 # [AGPGART] Whitespace/CodingStyle cleanups # -------------------------------------------- # 03/05/14 torvalds@home.transmeta.com 1.1113.3.5 # Merge bk://kernel.bkbits.net/gregkh/linux/linus-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/14 akpm@digeo.com 1.1113.6.3 # [NET]: Fix sb1000.c build. # -------------------------------------------- # 03/05/14 davem@nuts.ninka.net 1.1115 # Merge bk://kernel.bkbits.net/acme/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/14 acme@conectiva.com.br 1.1114.1.1 # o af_netlink: netlink_proto_init has to be core_initcall # # As it has to happen before pktsched_init, that is called from # net_dev_init that is a subsys_initcall, making it the same # init level as netlink_proto_init, that ends up being called # _after_ net_dev_init, so when pktsched_init is called it finds # rtnetlink_links[PF_UNSPEC] as null and therefore not sets # the ->dumpit entry for RTM_GETQDISC (and the others too): # b00m, rtnetlink_rcv sends a failure message to tc. # -------------------------------------------- # 03/05/14 davem@nuts.ninka.net 1.1116 # Merge bk://kernel.bkbits.net/acme/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/14 davem@nuts.ninka.net 1.1117 # [RTNETLINK]: extern __inline__ --> static inline. # -------------------------------------------- # 03/05/14 davem@nuts.ninka.net 1.1118 # [TCP]: extern __inline__ --> static inline where appropriate. # -------------------------------------------- # 03/05/14 davem@nuts.ninka.net 1.1119 # [IPV6]: extern __inline__ --> static inline. # -------------------------------------------- # 03/05/14 davem@nuts.ninka.net 1.1120 # [IPV4]: Fix ip_finish_output extern decl. # -------------------------------------------- # 03/05/14 davem@nuts.ninka.net 1.1121 # [AX25]: extern inline --> static inline. # -------------------------------------------- # 03/05/14 davem@nuts.ninka.net 1.1122 # [NET]: dev_load extern inline --> static inline. # -------------------------------------------- # 03/05/14 davem@nuts.ninka.net 1.1123 # [APPLETALK]: extern inline --> static inline. # -------------------------------------------- # 03/05/14 davem@nuts.ninka.net 1.1124 # [PKT_SCHED]: extern inline --> static inline # -------------------------------------------- # 03/05/14 davem@nuts.ninka.net 1.1125 # [AF_UNIX]: extern inline --> static inline # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1126 # [NETROM]: Fix netdevice leak, from 2.4.x # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.3.6 # [PATCH] Fix types on inflate.c constants # # This patch from Alan went into 2.4 last august with the comment # "get the types right on the lib/inflate.c constants" # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.3.7 # [PATCH] Preemption fixes for x86 MSR driver. # # wrmsr is ok, but needs cleans up, second part (rdmsr) # is currently broken. # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.3.8 # [PATCH] Avoid ide-scsi from starting DMA too soon # # This went into 2.4 with the following comments.. # # ide-scsi driver starts DMA as soon as it writes the ATAPI PACKET command # in command register and before sending the ATAPI command. This will # cause problems on many drives. Right way to do it is to start DMA after # sending the ATAPI command. I am attaching a patch that fixes this. This # patch will allow many more CD-RW drives to work reliably in DMA mode # than do today # # Alan's comment to this diff previously.. # "Thats the least of the 2.5 ide-scsi problems, but yes its probably one to add" # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.3.9 # [PATCH] i8253 locking. # # There are still a few places where we play with the RTC # directly, with no locking. This catches some of them. # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.3.10 # [PATCH] sx memleak. # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.3.11 # [PATCH] Fix ISDN return types. # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.3.12 # [PATCH] Fix standards compliance bugs in the tty layer # # This went into 2.4 back last August with the comment in $subject. # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.3.13 # [PATCH] pcwatchdog firmware memory leak # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.3.14 # [PATCH] iphase fix. # # This went into 2.4 nearly a year back with the wonderfully # descriptive "Fix from maintainer" comment. # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.3.15 # [PATCH] ASUS P4B SMBus quirks. # # From Dominik Brodowski, comments says it all.. # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.3.16 # [PATCH] typo # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.3.17 # [PATCH] Fix pnpbios switch # # Erk, that's a really funny looking switch. # Every case fell through.. # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.3.18 # [PATCH] copy_to_user check for sgiserial # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.3.19 # [PATCH] fix module-init-tools ver_linux problem. # # Patch from Steven Cole to fix up ver_linux output on a system # with no module-init-tools, just modutils. # # As noted in bugzilla #267 and at # http://marc.theaimsgroup.com/?l=linux-kernel&m=104492524815220&w=2 # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.3.20 # [PATCH] Shorten rcu_check_quiescent_state. # # Single spin_unlock path cuts this down a little.. # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.3.21 # [PATCH] byte counters for mkiss # # From 2.4 from way back 13 months ago.. # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.3.22 # [PATCH] shorten rclan debug output # # From 2.4 long long ago. # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.3.23 # [PATCH] i810 no codec fix. # # Syncs up with 2.4 # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.3.24 # [PATCH] shrink zonelists. # # Originally from Matt Dobson. I've been running with this for a while # in -dj, with no noticable side-effects. # # Matt: # # node_zonelists looks like it should really be declared of size # MAX_NR_ZONES, not GFP_ZONEMASK. GFP_ZONEMASK is currently 15, making # node_zonelists an array of 16 elements. The extra zonelists are all # just duplicates of the *real* zonelists, namely the first 3 entries. # Again, if anyone can explain to me why I'm wrong in my thinking, I'd # love to know. There's certainly no way you could bitwise-and something # with any combination of the GFP_DMA and GFP_HIGHMEM flags to refer to # the 12th zonelist or some such! Or am I crazy? # -------------------------------------------- # 03/05/14 davem@kernel.bkbits.net 1.1127 # Merge davem@nuts.ninka.net:/home/davem/src/BK/net-2.5 # into kernel.bkbits.net:/home/davem/net-2.5 # -------------------------------------------- # 03/05/15 davem@nuts.ninka.net 1.1128 # [SUNHME]: Use PCI config space if hm-rev property does not exist. # -------------------------------------------- # 03/05/15 davej@tetrachloride.(none) 1.1127.1.1 # Merge tetrachloride.(none):/mnt/raid/src/kernel/2.5/bk-linus # into tetrachloride.(none):/mnt/raid/src/kernel/2.5/agpgart # -------------------------------------------- # 03/05/15 davej@codemonkey.org.uk 1.1127.1.2 # [AGPGART] pci_driver structures must remain valid while they are registered. # Spotted by Russell King. # -------------------------------------------- # 03/05/15 rmk@flint.arm.linux.org.uk 1.1063.32.13 # [ARM] Fix SA1100_ir irqreturn_t. # -------------------------------------------- # 03/05/15 rmk@flint.arm.linux.org.uk 1.1063.32.14 # [ARM] Fix RiscPC i2c drivers for device model. # # These drivers got missed when the i2c subsystem was converted to the # device model. # -------------------------------------------- # 03/05/15 mochel@osdl.org 1.1063.39.5 # driver model: Add resources to struct platform_device. # # From Russell King: # # The location and interrupt of some platform devices are only known by # platform specific code. In order to avoid putting platform specific # parameters into drivers, place resource and irq members into struct # platform_device. # -------------------------------------------- # 03/05/15 akpm@digeo.com 1.1127.2.1 # [PATCH] ipmi warning fixes # # CPU flags are unsigned long. # -------------------------------------------- # 03/05/15 akpm@digeo.com 1.1127.2.2 # [PATCH] sound/core comparison fix # # From: Hal Duston # # This fixes a bug that appears to have crept in between 2.5.69-mm1 and # 2.5.69-mm2 with the "switch most remaining drivers over to devfs_mk_bdev" # patch # -------------------------------------------- # 03/05/15 akpm@digeo.com 1.1127.2.3 # [PATCH] pass the stack protection flags into put_dirty_page() # # put_dirty_page() currently assumes PAGE_COPY for the stack page's ptes. But # for x86_64 (at least) this is not the case. # # The patch adds the extra arg to put_dirty_page(), updates all callers and fixes # x86_64. # -------------------------------------------- # 03/05/15 akpm@digeo.com 1.1127.2.4 # [PATCH] fix hugetlbpage scoping # # From: norbert_wolff@t-online.de (Norbert Wolff) # # In arch/i386/mm/hugetlbpage.c htlbzone_pages and htlbpage_freelist are # declared static at the Top of the File and later in set_hugetlb_mem_size() # as extern. # # gcc-3.4 does not accept this conflict. # -------------------------------------------- # 03/05/15 akpm@digeo.com 1.1127.2.5 # [PATCH] DAC960 typedef cleanup patch # # From: Dave Olien # # I'm forwarding this patch to the DAC9690 driver from Christoph. I've # applied it to the 2.5.69 DAC960 driver, compiled it, and ran it through # some tests on both V1 and V2 type controllers. It looks good. # -------------------------------------------- # 03/05/15 akpm@digeo.com 1.1127.2.6 # [PATCH] loop.c warning removal # # From: Rusty Russell # # loop.c has one of those places where manipulating own refcounts is safe: to # get into the ioctl handler you need to have the device open, so that holds a # refcount already (verified that this actually happens). # # The compile warning is irritating. # -------------------------------------------- # 03/05/15 akpm@digeo.com 1.1127.2.7 # [PATCH] mtrr warning fix # # From: Faik Uygur : # # mtrr_file_del() is using the wrong thing for fcount. This causes it to # print mtrr: MTRR 2 not used" twice when exiting X. # -------------------------------------------- # 03/05/15 akpm@digeo.com 1.1127.2.8 # [PATCH] SMI clearing fix # # From: john stultz # # I've been having problems with ACPI on a box here in our lab. Some of our # more recent hardware requires that SMIs are routed through the IOAPIC, thus # when we clear_IO_APIC() at boot time, we clear the BIOS initialized SMI # pin. This basically clobbers the SMI so we can then never make the # transition into ACPI mode. # # This patch simply reads the apic entry in clear_IO_APIC to make sure the # delivery_mode isn't dest_SMI. If it is, we leave the apic entry alone and # return. # # With this patch, the box boots and SMIs function properly. # -------------------------------------------- # 03/05/15 akpm@digeo.com 1.1127.2.9 # [PATCH] Make debugging variant of spinlocks a bit more robust # # From: Petr Vandrovec # # While I was trying to hunt down problem with spin_lock_irq in # send_sig_info, I noticed that debugging spinlocks are a bit unusable. # # The problem is that these spinlocks first print warning, and then # decrement babble. So if the lock is used by printk code (like runqueue # lock was), we get nothing, just a lockup or a double fault... When we # first decrement babble and then print the error message we can break # this unfortunate situation and the error message (5 of the same...) # appear on screen. # -------------------------------------------- # 03/05/15 akpm@digeo.com 1.1127.2.10 # [PATCH] fix lots of error-path memory leaks # # From Badari Pulavarti. # # Fixes lots of error-path memleaks which the Stanford guys found. # -------------------------------------------- # 03/05/15 akpm@digeo.com 1.1127.2.11 # [PATCH] miropcm20-rds.c build fix # # It needs fs.h for struct inode. # -------------------------------------------- # 03/05/15 akpm@digeo.com 1.1127.2.12 # [PATCH] synclink_cs update # # From: Paul Fulghum # # * Remove PCMCIA release from timer context # * Add irqreturn_t to ISR # * Add dosyncppp module parameter # -------------------------------------------- # 03/05/15 akpm@digeo.com 1.1127.2.13 # [PATCH] remove some cruft from smp.h # # From: Christoph Hellwig # # Remove smp.h leftovers. From the ia64 tree. # -------------------------------------------- # 03/05/15 akpm@digeo.com 1.1127.2.14 # [PATCH] ->llseek returns loff_t, even for /dev/mem # # From: Christoph Hellwig # # memory_lseek() should return a loff_t. # -------------------------------------------- # 03/05/15 akpm@digeo.com 1.1127.2.15 # [PATCH] visws: fix for generic-subarch # # From: Andy Wihitcroft # # The generic-subarch patch broke visws builds. # -------------------------------------------- # 03/05/15 akpm@digeo.com 1.1127.2.16 # [PATCH] fix bug in drivers/net/cs89x0.c:set_mac_address() # # From: Bernardo Innocenti # # the following patch fixes a bug in the CS89xx net device which would set # new MAC address through SIOCSIFHWADDR _only_ when net_debug is set, which # is obviously not what it was meant to do. The original code bogusly # interpreted the addr argument as a buffer containing the MAC address # instead of a struct sockaddr. # -------------------------------------------- # 03/05/15 davej@tetrachloride.(none) 1.1127.1.3 # Merge tetrachloride.(none):/mnt/raid/src/kernel/2.5/bk-linus # into tetrachloride.(none):/mnt/raid/src/kernel/2.5/agpgart # -------------------------------------------- # 03/05/15 davej@codemonkey.org.uk 1.1127.1.4 # [AGPGART] nForce driver needs its own insert/remove routines. # These can't use the generic routines due to alignment issues. # -------------------------------------------- # 03/05/15 davej@codemonkey.org.uk 1.1127.1.5 # [AGPGART] Fix oops in VIA initialisation. # From Christoph. # -------------------------------------------- # 03/05/15 mochel@osdl.org 1.1127.2.17 # Merge osdl.org:/home/mochel/src/kernel/devel/linux-2.5-virgin # into osdl.org:/home/mochel/src/kernel/devel/linux-2.5-core # -------------------------------------------- # 03/05/15 acme@conectiva.com.br 1.1127.3.1 # o wanrouter: don't use typedefs for wan_device, just struct wan_device # -------------------------------------------- # 03/05/15 akpm@digeo.com 1.1127.4.1 # [PATCH] Allow architecture to overwrite stack flags # # This is a bit neater. # -------------------------------------------- # 03/05/15 acme@conectiva.com.br 1.1127.3.2 # o wanrouter: kill netdevice_t, do as all the rest of the tree, use struct net_device # -------------------------------------------- # 03/05/15 mochel@osdl.org 1.1127.2.18 # driver model: Modify resource representation in struct platform_device. # # This way, we can easily handle devices that contain an arbitrary number of # resources reported by the platform. # -------------------------------------------- # 03/05/15 bgerst@didntduck.org 1.1127.4.2 # [PATCH] remove fake_sep_struct # # fake_sep_struct is no longer used. # -------------------------------------------- # 03/05/15 mochel@osdl.org 1.1127.2.19 # Merge osdl.org:/home/mochel/src/kernel/devel/linux-2.5-virgin # into osdl.org:/home/mochel/src/kernel/devel/linux-2.5-core # -------------------------------------------- # 03/05/15 torvalds@home.transmeta.com 1.1127.2.20 # Merge bk://ldm.bkbits.net/linux-2.5-core # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/15 acme@conectiva.com.br 1.1127.3.3 # o wan/cycx: typedef cleanup # -------------------------------------------- # 03/05/15 davem@nuts.ninka.net 1.1129 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/15 akpm@digeo.com 1.1130 # [CRYPTO]: Fix memcpy/memset args. # -------------------------------------------- # 03/05/15 chas@cmf.nrl.navy.mil 1.1131 # [ATM]: Fix module handling in USB speedtouch driver. # -------------------------------------------- # 03/05/15 chas@cmf.nrl.navy.mil 1.1132 # [ATM]: Add refcounting to atmdev. # -------------------------------------------- # 03/05/16 rmk@flint.arm.linux.org.uk 1.1063.32.15 # [ARM] Update Acorn platform scsi drivers. # # These were broken by two changes - the removal of the old device model # class code, and when scsi device lists appeared. This cset allows # these drivers to build again. We also drop some unnecessary code # from one of the drivers. # -------------------------------------------- # 03/05/15 yoshfuji@linux-ipv6.org 1.1133 # [IPV6]: ARCnet support, driver side. # -------------------------------------------- # 03/05/15 yoshfuji@linux-ipv6.org 1.1134 # [IPV6]: ARCnet support, protocol side. # -------------------------------------------- # 03/05/15 davem@nuts.ninka.net 1.1135 # Merge bk://kernel.bkbits.net/acme/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/15 davem@nuts.ninka.net 1.1136 # Merge bk://kernel.bkbits.net/acme/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/15 acme@conectiva.com.br 1.1127.3.4 # o wan/cycx: fix module refcounting, removing MOD_{INC,DEC}_USE_COUNT # -------------------------------------------- # 03/05/15 davem@nuts.ninka.net 1.1137 # Merge bk://kernel.bkbits.net/acme/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/15 acme@conectiva.com.br 1.1127.3.5 # o wan/cycx: further cleanups # # . remove whitespaces # . use tabs instead of sequences of 8 spaces # . remove the wrappers for write{b,w} & friends # . align case entries with corresponding switch statement # -------------------------------------------- # 03/05/15 davem@nuts.ninka.net 1.1138 # Merge bk://kernel.bkbits.net/acme/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/15 acme@conectiva.com.br 1.1127.3.6 # o wan/cycx: remove more typedefs # # Also use kernel-doc for struct cycx_hw # -------------------------------------------- # 03/05/15 davem@nuts.ninka.net 1.1139 # Merge bk://kernel.bkbits.net/acme/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/15 acme@conectiva.com.br 1.1127.3.7 # o wan/cycx: remove the last typedefs, some kernel doc comments # -------------------------------------------- # 03/05/15 davem@nuts.ninka.net 1.1140 # Merge bk://kernel.bkbits.net/acme/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/15 acme@conectiva.com.br 1.1127.3.8 # o wan/cycx: use min_t and remove one more private MIN() implementation # -------------------------------------------- # 03/05/15 davem@nuts.ninka.net 1.1141 # Merge bk://kernel.bkbits.net/acme/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/15 davem@nuts.ninka.net 1.1142 # [NET]: Split out policy flow cache to be a generic facility. # -------------------------------------------- # 03/05/15 chas@cmf.nrl.navy.mil 1.1143 # [ATM]: Allow ATM to be loaded as a module. # -------------------------------------------- # 03/05/15 davem@nuts.ninka.net 1.1144 # [ATM]: common.c needs linux/init.h # -------------------------------------------- # 03/05/16 acme@conectiva.com.br 1.1127.3.9 # o ipx: remove debug message for successfull bind # -------------------------------------------- # 03/05/15 davem@nuts.ninka.net 1.1145 # [ATM]: atm{pvc,svc}_exit cannot be __exit. # -------------------------------------------- # 03/05/15 davem@nuts.ninka.net 1.1146 # Merge bk://kernel.bkbits.net/acme/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/15 davem@nuts.ninka.net 1.1147 # [NET]: Regenerate flow cache hash rnd more sanely. # -------------------------------------------- # 03/05/15 davem@nuts.ninka.net 1.1148 # [NET]: Hoplimit is a metric not a route attribute. # -------------------------------------------- # 03/05/16 davem@nuts.ninka.net 1.1149 # [IPV4]: Respect hoplimit route metric. # -------------------------------------------- # 03/05/16 davem@kernel.bkbits.net 1.1150 # Merge davem@nuts.ninka.net:/home/davem/src/BK/net-2.5 # into kernel.bkbits.net:/home/davem/net-2.5 # -------------------------------------------- # 03/05/16 stevef@steveft21.ltcsamba 1.1113.2.2 # Fix oops caused by lack of spinlock protection on some lists. Fix display # of NTFS dfs junctions (which now correctly appear as symlinks). # Return writebehind caching errors on file close. # -------------------------------------------- # 03/05/16 acme@conectiva.com.br 1.1127.3.10 # o ipx: move route functions to net/ipx/ipx_route.c # -------------------------------------------- # 03/05/16 agrover@groveronline.com 1.1063.36.2 # ACPI: Return only proper values (0 or 1) from our interrupt handler # (Andrew Morton) # -------------------------------------------- # 03/05/16 agrover@groveronline.com 1.1127.2.21 # Merge groveronline.com:/root/bk/linux-2.5 # into groveronline.com:/root/bk/linux-acpi # -------------------------------------------- # 03/05/16 mk@linux-ipv6.org 1.1149.1.1 # [IPV6]: Add IPCOMP support. # -------------------------------------------- # 03/05/16 davem@nuts.ninka.net 1.1149.1.2 # Merge bk://kernel.bkbits.net/acme/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/16 torvalds@penguin.transmeta.com 1.1127.5.1 # Fix up thinko in nasty "NMI while debug while systenter" # codepath. # # The bug was that the NMI stack fixup triggered even if the # debug exception had _not_ happened on the exact sysenter # entrypoint. The new version should be more robust. # -------------------------------------------- # 03/05/16 yoshfuji@linux-ipv6.org 1.1149.1.3 # [IPV6]: Fix RFC number in ipcomp6.c # -------------------------------------------- # 03/05/16 chas@cmf.nrl.navy.mil 1.1149.1.4 # [ATM]: Fix modular CLIP. # -------------------------------------------- # 03/05/16 jmorris@intercode.com.au 1.1149.1.5 # [IPV4]: Fix RFC number in ipcomp.c # -------------------------------------------- # 03/05/16 davem@kernel.bkbits.net 1.1151 # Merge davem@nuts.ninka.net:/home/davem/src/BK/net-2.5 # into kernel.bkbits.net:/home/davem/net-2.5 # -------------------------------------------- # 03/05/17 rmk@flint.arm.linux.org.uk 1.1063.32.16 # [ARM] Relocate ARM SCSI and Net drivers # # Move Acorn and ARM SCSI and net drivers to drivers/{net,scsi}/arm. # This also allows us to find a reasonable home for other ARM specific # net drivers. # -------------------------------------------- # 03/05/17 rmk@flint.arm.linux.org.uk 1.1063.32.17 # [ARM] Update cyber2000fb.c # # - Fix build warnings. # - Don't modify region in copyarea method. # - Remove FBCON_HAS_CFBx preprocessor tests. # - Use runtime test for netwinder mclk parameters. # -------------------------------------------- # 03/05/17 rmk@flint.arm.linux.org.uk 1.1063.32.18 # [ARM] Fixup yet another missing irqreturn_t # -------------------------------------------- # 03/05/17 rmk@flint.arm.linux.org.uk 1.1063.32.19 # [ARM] Update Acorn IDE drivers. # # icside.c: # - Use C99 structure initialisers. # - Use generic DMA API. # - Use new hwif->hwif_data rather than hwif->hw.priv. # - Add DMA supported/dma supported masks. # - Remember the card type for the remove/shutdown methods. # - Add shutdown method. # rapide.c # - ecard_{claim,release} are no longer required. # -------------------------------------------- # 03/05/17 rmk@flint.arm.linux.org.uk 1.1063.32.20 # [ARM] Remove .devclass initialiser from sa1111ps2. # -------------------------------------------- # 03/05/17 rmk@flint.arm.linux.org.uk 1.1063.32.21 # [ARM] Fix time_after() warnings in ether1.c. # -------------------------------------------- # 03/05/17 rmk@flint.arm.linux.org.uk 1.1127.5.2 # [ARM] Merge Linus' tree with current ARM tree. # -------------------------------------------- # 03/05/17 torvalds@home.transmeta.com 1.1152 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/17 axboe@suse.de 1.1153 # [PATCH] Always allocate sense buffer for block commands # # This always set ->sense for blk_pc_requests(), even if the actual user # doesn't care about the sense results. This is a lot nicer than then # having to have conditional checks for it all over the place in the low- # level drivers. # -------------------------------------------- # 03/05/17 sam@ravnborg.org 1.1154 # [PATCH] Remove 'strchr' warning from reiserfs # # Reiserfs emits a warning about strchr being defined but not used. I # finally tracked down the reason for this. gcc - when seeing strstr(x, # "%") recognized that the second parameter is a char, and therefore uses # strchr instead of strstr. The workaround to avoid the warning is to # replace the call to strstr with strchr - which is OK. # # This hides the warning, and brings us down to 6 warnings for a make # defconfig bzImage. # -------------------------------------------- # 03/05/17 torvalds@home.transmeta.com 1.1155 # Make request_module() take a printf-like vararg argument instead of a string. # # This is what a lot of the callers really wanted. # -------------------------------------------- # 03/05/17 rmk@flint.arm.linux.org.uk 1.1127.5.3 # [ARM] Fix DMA handler race condition. # # This fixes a race condition in the RiscPC DMA code, which causes # DMA for a channel to halt due to a race condition between the # hardware state machine and the software programming the next DMA # buffer. # -------------------------------------------- # 03/05/17 acme@conectiva.com.br 1.1156 # o ipv6/route: fix .dst.metrics struct init for ip6_null_entry # # Thanks to Andrew Morton for reporting. # -------------------------------------------- # 03/05/17 acme@conectiva.com.br 1.1157 # o ipv6/route: use C99 style init for struct init # # Also move ft6_dflt_pointer to .bss and use void # in ip6_dst_gc as it doesn't take any paramenters # -------------------------------------------- # 03/05/17 mk@linux-ipv6.org 1.1156.1.1 # [CRYPTO]: Update deflate dependencies. # -------------------------------------------- # 03/05/17 davem@nuts.ninka.net 1.1158 # Merge bk://kernel.bkbits.net/acme/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/17 rusty@rustcorp.com.au 1.1159 # [NETFILTER]: Move skb_ip_make_writable to netfilter.c. # -------------------------------------------- # 03/05/17 acme@conectiva.com.br 1.1157.1.1 # o ipv6/addrconf: use C99 struct init style for inet6_rtnetlink_table # -------------------------------------------- # 03/05/17 acme@conectiva.com.br 1.1157.1.2 # o ipv6/exthdrs: use C99 struct init style. # -------------------------------------------- # 03/05/17 davem@nuts.ninka.net 1.1160 # Merge bk://kernel.bkbits.net/acme/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/17 acme@conectiva.com.br 1.1157.1.3 # o ipv6/icmp: use C99 struct style init for tab_unreach # -------------------------------------------- # 03/05/17 acme@conectiva.com.br 1.1157.1.4 # o ipv6/ip6_fib: use C99 struct style init and move rt_sernum to .bss # -------------------------------------------- # 03/05/17 davem@nuts.ninka.net 1.1161 # [NETFILTER]: Move skb_ip_make_writable symbol export. # -------------------------------------------- # 03/05/17 davem@nuts.ninka.net 1.1162 # Merge bk://kernel.bkbits.net/acme/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/17 mk@linux-ipv6.org 1.1163 # [IPSEC]: Fix ipv4 ipcomp threshold calculation. # -------------------------------------------- # 03/05/17 davem@nuts.ninka.net 1.1164 # [IPV4]: Flush routing cache on sysctl_ip_default_ttl changes. # -------------------------------------------- # 03/05/18 zaitcev@redhat.com 1.1155.1.1 # [SPARC]: Keiths SMP patch #1 # -------------------------------------------- # 03/05/18 zaitcev@redhat.com 1.1155.1.2 # [SPARC]: Add ->release to ESP driver. # -------------------------------------------- # 03/05/18 zaitcev@redhat.com 1.1155.1.3 # [SPARC]: Update defconfig. # -------------------------------------------- # 03/05/18 zaitcev@redhat.com 1.1155.1.4 # [SPARC]: Sanitize BUG(). # -------------------------------------------- # 03/05/18 acme@conectiva.com.br 1.1157.1.5 # o wanrouter/wanproc: code cleanups # # . Use seq_puts in places where seq_printf is not needed # . remove trailing whitespaces and tabs # . remove some unneeded includes # . move the space before the third and fourth columns from # the values to be inserted to the mask # . some other CodingStyle changes # -------------------------------------------- # 03/05/18 acme@conectiva.com.br 1.1157.1.6 # o drivers/net/wan/sdla*: use SET_MODULE_OWNER at net_device setup # -------------------------------------------- # 03/05/18 chas@cmf.nrl.navy.mil 1.1165 # [ATM]: Need to use try_module_get not __module_get. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.1 # [PATCH] sysfs_create_link() fix # # It is incorrectly precalculating the string's length. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.2 # [PATCH] ia32 subarch circular dependency fix # # From: john stultz # # This patch fixes a circular dependency (a function in mach_apic.h requires # hard_smp_processor_id() and hard_smp_processor_id() requires macros from # mach_apic.h) that has been in the subarch code for a bit, but was hacked # around with some #ifdefs. # # With the inclusion of the generic-subarch the hack was dropped and bigsmp # and summit promptly broke. So this makes things compile again. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.3 # [PATCH] genarch cpu_mask_to_apicid fix # # From: Martin Bligh # # Add cpu_mask_to_apicid to generic arch to fit with Keith's changes. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.4 # [PATCH] [patch 4/29 voyager cpu_callout_map fix # # From: Martin Bligh # # Change the defn of cpu_callout_map for voyager to volatile to match other # stuff. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.5 # [PATCH] ppp warning fix # # Fix an accidentally negated comparison. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.6 # [PATCH] misc fixes # # - generic_file_open() comment fix (Bill Irwin) # # - kerneldoc fix in truncate.c (Aniruddha M Marathe) # # - remove truncate debug check. # # - page_lock comment fix (Robert Love) # # - remove unused device mapper label. # # - 3c509 docco fix ("Mark Tranchant" ) # # -- # # Documentation/networking/3c509.txt | 2 +- # drivers/md/dm-ioctl.c | 1 - # fs/open.c | 2 +- # include/linux/fs.h | 2 +- # mm/truncate.c | 8 +++----- # 5 files changed, 6 insertions(+), 9 deletions(-) # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.7 # [PATCH] large-dma_addr_t-PAE-only.patch # # From: William Lee Irwin III # # I was just looking over this and noticed 2.4.x makes u64 dma_addr_t # conditional on CONFIG_HIGHMEM64G where 2.5.x uses CONFIG_HIGHMEM. It's # clearly not necessary on CONFIG_HIGHMEM4G, hence this obvious patch. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.8 # [PATCH] 3c59x irqreturn fix # # Apparently boomerang_interrupt() is generating lots of "nobody cared" # warnings - one per packet it seems. Frankly, I don't have a clue why. # # These are ancient cards and the driver is otherwise stable, so just # change it to return IRQ_HANDLED and move on... # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.9 # [PATCH] reiserfs: allow multiple block insertion into the tree # # I've had these reiserfs patches in -mm for many months. We've been # undecided because they trigger bugs in a couple of apps. But those apps # are now fixed, so it's best to get these speedups in. # # # From: Oleg Drokin # # This patch allows insertion of more than one "indirect" block pointer into # the tree in reiserfs. (with all the necessary balancing code changes). # The first user of that feature is hole-creation code that is now ~1000 # times more cpu-efficient for the case of large holes. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.10 # [PATCH] reiserfs: reiserfs_file_write implementation # # From: Oleg Drokin # # With the current 'one block at a time' algorithm, writes past the end of a # file are slow because each new file block is separately added into the tree # causing shifting of other items which is CPU expensive. # # With this new implementation if you write into file with big enough chunks, # it uses half as much CPU. Also this version is more SMP friendly than the # current one. # # There are some known-bad applications that break with this patch (ie. start # to work very slow or even hang). # # This is because the filesystem returns a large value in the stat.st_blocksize # hint (128k instead of 4k). This tickles a small number of application bugs. # One is KDE's kmail 3.04 (fixed by upgrading to 3.1+) and the other is # sleepycat's database from before 1997. # # If you hit a slowdown problem that you believe is related to the increased # "recommended i/o size" value, try to mount your fs with nolargeio=1 mount # option (remount should work too). # # This patch exports block_commit_write(), generic_osync_inode() and # remove_suid() to modules. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.11 # [PATCH] fix CONFIG_APM=m # # From: mikpe@csd.uu.se # # Here is a patch to fix CONFIG_APM=m in 2.5.69-bk11. My patch to have APM # restore the systenter MSRs failed to handle the modular case, which fails # with unresolved symbols. # # Since suspend.o is used from both APM (module or built-in) and ACPI sleep # (built-in), I made suspend.o built-in and dependent on CONFIG_PM. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.12 # [PATCH] Fix for latent bug in vmtruncate() # # From: "Paul E. McKenney" # # The vmtruncate() function shifts down by PAGE_CACHE_SHIFT, then calls # vmtruncate_list(), which deals in terms of PAGE_SHIFT instead. Currently, # no harm done, since PAGE_CACHE_SHIFT and PAGE_SHIFT are identical. Some # day they might not be, hence this patch. # # I also took the liberty of modifying a hand-coded "if" that seems to # optimize for files that are not mapped to instead use unlikely(). # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.13 # [PATCH] v4l: #1 - video-buf update # # From: Gerd Knorr # # This minor patch updates the video-buf module. It just adds a export # for the videobuf_next_field function and adds some debug printk's. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.14 # [PATCH] v4l: #2 - v4l1-compat update # # From: Gerd Knorr # # This patch updates the v4l1-compat module. Changes: # # * use f_op->poll() instead of do_select() # # * reduce stack usage of the v4l1_translate_ioctl() function. # # * misc minor fixes here and there. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.15 # [PATCH] v4l: #4 - bttv docmentation update # # From: Gerd Knorr # # This patch updates the bttv documentation. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.16 # [PATCH] v4l: #5 - i2c module updates. # # From: Gerd Knorr # # This patch updates a number of video4linux-related i2c modules. There are a # number of bugfixes which accumulated over time, also some no-op i2c changes # due to merging the i2c cleanups back into my tree and tweak them to make the # modules compile on both 2.5.x and 2.4.x. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.17 # [PATCH] v4l: #6 - tuner module update # # From: Gerd Knorr # # This patch updates the tv card tuner module. It adds support for a new tuner # and has some minor fixes + cleanups. Also deletes some dead code. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.18 # [PATCH] v4l: #7 - saa7134 driver update # # From: Gerd Knorr # # Yet another big one (due to not being updated for a long time) -- saa7134 # driver update. Changes: # # * various bugfixes / cleanups. # # * new cards added to the cardlist. # # * started support for saa7133/35 chips. # # * make the driver check pci quirks. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.19 # [PATCH] fix tuner.c and tda9887.c # # From: Shane Shrybman # # Attached are two patches that make bttv compile and work in 2.5.69-mm6. I # think this broke in -mm4. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.20 # [PATCH] radeonfb.c 64-bit fixes # # From: David Mosberger # # Don't truncate the ioremap return value to 32-bits. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.21 # [PATCH] use %p to print pointers in cs4281 # # From: Christoph Hellwig # # This is a really old patch from the IA64 tree and as Cirrus Logic doesn't # maintain the driver anymore for about two years now no one picked it up.. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.22 # [PATCH] memcpy/memset fixes # # Fix some places which were doing # # memcpy(to, from, sizeof(to)); # and # memset(to, 0, sizeof(to)); # # Found by the Stanford checker. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.23 # [PATCH] BUG() -> BUG_ON() conversions. # # From: davej@codemonkey.org.uk # # Various performance critical sections. # # The increased cache footprint may be a pessimisation, especially on earlier # CPUs where unlikely() doesn't do anything useful, and we fall back to # trusting gcc to DTRT. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.24 # [PATCH] 3c59x: add support for 3c905B-T4, 3C920B-EMB-WNM # # A couple of new PCI IDs which were found in 3com's driver by Xose Vazquez # Perez . # # We don't know if these work, but if they are really 905B's and 920's it # should be OK. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.25 # [PATCH] CONFIG_ACPI_SLEEP compile fix # # From: mikpe@csd.uu.se # # When I grepped for these variables I failed to notice the references in # acpi/wakeup.S. This patch fixes this. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.26 # [PATCH] fix handling of spares physical APIC ids # # From: William Lee Irwin III # # To handle sparse physical APIC ID's properly the phys_cpu_present_map must # be scanned beyond bit NR_CPUS while ensuring no more than NR_CPUS are woken # in order not to attempt to wake non-addressible cpus. # # The following patch adds that logic to smp_boot_cpus() and corrects the # failure to wake secondaries reported by dhowells, with successful wakeup, # runtime, reboot, and halting reported after it was applied. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.27 # [PATCH] put_page_testzero() fix # # From: William Lee Irwin III # # put_page_testzero() does BUG_ON(page_count(page)) when its argument is p. # -------------------------------------------- # 03/05/19 akpm@digeo.com 1.1155.2.28 # [PATCH] DAC960 oops fix # # ioctl_by_bdev() passes in a NULL file*, so we had better not dereference it. # -------------------------------------------- # 03/05/19 warp@mercury.d2dc.net 1.1093.2.3 # [PATCH] I2C: And yet another it87 patch. # # Trivial, but important. # # Somehow in the patching the bk tree somehow got two memset's to clear # new_client in it87_detect, normally while this would be bad, it would # not be critical. # # However one of the two happens BEFORE the variable is set, and thus # things go badly. # -------------------------------------------- # 03/05/19 torvalds@home.transmeta.com 1.1164.1.1 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/19 mingo@elte.hu 1.1164.1.2 # [PATCH] signal latency fixes # # This fixes an SMP window where the kernel could miss to handle a signal, # and increase signal delivery latency up to 200 msecs. Sun has reported # to Ulrich that their JVM sees occasional unexpected signal delays under # Linux. The more CPUs, the more delays. # # The cause of the problem is that the current signal wakeup # implementation is racy in kernel/signal.c:signal_wake_up(): # # if (t->state == TASK_RUNNING) # kick_if_running(t); # ... # if (t->state & mask) { # wake_up_process(t); # return; # } # # If thread (or process) 't' is woken up on another CPU right after the # TASK_RUNNING check, and thread starts to run, then the wake_up_process() # here will do nothing, and the signal stays pending up until the thread # will call into the kernel next time - which can be up to 200 msecs # later. # # The solution is to do the 'kicking' of a running thread on a remote CPU # atomically with the wakeup. For this i've added wake_up_process_kick(). # There is no slowdown for the other wakeup codepaths, the new flag to # try_to_wake_up() is compiled off for them. Some other subsystems might # want to use this wakeup facility as well in the future (eg. AIO). # # In fact this race triggers quite often under Volanomark rusg, with this # change added, Volanomark performance is up from 500-800 to 2000-3000, on # a 4-way x86 box. # -------------------------------------------- # 03/05/19 mingo@elte.hu 1.1164.1.3 # [PATCH] scheduler cleanup # # This removes the unused requeueing code. # -------------------------------------------- # 03/05/19 mingo@elte.hu 1.1164.1.4 # [PATCH] sync wakeup on UP # # This fixes the scheduler's sync-wakeup code to be consistent on UP as # well. # # Right now there's a behavioral difference between an UP kernel and an # SMP kernel running on a UP box: sync wakeups (which are only activated # on SMP) can cause a wakeup of a higher prio task, without preemption. # On UP kernels this does not happen. This difference in wakeup behavior # is bad. # # This patch activates sync wakeups on UP as well - in the cases sync # wakeups are done the waker knows that it will schedule away soon, so # this 'delay preemption' decision is correct on UP as well. # -------------------------------------------- # 03/05/19 david-b@pacbell.net 1.1155.3.1 # [PATCH] USB: usbtest, talk to user mode "firmware" # # Supports some user-mode testing "firmware". # -------------------------------------------- # 03/05/19 mingo@elte.hu 1.1164.1.5 # [PATCH] Fix lost scheduler rebalances # # This fixes a race noticed by Mike Galbraith: the scheduler can lose a # rebalance tick if some task happens to not be rescheduled in time. This # is not a fatal condition, but an inconsistency nevertheless. # -------------------------------------------- # 03/05/19 lkml001@vrfy.org 1.1155.3.2 # [PATCH] USB: usb-skeleton compile fix # # usb-skelteon doesn't compile after recent changes. # -------------------------------------------- # 03/05/19 anton@samba.org 1.1155.3.3 # [PATCH] USB: gadget compile error on ppc64 # # I tried compiling USB gadget support on ppc64 (why not :). Looks like Im # seeing a conflict between const and __devinitdata: # # drivers/usb/gadget/net2280.c:2645: pci_ids causes a section type conflict # -------------------------------------------- # 03/05/19 mdharm-usb@one-eyed-alien.net 1.1155.3.4 # [PATCH] USB: storage: generate BBB reset after abort # # This patch forces the generation of a bulk-transport reset after a command # abort. Careful reading of the bulk-only specification shows that a reset # must be done after an abort to get the host and target back into phase. # -------------------------------------------- # 03/05/19 mdharm-usb@one-eyed-alien.net 1.1155.3.5 # [PATCH] USB: storage: remove inline function # # This patch removes a single-line inline function and replaces it with it's # expansion everywhere. The inline function was really only there for a # transitional step. # -------------------------------------------- # 03/05/19 torvalds@home.transmeta.com 1.1164.1.6 # Merge bk://bk.arm.linux.org.uk/linux-2.5-rmk # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/19 Walter.Harms@Informatik.Uni-Oldenburg.DE 1.1155.3.6 # [PATCH] USB: fixes kernel_thread # -------------------------------------------- # 03/05/19 agrover@groveronline.com 1.1127.2.22 # ACPI: Update Toshiba driver to 0.15 (John Belmonte) # - workaround sporadic problem with hotkey ceasing to work # - cleanups # -------------------------------------------- # 03/05/19 bcollins@debian.org 1.1164.1.7 # [PATCH] Update IEEE1394 (r931) # # - Fix possible memory leak in iso.c # - Added handling for more than 1 Logical_Unit_Number entry in a unit # directory for SBP-2. This allows for handling the second type of LUN # that we didn't support yet. # -------------------------------------------- # 03/05/19 hch@sgi.com 1.1155.4.1 # [XFS] merge Steve's sync changes over to 2.5 # # SGI Modid: 2.5.x-xfs:slinx:147932a # -------------------------------------------- # 03/05/19 agrover@groveronline.com 1.1155.5.1 # Merge groveronline.com:/root/bk/linux-2.5 # into groveronline.com:/root/bk/linux-acpi # -------------------------------------------- # 03/05/19 Andries.Brouwer@cwi.nl 1.1164.1.8 # [PATCH] namespace fix # # After # # # mount --rbind /tmp /mnt # # (on 2.5.68) I have a corrupted namespace. Umounting /mnt fails, # and /proc/mounts contains # # ... # /dev/root /mnt ext3 rw 0 0 # proc /mnt/proc proc rw 0 0 # usbfs /mnt/proc/bus/usb usbfs rw 0 0 # /dev/hdb5 /mnt/usr reiserfs rw 0 0 # ... # # where of course no directories /mnt/proc or /mnt/usr exist. # # This is caused by the fact that copy_tree() thinks that the dentry # it is called with is the root of the filesystem. If it is not, # confusion arose. # # This patch fixes this confusion. # -------------------------------------------- # 03/05/19 Andries.Brouwer@cwi.nl 1.1164.1.9 # [PATCH] NCR5380.c fix # # Several SCSI drivers confuse CHECK_CONDITION and CHECK_CONDITION << 1. # One of them is NCR5380.c. Below a patch adding status_byte() twice. # # (On the other hand, sun3_NCR5380.c does this right, and generally # looks better. Maybe they can be merged eventually.) # -------------------------------------------- # 03/05/19 cwf@sgi.com 1.1155.4.2 # [XFS] Merge over an irix fix # # SGI Modid: 2.5.x-xfs:slinx:132737a # -------------------------------------------- # 03/05/19 Andries.Brouwer@cwi.nl 1.1164.1.10 # [PATCH] fix oops in namespace.c # # A familar type of Oops: d_path() can return an error ENAMETOOLONG, and # if we fail to test a segfault occurs. # # So we must test. What we do is a different matter. Rather arbitrarily # I return the string " (too long)" for use in /proc/mounts. # -------------------------------------------- # 03/05/19 nathans@sgi.com 1.1155.4.3 # [XFS] Fix up error handling on the initial superblock read. # # SGI Modid: 2.5.x-xfs:slinx:148285a # -------------------------------------------- # 03/05/19 hch@sgi.com 1.1155.4.4 # [XFS] avoid sleep_on in the sync code # # SGI Modid: 2.5.x-xfs:slinx:148415a # -------------------------------------------- # 03/05/19 nathans@sgi.com 1.1155.4.5 # [XFS] Fix up a pagebuf spelling mistake and a couple of whitespace botches. # # SGI Modid: 2.5.x-xfs:slinx:148595a # -------------------------------------------- # 03/05/19 mingo@elte.hu 1.1164.1.11 # [PATCH] fix do_fork() return value # # Noticed by Julie DeWandel . # # do_fork() needs to return the pid (or error), not the pointer to the # resulting process structure. The process structure may not even be # valid any more, since do_fork() has already woken the process up (and as # a result it might already have done its thing and gone away). # # Besides, doing it this way cleans up the users, which all really just # wanted the pid or error number _anyway_. # # This fixes the x86 users, other architectures need to be fixed up as # well. # -------------------------------------------- # 03/05/19 lord@sgi.com 1.1155.4.6 # [XFS] Move xfs_syncd code into xfs_super.c which is the only place which uses it # # SGI Modid: 2.5.x-xfs:slinx:148433a # -------------------------------------------- # 03/05/19 hch@sgi.com 1.1155.4.7 # [XFS] Fix compile warning on my iBook # # SGI Modid: 2.5.x-xfs:slinx:148598a # -------------------------------------------- # 03/05/19 nathans@sgi.com 1.1155.4.8 # [XFS] V1 log tweak - fix log record length used when checking for a partial log # record write during log recovery head/tail calculations. # # SGI Modid: 2.5.x-xfs:slinx:148895a # -------------------------------------------- # 03/05/19 hch@sgi.com 1.1155.4.9 # [XFS] simplify memory allocation code big time # # SGI Modid: 2.5.x-xfs:slinx:148933a # -------------------------------------------- # 03/05/19 hch@sgi.com 1.1155.4.10 # [XFS] Use __GFP_NORETRY in pagebuf readahead code # # SGI Modid: 2.5.x-xfs:slinx:148940a # -------------------------------------------- # 03/05/19 lord@sgi.com 1.1155.4.11 # [XFS] remove the excess ; which crept into the syncd thread somewhere and # basically turned it off. # # SGI Modid: 2.5.x-xfs:slinx:148955a # -------------------------------------------- # 03/05/19 nathans@sgi.com 1.1155.4.12 # [XFS] Large sector changes - fixup definition of xfs_agfl_t, and numerous # changes to make log recovery respect the log device sector size. # # SGI Modid: 2.5.x-xfs:slinx:149230a # -------------------------------------------- # 03/05/19 nathans@sgi.com 1.1155.4.13 # [XFS] Small buftarg cleanup - keep code which pokes inside a buftarg all in # one spot, which lets us keep more common code in sync, 2.4/2.5 and is # slightly cleaner anyway. # # SGI Modid: 2.5.x-xfs:slinx:149231a # -------------------------------------------- # 03/05/19 nathans@sgi.com 1.1155.4.14 # [XFS] Second part buftarg cleanup, don't poke inside a buftarg here anymore # # SGI Modid: 2.5.x-xfs:slinx:149232a # -------------------------------------------- # 03/05/19 nathans@sgi.com 1.1155.4.15 # [XFS] Remove a void* from the xfs_mount structure, move the log stripe mask # field from the xfs_mount structure to the log structure (saves a couple # of pointer dereferences when writing to the log, with v2 logs only). # # SGI Modid: 2.5.x-xfs:slinx:149395a # -------------------------------------------- # 03/05/19 nathans@sgi.com 1.1155.4.16 # [XFS] Rationalise xlog_in_core2 definition, remove some ifdef __KERNEL__ code # which is unnecessary in log recovery, clarify some recovery debug code. # # SGI Modid: 2.5.x-xfs:slinx:149396a # -------------------------------------------- # 03/05/19 nathans@sgi.com 1.1155.4.17 # [XFS] Make log recovery code style consistent with a/ itself and b/ much of # the rest of XFS. Fix numerous crimes against whitespace. # # SGI Modid: 2.5.x-xfs:slinx:149398a # -------------------------------------------- # 03/05/19 nathans@sgi.com 1.1155.4.18 # [XFS] Fix two remaining indentation inconsistencies. # # SGI Modid: 2.5.x-xfs:slinx:149400a # -------------------------------------------- # 03/05/19 nathans@sgi.com 1.1155.4.19 # [XFS] Remove some dead code. # # SGI Modid: 2.5.x-xfs:slinx:149409a # -------------------------------------------- # 03/05/19 hch@hera.kernel.org 1.1164.1.12 # Merge # -------------------------------------------- # 03/05/19 torvalds@penguin.transmeta.com 1.1164.2.1 # Merge bk://cifs.bkbits.net/linux-2.5cifs # into penguin.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/19 torvalds@penguin.transmeta.com 1.1164.1.13 # Merge ssh://master.kernel.org//home/hch/BK/xfs/linux-2.5/ # into penguin.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/19 davej@codemonkey.org.uk 1.1127.1.6 # [AGPGART] Add support for VIA K8T400M GART. # -------------------------------------------- # 03/05/19 davej@codemonkey.org.uk 1.1127.1.7 # [AGPGART] Improve Kconfig. # The AMD K8 GART driver is really for the on-CPU GART not the chipset as the Kconfig described. # Also fix up some grammar elsewhere. # -------------------------------------------- # 03/05/19 greg@kroah.com 1.1093.2.4 # i2c: fix up i2c-dev driver based on previous core changes. # # This fixes the problem that adapter id's are not the minor number for the # i2c-dev devices anymore. Also adds a i2c-dev class to let userspace know # which i2c-dev device is bound to which i2c adapter. # -------------------------------------------- # 03/05/19 greg@kroah.com 1.1164.1.14 # Merge # -------------------------------------------- # 03/05/20 davej@codemonkey.org.uk 1.1127.1.8 # [AGPGART] agp_3_5_enable() doesn't need mode parameter. # -------------------------------------------- # 03/05/20 davej@codemonkey.org.uk 1.1127.1.9 # [AGPGART] Sanity check (and fix up broken) AGP modes when in AGP 3.0 mode. # -------------------------------------------- # 03/05/19 david-b@pacbell.net 1.1155.3.7 # [PATCH] USB: Fix machine lockup when unloading HC driver # # Alan Stern wrote: # > I finally got tired of my computer locking up when I tried to rmmod the # > low-level host controller driver. It turns out the problem lies in the # > root-hub status urb code in core/hcd.c -- primarily a result of # > rh_report_status() not calling hcd_giveback_urb()... # # Or in short: your patch removes some old logic for the "automagic # interrupt transfer" special casing ... which recently started to # break that rmmod path. # # With automagic, the only time an interrupt urb (like the root hub # status urb) could legitimately be given back was for unlink. But # that unlink doesn't seem to be issued in the same way lately during # the rmmod paths. (If they're less bizarre lately, that's good!) # # # > If this patch seems all right, will you please let Greg know it's okay to # > apply it? # # I changed a couple minor things below ... basically (a) fixing the # issue Duncan Sands pointed out (always call completions with irqs # disabled, even if hub driver currently doesn't care), (b) better # logic to avoid retriggering the timer during shutdown, (c) not # doing del_timer_sync() while holding that lock, plus (d) a minor # linewrap fix. # -------------------------------------------- # 03/05/19 greg@kroah.com 1.1164.3.1 # Merge kroah.com:/home/greg/linux/BK/bleed-2.5 # into kroah.com:/home/greg/linux/BK/gregkh-2.5 # -------------------------------------------- # 03/05/19 davem@nuts.ninka.net 1.1166 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/19 davem@nuts.ninka.net 1.1164.4.1 # Merge nuts.ninka.net:/home/davem/src/BK/sparcwork-2.5 # into nuts.ninka.net:/home/davem/src/BK/sparc-2.5 # -------------------------------------------- # 03/05/20 davej@codemonkey.org.uk 1.1127.1.10 # [AGPGART] Log broken applications that pass crap flags so they can be fixed. # -------------------------------------------- # 03/05/19 davem@nuts.ninka.net 1.1164.4.2 # [SPARC{32,64}]: Adjust for changed do_fork return value. # -------------------------------------------- # 03/05/19 zaitcev@redhat.com 1.1164.4.3 # [SPARC]: Fix ptracing of syscalls. # -------------------------------------------- # 03/05/19 zaitcev@redhat.com 1.1164.4.4 # [SPARC]: Switch bitops to unsigned long. # -------------------------------------------- # 03/05/20 davej@codemonkey.org.uk 1.1127.1.11 # [AGPGART] Skip nonisoch setup if isoch setup was successful. # -------------------------------------------- # 03/05/20 davej@codemonkey.org.uk 1.1127.1.12 # [AGPGART] Silly typo that put tried to put things into a impossible x16 mode. # -------------------------------------------- # 03/05/20 davej@tetrachloride.(none) 1.1164.1.15 # Merge tetrachloride.(none):/mnt/raid/src/kernel/2.5/bk-linus # into tetrachloride.(none):/mnt/raid/src/kernel/2.5/agpgart # -------------------------------------------- # 03/05/19 davem@nuts.ninka.net 1.1167 # [NET]: Fix netdevice unregister races. # # We had two major issues when unregistering networking devices. # 1) Even trying to run hotplug asynchronously could deadlock # if keventd was currently trying to get the RTNL semaphore # in order to process linkwatch events. # 2) Unregister needs to wait for the last reference to go away # before the finalization of the unregister can execute. This # cannot occur under the RTNL semaphore as this is deadlock # prone as well. # # The solution is to do all of this stuff after dropping the # RTNL semaphore. rtnl_lock, if it is about to protect a region # of code that could unregister network devices, registers a list # to which unregistered netdevs are attached. At rtnl_unlock time # this list is processed to wait for refcounts to drop to zero and # then finalize the unregister. # -------------------------------------------- # 03/05/19 torvalds@home.transmeta.com 1.1164.1.16 # Merge bk://kernel.bkbits.net/davem/sparc-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/20 acme@conectiva.com.br 1.1164.1.17 # o sock.h: kernel-doc style comment for struct sock # -------------------------------------------- # 03/05/19 davem@nuts.ninka.net 1.1168 # [NET]: More device register/unregister fixing. # # Revert the rtnl_lock API change, it is totally unneeded. # Instead we manage the todo work inside of net/core/dev.c # # Also, we have to move sbin hotplug invocation outside of # the RTNL semaphore as well, both for register and unregister. # -------------------------------------------- # 03/05/19 davem@nuts.ninka.net 1.1169 # [NET]: Fix sock_fprog setsockopt compat handling. Based upon patch from Andi Kleen. # -------------------------------------------- # 03/05/19 benh@kernel.crashing.org 1.1170 # [SUNGEM]: Updates from PowerPC people. # # Support more chips and split out all the complex PHY # handling into a seperate file. # -------------------------------------------- # 03/05/19 yoshfuji@linux-ipv6.org 1.1171 # [NET]: Misplaced description in ip-sysctl.txt. # -------------------------------------------- # 03/05/19 yoshfuji@linux-ipv6.org 1.1172 # [IPV6]: Move NIP6 macro into general header. # -------------------------------------------- # 03/05/19 yoshfuji@linux-ipv6.org 1.1173 # [IPV6]: Update RFC references. # -------------------------------------------- # 03/05/19 davem@nuts.ninka.net 1.1174 # Merge bk://kernel.bkbits.net/acme/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/19 hch@lst.de 1.1175 # [NET]: Fix dev_load for !CONFIG_KMOD. # -------------------------------------------- # 03/05/19 hch@lst.de 1.1176 # [NET]: Switch comx over to initcalls. # -------------------------------------------- # 03/05/20 davem@nuts.ninka.net 1.1177 # [NET]: Comment typo in net/core/dev.c, thanks akpm. # -------------------------------------------- # 03/05/20 davem@nuts.ninka.net 1.1178 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/20 davem@nuts.ninka.net 1.1179 # Merge bk://kernel.bkbits.net/acme/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/20 rmk@flint.arm.linux.org.uk 1.1164.5.1 # [ARM] do_fork() now returns the PID. # -------------------------------------------- # 03/05/20 acme@conectiva.com.br 1.1164.1.18 # o wan/cycx: remove unneeded ioctl stub and fix namespace # -------------------------------------------- # 03/05/20 akpm@digeo.com 1.1180 # [PATCH] apply_alternatives() fix # # From: Andi Kleen # # There is some assembly code in setup.c which doesn't explicitly set its # section. It comes after a C function which is marked __init. The compiler # does not reset the section after such C functions. The assembly code is # going into .text.init. # # That's the wrong section. We get oopses modprobing sctp and, with Manfred's # unmap-free-pages debug patch we get oopses modprobing e100.ko. In # apply_alternatives(). # -------------------------------------------- # 03/05/20 akpm@digeo.com 1.1181 # [PATCH] sound/core/memalloc.c needs mm.h # # struct page is undefined in this file without this on Alpha. # -------------------------------------------- # 03/05/20 akpm@digeo.com 1.1182 # [PATCH] revert sysfs non-fix # # I completely misread this code and there was no bug. In fact yesterday's fix # broke it. Revert. # -------------------------------------------- # 03/05/20 akpm@digeo.com 1.1183 # [PATCH] ppc64 update for do_fork() change # # This updates ppc64 for the do_fork() semantics change. # -------------------------------------------- # 03/05/20 hch@lst.de 1.1184 # [PATCH] do_fork updates for ppc # # Update ppc for mingo's do_fork changes. Together with the pmac compile # fixes this allows me to stay at the bleeding edge with my my ibook.. # -------------------------------------------- # 03/05/20 greg@kroah.com 1.1185 # Merge gregkh@kernel.bkbits.net:/home/gregkh/linux/linus-2.5 # into kroah.com:/home/linux/linux/BK/gregkh-2.5 # -------------------------------------------- # 03/05/20 rth@kanga.twiddle.net 1.1155.6.1 # [ALPHA] Fix single-step breakpoints. # From Ivan Kokshaysky . # -------------------------------------------- # 03/05/20 rth@kanga.twiddle.net 1.1184.1.1 # Merge kanga.twiddle.net:/home/rth/work/linux/linus-2.5 # into kanga.twiddle.net:/home/rth/work/linux/axp-2.5 # -------------------------------------------- # 03/05/20 rth@kanga.twiddle.net 1.1184.1.2 # [ALPHA] Update for do_fork changes. # From Marc Zyngier . # -------------------------------------------- # 03/05/20 david-b@pacbell.net 1.1186 # [PATCH] USB: Fix machine lockup when unloading HC driver (part 2) # # Alan Stern wrote: # > I suggest you just forget about acquiring the lock in status_dequeue() and # > simply leave it as # > # > del_timer_sync (&hcd->rh_timer); # > hcd->rh_timer.data = 0; # # Hmm, so if some other URB gets queued in that window, # it'll get trashed? Unlikely .. the clean fix would be # making the status endpoint have a real URB queue. # # I combined your suggested change with two others: # (a) protect the status-unlink and control completion # handlers against IRQs [ the cases Duncan noted] # (b) use mod_timer to retrigger the timer, instead of the # heavy weight path. # -------------------------------------------- # 03/05/20 david-b@pacbell.net 1.1187 # [PATCH] USB: SMP ehci-q.c 1010 BUG() # # Stefano Barbato wrote: # > Dual PIII # > kernel 2.4.21-rc2 (w/ SMP) (2.5.69 below) # > ... # > # > I put a few printk before the BUG() and I found that the offending if() is # > this: # > if(qh->qh_state != QH_STATE_LINKED # > && qh->qh_state != QH_STATE_UNLINK_WAIT) # > # > because qh_state were QH_STATE_COMPLETING. # # I got a similar SMP report recently, but without info about # which clause was failing -- which is a key clue, thanks!! # # The COMPLETING state is used only while a QH is being # scanned for completed TDs. (Think CPU-0 irq handler.) # Looking at the handful of places that call the routine # reporting the BUG(), a couple seem like they could make # trouble with multiple CPUs in the driver. # -------------------------------------------- # 03/05/20 david-b@pacbell.net 1.1188 # [PATCH] USB: disable usb device endpoints in more places # # This patch touches the most significant places in usbcore # that need to respond to configuration change events: # # - set_interface changes altsettings; affects endpoints # in both new and old settings (but not other endpoints). # # - set_configuration; affects every endpoint # # The endpoints get disabled, flushing hardware state # reliably. This resolves two FIXMEs here, part of one # in OHCI (ed_get) and all of one in EHCI (qh_append_tds). # # Not many drivers currently use these code paths, but # now they should start to work properly. # -------------------------------------------- # 03/05/20 James.Bottomley@SteelEye.com 1.1184.2.1 # [PATCH] do_fork fixes for voyager x86 subarch # # It looks like the do_fork was converted in voyager_smp.c, but the # addition of wake_up_forked_process() was missed leading to a boot # panic. The attached fixes it. # -------------------------------------------- # 03/05/20 agrover@groveronline.com 1.1184.3.1 # Merge groveronline.com:/root/bk/linux-2.5 # into groveronline.com:/root/bk/linux-acpi # -------------------------------------------- # 03/05/20 davej@codemonkey.org.uk 1.1164.6.1 # [AGPGART] PPC compile fix. # Generic suspend/resume methods are no more. # -------------------------------------------- # 03/05/20 torvalds@penguin.transmeta.com 1.1184.1.3 # Merge bk://bk.arm.linux.org.uk/linux-2.5-rmk # into penguin.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/21 paulus@samba.org 1.1184.4.1 # PPC32: Need to call wake_up_forked_process in SMP idle task setup. # -------------------------------------------- # 03/05/20 baldrick@wanadoo.fr 1.1189 # [PATCH] USB speedtouch: replace yield() # # Use set_current_state (TASK_RUNNING); schedule(); instead. # -------------------------------------------- # 03/05/20 baldrick@wanadoo.fr 1.1190 # [PATCH] USB speedtouch: add defensive memory barriers # # Defend against future maintainers. # -------------------------------------------- # 03/05/20 baldrick@wanadoo.fr 1.1191 # [PATCH] USB speedtouch: remove stale code # # Should have gone long ago. # -------------------------------------------- # 03/05/20 baldrick@wanadoo.fr 1.1192 # [PATCH] USB speedtouch: spin_lock_irqsave -> spin_lock_irq in process context # # Replace spin_lock_irqsave/spin_unlock_irqrestore with # spin_lock_irq/spin_unlock_irq in routines that are only # called in process context. # -------------------------------------------- # 03/05/20 baldrick@wanadoo.fr 1.1193 # [PATCH] USB speedtouch: spin_lock_irqsave -> spin_lock_irq in tasklets # # Replace spin_lock_irqsave/spin_unlock_irqrestore with # spin_lock_irq/spin_unlock_irq in tasklet actions, since # these are always called with local irqs enabled. # -------------------------------------------- # 03/05/20 baldrick@wanadoo.fr 1.1194 # [PATCH] USB speedtouch: remove useless NULL pointer checks # # The stats field is never NULL. # -------------------------------------------- # 03/05/20 baldrick@wanadoo.fr 1.1195 # [PATCH] USB speedtouch: receive path micro optimization # # Make the most discriminating comparison first. # -------------------------------------------- # 03/05/20 baldrick@wanadoo.fr 1.1196 # [PATCH] USB speedtouch: verbose debugging # # Add a vdbg macro for verbose debugging, and convert some # noisy debugging statements to use it. # -------------------------------------------- # 03/05/21 davej@codemonkey.org.uk 1.1164.6.2 # [AGPGART] Remove duplicated fast writes test. # -------------------------------------------- # 03/05/20 torvalds@home.transmeta.com 1.1197 # Merge bk://kernel.bkbits.net/gregkh/linux/linus-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/21 davej@codemonkey.org.uk 1.1164.6.3 # [AGPGART] sanity check printk's. # -------------------------------------------- # 03/05/20 torvalds@home.transmeta.com 1.1198 # Merge penguin:v2.5/linux # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/20 davem@nuts.ninka.net 1.1184.5.1 # [IPV4]: Fix route copying during redirects. # -------------------------------------------- # 03/05/20 davem@nuts.ninka.net 1.1184.5.2 # Merge bk://kernel.bkbits.net/acme/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/20 hch@lst.de 1.1184.5.3 # [NET]: Clean up the divert ifdef mess. # -------------------------------------------- # 03/05/20 shemminger@osdl.org 1.1184.5.4 # [NET]: Use SET_MODULE_OWNER in ns83820 driver. # -------------------------------------------- # 03/05/20 davem@nuts.ninka.net 1.1184.5.5 # [NET]: Use irqreturn_t in acenic driver. # -------------------------------------------- # 03/05/20 davem@nuts.ninka.net 1.1184.5.6 # [NET]: Fix build warning in ns83820 driver. # -------------------------------------------- # 03/05/20 kumarkr@us.ibm.com 1.1184.5.7 # [TCP]: Handle NLM_F_ACK in tcp_diag.c # -------------------------------------------- # 03/05/20 Andries.Brouwer@cwi.nl 1.1184.5.8 # [NET]: Use ARRAY_SIZE where appropriate. # -------------------------------------------- # 03/05/20 shemminger@osdl.org 1.1184.5.9 # [NET]: sysfs support of network devices. # -------------------------------------------- # 03/05/20 shemminger@osdl.org 1.1184.5.10 # [NET]: Add sysfs support to several net devices. # -------------------------------------------- # 03/05/20 neilb@cse.unsw.edu.au 1.1199 # [PATCH] kNFSd: TCP nfsd connection hangs when partial record header is received # # Below patch resolves a hang where a TCP nfsd connection will hang even # though new data is received on the socket. We've seen this a few times in # our lab, but it usually happened every few weeks. # # If a short record header is received, the SK_BUSY flag is never cleared, # and even though new data arrives, it will not be handled. This in turn # leads to hangs of particular clients (while others will continue to work # without problem). # # I also changed the return code for that condition to be the same as for a # (regular) short read. # -------------------------------------------- # 03/05/20 neilb@cse.unsw.edu.au 1.1200 # [PATCH] kNFSd: SVC sockets don't disable Nagle # # I noticed that the Nagle algorithm was disabled just recently on the # client side, while it still seems to be enabled on the server side. The # previous patch came from Chuck Lever. # # Below patch disables it on the server side as well. For latency reasons, # this should be the desired behaviour NFS at both client and server. # -------------------------------------------- # 03/05/20 neilb@cse.unsw.edu.au 1.1201 # [PATCH] kNFSd: RPC server need to know that TCP and UDP have different wspace functions. # # From: Hirokazu Takahashi # # sock_wspace() is used to see how much can be written to a udp socket, # but tcp_wspace must be used on a tcp socket. # This patch informs sunrpc/svcsock.c of this subtlety. # -------------------------------------------- # 03/05/20 neilb@cse.unsw.edu.au 1.1202 # [PATCH] kNFSd: Set SOCK_NOSPACE when RPC server decides there is insufficient. # # SOCK_NOSPACE is set, so we must set it when we want to get # a ->write_space callback. # -------------------------------------------- # 03/05/20 neilb@cse.unsw.edu.au 1.1203 # [PATCH] kNFSd: Make sure an RPC socket is closed immediately when a server write fails. # # The check for "write was incomplete" is not atomic with the actual write, # so a second write could slip in after a partial write to a tcp socket # and this will cause problems. # # So we move the locking out a bit, and test if the socket has # been deleted (SK_DEAD) between getting the lock and trying # to send. # -------------------------------------------- # 03/05/20 neilb@cse.unsw.edu.au 1.1204 # [PATCH] kNFSd: Fix #error message when bits are badly defined.. # -------------------------------------------- # 03/05/20 neilb@cse.unsw.edu.au 1.1205 # [PATCH] kNFSd: Minor rearrangements in NFSv4 server code to prepare for mroe state management. # # From: "William A.(Andy) Adamson" # # this is the first of several patches against 2.5 concerning NFSv4 state for # nfsd. it cleans up the names of state structures in preperation for future # share, lease, byte-range, and delegation patches. specifically, it # # 1) renames portions of the stateid_t and moves it along with the clientid_t # from xdr.h into state.h # # 2) uses xdr_netobj to gather related data and length fields in struct # nfs4_open (in xdr4.h) (e.g. we have op_fname.data and op_fname.len # instead of op_name and op_namelen). # # 3) renames NFSD4_CLIENT_MAXNAME to NFS4_OPAQUE_LIMIT which will be used in # other state fields (not just for name length) # -------------------------------------------- # 03/05/20 neilb@cse.unsw.edu.au 1.1206 # [PATCH] kNFSd: NFSv4 open share state patch # # From: "William A.(Andy) Adamson" # # # this open share state patch creates all the structures and hash tables needed # to create and destroy share state on OPEN. # # a struct nfs4_stateowner is introduced. this is currently only used for share # state, but will also be used as an anchor for byte-range lock state. e.g. it # will be either an (open)stateowner or a (lock)stateower. # # a struct nfs4_stateid is introduced with holds stateid info for openfiles per # (open)stateowner. this struct will also hold byte-range lock info for # (lock)stateowners. # # ownerstr_hashtbl[] holds nfs4_stateowners hashed by the nfs4_open owner and # clientid, and is used to lookup nfs4_stateowners on OPEN. # # a struct nfs4_file is introduced which holds info on open files with state. # # file_hashtbl[] holds nfs4_files, and is used to find a file in order to search # for conflicting share locks on OPEN. delegation info will hang off the # nf4_file struct. # # i moved nfsd4_process_open1() into nfs4state.c, and added nfs4_process_open2() # there as well # # i've left lease management, state reclaim, and the special replay management # on sequenceid mutating operations like OPEN for subsequent patches. # -------------------------------------------- # 03/05/20 neilb@cse.unsw.edu.au 1.1207 # [PATCH] kNFSd: Allow request for nfsv4 pseudo root to perform an upcall. # # Most cache-lookups to find export information will cause # an upcall, but currently the lookup to find the pseudo root # for nfsv4 wont asthe cache-handle isn't made available. # This patch makes it available and makes sure that if the # upcall is made, the request is dropped (for now). # -------------------------------------------- # 03/05/20 davem@nuts.ninka.net 1.1184.5.11 # [NET]: Fix typo in ns83820 sysfs changes. # -------------------------------------------- # 03/05/20 davem@nuts.ninka.net 1.1184.5.12 # [ATM]: Fix build after netdev sysfs changes. # -------------------------------------------- # 03/05/20 davem@kernel.bkbits.net 1.1208 # Merge davem@nuts.ninka.net:/home/davem/src/BK/net-2.5 # into kernel.bkbits.net:/home/davem/net-2.5 # -------------------------------------------- # 03/05/20 viro@parcelfarce.linux.theplanet.co.uk 1.1207.1.1 # [PATCH] seq_path(), /proc/mounts and /proc/swaps # # This adds a new seq_...() helper: # # seq_path(seq_file, mnt, dentry, escape) # # It spits the pathname into seq_file, does octal escapes for given set of # characters, returns the number of characters it'd produced or -1 in case # of error. Long names are handled gracefully - you don't need anything # to do, generic seq_file logics will do the right thing. # # /proc/mounts and /proc/swaps are converted to use of seq_path(), some # junk removed. # # /proc/pid/maps will be converted next. # -------------------------------------------- # 03/05/20 viro@parcelfarce.linux.theplanet.co.uk 1.1207.1.2 # [PATCH] seq_path() for /proc/pid/maps # # This converts /proc/pid/maps to use of seq_file, cleans the issues with # d_path() overflows as a side effect. # # It's incremental to seq_path() patch. # -------------------------------------------- # 03/05/21 porter@cox.net 1.1184.4.2 # PPC32: Allow lowmem size to be set even if we don't have HIGHMEM. # -------------------------------------------- # 03/05/21 paulus@samba.org 1.1184.4.3 # PPC32: Makefile cleanups, patch from Sam Ravnborg # -------------------------------------------- # 03/05/20 vojtech@suse.cz 1.1196.1.1 # [PATCH] USB: Make Olympus cameras work with usb-storage # # According to Jan Derfinak, Olympus USB cameras mistakenly report an # 'USBU' signature instead of 'USBS', while using the normal USB Storage # protocol. # # The attached patches (again by Jan) fix this problem in 2.4 and 2.5. # -------------------------------------------- # 03/05/20 viro@parcelfarce.linux.theplanet.co.uk 1.1207.1.3 # [PATCH] O_DIRECT open() fix # # Trivial bugfix: opening a file that doesn't have ->direct_IO() with # O_DIRECT passed in flags fails (as it should) but doesn't call # ->release() even though ->open() had been successful. # # IOW, we have a leak there - e.g. open() of a tty with O_DIRECT will # leak a reference to tty and tty_driver. Besides, quite a few drivers # are _not_ happy with struct file being freed without ->release() after # ->open() has returned 0. # -------------------------------------------- # 03/05/21 paulus@samba.org 1.1184.4.4 # PPC32: Further makefile updates from Sam Ravnborg. # -------------------------------------------- # 03/05/20 torvalds@home.transmeta.com 1.1209 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/21 paulus@samba.org 1.1184.4.5 # PPC32: Minor whitespace and ifdef fixes. # -------------------------------------------- # 03/05/21 paulus@samba.org 1.1184.4.6 # PPC32: Better allocation of DMA-consistent memory on incoherent machines. # -------------------------------------------- # 03/05/21 paulus@samba.org 1.1184.4.7 # PPC32: Fix the declaration of openpic_ipi_action(). # -------------------------------------------- # 03/05/21 paulus@samba.org 1.1184.4.8 # PPC32: Use might_sleep() in kmap(). # -------------------------------------------- # 03/05/21 paulus@samba.org 1.1184.4.9 # PPC32: More fixes for PCI on non-cache-coherent platforms. # -------------------------------------------- # 03/05/21 paulus@samba.org 1.1184.4.10 # PPC32: Define a suitable value for PAGE_KERNEL_NOCACHE # -------------------------------------------- # 03/05/21 davej@tetrachloride.(none) 1.1210 # Merge tetrachloride.(none):/mnt/raid/src/kernel/2.5/bk-linus # into tetrachloride.(none):/mnt/raid/src/kernel/2.5/agpgart # -------------------------------------------- # 03/05/21 davej@codemonkey.org.uk 1.1211 # [AGPGART] Rid AGP/DRM of more typedefs. # -------------------------------------------- # 03/05/21 acme@conectiva.com.br 1.1209.1.1 # o wanrouter/wanmain: fix namespace, fixing the current problem with device_shutdown # -------------------------------------------- # 03/05/21 baldrick@wanadoo.fr 1.1188.1.1 # [PATCH] USB speedtouch: trivial whitespace and name changes # # No real code changes. # -------------------------------------------- # 03/05/21 baldrick@wanadoo.fr 1.1188.1.2 # [PATCH] USB speedtouch: replace yield() # # Use set_current_state (TASK_RUNNING); schedule(); instead. # -------------------------------------------- # 03/05/21 baldrick@wanadoo.fr 1.1188.1.3 # [PATCH] USB speedtouch: add defensive memory barriers # # Defend against future maintainers. # -------------------------------------------- # 03/05/21 baldrick@wanadoo.fr 1.1188.1.4 # [PATCH] USB speedtouch: spin_lock_irqsave -> spin_lock_irq in process context # # Replace spin_lock_irqsave/spin_unlock_irqrestore with # spin_lock_irq/spin_unlock_irq in routines that are only # called in process context. # -------------------------------------------- # 03/05/21 baldrick@wanadoo.fr 1.1188.1.5 # [PATCH] USB speedtouch: spin_lock_irqsave -> spin_lock_irq in tasklets # # Replace spin_lock_irqsave/spin_unlock_irqrestore with # spin_lock_irq/spin_unlock_irq in tasklet actions, since # these are always called with local irqs enabled. # -------------------------------------------- # 03/05/21 baldrick@wanadoo.fr 1.1188.1.6 # [PATCH] USB speedtouch: verbose debugging # # Add a vdbg macro for verbose debugging, and convert some # noisy debugging statements to use it. # -------------------------------------------- # 03/05/21 baldrick@wanadoo.fr 1.1188.1.7 # [PATCH] USB speedtouch: remove stale code # # Should have gone long ago. # -------------------------------------------- # 03/05/21 baldrick@wanadoo.fr 1.1188.1.8 # [PATCH] USB speedtouch: use optimally sized reconstruction buffers # # Calculate the maximum size needed for the SAR # reconstruction buffer from the supplied qos parameters. # -------------------------------------------- # 03/05/21 baldrick@wanadoo.fr 1.1188.1.9 # [PATCH] USB speedtouch: send path micro optimizations # -------------------------------------------- # 03/05/21 baldrick@wanadoo.fr 1.1188.1.10 # [PATCH] USB speedtouch: kfree_skb -> dev_kfree_skb # # Always use dev_kfree_skb. # -------------------------------------------- # 03/05/21 baldrick@wanadoo.fr 1.1188.1.11 # [PATCH] USB speedtouch: remove useless NULL pointer checks # # The stats field is never NULL. # -------------------------------------------- # 03/05/21 baldrick@wanadoo.fr 1.1188.1.12 # [PATCH] USB speedtouch: receive path micro optimization # # Make the most discriminating comparison first. # -------------------------------------------- # 03/05/21 baldrick@wanadoo.fr 1.1188.1.13 # [PATCH] USB speedtouch: receive code rewrite # # Main points: # - receive buffers are decoupled from urbs, so an urb can be # resubmitted with a new buffer before the old buffer is processed. # - the packet reconstruction code is much simpler. # - locking is simplified by the fact that only the tasklet launches # receive urbs # -------------------------------------------- # 03/05/21 greg@kroah.com 1.1196.1.2 # merge # -------------------------------------------- # 03/05/21 greg@kroah.com 1.1196.1.3 # USB: speedtch merge fixups by hand. # -------------------------------------------- # 03/05/21 greg@kroah.com 1.1209.2.1 # Merge kroah.com:/home/greg/linux/BK/bleed-2.5 # into kroah.com:/home/greg/linux/BK/gregkh-2.5 # -------------------------------------------- # 03/05/21 davej@codemonkey.org.uk 1.1212 # [AGPGART] Make alpha AGP work again. # From Jeff Wiedemeier and Richard Henderson # -------------------------------------------- # 03/05/22 paulus@samba.org 1.1209.3.1 # Merge samba.org:/stuff/paulus/kernel/linux-2.5 # into samba.org:/stuff/paulus/kernel/for-linus-ppc # -------------------------------------------- # 03/05/21 agrover@groveronline.com 1.1184.3.2 # ACPI: Do not reinit ACPI irq entry in ioapic (thanks to Stian Jordet) # -------------------------------------------- # 03/05/21 rusty@rustcorp.com.au 1.1209.4.1 # [NETFILTER]: Non-linear iptables: core code. # # Adjusts the IPTables core to handle non-linear packets. Extensions # done separately in next patch. Also, comments about when to set # "me" field in struct ipt_match, ipt_table and ipt_target are # corrected. # -------------------------------------------- # 03/05/21 rusty@rustcorp.com.au 1.1209.4.2 # [NETFILTER]: Linearize iptables matches. # # Adjusts the IPTables matches to handle non-linear packets. # Untested: ipt_ah and ipt_esp. # -------------------------------------------- # 03/05/21 rusty@rustcorp.com.au 1.1209.4.3 # [NETFILTER]: Linearize iptables targets. # # Adjusts the IPTables targets to handle non-linear packets. # ipt_ULOG untested. # -------------------------------------------- # 03/05/21 davem@nuts.ninka.net 1.1209.4.4 # [NETFILTER]: Use proper printf format for size_t in ipt_owner.c # -------------------------------------------- # 03/05/21 davem@nuts.ninka.net 1.1209.4.5 # [NETFILTER]: Update ipt_physdev.c for match arg changes. # -------------------------------------------- # 03/05/22 davem@nuts.ninka.net 1.1209.4.6 # [IPV6]: DST entry leak found by stanford checker. # -------------------------------------------- # 03/05/22 davem@nuts.ninka.net 1.1209.4.7 # [IPV6]: Memory leak found by stanford checker. # -------------------------------------------- # 03/05/22 davem@nuts.ninka.net 1.1209.4.8 # [NET]: In dst_alloc, do not assume layout of atomic_t. # -------------------------------------------- # 03/05/22 hch@lst.de 1.1209.4.9 # [NET]: Make dv_init an initcall. # -------------------------------------------- # 03/05/22 yoshfuji@linux-ipv6.org 1.1209.4.10 # [IPV6]: Remove obsolete declaration in transp_v6.h # -------------------------------------------- # 03/05/22 davem@nuts.ninka.net 1.1209.1.2 # Merge bk://kernel.bkbits.net/acme/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/22 hch@lst.de 1.1209.1.3 # [NET]: Switch arcnet over to initcalls. # -------------------------------------------- # 03/05/22 yoshfuji@linux-ipv6.org 1.1209.1.4 # [IPV4]: Use seq_release_private(), kill ip_seq_release() since no longer used. # -------------------------------------------- # 03/05/22 torvalds@home.transmeta.com 1.1209.5.1 # Use proper ANSI stype function declarations in definitions. # -------------------------------------------- # 03/05/22 torvalds@home.transmeta.com 1.1209.1.5 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/22 greg@kroah.com 1.1209.6.1 # PCI: add pci_get_dev() and pci_put_dev() # # Move the PCI core to start using these, enabling proper reference counting # on struct pci_dev. # -------------------------------------------- # 03/05/22 greg@kroah.com 1.1209.6.2 # Merge http://mdomsch.bkbits.net/linux-2.5-dynids # into kroah.com:/home/linux/linux/BK/pci-2.5 # -------------------------------------------- # 03/05/22 davej@tetrachloride.(none) 1.1213 # Merge tetrachloride.(none):/mnt/raid/src/kernel/2.5/bk-linus # into tetrachloride.(none):/mnt/raid/src/kernel/2.5/agpgart # -------------------------------------------- # 03/05/22 greg@kroah.com 1.1209.6.3 # [PATCH] PCI: remove pci_insert_device() as no one uses it anymore. # -------------------------------------------- # 03/05/23 paulus@samba.org 1.1209.1.6 # Merge samba.org:/home/paulus/kernel/linux-2.5 # into samba.org:/home/paulus/kernel/for-linus-ppc # -------------------------------------------- # 03/05/22 akpm@digeo.com 1.1209.7.1 # [PATCH] shrink_all_memory() fix # # The calling task must have a valid reclaim_state when running page # reclaim. But I had forgotten about shrink_all_memory(). # -------------------------------------------- # 03/05/22 torvalds@home.transmeta.com 1.1214 # Merge bk://linux-dj.bkbits.net/agpgart # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/22 torvalds@home.transmeta.com 1.1215 # Merge bk://kernel.bkbits.net/gregkh/linux/pci-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/22 davem@nuts.ninka.net 1.1209.8.1 # [IPV6]: Dont store pointers to in6_addrs in struct flowi. # -------------------------------------------- # 03/05/22 davem@nuts.ninka.net 1.1209.8.2 # [IPV4]: Fix fib_hash performance problems with huge route tables. # -------------------------------------------- # 03/05/23 paulus@samba.org 1.1216 # Merge samba.org:/home/paulus/kernel/linux-2.5 # into samba.org:/home/paulus/kernel/for-linus-ppc # -------------------------------------------- # 03/05/22 yoshfuji@linux-ipv6.org 1.1209.8.3 # [IPV4]: Dont erroneously print UDP6 sockets in /proc/net/udp. # -------------------------------------------- # 03/05/22 herbert@gondor.apana.org.au 1.1209.8.4 # [AF_KEY]: Zero out sadb_prop_reserved. # -------------------------------------------- # 03/05/22 yoshfuji@linux-ipv6.org 1.1209.8.5 # [IPV6]: procfs clean-up # -------------------------------------------- # 03/05/22 davem@nuts.ninka.net 1.1209.8.6 # [NET]: Zap non-netdevice usage of SET_MODULE_OWNER. # -------------------------------------------- # 03/05/22 davem@kernel.bkbits.net 1.1215.1.1 # Merge davem@nuts.ninka.net:/home/davem/src/BK/net-2.5 # into kernel.bkbits.net:/home/davem/net-2.5 # -------------------------------------------- # 03/05/23 ak@suse.de 1.1215.1.2 # [PATCH] x86-64 merge # # Lots of changes that have accumulated over the last weeks. # # This makes it compile and boot again, Lots of bug fixes, including # security fixes. Several speedups. # # Only changes x86-64 specific files. # # - Use private copy of siginfo.h (for si_band) # - Align 32bit vsyscall coredump (from Roland McGrath) # - First steps towards 64bit vsyscall coredump (not working yet) # - Use in kernel trampoline for signals # - Merge APIC pm update from Pavel/Mikael # - Security fix for ioperm (from i386) # - Reenable vsyscall dumping for 32bit coredumps # - Fix bugs in 32bit coredump that could lead to oopses. # - Fix 64bit vsyscalls # - Revert change in pci-gart.c: pci_alloc_consistent must use an # 0xffffffff mask hardcoded. # - Fix bug in noexec= option handling # - Export fake_node # - Cleanups from Pavel # - Disable 32bit vsyscall coredump again. Still has some problems. # - Implement new noexec= and noexec32= options to give a wide choice # of support for non executable mappings for 32bit and 64bit processes. # The default is now to honor PROT_EXEC, but mark stack and heap # PROT_EXEC. # - 32bit emulation changes from Pavel: use compat_* types. # - (2.4) Use physical address for GART register. # - Convert debugreg array to individual members and clean up ptrace # access. This saves 16 byte per task. # - (2.4) Use new streamlined context switch code. This avoids a # pipeline stall and pushes the register saving to C code. # - Save flags register in context switch # - Clean up SMP early bootup. Remove some unnecessary code. # - (2.4) Process numa= option early # - (2.4) Merge 2.4 clear_page, copy_*_user, copy_page, memcpy, memset. # These are much faster. clear/copy_page don't force the new page out # of memory now which should speed up user processes. Also full # workaround for errata #91. # - Some cleanup in pageattr.c code. # - Fix warning in i387.h # - Fix wrong PAGE_KERNEL_LARGE define. This fixes a security hole and # makes AGP work again. # - Fix wrong segment exception handler to not crash. # - Fix incorrect swapgs handling in bad iret exception handling # - Clean up some boot printks # - Micro optimize exception handling preamble. # - New reboot handling. Supports warm reboot and BIOS reboot vector # reboot now. # - (2.4) Use MTRRs by default in vesafb # - Fix bug in put_dirty_page: use correct page permissions for the stack # - Fix type of si_band in asm-generic/siginfo.h to match POSIX/glibc # (needs checking with other architecture maintainers) # - (2.4) Define ARCH_HAS_NMI_WATCHDOG # - Minor cleanup in calling.h # - IOMMU tuning: only flush the GART TLB when the IOMMU aperture area # allocation wraps. Also don't clear entries until needed. This # should increase IO performance for IOMMU devices greatly. Still a # bit experimental, handle with care. # - Unmap the IOMMU aperture from kernel mapping to prevent unwanted CPU # prefetches. # - Make IOMMU_LEAK_TRACE depend on IOMMU_DEBUG # - Fix minor bug in pci_alloc_consistent - always check against the dma # mask of the device, not 0xffffffff. # - Remove streamining mapping delayed flush in IOMMU: not needed anymore # and didn't work correctly in 2.5 anyways. # - Fix the bad pte warnings caused by the SMP/APIC bootup. # - Forward port 2.4 fix: ioperm was changing the wrong io ports in some # cases. # - Minor cleanups # - Some cleanups in pageattr.c (still buggy) # - Fix some bugs in the AGP driver. # - Forward port from 2.4: mask all reserved bits in debug register in # ptrace. Previously gdb could crash the kernel by passing invalid # values. # - Security fix: make sure FPU is in a defined state after an # FXSAVE/FXRSTOR exception occurred. # - Eats keys on panic (works around a buggy KVM) # - Make user.h user includeable. # - Disable sign compare warnings for gcc 3.3-hammer # - Use DSO for 32bit vsyscalls and dump it in core dumps. Add dwarf2 # information for the vsyscalls. # Thanks to Richard Henderson for helping me with the nasty parts of # it. I had to do some changes over his patch and it's currently only # lightly tested. Handle with care. This only affects 32bit programs # that use a glibc 3.2 with sysenter support. # - Security fixes for the 32bit ioctl handlers. Also some simplications # and speedups. # - gcc 3.3-hammer compile fixes for inline assembly # - Remove acpi.c file corpse. # - Lots of warning fixes # - Disable some Dprintks to make the bootup quieter again # - Clean up ptrace a bit (together with warning fixes) # - Merge with i386 (handle ACPI dynamic irq entries properly) # - Disable change_page_attr in pci-gart for now. Strictly that's # incorrect, need to do more testing for the root cause of the current # IOMMU problems. # - Update defconfig # - Disable first prefetch in copy_user that is likely to trigger Opteron # Errata #91 # - More irqreturn_t fixes # - Add pte_user and fix the vsyscall ptrace hack in generic code. # It's still partly broken # - Port verbose MCE handler from 2.4 # -------------------------------------------- # 03/05/23 greg@kroah.com 1.1215.2.1 # Merge kroah.com:/home/greg/linux/BK/bleed-2.5 # into kroah.com:/home/greg/linux/BK/gregkh-2.5 # -------------------------------------------- # 03/05/23 david-b@pacbell.net 1.1215.2.2 # [PATCH] USB: bugfix endpoint state # # This resolves some problems in the endpoint disable # patch I sent recently: # # - wasn't un-halting some endpoints # - was clobbering ep0 setup in some cases. # -------------------------------------------- # 03/05/23 baldrick@wanadoo.fr 1.1215.2.3 # [PATCH] USB speedtouch: set owner fields # # I think I'd better work on my plausible deniability... # -------------------------------------------- # 03/05/23 stern@rowland.harvard.edu 1.1215.2.4 # [PATCH] USB: uhci Interrupt Latency fix # # Paul: # # Okay, I think this patch ought to do the trick. I modified the PM # suspend/resume code so that on buggy motherboards like yours the suspend # routine really does a reset, while on normal motherboards the resume # routine really does a resume. I haven't tried that part out because, # truth to tell, I'm a little scared of doing an APM/ACPI suspend. Not long # ago I walked away from my computer for about a half-hour, leaving 2.5.69 # running. When I got back the screen was blank and the machine was totally # non-responsive. # # I changed the delays in reset_hc() to use schedule_timeout() rather than # wait_ms(), which should make it more friendly. # # Finally, I put the USBCMD_FGR back into wakeup_hc(). The reason for it is # now evident: a wakeup might be the result of a system-initiated event # as opposed to something requested by a device. # -------------------------------------------- # 03/05/23 stern@rowland.harvard.edu 1.1215.2.5 # [PATCH] USB: Addition to previous patch needed for PM UHCI # # This is the addition needed to make my previous patch for the UHCI # controller work properly with PM suspend/resume. # -------------------------------------------- # 03/05/23 david-b@pacbell.net 1.1215.2.6 # [PATCH] USB: net2280, control requests can be deferred # # To handle control messaging in contexts other than the # IRQ handler's setup() callback, a bit of automagic needed # to be removed; and some minor bugs fixed. # -------------------------------------------- # 03/05/23 torvalds@penguin.transmeta.com 1.1215.1.3 # Merge bk://kernel.bkbits.net/gregkh/linux/linus-2.5 # into penguin.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/23 agrover@groveronline.com 1.1215.1.4 # Merge groveronline.com:/root/bk/linux-2.5 # into groveronline.com:/root/bk/linux-acpi # -------------------------------------------- # 03/05/23 agrover@groveronline.com 1.1215.1.5 # ACPI: update to 20030522 # # Found and fixed a reported problem where an AE_NOT_FOUND error occurred occasionally # during _BST evaluation. This turned out to be an Owner ID allocation issue where a # called method did not get a new ID assigned to it. Eventually, (after 64k calls), the # Owner ID UINT16 would wraparound so that the ID would be the same as the caller's and the # called method would delete the caller's namespace. # # Implemented extended error reporting for control methods that are aborted due to a # run-time exception. Output includes the exact AML instruction that caused the method # abort, a dump of the method locals and arguments at the time of the abort, and a trace of # all nested control method calls. # # Modified the interpreter to allow the creation of buffers of zero length from the AML # code. Implemented new code to ensure that no attempt is made to actually allocate a # memory buffer (of length zero), only a buffer object with a NULL buffer pointer and # length zero. A warning is no longer issued when the AML attempts to create a zero-length # buffer. # # Implemented a workaround for the "leading asterisk problem" in _HIDs, _UIDs, and _CIDs. # One leading asterisk is automatically removed if present in all HID, UID, and CID # strings. # # Implemented full support for _CID methods that return a package of multiple CIDs. The # AcpiGetObjectInfo interface now returns a device _HID, _UID, and _CID list if present. # This required a change to the external interface to pass an ACPI_BUFFER object as a # parameter, since the _CID list is of variable length. # # Fixed a problem with the new AE_SAME_HANDLER exception where handler initialization code # did not know about this exception. # -------------------------------------------- # 03/05/23 agrover@groveronline.com 1.1215.1.6 # ACPI: Allow multiple compatible IDs for PnP purposes # -------------------------------------------- # 03/05/24 paulus@samba.org 1.1217 # Merge samba.org:/stuff/paulus/kernel/linux-2.5 # into samba.org:/stuff/paulus/kernel/for-linus-ppc # -------------------------------------------- # 03/05/23 B.Zolnierkiewicz@elka.pw.edu.pl 1.1215.3.1 # [PATCH] Fix incorrect enablebits for all AMD and nVidia IDE chipsets. # # Fix incorrect enablebits for all AMD and nVidia IDE chipsets. # Author: Vojtech Pavlik # -------------------------------------------- # 03/05/23 B.Zolnierkiewicz@elka.pw.edu.pl 1.1215.3.2 # [PATCH] Add IDE support for VIA vt8237 southbridge. # # Add IDE support for VIA vt8237 southbridge. # Author: Vojtech Pavlik # -------------------------------------------- # 03/05/23 B.Zolnierkiewicz@elka.pw.edu.pl 1.1215.3.3 # [PATCH] Intel ICH5 basic SATA support # # Add Intel ICH5 basic SATA support (from 2.4 by Andre Hedrick) # and as a bonus kill duplicate entry in piix_pci_info[]. # -------------------------------------------- # 03/05/23 B.Zolnierkiewicz@elka.pw.edu.pl 1.1215.3.4 # [PATCH] misc AMD IDE driver fixes # # Fix incorrect UDMA100 cable test (by Dave Jones). # Fix compilation warning. # -------------------------------------------- # 03/05/23 B.Zolnierkiewicz@elka.pw.edu.pl 1.1215.3.5 # [PATCH] add hwif->hold flag # # Add hwif->hold flag for hotswap interfaces. # Initialize founded hwif in ide_register_hw(). # # Original patch by Benjamin Herrenschmidt. # -------------------------------------------- # 03/05/23 B.Zolnierkiewicz@elka.pw.edu.pl 1.1215.3.6 # [PATCH] SiS IDE driver fixes # # SiS IDE driver fixes by Lionel Bouton: # - support for SiS655 # - support for SiS630S/ET UDMA5 mode # - corrected /proc/ide/sis output for ATA133 chipsets # (drives' positions were swapped) # - use of pci_read_config_byte() instead of direct PCI poking # for SiS962+ detection # -------------------------------------------- # 03/05/23 B.Zolnierkiewicz@elka.pw.edu.pl 1.1215.3.7 # [PATCH] ServerWorks IDE driver update # # ServerWorks CSB5 IDE fixes (from 2.4 patches by Duncan Laurie) # # - blacklist drives overrunning their FIFOs in UDMA5/6 modes # - add PCI quirk (CSB5 IDE doesn't fully support native mode) # # plus sync driver with 2.4 version. # -------------------------------------------- # 03/05/23 B.Zolnierkiewicz@elka.pw.edu.pl 1.1215.3.8 # [PATCH] add hwif->rw_disk callout # # Add hwif->rw_disk callout (forward port of 2.4 Alan's work). # # "This allows us to remove the PDC4030 special case # and also allows for the 372N clock switch stuff." # -------------------------------------------- # 03/05/23 B.Zolnierkiewicz@elka.pw.edu.pl 1.1215.3.9 # [PATCH] _IDE_C cleanup # # Since ide_get_best_pio_mode() and ide_pio_timings[] # are now properly exported in ide-lib.c, we can remove # dirty include hacks from some legacy drivers. # -------------------------------------------- # 03/05/23 torvalds@home.transmeta.com 1.1215.1.7 # Merge http://linux-acpi.bkbits.net/linux-acpi # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/24 paulus@samba.org 1.1218 # Fix preempt on PPC32 - have to set PREEMPT_ACTIVE when preempting kernel stuff. # -------------------------------------------- # 03/05/24 paulus@samba.org 1.1219 # PPC32: Export a couple of symbols needed by direct rendering modules. # -------------------------------------------- # 03/05/24 paulus@samba.org 1.1220 # Merge samba.org:/home/paulus/kernel/linux-2.5 # into samba.org:/home/paulus/kernel/for-linus-ppc # -------------------------------------------- # 03/05/24 zippel@linux-m68k.org 1.1221 # [PATCH] kconfig check fixes # # - fix a problem with a unset menuconfig, during the config check it's possible # conf selects the wrong parent menu and the result is an endless loop. # - only changable config symbols are relevant during config check, # otherwise we get another endless loop. # -------------------------------------------- # 03/05/24 minyard@acm.org 1.1222 # [PATCH] IPMI update # # - small cleanups to make the spacing consistent # - modifications to the watchdog so it starts the first time # you hit it, not the second. # - Fix for returning the proper value when starting the # sequence number timer. # - Fix a parameter name in the watchdog. # -------------------------------------------- # 03/05/24 ak@suse.de 1.1223 # [PATCH] Make ACPI compile again on 64bit/gcc 3.3 # # Fix prototypes to match function definitions # -------------------------------------------- # 03/05/24 axboe@suse.de 1.1224 # [PATCH] elevator core update # # The noop io scheduler has a data corrupting bug, because q->last_merge # doesn't get cleared properly. So do that in io scheduler core, and # remove the same code from deadline. # # Also kill bio_rq_in_between(), it's not used by anyone anymore. rbtrees # are the hot thing these days. # # And finally, remove a direct test for REQ_CMD in rq flags, use # blk_fs_request() instead. # -------------------------------------------- # 03/05/24 hch@lst.de 1.1225 # [PATCH] make vt_ioctl ix86isms explicit # # sys_ioperm is only implemented on x86 (i386/x86_64). Make the # ifdefs in vt_ioctl.c more explicit so the other architectures can # get rid of their stubs in favour of just using sys_ni_syscall in # the syscall table. # # Maybe we should remove it altogether, it looks like remnants from # some very early X386 times (ie the Thomas Roell timeframe). # -------------------------------------------- # diff -Nru a/CREDITS b/CREDITS --- a/CREDITS Sat May 24 12:48:29 2003 +++ b/CREDITS Sat May 24 12:48:29 2003 @@ -1549,6 +1549,18 @@ S: 8103 Rein S: Austria +N: Mitsuru Kanda +E: mk@linux-ipv6.org +E: mk@isl.rdc.toshiba.co.jp +E: mk@karaba.org +W: http://www.karaba.org/~mk/ +P: 1024D/2EC7E30D 9A35 D378 F084 9EA4 EFBA 925B 1C93 B376 F0EF BE59 +D: IPsec, IPv6 +D: USAGI/WIDE Project, TOSHIBA CORPORATION +S: 2-47-8, Takinogawa, +S: Kita, Tokyo 114-0023 +S: Japan + N: Jan Kara E: jack@atrey.karlin.mff.cuni.cz E: jack@suse.cz @@ -2200,6 +2212,17 @@ S: Garland, Texas 75044 S: USA +N: Kazunori Miyazawa +E: miyazawa@linux-ipv6.org +E: Kazunori.Miyazawa@jp.yokogawa.com +E: kazunori@miyazawa.org +W: http://www.miyazawa.org/~kazunori/ +D: IPsec, IPv6 +D: USAGI/WIDE Project, Yokogawa Electric Corporation +S: 2-20-4-203, Nakacho, +S: Musashino, Tokyo 180-0006 +S: Japan + N: Patrick Mochel E: mochel@osdl.org E: mochelp@infinity.powertie.org @@ -3027,8 +3050,8 @@ W: http://www.cs.helsinki.fi/Linus.Torvalds P: 1024/A86B35C5 96 54 50 29 EC 11 44 7A BE 67 3C 24 03 13 62 C8 D: Original kernel hacker -S: 1050 Woodduck Avenue -S: Santa Clara, California 95051 +S: 3990 Freedom Circle +S: Santa Clara, California 95054 S: USA N: Marcelo W. Tosatti @@ -3440,6 +3463,17 @@ E: yokota@netlab.is.tsukuba.ac.jp D: Workbit NinjaSCSI-3/32Bi PCMCIA driver D: Workbit NinjaSCSI-32Bi/UDE driver +S: Japan + +N: Hideaki YOSHIFUJI +E: hideaki@yoshifuji.org +E: yoshfuji@linux-ipv6.org +W: http://www.yoshifuji.org/~hideaki/ +P: 1024D/E0620EEA 9022 65EB 1ECF 3AD1 0BDF 80D8 4807 F894 E062 0EEA +D: IPv6 and other networking related stuff +D: USAGI/WIDE Project, The University of Tokyo +S: Green House #102, 1-15-5, Nishikata, +S: Bunkyo, Tokyo 113-0024 S: Japan N: Eric Youngdale diff -Nru a/Documentation/BK-usage/bk-kernel-howto.txt b/Documentation/BK-usage/bk-kernel-howto.txt --- a/Documentation/BK-usage/bk-kernel-howto.txt Sat May 24 12:48:25 2003 +++ b/Documentation/BK-usage/bk-kernel-howto.txt Sat May 24 12:48:25 2003 @@ -273,3 +273,11 @@ A tag is just an alias for a specific changeset... and since changesets are ordered, a tag is thus a marker for a specific point in time (or specific state of the tree). + + +3) Is there an easy way to generate One Big Patch versus mainline, + for my long-lived kernel branch? +A. Yes. This requires BK 3.x, though. + + bk export -tpatch -r`bk repogca bk://linux.bkbits.net/linux-2.5`,+ + diff -Nru a/Documentation/Changes b/Documentation/Changes --- a/Documentation/Changes Sat May 24 12:48:32 2003 +++ b/Documentation/Changes Sat May 24 12:48:32 2003 @@ -50,7 +50,7 @@ o Gnu C 2.95.3 # gcc --version o Gnu make 3.78 # make --version -o binutils 2.9.5.0.25 # ld -v +o binutils 2.12 # ld -v o util-linux 2.10o # fdformat --version o module-init-tools 0.9.9 # depmod -V o e2fsprogs 1.29 # tune2fs diff -Nru a/Documentation/driver-model/binding.txt b/Documentation/driver-model/binding.txt --- a/Documentation/driver-model/binding.txt Sat May 24 12:48:23 2003 +++ b/Documentation/driver-model/binding.txt Sat May 24 12:48:23 2003 @@ -11,11 +11,11 @@ Bus ~~~ -The bus type structure contains a list of all devices that on that bus +The bus type structure contains a list of all devices that are on that bus type in the system. When device_register is called for a device, it is inserted into the end of this list. The bus object also contains a list of all drivers of that bus type. When driver_register is called -for a driver, it is inserted into the end of this list. These are the +for a driver, it is inserted at the end of this list. These are the two events which trigger driver binding. @@ -42,7 +42,7 @@ ~~~~~~~~~~~~ Upon the successful completion of probe, the device is registered with -the class to which it belongs. Device drivers belong to one and only +the class to which it belongs. Device drivers belong to one and only one class, and that is set in the driver's devclass field. devclass_add_device is called to enumerate the device within the class and actually register it with the class, which happens with the @@ -61,7 +61,7 @@ sysfs -~~~~~~~~ +~~~~~ A symlink is created in the bus's 'devices' directory that points to the device's directory in the physical hierarchy. diff -Nru a/Documentation/driver-model/bus.txt b/Documentation/driver-model/bus.txt --- a/Documentation/driver-model/bus.txt Sat May 24 12:48:26 2003 +++ b/Documentation/driver-model/bus.txt Sat May 24 12:48:26 2003 @@ -58,7 +58,7 @@ The format of device ID structures and the semantics for comparing them are inherently bus-specific. Drivers typically declare an array -of device IDs of device they support that reside in a bus-specific +of device IDs of devices they support that reside in a bus-specific driver structure. The purpose of the match callback is provide the bus an opportunity to @@ -153,7 +153,7 @@ |-- agpgart `-- e100 -Each device that is discovered a bus of that type gets a symlink in +Each device that is discovered on a bus of that type gets a symlink in the bus's devices directory to the device's directory in the physical hierarchy: diff -Nru a/Documentation/driver-model/class.txt b/Documentation/driver-model/class.txt --- a/Documentation/driver-model/class.txt Sat May 24 12:48:20 2003 +++ b/Documentation/driver-model/class.txt Sat May 24 12:48:20 2003 @@ -105,7 +105,7 @@ Drivers registered with the class get a symlink in the drivers/ directory -that points the driver's directory (under its bus directory): +that points to the driver's directory (under its bus directory): class/ `-- input diff -Nru a/Documentation/driver-model/device.txt b/Documentation/driver-model/device.txt --- a/Documentation/driver-model/device.txt Sat May 24 12:48:25 2003 +++ b/Documentation/driver-model/device.txt Sat May 24 12:48:25 2003 @@ -47,11 +47,13 @@ children: List of child devices. +parent: *** FIXME *** + name: ASCII description of device. Example: " 3Com Corporation 3c905 100BaseTX [Boomerang]" bus_id: ASCII representation of device's bus position. This - field should a name unique across all devices on the + field should be a name unique across all devices on the bus type the device belongs to. Example: PCI bus_ids are in the form of @@ -66,12 +68,12 @@ dir: Device's sysfs directory. +class_num: Class-enumerated value of the device. + driver: Pointer to struct device_driver that controls the device. driver_data: Driver-specific data. -class_num: Class-enumerated value of the device. - platform_data: Platform data specific to the device. current_state: Current power state of the device. @@ -108,7 +110,7 @@ if the reference is not already 0 (if it's in the process of being removed already). -A driver can take use the lock in the device structure using: +A driver can access the lock in the device structure using: void lock_device(struct device * dev); void unlock_device(struct device * dev); diff -Nru a/Documentation/driver-model/driver.txt b/Documentation/driver-model/driver.txt --- a/Documentation/driver-model/driver.txt Sat May 24 12:48:25 2003 +++ b/Documentation/driver-model/driver.txt Sat May 24 12:48:25 2003 @@ -63,9 +63,9 @@ model because the bus they belong to has a bus-specific structure with bus-specific fields that cannot be generalized. -The most common example this are device ID structures. A driver +The most common example of this are device ID structures. A driver typically defines an array of device IDs that it supports. The format -of this structure and the semantics for comparing device IDs is +of these structures and the semantics for comparing device IDs are completely bus-specific. Defining them as bus-specific entities would sacrifice type-safety, so we keep bus-specific structures around. @@ -77,8 +77,8 @@ struct device_driver driver; }; -A definition that included bus-specific fields would look something -like (using the eepro100 driver again): +A definition that included bus-specific fields would look like +(using the eepro100 driver again): static struct pci_driver eepro100_driver = { .id_table = eepro100_pci_tbl, @@ -109,7 +109,7 @@ Most drivers, however, will have a bus-specific structure and will need to register with the bus using something like pci_driver_register. -It is important that drivers register their drivers as early as +It is important that drivers register their driver structure as early as possible. Registration with the core initializes several fields in the struct device_driver object, including the reference count and the lock. These fields are assumed to be valid at all times and may be @@ -148,7 +148,7 @@ sysfs -~~~~~~~~ +~~~~~ When a driver is registered, a sysfs directory is created in its bus's directory. In this directory, the driver can export an interface @@ -205,7 +205,7 @@ user-defined policy. SUSPEND_NOTIFY notifies the device that a suspend transition is about -to happen. This happens on system power state transition to verify +to happen. This happens on system power state transitions to verify that all devices can successfully suspend. A driver may choose to fail on this call, which should cause the diff -Nru a/Documentation/driver-model/interface.txt b/Documentation/driver-model/interface.txt --- a/Documentation/driver-model/interface.txt Sat May 24 12:48:25 2003 +++ b/Documentation/driver-model/interface.txt Sat May 24 12:48:25 2003 @@ -82,7 +82,7 @@ and the enumerated value is stored in the struct intf_data for that device. sysfs -~~~~~~~~ +~~~~~ Each interface is given a directory in the directory of the device class it belongs to: @@ -120,10 +120,10 @@ Many interfaces have a major number associated with them and each device gets a minor number. Or, multiple interfaces might share one -major number, and each get receive a range of minor numbers (like in +major number, and each will receive a range of minor numbers (like in the case of input devices). These major and minor numbers could be stored in the interface -structure. Major and minor allocation could happen when the interface +structure. Major and minor allocations could happen when the interface is registered with the class, or via a helper function. diff -Nru a/Documentation/driver-model/overview.txt b/Documentation/driver-model/overview.txt --- a/Documentation/driver-model/overview.txt Sat May 24 12:48:22 2003 +++ b/Documentation/driver-model/overview.txt Sat May 24 12:48:22 2003 @@ -9,7 +9,7 @@ ~~~~~~~~ This driver model is a unification of all the current, disparate driver models -that are currently in the kernel. It is intended is to augment the +that are currently in the kernel. It is intended to augment the bus-specific drivers for bridges and devices by consolidating a set of data and operations into globally accessible data structures. @@ -23,7 +23,7 @@ of the global tree. Common data fields can also be moved out of the local bus models into the -global model. Some of the manipulation of these fields can also be +global model. Some of the manipulations of these fields can also be consolidated. Most likely, manipulation functions will become a set of helper functions, which the bus drivers wrap around to include any bus-specific items. @@ -71,7 +71,7 @@ This abstraction is prevention of unnecessary pain during transitional phases. If the name of the field changes or is removed, then every downstream driver will break. On the other hand, if only the bus layer (and not the device -layer) accesses struct device, it is only those that need to change. +layer) accesses struct device, it is only that layer that needs to change. User Interface @@ -96,9 +96,9 @@ This directory may be populated at each layer of discovery - the global layer, the bus layer, or the device layer. -The global layer currently creates two files - name and 'power'. The +The global layer currently creates two files - 'name' and 'power'. The former only reports the name of the device. The latter reports the -current power state of the device. It also be used to set the current +current power state of the device. It will also be used to set the current power state. The bus layer may also create files for the devices it finds while probing the diff -Nru a/Documentation/driver-model/platform.txt b/Documentation/driver-model/platform.txt --- a/Documentation/driver-model/platform.txt Sat May 24 12:48:31 2003 +++ b/Documentation/driver-model/platform.txt Sat May 24 12:48:31 2003 @@ -10,9 +10,9 @@ Platform drivers ~~~~~~~~~~~~~~~~ -Drivers for platform devices have typically very simple and +Drivers for platform devices are typically very simple and unstructured. Either the device was present at a particular I/O port -and the driver was loaded, or there was not. There was no possibility +and the driver was loaded, or it was not. There was no possibility of hotplugging or alternative discovery besides probing at a specific I/O address and expecting a specific response. @@ -49,7 +49,7 @@ Bus IDs ~~~~~~~ -Bus IDs are the canonical name for the device. There is no globally +Bus IDs are the canonical names for the devices. There is no globally standard addressing mechanism for legacy devices. In the IA-32 world, we have Pnp IDs to use, as well as the legacy I/O ports. However, neither tell what the device really is or have any meaning on other @@ -62,7 +62,7 @@ For example, a serial driver might find a device at I/O 0x3f8. The ACPI firmware might also discover a device with PnP ID (_HID) -PNP0501. Both correspond to the same device should be mapped to the +PNP0501. Both correspond to the same device and should be mapped to the canonical name 'serial'. The bus_id field should be a concatenation of the canonical name and @@ -88,7 +88,7 @@ ~~~~~~~~~~~~~~ Legacy drivers assume they are bound to the device once they start up and probe an I/O port. Divorcing them from this will be a difficult -process. However, that shouldn't prevent us from impelementing +process. However, that shouldn't prevent us from implementing firmware-based enumeration. The firmware should notify the platform bus about devices before the diff -Nru a/Documentation/driver-model/porting.txt b/Documentation/driver-model/porting.txt --- a/Documentation/driver-model/porting.txt Sat May 24 12:48:28 2003 +++ b/Documentation/driver-model/porting.txt Sat May 24 12:48:28 2003 @@ -128,7 +128,7 @@ The bus_id is an ASCII string that contains the device's address on the bus. The format of this string is bus-specific. This is - necessary for representing device in sysfs. + necessary for representing devices in sysfs. parent is the physical parent of the device. It is important that the bus driver sets this field correctly. @@ -286,7 +286,7 @@ It would be difficult and tedious to force every driver on a bus to simultaneously convert their drivers to generic format. Instead, the bus driver should define single instances of the generic methods that -forward calls to the bus-specific drivers. For instance: +forward call to the bus-specific drivers. For instance: static int pci_device_remove(struct device * dev) @@ -330,8 +330,8 @@ devices must be bound to a driver, or drivers must be bound to all devices that it supports. -Drivers typically contain a list of device IDs that it supports. The -bus driver compares this ID to the ID of devices registered with it. +A driver typically contains a list of device IDs that it supports. The +bus driver compares these IDs to the IDs of devices registered with it. The format of the device IDs, and the semantics for comparing them are bus-specific, so the generic model does attempt to generalize them. @@ -396,7 +396,7 @@ Step 7: Cleaning up the bus driver. The generic bus, device, and driver structures provide several fields -that can replace those define privately to the bus driver. +that can replace those defined privately to the bus driver. - Device list. diff -Nru a/Documentation/kobject.txt b/Documentation/kobject.txt --- a/Documentation/kobject.txt Sat May 24 12:48:22 2003 +++ b/Documentation/kobject.txt Sat May 24 12:48:22 2003 @@ -9,7 +9,7 @@ The kobject infrastructure performs basic object management that larger data structures and subsystems can leverage, rather than reimplement -similar functionality. This functionality consists primarily concerns: +similar functionality. This functionality primarily concerns: - Object reference counting. - Maintaining lists (sets) of objects. @@ -45,7 +45,7 @@ struct kobject is a simple data type that provides a foundation for more complex object types. It provides a set of basic fields that almost all complex data types share. kobjects are intended to be -embedded in larger data structures and replace fields it duplicates. +embedded in larger data structures and replace fields they duplicate. 1.2 Defintion @@ -77,7 +77,7 @@ includes inserting the kobject in the list of its dominant kset and creating a directory for it in sysfs. -Alternatively, one may use a kobject without adding to its kset's list +Alternatively, one may use a kobject without adding it to its kset's list or exporting it via sysfs, by simply calling kobject_init(). An initialized kobject may later be added to the object hierarchy by calling kobject_add(). An initialized kobject may be used for @@ -87,8 +87,8 @@ equivalent to calling kobject_register(). When a kobject is unregistered, it is removed from its kset's list, -removed from the sysfs filesystem, and its reference decremented. List -and sysfs removal happen in kobject_del(), and may be called +removed from the sysfs filesystem, and its reference count is decremented. +List and sysfs removal happen in kobject_del(), and may be called manually. kobject_put() decrements the reference count, and may also be called manually. @@ -98,8 +98,8 @@ it is already positive. When a kobject's reference count reaches 0, the method struct -ktype::release() (which the kobject's kset points to) is called. This -allows any memory allocated for the object to be freed. +kobj_type::release() (which the kobject's kset points to) is called. +This allows any memory allocated for the object to be freed. 1.4 sysfs @@ -118,7 +118,7 @@ 2. ksets -2.1 Desecription +2.1 Description A kset is a set of kobjects that are embedded in the same type. @@ -163,9 +163,9 @@ kset_register(&disk->kset); - The kset that the disk's embedded object belongs to is the - block_kset, and is pointed to disk->kset.kobj.kset. + block_kset, and is pointed to by disk->kset.kobj.kset. -- The type of object of the disk's _subordinate_ list are partitions, +- The type of objects on the disk's _subordinate_ list are partitions, and is set in disk->kset.ktype. - The kset is then registered, which handles initializing and adding @@ -218,13 +218,13 @@ - sysfs_ops: Provides conversion functions for sysfs access. Please see the sysfs documentation for more information. -- default_attrs: Default attributes to exported via sysfs when the +- default_attrs: Default attributes to be exported via sysfs when the object is registered. Instances of struct kobj_type are not registered; only referenced by the kset. A kobj_type may be referenced by an arbitrary number of -ksets, as their may be disparate sets of identical objects. +ksets, as there may be disparate sets of identical objects. diff -Nru a/Documentation/networking/3c509.txt b/Documentation/networking/3c509.txt --- a/Documentation/networking/3c509.txt Sat May 24 12:48:22 2003 +++ b/Documentation/networking/3c509.txt Sat May 24 12:48:22 2003 @@ -52,7 +52,7 @@ For example, setting two cards to 10base2/IRQ10 and AUI/IRQ11 is done by using the xcvr and irq module options: - options 3c509 xcvr=3,3 irq=10,11 + options 3c509 xcvr=3,1 irq=10,11 (2) Full-duplex mode diff -Nru a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt --- a/Documentation/networking/ip-sysctl.txt Sat May 24 12:48:24 2003 +++ b/Documentation/networking/ip-sysctl.txt Sat May 24 12:48:24 2003 @@ -613,12 +613,6 @@ routers are present. Default: 3 -icmp/*: -ratelimit - INTEGER - Limit the maximal rates for sending ICMPv6 packets. - 0 to disable any limiting, otherwise the maximal rate in jiffies(1) - Default: 100 - use_tempaddr - INTEGER Preference for Privacy Extensions (RFC3041). <= 0 : disable Privacy Extensions @@ -648,6 +642,12 @@ Number of attempts before give up attempting to generate valid temporary addresses. Default: 5 + +icmp/*: +ratelimit - INTEGER + Limit the maximal rates for sending ICMPv6 packets. + 0 to disable any limiting, otherwise the maximal rate in jiffies(1) + Default: 100 IPv6 Update by: diff -Nru a/Documentation/pci.txt b/Documentation/pci.txt --- a/Documentation/pci.txt Sat May 24 12:48:24 2003 +++ b/Documentation/pci.txt Sat May 24 12:48:24 2003 @@ -45,8 +45,6 @@ id_table Pointer to table of device ID's the driver is interested in. Most drivers should export this table using MODULE_DEVICE_TABLE(pci,...). - Set to NULL to call probe() function for every - PCI device known to the system. probe Pointer to a probing function which gets called (during execution of pci_register_driver for already existing devices or later if a new device gets inserted) for all @@ -82,6 +80,28 @@ class, Device class to match. The class_mask tells which bits class_mask of the class are honored during the comparison. driver_data Data private to the driver. + +Most drivers don't need to use the driver_data field. Best practice +for use of driver_data is to use it as an index into a static list of +equivalant device types, not to use it as a pointer. + +Have a table entry {PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID} +to have probe() called for every PCI device known to the system. + +New PCI IDs may be added to a device driver at runtime by writing +to the file /sys/bus/pci/drivers/{driver}/new_id. When added, the +driver will probe for all devices it can support. + +echo "vendor device subvendor subdevice class class_mask driver_data" > \ + /sys/bus/pci/drivers/{driver}/new_id +where all fields are passed in as hexadecimal values (no leading 0x). +Users need pass only as many fields as necessary; vendor, device, +subvendor, and subdevice fields default to PCI_ANY_ID (FFFFFFFF), +class and classmask fields default to 0, and driver_data defaults to +0UL. Device drivers must call + pci_dynids_set_use_driver_data(pci_driver *, 1) +in order for the driver_data field to get passed to the driver. +Otherwise, only a 0 is passed in that field. When the driver exits, it just calls pci_unregister_driver() and the PCI layer automatically calls the remove hook for all devices handled by the driver. diff -Nru a/Documentation/scsi/aic79xx.txt b/Documentation/scsi/aic79xx.txt --- a/Documentation/scsi/aic79xx.txt Sat May 24 12:48:29 2003 +++ b/Documentation/scsi/aic79xx.txt Sat May 24 12:48:29 2003 @@ -371,9 +371,33 @@ - Fax Technical Support at +852-2869-7100 ------------------------------------------------------------------- - -(c) 2003 Adaptec, Inc. All Rights Reserved. No part of this -publication may be reproduced, stored in a retrieval system, or -transmitted in any form or by any means, electronic, mechanical, -photocopying, recording or otherwise, without prior written consent -of Adaptec, Inc., 691 South Milpitas Blvd., Milpitas, CA 95035. +/* + * Copyright (c) 2003 Adaptec Inc. 691 S. Milpitas Blvd., Milpitas CA 95035 USA. + * All rights reserved. + * + * You are permitted to redistribute, use and modify this README file in whole + * or in part in conjunction with redistribution of software governed by the + * General Public License, provided that the following conditions are met: + * 1. Redistributions of README file must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * 3. Modifications or new contributions must be attributed in a copyright + * notice identifying the author ("Contributor") and added below the + * original copyright notice. The copyright notice is for purposes of + * identifying contributors and should not be deemed as permission to alter + * the permissions given by Adaptec. + * + * THIS README FILE IS PROVIDED BY ADAPTEC AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ANY + * WARRANTIES OF NON-INFRINGEMENT OR THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * ADAPTEC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS README + * FILE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ diff -Nru a/Documentation/scsi/aic7xxx.txt b/Documentation/scsi/aic7xxx.txt --- a/Documentation/scsi/aic7xxx.txt Sat May 24 12:48:22 2003 +++ b/Documentation/scsi/aic7xxx.txt Sat May 24 12:48:22 2003 @@ -132,6 +132,16 @@ 2. Version History + 6.2.33 - Dynamically disable PCI parity error reporting after + 10 errors are reported to the user. These errors are + the result of some other device issuing PCI transactions + with bad parity. Once the user has been informed of the + problem, continuing to report the errors just degrades + our performance. + + 6.2.32 - Dynamically sized S/G lists to avoid SCSI malloc + pool fragmentation and SCSI mid-layer deadlock. + 6.2.28 - Domain Validation Fixes PCI parity error disable Enhanced Memory Mapped I/O probe @@ -160,6 +170,7 @@ Default Value: 0x0000 ----------------------------------------------------------------- Option: no_probe + Option: probe_eisa_vl Definition: Do not probe for EISA/VLB controllers. This is a toggle. If the driver is compiled to not probe EISA/VLB controllers by default, @@ -339,9 +350,33 @@ - Fax Technical Support at +852-2869-7100 ------------------------------------------------------------------- - -(c) 2002 Adaptec, Inc. All Rights Reserved. No part of this -publication may be reproduced, stored in a retrieval system, or -transmitted in any form or by any means, electronic, mechanical, -photocopying, recording or otherwise, without prior written consent -of Adaptec, Inc., 691 South Milpitas Blvd., Milpitas, CA 95035. +/* + * Copyright (c) 2003 Adaptec Inc. 691 S. Milpitas Blvd., Milpitas CA 95035 USA. + * All rights reserved. + * + * You are permitted to redistribute, use and modify this README file in whole + * or in part in conjunction with redistribution of software governed by the + * General Public License, provided that the following conditions are met: + * 1. Redistributions of README file must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * 3. Modifications or new contributions must be attributed in a copyright + * notice identifying the author ("Contributor") and added below the + * original copyright notice. The copyright notice is for purposes of + * identifying contributors and should not be deemed as permission to alter + * the permissions given by Adaptec. + * + * THIS README FILE IS PROVIDED BY ADAPTEC AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ANY + * WARRANTIES OF NON-INFRINGEMENT OR THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * ADAPTEC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS README + * FILE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ diff -Nru a/Documentation/video4linux/bttv/CARDLIST b/Documentation/video4linux/bttv/CARDLIST --- a/Documentation/video4linux/bttv/CARDLIST Sat May 24 12:48:20 2003 +++ b/Documentation/video4linux/bttv/CARDLIST Sat May 24 12:48:20 2003 @@ -22,7 +22,7 @@ card=20 - CEI Raffles Card card=21 - Lifeview FlyVideo 98/ Lucky Star Image World ConferenceTV LR50 card=22 - Askey CPH050/ Phoebe Tv Master + FM - card=23 - Modular Technology MM205 PCTV, bt878 + card=23 - Modular Technology MM201/MM202/MM205/MM210/MM215 PCTV, bt878 card=24 - Askey CPH05X/06X (bt878) [many vendors] card=25 - Terratec TerraTV+ Version 1.0 (Bt848)/ Terra TValue Version 1.0/ Vobis TV-Boostar card=26 - Hauppauge WinCam newer (bt878) @@ -39,7 +39,7 @@ card=37 - Prolink PixelView PlayTV pro card=38 - Askey CPH06X TView99 card=39 - Pinnacle PCTV Studio/Rave - card=40 - STB TV PCI FM, Gateway P/N 6000704 (bt878) + card=40 - STB TV PCI FM, Gateway P/N 6000704 (bt878), 3Dfx VoodooTV 100 card=41 - AVerMedia TVPhone 98 card=42 - ProVideo PV951 card=43 - Little OnAir TV @@ -81,11 +81,27 @@ card=79 - DSP Design TCVIDEO card=80 - Hauppauge WinTV PVR card=81 - GV-BCTV5/PCI + card=82 - Osprey 100/150 (878) + card=83 - Osprey 100/150 (848) + card=84 - Osprey 101 (848) + card=85 - Osprey 101/151 + card=86 - Osprey 101/151 w/ svid + card=87 - Osprey 200/201/250/251 + card=88 - Osprey 200/250 + card=89 - Osprey 210/220 + card=90 - Osprey 500 + card=91 - Osprey 540 + card=92 - Osprey 2000 + card=93 - IDS Eagle + card=94 - Pinnacle PCTV Sat + card=95 - Formac ProTV II + card=96 - MachTV + card=97 - Euresys Picolo tuner.o type=0 - Temic PAL (4002 FH5) type=1 - Philips PAL_I (FI1246 and compatibles) - type=2 - Philips NTSC (FI1236 and compatibles) + type=2 - Philips NTSC (FI1236,FM1236 and compatibles) type=3 - Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF) type=4 - NoTuner type=5 - Philips PAL_BG (FI1216 and compatibles) diff -Nru a/Documentation/video4linux/bttv/Cards b/Documentation/video4linux/bttv/Cards --- a/Documentation/video4linux/bttv/Cards Sat May 24 12:48:21 2003 +++ b/Documentation/video4linux/bttv/Cards Sat May 24 12:48:21 2003 @@ -179,7 +179,8 @@ has not yet been seen (perhaps it was the german name for LR90 [stereo]). These cards are sold by many OEMs too. - FlyVideo A2 = LR90 Rev.F (w/Remote, w/o FM, stereo TV by tda9821) {Germany} + FlyVideo A2 (Elta 8680)= LR90 Rev.F (w/Remote, w/o FM, stereo TV by tda9821) {Germany} + Lifeview 3000 (Elta 8681) as sold by Plus(April 2002), Germany = LR138 w/ saa7134 Typhoon TV card series: @@ -397,6 +398,8 @@ AVerTV98 mit Fernbedienung (BT-878 chip) AVerTV/FM98 (BT-878 chip) + VDOmate (www.averm.com.cn) = M168U ? + Aimslab ------- Video Highway or "Video Highway TR200" (ISA) @@ -413,7 +416,8 @@ LT9306/MD9306 = CPH061 LT9415/MD9415 = LR90 Rev.F or Rev.G MD9592 = Avermedia TVphone98 (PCI_ID=1461:0003), PCB-Rev=M168II-B (w/TDA9873H) - MD9717 = KNC One (Rev D4, saa7134) + MD9717 = KNC One (Rev D4, saa7134, FM1216 MK2 tuner) + MD5044 = KNC One (Rev D4, saa7134, FM1216ME MK3 tuner) Modular Technologies (www.modulartech.com) UK --------------------------------------------- @@ -481,7 +485,8 @@ Studio PCTV Pro (Bt878 stereo w/ FM) Pinnacle PCTV (Bt878, MT2032) Pinnacle PCTV Pro (Bt878, MT2032) - Pinncale PCTV Sat (bt878a, HM1821/1221) + Pinncale PCTV Sat (bt878a, HM1821/1221) ["Conexant CX24110 with CX24108 tuner, aka HM1221/HM1811"] + Pinnacle PCTV Sat XE M(J)PEG capture and playback: DC1+ (ISA) @@ -654,9 +659,9 @@ WinTV PVR 450 US models - 990 WinTV-PVR-350 (249USD) - 980 WinTV-PVR-250 (149USD) - 880 WinTV-PVR-PCI (199USD) + 990 WinTV-PVR-350 (249USD) (iTVC15 chipset + radio) + 980 WinTV-PVR-250 (149USD) (iTVC15 chipset) + 880 WinTV-PVR-PCI (199USD) (KFIR chipset + bt878) 881 WinTV-PVR-USB 190 WinTV-GO 191 WinTV-GO-FM @@ -697,11 +702,40 @@ 566 WinTV USB (UK) 573 WinTV USB FM 429 Impact VCB (bt848) - 600 USB Libe (Video-In 1x Comp, 1xSVHS) + 600 USB Live (Video-In 1x Comp, 1xSVHS) 542 WinTV Nova 717 WinTV DVB-S 909 Nova-t PCI 893 Nova-t USB (Duplicate entry) + 802 MyTV + 804 MyView + 809 MyVideo + 872 MyTV2Go FM + + + 546 WinTV Nova-S CI + 543 WinTV Nova + 907 Nova-S USB + 908 Nova-T USB + 717 WinTV Nexus-S + 157 DEC3000-s Standalone + USB + + Spain + 685 WinTV-Go + 690 WinTV-PrimioFM + 416 WinTV-PCI Nicam Estereo + 677 WinTV-PCI-FM + 699 WinTV-Theater + 683 WinTV-USB + 678 WinTV-USB-FM + 983 WinTV-PVR-250 + 883 WinTV-PVR-PCI + 993 WinTV-PVR-350 + 893 WinTV-PVR-USB + 728 WinTV-DVB-C PCI + 832 MyTV2Go + 869 MyTV2Go-FM + 805 MyVideo (USB) Matrix-Vision @@ -713,6 +747,7 @@ Conceptronic (.net) ------------ TVCON FM, TV card w/ FM = CPH05x + TVCON = CPH06x BestData -------- @@ -747,11 +782,22 @@ Kworld (www.kworld.com.tw) -------------------------- - KWORLD KW-TV878RF-Pro TV Capture with FM Radio - KWORLD KW-TV878R-Pro TV - KWORLD KW-TVL878RF (low profile) - KWORLD KW-TV878R TV Capture (No FM Radio) - KWORLD KW-TV878RF TV + PC TV Station + KWORLD KW-TV878R TV (no radio) + KWORLD KW-TV878RF TV (w/ radio) + + KWORLD KW-TVL878RF (low profile) + + KWORLD KW-TV713XRF (saa7134) + + + MPEG TV Station (same cards as above plus WinDVR Software MPEG en/decoder) + KWORLD KW-TV878R -Pro TV (no Radio) + KWORLD KW-TV878RF-Pro TV (w/ Radio) + KWORLD KW-TV878R -Ultra TV (no Radio) + KWORLD KW-TV878RF-Ultra TV (w/ Radio) + + JTT/ Justy Corp.http://www.justy.co.jp/ (www.jtt.com.jp website down) --------------------------------------------------------------------- @@ -793,7 +839,7 @@ TV-FM =KNC1 saa7134 Standard PCI (DVB-S) = Technotrend Budget Standard PCI (DVB-S) w/ CI - Satelco Hoghend PCI (DVB-S) = Technotrend Premium + Satelco Highend PCI (DVB-S) = Technotrend Premium Sensoray www.sensoray.com @@ -879,3 +925,37 @@ Mercury www.kobian.com (UK and FR) LR50 LR138RBG-Rx == LR138 + +TEC sound (package and manuals don't have any other manufacturer info) TecSound + Though educated googling found: www.techmakers.com + TV-Mate = Zoltrix VP-8482 + +Lorenzen www.lorenzen.de +-------- + SL DVB-S PCI = Technotrend Budget PCI (su1278 or bsru version) + +Origo (.uk) www.origo2000.com + PC TV Card = LR50 + +I/O Magic www.iomagic.com +--------- + PC PVR - Desktop TV Personal Video Recorder DR-PCTV100 = Pinnacle ROB2D-51009464 4.0 + Cyberlink PowerVCR II + +Arowana +------- + TV-Karte / Poso Power TV (?) = Zoltrix VP-8482 (?) + +iTVC15 boards: +------------- +kuroutoshikou.com ITVC15 +yuan.com MPG160 PCI TV (Internal PCI MPEG2 encoder card plus TV-tuner) + +Asus www.asuscom.com + Asus TV Tuner Card 880 NTSC (low profile, cx23880) + Asus TV (saa7134) + +Hoontech +-------- +http://www.hoontech.com/korean/download/down_driver_list03.html + HART Vision 848 (H-ART Vision 848) + HART Vision 878 (H-Art Vision 878) diff -Nru a/Documentation/video4linux/bttv/Sound-FAQ b/Documentation/video4linux/bttv/Sound-FAQ --- a/Documentation/video4linux/bttv/Sound-FAQ Sat May 24 12:48:33 2003 +++ b/Documentation/video4linux/bttv/Sound-FAQ Sat May 24 12:48:33 2003 @@ -79,10 +79,11 @@ What you have to do is figure out the correct values for gpiomask and the audiomux array. If you have Windows and the drivers four your card installed, you might to check out if you can read these registers -values used by the windows driver. A tool to do this is available from -ftp://telepresence.dmem.strath.ac.uk/pub/bt848/winutil, but it does'nt -work with bt878 boards according to some reports I received. Another -one is available from http://www.kki.net.pl/~borgx/bTV.html. +values used by the windows driver. A tool to do this is available +from ftp://telepresence.dmem.strath.ac.uk/pub/bt848/winutil, but it +does'nt work with bt878 boards according to some reports I received. +Another one with bt878 suport is available from +http://btwincap.sourceforge.net/Files/btspy2.00.zip You might also dig around in the *.ini files of the Windows applications. You can have a look at the board to see which of the gpio pins are diff -Nru a/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS Sat May 24 12:48:26 2003 +++ b/MAINTAINERS Sat May 24 12:48:26 2003 @@ -679,7 +679,7 @@ EXT3 FILE SYSTEM P: Stephen Tweedie, Andrew Morton -M: sct@redhat.com, akpm@zip.com.au, adilger@clusterfs.com +M: sct@redhat.com, akpm@digeo.com, adilger@clusterfs.com L: ext3-users@redhat.com S: Maintained @@ -801,20 +801,13 @@ M: drivers@neukum.org S: Maintained -I2C DRIVERS -P: Simon Vogl -M: simon@tk.uni-linz.ac.at -P: Frodo Looijaard -M: frodol@dds.nl -L: linux-i2c@pelican.tk.uni-linz.ac.at -W: http://www.tk.uni-linz.ac.at/~simon/private/i2c -S: Maintained - -SENSORS DRIVERS +I2C AND SENSORS DRIVERS P: Frodo Looijaard M: frodol@dds.nl P: Philip Edelbrock M: phil@netroedge.com +P: Greg Kroah-Hartman +M: greg@kroah.com L: sensors@stimpy.netroedge.com W: http://www.lm-sensors.nu/ S: Maintained @@ -1264,7 +1257,7 @@ NETWORK DEVICE DRIVERS P: Andrew Morton -M: akpm@zip.com.au +M: akpm@digeo.com P: Jeff Garzik M: jgarzik@pobox.com L: linux-net@vger.kernel.org @@ -1285,6 +1278,8 @@ M: pekkas@netcore.fi P: James Morris M: jmorris@intercode.com.au +P: Hideaki YOSHIFUJI +M: yoshfuji@linux-ipv6.org L: netdev@oss.sgi.com S: Maintained diff -Nru a/Makefile b/Makefile --- a/Makefile Sat May 24 12:48:28 2003 +++ b/Makefile Sat May 24 12:48:28 2003 @@ -90,7 +90,7 @@ KBUILD_MODULES := 1 endif -export KBUILD_MODULES KBUILD_BUILTIN KBUILD_VERBOSE +export KBUILD_MODULES KBUILD_BUILTIN KBUILD_VERBOSE KBUILD_CHECKSRC # Beautify output # --------------------------------------------------------------------------- @@ -118,6 +118,16 @@ KBUILD_VERBOSE = 1 endif +ifdef C + ifeq ("$(origin C)", "command line") + KBUILD_CHECKSRC = $(C) + endif +endif +ifndef KBUILD_CHECKSRC + KBUILD_CHECKSRC = 0 +endif + + MAKEFLAGS += --no-print-directory # For maximum performance (+ possibly random breakage, uncomment @@ -172,6 +182,7 @@ DEPMOD = /sbin/depmod KALLSYMS = scripts/kallsyms PERL = perl +CHECK = /home/torvalds/parser/check MODFLAGS = -DMODULE CFLAGS_MODULE = $(MODFLAGS) AFLAGS_MODULE = $(MODFLAGS) @@ -189,7 +200,7 @@ export VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION KERNELRELEASE ARCH \ CONFIG_SHELL TOPDIR HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \ CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE \ - HOSTCXX HOSTCXXFLAGS LDFLAGS_BLOB LDFLAGS_MODULE + HOSTCXX HOSTCXXFLAGS LDFLAGS_BLOB LDFLAGS_MODULE CHECK export CPPFLAGS NOSTDINC_FLAGS OBJCOPYFLAGS LDFLAGS export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE diff -Nru a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c --- a/arch/alpha/kernel/core_marvel.c Sat May 24 12:48:20 2003 +++ b/arch/alpha/kernel/core_marvel.c Sat May 24 12:48:20 2003 @@ -780,7 +780,7 @@ rtc_access.function = 0x49; /* GET_TOY */ if (write) rtc_access.function = 0x48; /* PUT_TOY */ -#if CONFIG_SMP +#ifdef CONFIG_SMP if (smp_processor_id() != boot_cpuid) smp_call_function_on_cpu(__marvel_access_rtc, &rtc_access, @@ -1075,7 +1075,6 @@ /* * Fill it in. */ - agp->type = ALPHA_CORE_AGP; agp->hose = hose; agp->private = NULL; agp->ops = &marvel_agp_ops; diff -Nru a/arch/alpha/kernel/core_titan.c b/arch/alpha/kernel/core_titan.c --- a/arch/alpha/kernel/core_titan.c Sat May 24 12:48:22 2003 +++ b/arch/alpha/kernel/core_titan.c Sat May 24 12:48:22 2003 @@ -763,7 +763,6 @@ /* * Fill it in. */ - agp->type = ALPHA_CORE_AGP; agp->hose = hose; agp->private = port; agp->ops = &titan_agp_ops; diff -Nru a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S --- a/arch/alpha/kernel/entry.S Sat May 24 12:48:19 2003 +++ b/arch/alpha/kernel/entry.S Sat May 24 12:48:19 2003 @@ -849,7 +849,7 @@ about this loop. */ ldq $3, TASK_REAL_PARENT($2) 1: ldl $1, TASK_TGID($3) -#if CONFIG_SMP +#ifdef CONFIG_SMP mov $3, $4 mb ldq $3, TASK_REAL_PARENT($2) diff -Nru a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c --- a/arch/alpha/kernel/irq.c Sat May 24 12:48:30 2003 +++ b/arch/alpha/kernel/irq.c Sat May 24 12:48:30 2003 @@ -556,7 +556,7 @@ unlock: spin_unlock_irqrestore(&irq_desc[i].lock, flags); } -#if CONFIG_SMP +#ifdef CONFIG_SMP seq_puts(p, "IPI: "); for (i = 0; i < NR_CPUS; i++) if (cpu_online(i)) diff -Nru a/arch/alpha/kernel/module.c b/arch/alpha/kernel/module.c --- a/arch/alpha/kernel/module.c Sat May 24 12:48:19 2003 +++ b/arch/alpha/kernel/module.c Sat May 24 12:48:19 2003 @@ -300,3 +300,8 @@ { return 0; } + +void +module_arch_cleanup(struct module *mod) +{ +} diff -Nru a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c --- a/arch/alpha/kernel/process.c Sat May 24 12:48:31 2003 +++ b/arch/alpha/kernel/process.c Sat May 24 12:48:31 2003 @@ -235,23 +235,18 @@ alpha_clone(unsigned long clone_flags, unsigned long usp, int *parent_tid, int *child_tid, unsigned long tls_value, struct pt_regs *regs) { - struct task_struct *p; - if (!usp) usp = rdusp(); - p = do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0, - parent_tid, child_tid); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0, + parent_tid, child_tid); } int alpha_vfork(struct pt_regs *regs) { - struct task_struct *p; - p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), - regs, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), + regs, 0, NULL, NULL); } /* diff -Nru a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c --- a/arch/alpha/kernel/ptrace.c Sat May 24 12:48:31 2003 +++ b/arch/alpha/kernel/ptrace.c Sat May 24 12:48:31 2003 @@ -366,8 +366,8 @@ ret = -EIO; if ((unsigned long) data > _NSIG) break; - /* Mark single stepping. */ - child->thread_info->bpt_nsaved = -1; + /* Set single stepping. */ + ptrace_set_bpt(child); clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); wake_up_process(child); child->exit_code = data; @@ -397,11 +397,11 @@ return; if (!(current->ptrace & PT_PTRACED)) return; - current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0); - current->state = TASK_STOPPED; - notify_parent(current, SIGCHLD); - schedule(); + /* The 0x80 provides a way for the tracing parent to distinguish + between a syscall stop and SIGTRAP delivery */ + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0)); + /* * This isn't the same as continuing with a signal, but it will do * for normal use. strace only continues with a signal if the diff -Nru a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c --- a/arch/alpha/kernel/smp.c Sat May 24 12:48:22 2003 +++ b/arch/alpha/kernel/smp.c Sat May 24 12:48:22 2003 @@ -417,7 +417,12 @@ /* Don't care about the contents of regs since we'll never reschedule the forked task. */ struct pt_regs regs; - return do_fork(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); + int pid; + pid = do_fork(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); + if (pid < 0) + return NULL; + + return find_task_by_pid (pid); } /* @@ -436,7 +441,7 @@ wish. We can't use kernel_thread since we must avoid rescheduling the child. */ idle = fork_by_hand(); - if (IS_ERR(idle)) + if (!idle) panic("failed fork for CPU %d", cpuid); init_idle(idle, cpuid); diff -Nru a/arch/alpha/kernel/sys_titan.c b/arch/alpha/kernel/sys_titan.c --- a/arch/alpha/kernel/sys_titan.c Sat May 24 12:48:31 2003 +++ b/arch/alpha/kernel/sys_titan.c Sat May 24 12:48:31 2003 @@ -204,13 +204,14 @@ .set_affinity = titan_set_irq_affinity, }; -static void +static irqreturn_t titan_intr_nop(int irq, void *dev_id, struct pt_regs *regs) { /* * This is a NOP interrupt handler for the purposes of * event counting -- just return. */ + return IRQ_HANDLED; } static void __init diff -Nru a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c --- a/arch/arm/common/sa1111.c Sat May 24 12:48:31 2003 +++ b/arch/arm/common/sa1111.c Sat May 24 12:48:31 2003 @@ -419,7 +419,7 @@ spin_lock_irqsave(&sachip->lock, flags); -#if CONFIG_ARCH_SA1100 +#ifdef CONFIG_ARCH_SA1100 /* * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111: * (SA-1110 Developer's Manual, section 9.1.2.1) diff -Nru a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c --- a/arch/arm/kernel/asm-offsets.c Sat May 24 12:48:20 2003 +++ b/arch/arm/kernel/asm-offsets.c Sat May 24 12:48:20 2003 @@ -1,5 +1,5 @@ /* - * Copyright (C) 1995-2001 Russell King + * Copyright (C) 1995-2003 Russell King * 2001-2002 Keith Owens * * Generate definitions needed by assembly language modules. @@ -24,12 +24,21 @@ #if defined(__APCS_26__) #error Sorry, your compiler targets APCS-26 but this kernel requires APCS-32 #endif -#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 95) -#error Sorry, your compiler is known to miscompile kernels. Only use gcc 2.95.3 and later. -#endif -#if __GNUC__ == 2 && __GNUC_MINOR__ == 95 -/* shame we can't detect the .1 or .2 releases */ -#warning GCC 2.95.2 and earlier miscompiles kernels. +/* + * GCC 2.95.1, 2.95.2: ignores register clobber list in asm(). + * GCC 3.0, 3.1: general bad code generation. + * GCC 3.2.0: incorrect function argument offset calculation. + * GCC 3.2.x: miscompiles NEW_AUX_ENT in fs/binfmt_elf.c + * (http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view&pr=8896) + */ +#if __GNUC__ < 2 || \ + (__GNUC__ == 2 && __GNUC_MINOR__ < 95) || \ + (__GNUC__ == 2 && __GNUC_MINOR__ == 95 && __GNUC_PATCHLEVEL__ != 0 && \ + __GNUC_PATCHLEVEL__ < 3) || \ + (__GNUC__ == 3 && __GNUC_MINOR__ < 2) || \ + (__GNUC__ == 3 && __GNUC_MINOR__ == 2 && __GNUC_PATCHLEVEL__ < 1) +#error Your compiler is too buggy; it is known to miscompile kernels. +#error Known good compilers: 2.95.3, 2.95.4, 2.96, 3.2.2+PR8896 #endif /* Use marker if you need to separate the values later */ @@ -61,7 +70,6 @@ DEFINE(LPTE_WRITE, L_PTE_WRITE); DEFINE(LPTE_EXEC, L_PTE_EXEC); DEFINE(LPTE_DIRTY, L_PTE_DIRTY); - BLANK(); BLANK(); DEFINE(PAGE_SZ, PAGE_SIZE); BLANK(); diff -Nru a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S --- a/arch/arm/kernel/calls.S Sat May 24 12:48:33 2003 +++ b/arch/arm/kernel/calls.S Sat May 24 12:48:33 2003 @@ -1,7 +1,7 @@ /* - * linux/arch/arm/lib/calls.h + * linux/arch/arm/kernel/calls.S * - * Copyright (C) 1995-1998 Russell King + * Copyright (C) 1995-2003 Russell King * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff -Nru a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S --- a/arch/arm/kernel/entry-armv.S Sat May 24 12:48:22 2003 +++ b/arch/arm/kernel/entry-armv.S Sat May 24 12:48:22 2003 @@ -621,7 +621,7 @@ rsb \irqstat, \irqnr, #0 and \irqstat, \irqstat, \irqnr clz \irqnr, \irqstat - rsb \irqnr, \irqnr, #23 + rsb \irqnr, \irqnr, #(31 - PXA_IRQ_SKIP) 1001: .endm diff -Nru a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c --- a/arch/arm/kernel/irq.c Sat May 24 12:48:19 2003 +++ b/arch/arm/kernel/irq.c Sat May 24 12:48:19 2003 @@ -58,6 +58,11 @@ { } +irqreturn_t no_action(int irq, void *dev_id, struct pt_regs *regs) +{ + return IRQ_NONE; +} + void do_bad_IRQ(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs) { irq_err_count += 1; @@ -222,6 +227,7 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs) { unsigned int status; + int retval = 0; spin_unlock(&irq_controller_lock); @@ -231,7 +237,7 @@ status = 0; do { status |= action->flags; - action->handler(irq, action->dev_id, regs); + retval |= action->handler(irq, action->dev_id, regs); action = action->next; } while (action); @@ -239,6 +245,19 @@ add_interrupt_randomness(irq); spin_lock_irq(&irq_controller_lock); + + if (retval != 1) { + static int count = 100; + if (count) { + count--; + if (retval) { + printk("irq event %d: bogus retval mask %x\n", + irq, retval); + } else { + printk("irq %d: nobody cared\n", irq); + } + } + } } /* @@ -606,7 +625,7 @@ * SA_SAMPLE_RANDOM The interrupt can be used for entropy * */ -int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), +int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long irq_flags, const char * devname, void *dev_id) { unsigned long retval; diff -Nru a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c --- a/arch/arm/kernel/module.c Sat May 24 12:48:20 2003 +++ b/arch/arm/kernel/module.c Sat May 24 12:48:20 2003 @@ -159,3 +159,8 @@ { return 0; } + +void +module_arch_cleanup(struct module *mod) +{ +} diff -Nru a/arch/arm/kernel/pm.c b/arch/arm/kernel/pm.c --- a/arch/arm/kernel/pm.c Sat May 24 12:48:33 2003 +++ b/arch/arm/kernel/pm.c Sat May 24 12:48:33 2003 @@ -16,10 +16,18 @@ #include #include +/* + * Tell the linker that pm_do_suspend may not be present. + */ +extern int pm_do_suspend(void) __attribute__((weak)); + int suspend(void) { int ret; + if (!pm_do_suspend) + return -ENOSYS; + /* * Suspend "legacy" devices. */ @@ -82,9 +90,26 @@ } #ifdef CONFIG_SYSCTL +/* + * We really want this to die. It's a disgusting hack using unallocated + * sysctl numbers. We should be using a real interface. + */ + #include #include +static int +pm_sysctl_proc_handler(ctl_table *ctl, int write, struct file *filp, + void *buffer, size_t *lenp) +{ + int ret = -EIO; + printk("PM: task %s (pid %d) uses deprecated sysctl PM interface\n", + current->comm, current->pid); + if (write) + ret = suspend(); + return ret; +} + /* * This came from arch/arm/mach-sa1100/pm.c: * Copyright (c) 2001 Cliff Brake @@ -102,13 +127,23 @@ static struct ctl_table pm_table[] = { - {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&suspend}, + { + .ctl_name = ACPI_S1_SLP_TYP, + .procname = "suspend", + .mode = 0200, + .proc_handler = pm_sysctl_proc_handler, + }, {0} }; static struct ctl_table pm_dir_table[] = { - {CTL_ACPI, "pm", NULL, 0, 0555, pm_table}, + { + .ctl_name = CTL_ACPI, + .procname = "pm", + .mode = 0555, + .child = pm_table, + }, {0} }; diff -Nru a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c --- a/arch/arm/kernel/ptrace.c Sat May 24 12:48:20 2003 +++ b/arch/arm/kernel/ptrace.c Sat May 24 12:48:20 2003 @@ -18,10 +18,12 @@ #include #include #include +#include #include #include #include +#include #include "ptrace.h" @@ -32,7 +34,7 @@ * in exit.c or in signal.c. */ -#if 1 +#if 0 /* * Breakpoint SWI instruction: SWI &9F0001 */ @@ -479,24 +481,46 @@ { siginfo_t info; - /* - * The PC is always left pointing at the next instruction. Fix this. - */ - regs->ARM_pc -= 4; - - if (tsk->thread.debug.nsaved == 0) - printk(KERN_ERR "ptrace: bogus breakpoint trap\n"); - ptrace_cancel_bpt(tsk); info.si_signo = SIGTRAP; info.si_errno = 0; info.si_code = TRAP_BRKPT; - info.si_addr = (void *)instruction_pointer(regs) - - (thumb_mode(regs) ? 2 : 4); + info.si_addr = (void *)instruction_pointer(regs); force_sig_info(SIGTRAP, &info, tsk); } + +static int break_trap(struct pt_regs *regs, unsigned int instr) +{ + ptrace_break(current, regs); + return 0; +} + +static struct undef_hook arm_break_hook = { + .instr_mask = 0x0fffffff, + .instr_val = 0x07f001f0, + .cpsr_mask = PSR_T_BIT, + .cpsr_val = 0, + .fn = break_trap, +}; + +static struct undef_hook thumb_break_hook = { + .instr_mask = 0xffff, + .instr_val = 0xde01, + .cpsr_mask = PSR_T_BIT, + .cpsr_val = PSR_T_BIT, + .fn = break_trap, +}; + +static int __init ptrace_break_init(void) +{ + register_undef_hook(&arm_break_hook); + register_undef_hook(&thumb_break_hook); + return 0; +} + +core_initcall(ptrace_break_init); /* * Read the word at offset "off" into the "struct user". We diff -Nru a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c --- a/arch/arm/kernel/sys_arm.c Sat May 24 12:48:21 2003 +++ b/arch/arm/kernel/sys_arm.c Sat May 24 12:48:21 2003 @@ -238,9 +238,7 @@ */ asmlinkage int sys_fork(struct pt_regs *regs) { - struct task_struct *p; - p = do_fork(SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL); } /* Clone a task - this clones the calling program thread. @@ -248,8 +246,6 @@ */ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, struct pt_regs *regs) { - struct task_struct *p; - /* * We don't support SETTID / CLEARTID */ @@ -259,16 +255,12 @@ if (!newsp) newsp = regs->ARM_sp; - p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL); - - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL); } asmlinkage int sys_vfork(struct pt_regs *regs) { - struct task_struct *p; - p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL); } /* sys_execve() executes a new program. diff -Nru a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c --- a/arch/arm/kernel/traps.c Sat May 24 12:48:23 2003 +++ b/arch/arm/kernel/traps.c Sat May 24 12:48:23 2003 @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include "ptrace.h" @@ -240,17 +240,56 @@ die(str, regs, err); } +static LIST_HEAD(undef_hook); +static spinlock_t undef_lock = SPIN_LOCK_UNLOCKED; + +void register_undef_hook(struct undef_hook *hook) +{ + spin_lock_irq(&undef_lock); + list_add(&hook->node, &undef_hook); + spin_unlock_irq(&undef_lock); +} + +void unregister_undef_hook(struct undef_hook *hook) +{ + spin_lock_irq(&undef_lock); + list_del(&hook->node); + spin_unlock_irq(&undef_lock); +} + asmlinkage void do_undefinstr(struct pt_regs *regs) { - unsigned long *pc; + unsigned int correction = thumb_mode(regs) ? 2 : 4; + unsigned int instr; + struct undef_hook *hook; siginfo_t info; + void *pc; /* - * According to the ARM ARM, PC is 2 or 4 bytes ahead, depending - * whether we're in Thumb mode or not. + * According to the ARM ARM, PC is 2 or 4 bytes ahead, + * depending whether we're in Thumb mode or not. + * Correct this offset. */ - regs->ARM_pc -= thumb_mode(regs) ? 2 : 4; - pc = (unsigned long *)instruction_pointer(regs); + regs->ARM_pc -= correction; + + pc = (void *)instruction_pointer(regs); + if (thumb_mode(regs)) { + get_user(instr, (u16 *)pc); + } else { + get_user(instr, (u32 *)pc); + } + + spin_lock_irq(&undef_lock); + list_for_each_entry(hook, &undef_hook, node) { + if ((instr & hook->instr_mask) == hook->instr_val && + (regs->ARM_cpsr & hook->cpsr_mask) == hook->cpsr_val) { + if (hook->fn(regs, instr) == 0) { + spin_unlock_irq(&undef_lock); + return; + } + } + } + spin_unlock_irq(&undef_lock); #ifdef CONFIG_DEBUG_USER printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n", @@ -377,6 +416,7 @@ return 0; case NR(breakpoint): /* SWI BREAK_POINT */ + regs->ARM_pc -= thumb_mode(regs) ? 2 : 4; ptrace_break(current, regs); return regs->ARM_r0; diff -Nru a/arch/arm/lib/copy_page.S b/arch/arm/lib/copy_page.S --- a/arch/arm/lib/copy_page.S Sat May 24 12:48:25 2003 +++ b/arch/arm/lib/copy_page.S Sat May 24 12:48:25 2003 @@ -13,11 +13,7 @@ #include #include -#ifndef PLD -#define COPY_COUNT PAGE_SZ/64 -#else -#define COPY_COUNT PAGE_SZ/64-1 -#endif +#define COPY_COUNT (PAGE_SZ/64 PLD( -1 )) .text .align 5 diff -Nru a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c --- a/arch/arm/mach-footbridge/dc21285.c Sat May 24 12:48:33 2003 +++ b/arch/arm/mach-footbridge/dc21285.c Sat May 24 12:48:33 2003 @@ -65,7 +65,7 @@ int size, u32 *value) { unsigned long addr = dc21285_base_address(bus, devfn); - u32 v; + u32 v = 0xffffffff; if (addr) switch (size) { @@ -82,8 +82,6 @@ : "=r" (v) : "r" (addr), "r" (where)); break; } - else - v = 0xffffffff; *value = v; @@ -154,7 +152,7 @@ /* * Warn on PCI errors. */ -static void dc21285_abort_irq(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t dc21285_abort_irq(int irq, void *dev_id, struct pt_regs *regs) { unsigned int cmd; unsigned int status; @@ -180,9 +178,11 @@ } *CSR_PCICMD = cmd; + + return IRQ_HANDLED; } -static void dc21285_serr_irq(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t dc21285_serr_irq(int irq, void *dev_id, struct pt_regs *regs) { struct timer_list *timer = dev_id; unsigned int cntl; @@ -200,15 +200,19 @@ disable_irq(irq); timer->expires = jiffies + HZ; add_timer(timer); + + return IRQ_HANDLED; } -static void dc21285_discard_irq(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t dc21285_discard_irq(int irq, void *dev_id, struct pt_regs *regs) { printk(KERN_DEBUG "PCI: discard timer expired\n"); *CSR_SA110_CNTL &= 0xffffde07; + + return IRQ_HANDLED; } -static void dc21285_dparity_irq(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t dc21285_dparity_irq(int irq, void *dev_id, struct pt_regs *regs) { unsigned int cmd; @@ -218,9 +222,11 @@ cmd = *CSR_PCICMD & 0xffff; *CSR_PCICMD = cmd | 1 << 24; + + return IRQ_HANDLED; } -static void dc21285_parity_irq(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t dc21285_parity_irq(int irq, void *dev_id, struct pt_regs *regs) { struct timer_list *timer = dev_id; unsigned int cmd; @@ -238,6 +244,8 @@ disable_irq(irq); timer->expires = jiffies + HZ; add_timer(timer); + + return IRQ_HANDLED; } int __init dc21285_setup(int nr, struct pci_sys_data *sys) diff -Nru a/arch/arm/mach-integrator/mm.c b/arch/arm/mach-integrator/mm.c --- a/arch/arm/mach-integrator/mm.c Sat May 24 12:48:33 2003 +++ b/arch/arm/mach-integrator/mm.c Sat May 24 12:48:33 2003 @@ -43,8 +43,6 @@ * f1500000 15000000 RTC * f1600000 16000000 UART 0 * f1700000 17000000 UART 1 - * f1800000 18000000 Keyboard - * f1900000 19000000 Mouse * f1a00000 1a000000 Debug LEDs * f1b00000 1b000000 GPIO */ @@ -58,8 +56,6 @@ { IO_ADDRESS(INTEGRATOR_RTC_BASE), INTEGRATOR_RTC_BASE, SZ_4K, MT_DEVICE }, { IO_ADDRESS(INTEGRATOR_UART0_BASE), INTEGRATOR_UART0_BASE, SZ_4K, MT_DEVICE }, { IO_ADDRESS(INTEGRATOR_UART1_BASE), INTEGRATOR_UART1_BASE, SZ_4K, MT_DEVICE }, - { IO_ADDRESS(INTEGRATOR_KBD_BASE), INTEGRATOR_KBD_BASE, SZ_4K, MT_DEVICE }, - { IO_ADDRESS(INTEGRATOR_MOUSE_BASE), INTEGRATOR_MOUSE_BASE, SZ_4K, MT_DEVICE }, { IO_ADDRESS(INTEGRATOR_DBG_BASE), INTEGRATOR_DBG_BASE, SZ_4K, MT_DEVICE }, { IO_ADDRESS(INTEGRATOR_GPIO_BASE), INTEGRATOR_GPIO_BASE, SZ_4K, MT_DEVICE }, { PCI_MEMORY_VADDR, PHYS_PCI_MEM_BASE, SZ_16M, MT_DEVICE }, diff -Nru a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c --- a/arch/arm/mach-pxa/irq.c Sat May 24 12:48:31 2003 +++ b/arch/arm/mach-pxa/irq.c Sat May 24 12:48:31 2003 @@ -50,9 +50,9 @@ * Use this instead of directly setting GRER/GFER. */ -static int GPIO_IRQ_rising_edge[3]; -static int GPIO_IRQ_falling_edge[3]; -static int GPIO_IRQ_mask[3]; +static long GPIO_IRQ_rising_edge[3]; +static long GPIO_IRQ_falling_edge[3]; +static long GPIO_IRQ_mask[3]; static int pxa_gpio_irq_type(unsigned int irq, unsigned int type) { @@ -189,7 +189,6 @@ .ack = pxa_ack_muxed_gpio, .mask = pxa_mask_muxed_gpio, .unmask = pxa_unmask_muxed_gpio, - .rerun = pxa_manual_rerun, .type = pxa_gpio_irq_type, }; @@ -217,20 +216,17 @@ /* GPIO 0 and 1 must have their mask bit always set */ GPIO_IRQ_mask[0] = 3; + for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) { + set_irq_chip(irq, &pxa_internal_chip); + set_irq_handler(irq, do_level_IRQ); + set_irq_flags(irq, IRQF_VALID); + } + for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) { set_irq_chip(irq, &pxa_low_gpio_chip); set_irq_handler(irq, do_edge_IRQ); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } - - for (irq = PXA_IRQ(11); irq <= PXA_IRQ(31); irq++) { - set_irq_chip(irq, &pxa_internal_chip); - set_irq_handler(irq, do_level_IRQ); - set_irq_flags(irq, IRQF_VALID); - } - /* Those are reserved */ - set_irq_flags(PXA_IRQ(15), 0); - set_irq_flags(PXA_IRQ(16), 0); for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(80); irq++) { set_irq_chip(irq, &pxa_muxed_gpio_chip); diff -Nru a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c --- a/arch/arm/mach-pxa/lubbock.c Sat May 24 12:48:23 2003 +++ b/arch/arm/mach-pxa/lubbock.c Sat May 24 12:48:23 2003 @@ -33,57 +33,41 @@ #include "generic.h" -static void lubbock_ack_irq(unsigned int irq) -{ - int lubbock_irq = (irq - LUBBOCK_IRQ(0)); - LUB_IRQ_SET_CLR &= ~(1 << lubbock_irq); -} + +static unsigned long lubbock_irq_enabled; static void lubbock_mask_irq(unsigned int irq) { int lubbock_irq = (irq - LUBBOCK_IRQ(0)); - LUB_IRQ_MASK_EN &= ~(1 << lubbock_irq); + LUB_IRQ_MASK_EN = (lubbock_irq_enabled &= ~(1 << lubbock_irq)); } static void lubbock_unmask_irq(unsigned int irq) { int lubbock_irq = (irq - LUBBOCK_IRQ(0)); - LUB_IRQ_MASK_EN |= (1 << lubbock_irq); + /* the irq can be acknowledged only if deasserted, so it's done here */ + LUB_IRQ_SET_CLR &= ~(1 << lubbock_irq); + LUB_IRQ_MASK_EN = (lubbock_irq_enabled |= (1 << lubbock_irq)); } static struct irqchip lubbock_irq_chip = { - .ack = lubbock_ack_irq, + .ack = lubbock_mask_irq, .mask = lubbock_mask_irq, .unmask = lubbock_unmask_irq, }; -void lubbock_irq_handler(unsigned int irq, struct irqdesc *desc, - struct pt_regs *regs) +static void lubbock_irq_handler(unsigned int irq, struct irqdesc *desc, + struct pt_regs *regs) { - unsigned int enabled, pending; - - /* get active pending irq mask */ - enabled = LUB_IRQ_MASK_EN & 0x003f; - pending = LUB_IRQ_SET_CLR & enabled; - + unsigned long pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled; do { -//printk("%s a: set_clr %#x, mask_en %#x LR/DR %d/%d\n", __FUNCTION__, LUB_IRQ_SET_CLR, LUB_IRQ_MASK_EN, GPLR(0)&1, GEDR(0)&1 ); - /* clear our parent irq */ - GEDR(0) = GPIO_bit(0); - - /* process them */ - irq = LUBBOCK_IRQ(0); - desc = irq_desc + irq; - do { - if (pending & 1) - desc->handle(irq, desc, regs); - irq++; - desc++; - pending >>= 1; - } while (pending); -//printk("%s b: set_clr %#x, mask_en %#x LR/DR %d/%d\n", __FUNCTION__, LUB_IRQ_SET_CLR, LUB_IRQ_MASK_EN, GPLR(0)&1, GEDR(0)&1 ); - enabled = LUB_IRQ_MASK_EN & 0x003f; - pending = LUB_IRQ_SET_CLR & enabled; + GEDR(0) = GPIO_bit(0); /* clear our parent irq */ + if (likely(pending)) { + irq = LUBBOCK_IRQ(0) + __ffs(pending); + desc = irq_desc + irq; + desc->handle(irq, desc, regs); + } + pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled; } while (pending); } diff -Nru a/arch/arm/mach-rpc/dma.c b/arch/arm/mach-rpc/dma.c --- a/arch/arm/mach-rpc/dma.c Sat May 24 12:48:33 2003 +++ b/arch/arm/mach-rpc/dma.c Sat May 24 12:48:33 2003 @@ -57,7 +57,7 @@ if (end > PAGE_SIZE) end = PAGE_SIZE; - if (offset + (int) TRANSFER_SIZE > end) + if (offset + TRANSFER_SIZE >= end) flags |= DMA_END_L; sg->length = end - TRANSFER_SIZE; @@ -83,7 +83,7 @@ sg->length |= flags; } -static void iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs) { dma_t *dma = (dma_t *)dev_id; unsigned long base = dma->dma_base; @@ -93,30 +93,36 @@ status = iomd_readb(base + ST); if (!(status & DMA_ST_INT)) - return; + return IRQ_HANDLED; - if (status & DMA_ST_OFL && !dma->sg) - break; - - iomd_get_next_sg(&dma->cur_sg, dma); + if ((dma->state ^ status) & DMA_ST_AB) + iomd_get_next_sg(&dma->cur_sg, dma); switch (status & (DMA_ST_OFL | DMA_ST_AB)) { case DMA_ST_OFL: /* OIA */ case DMA_ST_AB: /* .IB */ iomd_writel(dma->cur_sg.dma_address, base + CURA); iomd_writel(dma->cur_sg.length, base + ENDA); + dma->state = DMA_ST_AB; break; case DMA_ST_OFL | DMA_ST_AB: /* OIB */ case 0: /* .IA */ iomd_writel(dma->cur_sg.dma_address, base + CURB); iomd_writel(dma->cur_sg.length, base + ENDB); + dma->state = 0; break; } + + if (status & DMA_ST_OFL && + dma->cur_sg.length == (DMA_END_S|DMA_END_L)) + break; } while (1); - iomd_writeb(0, dma->dma_base + CR); + dma->state = ~DMA_ST_AB; disable_irq(irq); + + return IRQ_HANDLED; } static int iomd_request_dma(dmach_t channel, dma_t *dma) @@ -150,6 +156,7 @@ } iomd_writeb(DMA_CR_C, dma_base + CR); + dma->state = DMA_ST_AB; } if (dma->dma_mode == DMA_MODE_READ) @@ -163,13 +170,11 @@ { unsigned long dma_base = dma->dma_base; unsigned long flags; - unsigned int ctrl; local_irq_save(flags); - ctrl = iomd_readb(dma_base + CR); - if (ctrl & DMA_CR_E) + if (dma->state != ~DMA_ST_AB) disable_irq(dma->dma_irq); - iomd_writeb(ctrl & ~DMA_CR_E, dma_base + CR); + iomd_writeb(0, dma_base + CR); local_irq_restore(flags); } diff -Nru a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c --- a/arch/arm/mm/consistent.c Sat May 24 12:48:30 2003 +++ b/arch/arm/mm/consistent.c Sat May 24 12:48:30 2003 @@ -330,7 +330,7 @@ core_initcall(consistent_init); /* - * make an area consistent for devices. + * Make an area consistent for devices. */ void consistent_sync(void *vaddr, size_t size, int direction) { diff -Nru a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types --- a/arch/arm/tools/mach-types Sat May 24 12:48:24 2003 +++ b/arch/arm/tools/mach-types Sat May 24 12:48:24 2003 @@ -6,7 +6,7 @@ # To add an entry into this database, please see Documentation/arm/README, # or contact rmk@arm.linux.org.uk # -# Last update: Sat Apr 26 11:41:41 2003 +# Last update: Wed May 7 23:43:08 2003 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -328,3 +328,14 @@ nipc2 ARCH_NIPC2 NIPC2 317 fu7202 ARCH_FU7202 FU7202 318 adsagx ARCH_ADSAGX ADSAGX 319 +pxa_pooh ARCH_PXA_POOH PXA_POOH 320 +bandon ARCH_BANDON BANDON 321 +pcm7210 ARCH_PCM7210 PCM7210 322 +nms9200 ARCH_NMS9200 NMS9200 323 +gealog ARCH_GEALOG GEALOG 324 +m7140 SA1100_M7140 M7140 325 +korebot ARCH_KOREBOT KOREBOT 326 +iq31244 ARCH_IQ31244 IQ31244 327 +koan393 SA1100_KOAN393 KOAN393 328 +inhandftip3 ARCH_INHANDFTIP3 INHANDFTIP3 329 +gonzo ARCH_GONZO GONZO 330 diff -Nru a/arch/cris/drivers/eeprom.c b/arch/cris/drivers/eeprom.c --- a/arch/cris/drivers/eeprom.c Sat May 24 12:48:23 2003 +++ b/arch/cris/drivers/eeprom.c Sat May 24 12:48:23 2003 @@ -163,7 +163,7 @@ init_waitqueue_head(&eeprom.wait_q); eeprom.busy = 0; -#if CONFIG_ETRAX_I2C_EEPROM_PROBE +#ifdef CONFIG_ETRAX_I2C_EEPROM_PROBE #define EETEXT "Found" #else #define EETEXT "Assuming" @@ -191,7 +191,7 @@ eeprom.usec_delay_step = 128; eeprom.adapt_state = 0; -#if CONFIG_ETRAX_I2C_EEPROM_PROBE +#ifdef CONFIG_ETRAX_I2C_EEPROM_PROBE i2c_start(); i2c_outbyte(0x80); if(!i2c_getack()) diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig --- a/arch/i386/Kconfig Sat May 24 12:48:21 2003 +++ b/arch/i386/Kconfig Sat May 24 12:48:21 2003 @@ -65,19 +65,16 @@ config X86_SUMMIT bool "Summit/EXA (IBM x440)" + depends on SMP help This option is needed for IBM systems that use the Summit/EXA chipset. In particular, it is needed for the x440. If you don't have one of these computers, you should say N here. -config ACPI_SRAT - bool - default y - depends on NUMA && X86_SUMMIT - config X86_BIGSMP bool "Support for other sub-arch SMP systems with more than 8 CPUs" + depends on SMP help This option is needed for the systems that have more than 8 CPUs and if the system is not of any sub-arch type above. @@ -95,8 +92,24 @@ A kernel compiled for the Visual Workstation will not run on PCs and vice versa. See for details. +config X86_GENERICARCH + bool "Generic architecture (Summit, bigsmp, default)" + depends on SMP + help + This option compiles in the Summit, bigsmp, default subarchitectures. + It is intended for a generic binary kernel. + endchoice +config ACPI_SRAT + bool + default y + depends on NUMA && (X86_SUMMIT || X86_GENERICARCH) + +config X86_CYCLONE_TIMER + bool + default y + depends on X86_SUMMIT || X86_GENERICARCH choice prompt "Processor family" @@ -666,7 +679,7 @@ # Common NUMA Features config NUMA bool "Numa Memory Allocation Support" - depends on SMP && HIGHMEM64G && (X86_PC || X86_NUMAQ || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY)) + depends on SMP && HIGHMEM64G && (X86_PC || X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY)) default n if X86_PC default y if (X86_NUMAQ || X86_SUMMIT) @@ -764,7 +777,7 @@ # Summit needs it only when NUMA is on config BOOT_IOREMAP bool - depends on (X86_SUMMIT && NUMA) + depends on ((X86_SUMMIT || X86_GENERICARCH) && NUMA) default y endmenu diff -Nru a/arch/i386/Makefile b/arch/i386/Makefile --- a/arch/i386/Makefile Sat May 24 12:48:23 2003 +++ b/arch/i386/Makefile Sat May 24 12:48:23 2003 @@ -73,6 +73,11 @@ mflags-$(CONFIG_X86_SUMMIT) := -Iinclude/asm-i386/mach-summit mcore-$(CONFIG_X86_SUMMIT) := mach-default +# generic subarchitecture +mflags-$(CONFIG_X86_GENERICARCH) := -Iinclude/asm-i386/mach-generic +mcore-$(CONFIG_X86_GENERICARCH) := mach-default +core-$(CONFIG_X86_GENERICARCH) += arch/i386/mach-generic/ + # default subarch .h files mflags-y += -Iinclude/asm-i386/mach-default diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile --- a/arch/i386/kernel/Makefile Sat May 24 12:48:21 2003 +++ b/arch/i386/kernel/Makefile Sat May 24 12:48:21 2003 @@ -17,6 +17,7 @@ obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_MICROCODE) += microcode.o +obj-$(CONFIG_PM) += suspend.o obj-$(CONFIG_APM) += apm.o obj-$(CONFIG_X86_SMP) += smp.o smpboot.o obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o diff -Nru a/arch/i386/kernel/acpi/sleep.c b/arch/i386/kernel/acpi/sleep.c --- a/arch/i386/kernel/acpi/sleep.c Sat May 24 12:48:24 2003 +++ b/arch/i386/kernel/acpi/sleep.c Sat May 24 12:48:24 2003 @@ -75,7 +75,7 @@ printk(KERN_ERR "ACPI: Wakeup code way too big, S3 disabled.\n"); return; } -#if CONFIG_X86_PAE +#ifdef CONFIG_X86_PAE printk(KERN_ERR "ACPI: S3 and PAE do not like each other for now, S3 disabled.\n"); return; #endif diff -Nru a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c --- a/arch/i386/kernel/apm.c Sat May 24 12:48:20 2003 +++ b/arch/i386/kernel/apm.c Sat May 24 12:48:20 2003 @@ -226,6 +226,7 @@ #include #include #include +#include #include "io_ports.h" @@ -1165,9 +1166,13 @@ #endif } -static inline void reinit_timer(void) +static void reinit_timer(void) { #ifdef INIT_TIMER_AFTER_SUSPEND + unsigned long flags; + extern spinlock_t i8253_lock; + + spin_lock_irqsave(&i8253_lock, flags); /* set the clock to 100 Hz */ outb_p(0x34, PIT_MODE); /* binary, mode 2, LSB/MSB, ch 0 */ udelay(10); @@ -1175,6 +1180,7 @@ udelay(10); outb(LATCH >> 8, PIT_CH0); /* MSB */ udelay(10); + spin_unlock_irqrestore(&i8253_lock, flags); #endif } @@ -1212,7 +1218,9 @@ spin_unlock(&i8253_lock); write_sequnlock_irq(&xtime_lock); + save_processor_state(); err = set_system_power_state(APM_STATE_SUSPEND); + restore_processor_state(); write_seqlock_irq(&xtime_lock); spin_lock(&i8253_lock); @@ -2005,7 +2013,7 @@ apm_proc = create_proc_info_entry("apm", 0, NULL, apm_get_info); if (apm_proc) - SET_MODULE_OWNER(apm_proc); + apm_proc->owner = THIS_MODULE; kernel_thread(apm, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD); diff -Nru a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c --- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c Sat May 24 12:48:24 2003 +++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c Sat May 24 12:48:24 2003 @@ -147,7 +147,7 @@ #ifdef SUSPMOD_DEBUG #define dprintk(msg...) printk(KERN_DEBUG "cpufreq:" msg) #else -#define dprintk(msg...) do { } while(0); +#define dprintk(msg...) do { } while(0) #endif /** diff -Nru a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c Sat May 24 12:48:20 2003 +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c Sat May 24 12:48:20 2003 @@ -37,7 +37,7 @@ #ifdef DEBUG #define dprintk(msg...) printk(msg) #else -#define dprintk(msg...) do { } while(0); +#define dprintk(msg...) do { } while(0) #endif static unsigned int numscales=16, numvscales; diff -Nru a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c --- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c Sat May 24 12:48:31 2003 +++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c Sat May 24 12:48:31 2003 @@ -104,18 +104,20 @@ } rdmsr(MSR_IA32_THERM_STATUS, l, h); +#if 0 if (l & 0x01) -// printk(KERN_DEBUG PFX "CPU#%d currently thermal throttled\n", cpu); - + printk(KERN_DEBUG PFX "CPU#%d currently thermal throttled\n", cpu); +#endif if (has_N44_O17_errata[cpu] && (newstate == DC_25PT || newstate == DC_DFLT)) newstate = DC_38PT; rdmsr(MSR_IA32_THERM_CONTROL, l, h); if (newstate == DC_DISABLE) { -// printk(KERN_INFO PFX "CPU#%d disabling modulation\n", cpu); + /* printk(KERN_INFO PFX "CPU#%d disabling modulation\n", cpu); */ wrmsr(MSR_IA32_THERM_CONTROL, l & ~(1<<4), h); } else { -// printk(KERN_INFO PFX "CPU#%d setting duty cycle to %d%%\n", cpu, ((125 * newstate) / 10)); + /* printk(KERN_INFO PFX "CPU#%d setting duty cycle to %d%%\n", + cpu, ((125 * newstate) / 10)); */ /* bits 63 - 5 : reserved * bit 4 : enable/disable * bits 3-1 : duty cycle diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c Sat May 24 12:48:19 2003 +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c Sat May 24 12:48:19 2003 @@ -24,6 +24,7 @@ #include #include #include +#include #include "powernow-k7.h" @@ -32,7 +33,7 @@ #ifdef DEBUG #define dprintk(msg...) printk(msg) #else -#define dprintk(msg...) do { } while(0); +#define dprintk(msg...) do { } while(0) #endif #define PFX "powernow: " @@ -89,7 +90,7 @@ rdmsr (msr, l__, h__); \ val = l__; \ val |= ((u64)h__<<32); \ -} while(0); +} while(0) #endif #ifndef wrmsrl @@ -236,20 +237,24 @@ if (have_a0 == 1) /* A0 errata 5 */ __asm__("\tcli\n"); - rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); - fidvidctl.bits.SGTC = latency; /* Stop grant timeout counter */ - fidvidctl.bits.FID = fid; - fidvidctl.bits.FIDC = 1; + /* First change the frequency. */ + if (fidvidctl.bits.FID != fid) { + rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); + fidvidctl.bits.SGTC = latency; /* Stop grant timeout counter */ + fidvidctl.bits.FID = fid; + fidvidctl.bits.FIDC = 1; + wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); + } - /* Set the voltage lazily. Ie, only do voltage transition - if its changed since last time (Some speeds have the same voltage) */ + /* Now change voltage. */ if (fidvidctl.bits.VID != vid) { + rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); fidvidctl.bits.VID = vid; fidvidctl.bits.VIDC = 1; + wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); } - wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); if (have_a0 == 1) __asm__("\tsti\n"); @@ -386,6 +391,10 @@ static int __init powernow_init (void) { + if (dmi_broken & BROKEN_CPUFREQ) { + printk (KERN_INFO PFX "Disabled at boot time by DMI,\n"); + return -ENODEV; + } if (check_powernow()==0) return -ENODEV; return cpufreq_register_driver(&powernow_driver); diff -Nru a/arch/i386/kernel/cpu/mtrr/if.c b/arch/i386/kernel/cpu/mtrr/if.c --- a/arch/i386/kernel/cpu/mtrr/if.c Sat May 24 12:48:21 2003 +++ b/arch/i386/kernel/cpu/mtrr/if.c Sat May 24 12:48:21 2003 @@ -49,7 +49,7 @@ struct file *file, int page) { int reg; - unsigned int *fcount = file->private_data; + unsigned int *fcount = FILE_FCOUNT(file); if (!page) { if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) @@ -70,7 +70,7 @@ /* RED-PEN: seq_file can seek now. this is ignored. */ static ssize_t -mtrr_write(struct file *file, const char *buf, size_t len, loff_t * ppos) +mtrr_write(struct file *file, const char __user *buf, size_t len, loff_t * ppos) /* Format of control line: "base=%Lx size=%Lx type=%s" OR: "disable=%d" @@ -133,12 +133,13 @@ static int mtrr_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) + unsigned int cmd, unsigned long __arg) { int err; mtrr_type type; struct mtrr_sentry sentry; struct mtrr_gentry gentry; + void __user *arg = (void __user *) __arg; switch (cmd) { default: @@ -146,7 +147,7 @@ case MTRRIOC_ADD_ENTRY: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&sentry, (void *) arg, sizeof sentry)) + if (copy_from_user(&sentry, arg, sizeof sentry)) return -EFAULT; err = mtrr_file_add(sentry.base, sentry.size, sentry.type, 1, @@ -157,7 +158,7 @@ case MTRRIOC_SET_ENTRY: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&sentry, (void *) arg, sizeof sentry)) + if (copy_from_user(&sentry, arg, sizeof sentry)) return -EFAULT; err = mtrr_add(sentry.base, sentry.size, sentry.type, 0); if (err < 0) @@ -166,7 +167,7 @@ case MTRRIOC_DEL_ENTRY: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&sentry, (void *) arg, sizeof sentry)) + if (copy_from_user(&sentry, arg, sizeof sentry)) return -EFAULT; err = mtrr_file_del(sentry.base, sentry.size, file, 0); if (err < 0) @@ -175,14 +176,14 @@ case MTRRIOC_KILL_ENTRY: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&sentry, (void *) arg, sizeof sentry)) + if (copy_from_user(&sentry, arg, sizeof sentry)) return -EFAULT; err = mtrr_del(-1, sentry.base, sentry.size); if (err < 0) return err; break; case MTRRIOC_GET_ENTRY: - if (copy_from_user(&gentry, (void *) arg, sizeof gentry)) + if (copy_from_user(&gentry, arg, sizeof gentry)) return -EFAULT; if (gentry.regnum >= num_var_ranges) return -EINVAL; @@ -198,13 +199,13 @@ gentry.type = type; } - if (copy_to_user((void *) arg, &gentry, sizeof gentry)) + if (copy_to_user(arg, &gentry, sizeof gentry)) return -EFAULT; break; case MTRRIOC_ADD_PAGE_ENTRY: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&sentry, (void *) arg, sizeof sentry)) + if (copy_from_user(&sentry, arg, sizeof sentry)) return -EFAULT; err = mtrr_file_add(sentry.base, sentry.size, sentry.type, 1, @@ -215,7 +216,7 @@ case MTRRIOC_SET_PAGE_ENTRY: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&sentry, (void *) arg, sizeof sentry)) + if (copy_from_user(&sentry, arg, sizeof sentry)) return -EFAULT; err = mtrr_add_page(sentry.base, sentry.size, sentry.type, 0); if (err < 0) @@ -224,7 +225,7 @@ case MTRRIOC_DEL_PAGE_ENTRY: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&sentry, (void *) arg, sizeof sentry)) + if (copy_from_user(&sentry, arg, sizeof sentry)) return -EFAULT; err = mtrr_file_del(sentry.base, sentry.size, file, 1); if (err < 0) @@ -233,21 +234,21 @@ case MTRRIOC_KILL_PAGE_ENTRY: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (copy_from_user(&sentry, (void *) arg, sizeof sentry)) + if (copy_from_user(&sentry, arg, sizeof sentry)) return -EFAULT; err = mtrr_del_page(-1, sentry.base, sentry.size); if (err < 0) return err; break; case MTRRIOC_GET_PAGE_ENTRY: - if (copy_from_user(&gentry, (void *) arg, sizeof gentry)) + if (copy_from_user(&gentry, arg, sizeof gentry)) return -EFAULT; if (gentry.regnum >= num_var_ranges) return -EINVAL; mtrr_if->get(gentry.regnum, &gentry.base, &gentry.size, &type); gentry.type = type; - if (copy_to_user((void *) arg, &gentry, sizeof gentry)) + if (copy_to_user(arg, &gentry, sizeof gentry)) return -EFAULT; break; } diff -Nru a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c --- a/arch/i386/kernel/dmi_scan.c Sat May 24 12:48:23 2003 +++ b/arch/i386/kernel/dmi_scan.c Sat May 24 12:48:23 2003 @@ -511,6 +511,14 @@ return 0; } +static __init int acer_cpufreq_pst(struct dmi_blacklist *d) +{ + printk(KERN_WARNING "%s laptop with broken PST tables in BIOS detected.\n", d->ident); + printk(KERN_WARNING "You need to downgrade to 3A21 (09/09/2002), or try a newer BIOS than 3A71 (01/20/2003)\n"); + printk(KERN_WARNING "cpufreq scaling has been disabled as a result of this.\n"); + dmi_broken |= BROKEN_CPUFREQ; + return 0; +} /* @@ -823,6 +831,17 @@ { disable_smbus, "IBM", { MATCH(DMI_SYS_VENDOR, "IBM"), NO_MATCH, NO_MATCH, NO_MATCH + } }, + + /* + * Some Athlon laptops have really fucked PST tables. + * A BIOS update is all that can save them. + * Mention this, and disable cpufreq. + */ + { acer_cpufreq_pst, "Acer Aspire", { + MATCH(DMI_SYS_VENDOR, "Insyde Software"), + MATCH(DMI_BIOS_VERSION, "3A71"), + NO_MATCH, NO_MATCH, } }, { NULL, } diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S --- a/arch/i386/kernel/entry.S Sat May 24 12:48:22 2003 +++ b/arch/i386/kernel/entry.S Sat May 24 12:48:22 2003 @@ -497,13 +497,19 @@ pushl $do_debug jmp error_code +/* + * NMI is doubly nasty. It can happen _while_ we're handling + * a debug fault, and the debug fault hasn't yet been able to + * clear up the stack. So we first check whether we got an + * NMI on the sysenter entry path, but after that we need to + * check whether we got an NMI on the debug path where the debug + * fault happened on the sysenter path. + */ ENTRY(nmi) cmpl $sysenter_entry,(%esp) je nmi_stack_fixup - cmpl $debug - 1,(%esp) - jle nmi_stack_correct - cmpl $debug_esp_fix_insn,(%esp) - jle nmi_debug_stack_fixup + cmpl $sysenter_entry,12(%esp) + je nmi_debug_stack_check nmi_stack_correct: pushl %eax SAVE_ALL @@ -517,6 +523,13 @@ nmi_stack_fixup: FIX_STACK(12,nmi_stack_correct, 1) jmp nmi_stack_correct +nmi_debug_stack_check: + cmpw $__KERNEL_CS,16(%esp) + jne nmi_stack_correct + cmpl $debug - 1,(%esp) + jle nmi_stack_correct + cmpl $debug_esp_fix_insn,(%esp) + jle nmi_debug_stack_fixup nmi_debug_stack_fixup: FIX_STACK(24,nmi_stack_correct, 1) jmp nmi_stack_correct diff -Nru a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S --- a/arch/i386/kernel/head.S Sat May 24 12:48:20 2003 +++ b/arch/i386/kernel/head.S Sat May 24 12:48:20 2003 @@ -483,7 +483,7 @@ .quad 0x0000000000000000 /* 0xf0 - unused */ .quad 0x0000000000000000 /* 0xf8 - GDT entry 31: double-fault TSS */ -#if CONFIG_SMP +#ifdef CONFIG_SMP .fill (NR_CPUS-1)*GDT_ENTRIES,8,0 /* other CPU's GDT */ #endif diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c --- a/arch/i386/kernel/i386_ksyms.c Sat May 24 12:48:33 2003 +++ b/arch/i386/kernel/i386_ksyms.c Sat May 24 12:48:33 2003 @@ -73,9 +73,6 @@ #ifdef CONFIG_X86_NUMAQ EXPORT_SYMBOL(xquad_portio); #endif -#ifndef CONFIG_X86_WP_WORKS_OK -EXPORT_SYMBOL(__verify_write); -#endif EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(dump_extended_fpu); diff -Nru a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c --- a/arch/i386/kernel/i8259.c Sat May 24 12:48:32 2003 +++ b/arch/i386/kernel/i8259.c Sat May 24 12:48:32 2003 @@ -373,11 +373,16 @@ static void setup_timer(void) { + extern spinlock_t i8253_lock; + unsigned long flags; + + spin_lock_irqsave(&i8253_lock, flags); outb_p(0x34,PIT_MODE); /* binary, mode 2, LSB/MSB, ch 0 */ udelay(10); outb_p(LATCH & 0xff , PIT_CH0); /* LSB */ udelay(10); outb(LATCH >> 8 , PIT_CH0); /* MSB */ + spin_unlock_irqrestore(&i8253_lock, flags); } static int timer_resume(struct device *dev, u32 level) diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c --- a/arch/i386/kernel/io_apic.c Sat May 24 12:48:22 2003 +++ b/arch/i386/kernel/io_apic.c Sat May 24 12:48:22 2003 @@ -219,6 +219,14 @@ { struct IO_APIC_route_entry entry; unsigned long flags; + + /* Check delivery_mode to be sure we're not clearing an SMI pin */ + spin_lock_irqsave(&ioapic_lock, flags); + *(((int*)&entry) + 0) = io_apic_read(apic, 0x10 + 2 * pin); + *(((int*)&entry) + 1) = io_apic_read(apic, 0x11 + 2 * pin); + spin_unlock_irqrestore(&ioapic_lock, flags); + if (entry.delivery_mode == dest_SMI) + return; /* * Disable it in the IO-APIC irq-routing table: @@ -240,22 +248,22 @@ clear_IO_APIC_pin(apic, pin); } -static void set_ioapic_affinity (unsigned int irq, unsigned long mask) +static void set_ioapic_affinity (unsigned int irq, unsigned long cpu_mask) { unsigned long flags; int pin; struct irq_pin_list *entry = irq_2_pin + irq; - - /* - * Only the first 8 bits are valid. - */ - mask = mask << 24; + unsigned int apicid_value; + + apicid_value = cpu_mask_to_apicid(cpu_mask); + /* Prepare to do the io_apic_write */ + apicid_value = apicid_value << 24; spin_lock_irqsave(&ioapic_lock, flags); for (;;) { pin = entry->pin; if (pin == -1) break; - io_apic_write(entry->apic, 0x10 + 1 + pin*2, mask); + io_apic_write(entry->apic, 0x10 + 1 + pin*2, apicid_value); if (!entry->next) break; entry = irq_2_pin + entry->next; @@ -279,8 +287,10 @@ extern unsigned long irq_affinity[NR_IRQS]; -static int __cacheline_aligned pending_irq_balance_apicid[NR_IRQS]; -static int irqbalance_disabled = NO_BALANCE_IRQ; +static int __cacheline_aligned pending_irq_balance_cpumask[NR_IRQS]; + +#define IRQBALANCE_CHECK_ARCH -999 +static int irqbalance_disabled = IRQBALANCE_CHECK_ARCH; static int physical_balance = 0; struct irq_cpu_info { @@ -342,8 +352,10 @@ unsigned long allowed_mask; unsigned int new_cpu; - if (irqbalance_disabled) + if (irqbalance_disabled == IRQBALANCE_CHECK_ARCH && NO_BALANCE_IRQ) return; + else if (irqbalance_disabled) + return; allowed_mask = cpu_online_map & irq_affinity[irq]; new_cpu = move(cpu, allowed_mask, now, 1); @@ -352,7 +364,7 @@ unsigned long flags; spin_lock_irqsave(&desc->lock, flags); - pending_irq_balance_apicid[irq]=cpu_to_logical_apicid(new_cpu); + pending_irq_balance_cpumask[irq] = 1 << new_cpu; spin_unlock_irqrestore(&desc->lock, flags); } } @@ -549,8 +561,7 @@ selected_irq, min_loaded); /* mark for change destination */ spin_lock_irqsave(&desc->lock, flags); - pending_irq_balance_apicid[selected_irq] = - cpu_to_logical_apicid(min_loaded); + pending_irq_balance_cpumask[selected_irq] = 1 << min_loaded; spin_unlock_irqrestore(&desc->lock, flags); /* Since we made a change, come back sooner to * check for more variation. @@ -582,7 +593,7 @@ /* push everything to CPU 0 to give us a starting point. */ for (i = 0 ; i < NR_IRQS ; i++) - pending_irq_balance_apicid[i] = cpu_to_logical_apicid(0); + pending_irq_balance_cpumask[i] = 1; repeat: set_current_state(TASK_INTERRUPTIBLE); @@ -659,9 +670,9 @@ static inline void move_irq(int irq) { /* note - we hold the desc->lock */ - if (unlikely(pending_irq_balance_apicid[irq])) { - set_ioapic_affinity(irq, pending_irq_balance_apicid[irq]); - pending_irq_balance_apicid[irq] = 0; + if (unlikely(pending_irq_balance_cpumask[irq])) { + set_ioapic_affinity(irq, pending_irq_balance_cpumask[irq]); + pending_irq_balance_cpumask[irq] = 0; } } diff -Nru a/arch/i386/kernel/ioport.c b/arch/i386/kernel/ioport.c --- a/arch/i386/kernel/ioport.c Sat May 24 12:48:24 2003 +++ b/arch/i386/kernel/ioport.c Sat May 24 12:48:24 2003 @@ -84,15 +84,17 @@ t->ts_io_bitmap = bitmap; } - tss = init_tss + get_cpu(); - if (bitmap) - tss->bitmap = IO_BITMAP_OFFSET; /* Activate it in the TSS */ - /* * do it in the per-thread copy and in the TSS ... */ set_bitmap(t->ts_io_bitmap, from, num, !turn_on); - set_bitmap(tss->io_bitmap, from, num, !turn_on); + tss = init_tss + get_cpu(); + if (tss->bitmap == IO_BITMAP_OFFSET) { /* already active? */ + set_bitmap(tss->io_bitmap, from, num, !turn_on); + } else { + memcpy(tss->io_bitmap, t->ts_io_bitmap, IO_BITMAP_BYTES); + tss->bitmap = IO_BITMAP_OFFSET; /* Activate it in the TSS */ + } put_cpu(); out: return ret; diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c --- a/arch/i386/kernel/irq.c Sat May 24 12:48:20 2003 +++ b/arch/i386/kernel/irq.c Sat May 24 12:48:20 2003 @@ -92,7 +92,7 @@ * each architecture has to answer this themselves, it doesn't deserve * a generic callback i think. */ -#if CONFIG_X86 +#ifdef CONFIG_X86 printk("unexpected IRQ trap at vector %02x\n", irq); #ifdef CONFIG_X86_LOCAL_APIC /* @@ -173,7 +173,7 @@ if (cpu_online(j)) seq_printf(p, "%10u ", nmi_count(j)); seq_putc(p, '\n'); -#if CONFIG_X86_LOCAL_APIC +#ifdef CONFIG_X86_LOCAL_APIC seq_printf(p, "LOC: "); for (j = 0; j < NR_CPUS; j++) if (cpu_online(j)) @@ -189,7 +189,7 @@ return 0; } -#if CONFIG_SMP +#ifdef CONFIG_SMP inline void synchronize_irq(unsigned int irq) { while (irq_desc[irq].status & IRQ_INPROGRESS) @@ -828,7 +828,7 @@ #define HEX_DIGITS 8 -static unsigned int parse_hex_value (const char *buffer, +static unsigned int parse_hex_value (const char __user *buffer, unsigned long count, unsigned long *ret) { unsigned char hexnum [HEX_DIGITS]; @@ -865,7 +865,7 @@ return 0; } -#if CONFIG_SMP +#ifdef CONFIG_SMP static struct proc_dir_entry * smp_affinity_entry [NR_IRQS]; @@ -878,7 +878,7 @@ return sprintf (page, "%08lx\n", irq_affinity[(long)data]); } -static int irq_affinity_write_proc (struct file *file, const char *buffer, +static int irq_affinity_write_proc (struct file *file, const char __user *buffer, unsigned long count, void *data) { int irq = (long) data, full_count = count, err; @@ -914,7 +914,7 @@ return sprintf (page, "%08lx\n", *mask); } -static int prof_cpu_mask_write_proc (struct file *file, const char *buffer, +static int prof_cpu_mask_write_proc (struct file *file, const char __user *buffer, unsigned long count, void *data) { unsigned long *mask = (unsigned long *) data, full_count = count, err; @@ -944,7 +944,7 @@ /* create /proc/irq/1234 */ irq_dir[irq] = proc_mkdir(name, root_irq_dir); -#if CONFIG_SMP +#ifdef CONFIG_SMP { struct proc_dir_entry *entry; diff -Nru a/arch/i386/kernel/ldt.c b/arch/i386/kernel/ldt.c --- a/arch/i386/kernel/ldt.c Sat May 24 12:48:28 2003 +++ b/arch/i386/kernel/ldt.c Sat May 24 12:48:29 2003 @@ -119,7 +119,7 @@ } } -static int read_ldt(void * ptr, unsigned long bytecount) +static int read_ldt(void __user * ptr, unsigned long bytecount) { int err; unsigned long size; @@ -148,7 +148,7 @@ return bytecount; } -static int read_default_ldt(void * ptr, unsigned long bytecount) +static int read_default_ldt(void __user * ptr, unsigned long bytecount) { int err; unsigned long size; @@ -167,7 +167,7 @@ return err; } -static int write_ldt(void * ptr, unsigned long bytecount, int oldmode) +static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode) { struct mm_struct * mm = current->mm; __u32 entry_1, entry_2, *lp; @@ -226,7 +226,7 @@ return error; } -asmlinkage int sys_modify_ldt(int func, void *ptr, unsigned long bytecount) +asmlinkage int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) { int ret = -ENOSYS; diff -Nru a/arch/i386/kernel/module.c b/arch/i386/kernel/module.c --- a/arch/i386/kernel/module.c Sat May 24 12:48:24 2003 +++ b/arch/i386/kernel/module.c Sat May 24 12:48:24 2003 @@ -123,3 +123,7 @@ } return 0; } + +void module_arch_cleanup(struct module *mod) +{ +} diff -Nru a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c --- a/arch/i386/kernel/mpparse.c Sat May 24 12:48:22 2003 +++ b/arch/i386/kernel/mpparse.c Sat May 24 12:48:22 2003 @@ -73,7 +73,9 @@ /* Bitmask of physically existing CPUs */ unsigned long phys_cpu_present_map; +#ifndef CONFIG_X86_GENERICARCH int x86_summit = 0; +#endif u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; /* @@ -1084,7 +1086,7 @@ /* * Parsing through the PCI Interrupt Routing Table (PRT) and program - * routing for all static (IOAPIC-direct) entries. + * routing for all entries. */ list_for_each(node, &acpi_prt.entries) { entry = list_entry(node, struct acpi_prt_entry, node); @@ -1098,6 +1100,10 @@ else irq = entry->link.index; + /* Don't set up the ACPI SCI because it's already set up */ + if (acpi_fadt.sci_int == irq) + continue; + ioapic = mp_find_ioapic(irq); if (ioapic < 0) continue; diff -Nru a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c --- a/arch/i386/kernel/msr.c Sat May 24 12:48:24 2003 +++ b/arch/i386/kernel/msr.c Sat May 24 12:48:24 2003 @@ -120,8 +120,6 @@ preempt_disable(); if ( cpu == smp_processor_id() ) { ret = wrmsr_eio(reg, eax, edx); - preempt_enable(); - return ret; } else { cmd.cpu = cpu; cmd.reg = reg; @@ -129,17 +127,20 @@ cmd.data[1] = edx; smp_call_function(msr_smp_wrmsr, &cmd, 1, 1); - preempt_enable(); - return cmd.err; + ret = cmd.err; } + preempt_enable(); + return ret; } static inline int do_rdmsr(int cpu, u32 reg, u32 *eax, u32 *edx) { struct msr_command cmd; + int ret; + preempt_disable(); if ( cpu == smp_processor_id() ) { - return rdmsr_eio(reg, eax, edx); + ret = rdmsr_eio(reg, eax, edx); } else { cmd.cpu = cpu; cmd.reg = reg; @@ -149,8 +150,10 @@ *eax = cmd.data[0]; *edx = cmd.data[1]; - return cmd.err; + ret = cmd.err; } + preempt_enable(); + return ret; } #else /* ! CONFIG_SMP */ diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c --- a/arch/i386/kernel/process.c Sat May 24 12:48:19 2003 +++ b/arch/i386/kernel/process.c Sat May 24 12:48:19 2003 @@ -212,7 +212,6 @@ */ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { - struct task_struct *p; struct pt_regs regs; memset(®s, 0, sizeof(regs)); @@ -228,8 +227,7 @@ regs.eflags = 0x286; /* Ok, create the new process.. */ - p = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); } /* @@ -518,27 +516,22 @@ asmlinkage int sys_fork(struct pt_regs regs) { - struct task_struct *p; - - p = do_fork(SIGCHLD, regs.esp, ®s, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(SIGCHLD, regs.esp, ®s, 0, NULL, NULL); } asmlinkage int sys_clone(struct pt_regs regs) { - struct task_struct *p; unsigned long clone_flags; unsigned long newsp; - int *parent_tidptr, *child_tidptr; + int __user *parent_tidptr, *child_tidptr; clone_flags = regs.ebx; newsp = regs.ecx; - parent_tidptr = (int *)regs.edx; - child_tidptr = (int *)regs.edi; + parent_tidptr = (int __user *)regs.edx; + child_tidptr = (int __user *)regs.edi; if (!newsp) newsp = regs.esp; - p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, parent_tidptr, child_tidptr); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, parent_tidptr, child_tidptr); } /* @@ -553,10 +546,7 @@ */ asmlinkage int sys_vfork(struct pt_regs regs) { - struct task_struct *p; - - p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 0, NULL, NULL); } /* diff -Nru a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c --- a/arch/i386/kernel/ptrace.c Sat May 24 12:48:22 2003 +++ b/arch/i386/kernel/ptrace.c Sat May 24 12:48:22 2003 @@ -155,7 +155,7 @@ */ static int ptrace_get_thread_area(struct task_struct *child, - int idx, struct user_desc *user_desc) + int idx, struct user_desc __user *user_desc) { struct user_desc info; struct desc_struct *desc; @@ -206,7 +206,7 @@ */ static int ptrace_set_thread_area(struct task_struct *child, - int idx, struct user_desc *user_desc) + int idx, struct user_desc __user *user_desc) { struct user_desc info; struct desc_struct *desc; @@ -458,7 +458,7 @@ ret = 0; if (!child->used_math) init_fpu(child); - get_fpregs((struct user_i387_struct *)data, child); + get_fpregs((struct user_i387_struct __user *)data, child); break; } @@ -469,7 +469,7 @@ break; } child->used_math = 1; - set_fpregs(child, (struct user_i387_struct *)data); + set_fpregs(child, (struct user_i387_struct __user *)data); ret = 0; break; } @@ -482,7 +482,7 @@ } if (!child->used_math) init_fpu(child); - ret = get_fpxregs((struct user_fxsr_struct *)data, child); + ret = get_fpxregs((struct user_fxsr_struct __user *)data, child); break; } @@ -493,18 +493,18 @@ break; } child->used_math = 1; - ret = set_fpxregs(child, (struct user_fxsr_struct *)data); + ret = set_fpxregs(child, (struct user_fxsr_struct __user *)data); break; } case PTRACE_GET_THREAD_AREA: ret = ptrace_get_thread_area(child, - addr, (struct user_desc *) data); + addr, (struct user_desc __user *) data); break; case PTRACE_SET_THREAD_AREA: ret = ptrace_set_thread_area(child, - addr, (struct user_desc *) data); + addr, (struct user_desc __user *) data); break; default: diff -Nru a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c --- a/arch/i386/kernel/reboot.c Sat May 24 12:48:22 2003 +++ b/arch/i386/kernel/reboot.c Sat May 24 12:48:22 2003 @@ -215,7 +215,7 @@ void machine_restart(char * __unused) { -#if CONFIG_SMP +#ifdef CONFIG_SMP int cpuid; cpuid = GET_APIC_ID(apic_read(APIC_ID)); diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c --- a/arch/i386/kernel/setup.c Sat May 24 12:48:24 2003 +++ b/arch/i386/kernel/setup.c Sat May 24 12:48:24 2003 @@ -91,6 +91,7 @@ extern void early_cpu_init(void); extern void dmi_scan_machine(void); +extern void generic_apic_probe(char *); extern int root_mountflags; extern char _text, _etext, _edata, _end; extern int blk_nohighio; @@ -596,7 +597,7 @@ } else { if (highmem_pages == -1) highmem_pages = 0; -#if CONFIG_HIGHMEM +#ifdef CONFIG_HIGHMEM if (highmem_pages >= max_pfn) { printk(KERN_ERR "highmem size specified (%uMB) is bigger than pages available (%luMB)!.\n", pages_to_mb(highmem_pages), pages_to_mb(max_pfn)); highmem_pages = 0; @@ -798,13 +799,13 @@ /* Use inline assembly to define this because the nops are defined as inline assembly strings in the include files and we cannot get them easily into strings. */ -asm("intelnops: " +asm("\t.data\nintelnops: " GENERIC_NOP1 GENERIC_NOP2 GENERIC_NOP3 GENERIC_NOP4 GENERIC_NOP5 GENERIC_NOP6 GENERIC_NOP7 GENERIC_NOP8); -asm("k8nops: " +asm("\t.data\nk8nops: " K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6 K8_NOP7 K8_NOP8); -asm("k7nops: " +asm("\t.data\nk7nops: " K7_NOP1 K7_NOP2 K7_NOP3 K7_NOP4 K7_NOP5 K7_NOP6 K7_NOP7 K7_NOP8); @@ -959,6 +960,13 @@ smp_alloc_memory(); /* AP processor realmode stacks in low memory*/ #endif paging_init(); + + dmi_scan_machine(); + +#ifdef CONFIG_X86_GENERICARCH + generic_apic_probe(*cmdline_p); +#endif + #ifdef CONFIG_ACPI_BOOT /* * Parse the ACPI tables for possible boot-time SMP configuration. @@ -980,7 +988,6 @@ conswitchp = &dummy_con; #endif #endif - dmi_scan_machine(); } static int __init highio_setup(char *str) diff -Nru a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c --- a/arch/i386/kernel/signal.c Sat May 24 12:48:24 2003 +++ b/arch/i386/kernel/signal.c Sat May 24 12:48:24 2003 @@ -116,7 +116,7 @@ } asmlinkage int -sys_sigaltstack(const stack_t *uss, stack_t *uoss) +sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) { struct pt_regs *regs = (struct pt_regs *) &uss; return do_sigaltstack(uss, uoss, regs->esp); @@ -244,6 +244,11 @@ goto badframe; /* It is more difficult to avoid calling this function than to call it and ignore errors. */ + /* + * THIS CANNOT WORK! "&st" is a kernel address, and "do_sigaltstack()" + * takes a user address (and verifies that it is a user address). End + * result: it does exactly _nothing_. + */ do_sigaltstack(&st, NULL, regs->esp); return eax; diff -Nru a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c --- a/arch/i386/kernel/smp.c Sat May 24 12:48:20 2003 +++ b/arch/i386/kernel/smp.c Sat May 24 12:48:20 2003 @@ -123,7 +123,7 @@ return SET_APIC_DEST_FIELD(mask); } -static inline void __send_IPI_shortcut(unsigned int shortcut, int vector) +inline void __send_IPI_shortcut(unsigned int shortcut, int vector) { /* * Subtle. In the case of the 'never do double writes' workaround @@ -155,7 +155,7 @@ __send_IPI_shortcut(APIC_DEST_SELF, vector); } -static inline void send_IPI_mask_bitmask(int mask, int vector) +inline void send_IPI_mask_bitmask(int mask, int vector) { unsigned long cfg; unsigned long flags; @@ -186,7 +186,7 @@ local_irq_restore(flags); } -static inline void send_IPI_mask_sequence(int mask, int vector) +inline void send_IPI_mask_sequence(int mask, int vector) { unsigned long cfg, flags; unsigned int query_cpu, query_mask; diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c --- a/arch/i386/kernel/smpboot.c Sat May 24 12:48:24 2003 +++ b/arch/i386/kernel/smpboot.c Sat May 24 12:48:24 2003 @@ -493,7 +493,7 @@ * don't care about the eip and regs settings since * we'll never reschedule the forked task. */ - return do_fork(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); + return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); } #ifdef CONFIG_NUMA @@ -793,6 +793,7 @@ idle = fork_by_hand(); if (IS_ERR(idle)) panic("failed fork for CPU %d", cpu); + wake_up_forked_process(idle); /* * We remove it from the pidhash and the runqueue @@ -935,7 +936,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus) { - int apicid, cpu, bit; + int apicid, cpu, bit, kicked; /* * Setup boot CPU information @@ -1018,7 +1019,8 @@ */ Dprintk("CPU present map: %lx\n", phys_cpu_present_map); - for (bit = 0; bit < NR_CPUS; bit++) { + kicked = 1; + for (bit = 0; kicked < NR_CPUS && bit < BITS_PER_LONG; bit++) { apicid = cpu_present_to_apicid(bit); /* * Don't even attempt to start the boot CPU! @@ -1034,6 +1036,8 @@ if (do_boot_cpu(apicid)) printk("CPU #%d not responding - cannot use it.\n", apicid); + else + ++kicked; } /* @@ -1149,11 +1153,13 @@ void __init smp_cpus_done(unsigned int max_cpus) { +#ifdef CONFIG_X86_IO_APIC setup_ioapic_dest(TARGET_CPUS); +#endif zap_low_mappings(); } -void __init smp_intr_init() +void __init smp_intr_init(void) { /* * IRQ0 must be given a fixed assignment and initialized, diff -Nru a/arch/i386/kernel/suspend.c b/arch/i386/kernel/suspend.c --- a/arch/i386/kernel/suspend.c Sat May 24 12:48:30 2003 +++ b/arch/i386/kernel/suspend.c Sat May 24 12:48:30 2003 @@ -27,9 +27,7 @@ #include static struct saved_context saved_context; -unsigned long saved_context_eax, saved_context_ebx, saved_context_ecx, saved_context_edx; -unsigned long saved_context_esp, saved_context_ebp, saved_context_esi, saved_context_edi; -unsigned long saved_context_eflags; +static void fix_processor_context(void); extern void enable_sep_cpu(void *); @@ -107,7 +105,7 @@ do_fpu_end(); } -void fix_processor_context(void) +static void fix_processor_context(void) { int cpu = smp_processor_id(); struct tss_struct * t = init_tss + cpu; @@ -132,3 +130,6 @@ } } + +EXPORT_SYMBOL(save_processor_state); +EXPORT_SYMBOL(restore_processor_state); diff -Nru a/arch/i386/kernel/suspend_asm.S b/arch/i386/kernel/suspend_asm.S --- a/arch/i386/kernel/suspend_asm.S Sat May 24 12:48:23 2003 +++ b/arch/i386/kernel/suspend_asm.S Sat May 24 12:48:23 2003 @@ -6,6 +6,34 @@ #include #include + .data + .align 4 + .globl saved_context_eax, saved_context_ebx + .globl saved_context_ecx, saved_context_edx + .globl saved_context_esp, saved_context_ebp + .globl saved_context_esi, saved_context_edi + .globl saved_context_eflags +saved_context_eax: + .long 0 +saved_context_ebx: + .long 0 +saved_context_ecx: + .long 0 +saved_context_edx: + .long 0 +saved_context_esp: + .long 0 +saved_context_ebp: + .long 0 +saved_context_esi: + .long 0 +saved_context_edi: + .long 0 +saved_context_eflags: + .long 0 + + .text + ENTRY(do_magic) pushl %ebx cmpl $0,8(%esp) diff -Nru a/arch/i386/kernel/sys_i386.c b/arch/i386/kernel/sys_i386.c --- a/arch/i386/kernel/sys_i386.c Sat May 24 12:48:32 2003 +++ b/arch/i386/kernel/sys_i386.c Sat May 24 12:48:32 2003 @@ -26,7 +26,7 @@ * sys_pipe() is the normal C calling standard for creating * a pipe. It's not the way Unix traditionally does this, though. */ -asmlinkage int sys_pipe(unsigned long * fildes) +asmlinkage int sys_pipe(unsigned long __user * fildes) { int fd[2]; int error; @@ -88,7 +88,7 @@ unsigned long offset; }; -asmlinkage int old_mmap(struct mmap_arg_struct *arg) +asmlinkage int old_mmap(struct mmap_arg_struct __user *arg) { struct mmap_arg_struct a; int err = -EFAULT; @@ -106,15 +106,15 @@ } -extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); +extern asmlinkage int sys_select(int, fd_set __user *, fd_set __user *, fd_set __user *, struct timeval __user *); struct sel_arg_struct { unsigned long n; - fd_set *inp, *outp, *exp; - struct timeval *tvp; + fd_set __user *inp, *outp, *exp; + struct timeval __user *tvp; }; -asmlinkage int old_select(struct sel_arg_struct *arg) +asmlinkage int old_select(struct sel_arg_struct __user *arg) { struct sel_arg_struct a; @@ -130,7 +130,7 @@ * This is really horribly ugly. */ asmlinkage int sys_ipc (uint call, int first, int second, - int third, void *ptr, long fifth) + int third, void __user *ptr, long fifth) { int version, ret; @@ -139,10 +139,10 @@ switch (call) { case SEMOP: - return sys_semtimedop (first, (struct sembuf *)ptr, second, NULL); + return sys_semtimedop (first, (struct sembuf __user *)ptr, second, NULL); case SEMTIMEDOP: - return sys_semtimedop(first, (struct sembuf *)ptr, second, - (const struct timespec *)fifth); + return sys_semtimedop(first, (struct sembuf __user *)ptr, second, + (const struct timespec __user *)fifth); case SEMGET: return sys_semget (first, second, third); @@ -150,13 +150,13 @@ union semun fourth; if (!ptr) return -EINVAL; - if (get_user(fourth.__pad, (void **) ptr)) + if (get_user(fourth.__pad, (void * __user *) ptr)) return -EFAULT; return sys_semctl (first, second, third, fourth); } case MSGSND: - return sys_msgsnd (first, (struct msgbuf *) ptr, + return sys_msgsnd (first, (struct msgbuf __user *) ptr, second, third); case MSGRCV: switch (version) { @@ -166,7 +166,7 @@ return -EINVAL; if (copy_from_user(&tmp, - (struct ipc_kludge *) ptr, + (struct ipc_kludge __user *) ptr, sizeof (tmp))) return -EFAULT; return sys_msgrcv (first, tmp.msgp, second, @@ -174,35 +174,36 @@ } default: return sys_msgrcv (first, - (struct msgbuf *) ptr, + (struct msgbuf __user *) ptr, second, fifth, third); } case MSGGET: return sys_msgget ((key_t) first, second); case MSGCTL: - return sys_msgctl (first, second, (struct msqid_ds *) ptr); + return sys_msgctl (first, second, (struct msqid_ds __user *) ptr); case SHMAT: switch (version) { default: { ulong raddr; - ret = sys_shmat (first, (char *) ptr, second, &raddr); + ret = sys_shmat (first, (char __user *) ptr, second, &raddr); if (ret) return ret; - return put_user (raddr, (ulong *) third); + return put_user (raddr, (ulong __user *) third); } case 1: /* iBCS2 emulator entry point */ if (!segment_eq(get_fs(), get_ds())) return -EINVAL; - return sys_shmat (first, (char *) ptr, second, (ulong *) third); + /* The "(ulong *) third" is valid _only_ because of the kernel segment thing */ + return sys_shmat (first, (char __user *) ptr, second, (ulong *) third); } case SHMDT: - return sys_shmdt ((char *)ptr); + return sys_shmdt ((char __user *)ptr); case SHMGET: return sys_shmget (first, second, third); case SHMCTL: return sys_shmctl (first, second, - (struct shmid_ds *) ptr); + (struct shmid_ds __user *) ptr); default: return -ENOSYS; } @@ -211,7 +212,7 @@ /* * Old cruft */ -asmlinkage int sys_uname(struct old_utsname * name) +asmlinkage int sys_uname(struct old_utsname __user * name) { int err; if (!name) @@ -222,7 +223,7 @@ return err?-EFAULT:0; } -asmlinkage int sys_olduname(struct oldold_utsname * name) +asmlinkage int sys_olduname(struct oldold_utsname __user * name) { int error; diff -Nru a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c --- a/arch/i386/kernel/sysenter.c Sat May 24 12:48:33 2003 +++ b/arch/i386/kernel/sysenter.c Sat May 24 12:48:33 2003 @@ -21,21 +21,6 @@ extern asmlinkage void sysenter_entry(void); -/* - * Create a per-cpu fake "SEP thread" stack, so that we can - * enter the kernel without having to worry about things like - * "current" etc not working (debug traps and NMI's can happen - * before we can switch over to the "real" thread). - * - * Return the resulting fake stack pointer. - */ -struct fake_sep_struct { - struct thread_info thread; - struct task_struct task; - unsigned char trampoline[32] __attribute__((aligned(1024))); - unsigned char stack[0]; -} __attribute__((aligned(8192))); - void enable_sep_cpu(void *info) { int cpu = get_cpu(); diff -Nru a/arch/i386/kernel/timers/Makefile b/arch/i386/kernel/timers/Makefile --- a/arch/i386/kernel/timers/Makefile Sat May 24 12:48:19 2003 +++ b/arch/i386/kernel/timers/Makefile Sat May 24 12:48:19 2003 @@ -4,4 +4,4 @@ obj-y := timer.o timer_none.o timer_tsc.o timer_pit.o -obj-$(CONFIG_X86_SUMMIT) += timer_cyclone.o +obj-$(CONFIG_X86_CYCLONE_TIMER) += timer_cyclone.o diff -Nru a/arch/i386/kernel/timers/timer.c b/arch/i386/kernel/timers/timer.c --- a/arch/i386/kernel/timers/timer.c Sat May 24 12:48:32 2003 +++ b/arch/i386/kernel/timers/timer.c Sat May 24 12:48:32 2003 @@ -6,12 +6,12 @@ /* list of externed timers */ extern struct timer_opts timer_pit; extern struct timer_opts timer_tsc; -#ifdef CONFIG_X86_SUMMIT +#ifdef CONFIG_X86_CYCLONE_TIMER extern struct timer_opts timer_cyclone; #endif /* list of timers, ordered by preference, NULL terminated */ static struct timer_opts* timers[] = { -#ifdef CONFIG_X86_SUMMIT +#ifdef CONFIG_X86_CYCLONE_TIMER &timer_cyclone, #endif &timer_tsc, diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c --- a/arch/i386/kernel/traps.c Sat May 24 12:48:21 2003 +++ b/arch/i386/kernel/traps.c Sat May 24 12:48:21 2003 @@ -101,7 +101,7 @@ stack = (unsigned long*)&stack; printk("Call Trace:"); -#if CONFIG_KALLSYMS +#ifdef CONFIG_KALLSYMS printk("\n"); #endif i = 1; @@ -438,7 +438,7 @@ unsigned char reason = get_nmi_reason(); if (!(reason & 0xc0)) { -#if CONFIG_X86_LOCAL_APIC +#ifdef CONFIG_X86_LOCAL_APIC /* * Ok, so this is none of the documented NMI sources, * so it must be the NMI watchdog. diff -Nru a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c --- a/arch/i386/kernel/vm86.c Sat May 24 12:48:20 2003 +++ b/arch/i386/kernel/vm86.c Sat May 24 12:48:20 2003 @@ -170,7 +170,7 @@ static int do_vm86_irq_handling(int subfunction, int irqnumber); static void do_sys_vm86(struct kernel_vm86_struct *info, struct task_struct *tsk); -asmlinkage int sys_vm86old(struct vm86_struct * v86) +asmlinkage int sys_vm86old(struct vm86_struct __user * v86) { struct kernel_vm86_struct info; /* declare this _on top_, * this avoids wasting of stack space. @@ -199,7 +199,7 @@ } -asmlinkage int sys_vm86(unsigned long subfunction, struct vm86plus_struct * v86) +asmlinkage int sys_vm86(unsigned long subfunction, struct vm86plus_struct __user * v86) { struct kernel_vm86_struct info; /* declare this _on top_, * this avoids wasting of stack space. @@ -239,7 +239,7 @@ goto out; info.regs32 = (struct pt_regs *) &subfunction; info.vm86plus.is_vm86pus = 1; - tsk->thread.vm86_info = (struct vm86_struct *)v86; + tsk->thread.vm86_info = (struct vm86_struct __user *)v86; do_sys_vm86(&info, tsk); ret = 0; /* we never return here */ out: diff -Nru a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c --- a/arch/i386/lib/usercopy.c Sat May 24 12:48:19 2003 +++ b/arch/i386/lib/usercopy.c Sat May 24 12:48:19 2003 @@ -6,17 +6,22 @@ * Copyright 1997 Linus Torvalds */ #include +#include +#include +#include #include #include -static inline int movsl_is_ok(const void *a1, const void *a2, unsigned long n) +static inline int __movsl_is_ok(unsigned long a1, unsigned long a2, unsigned long n) { #ifdef CONFIG_X86_INTEL_USERCOPY - if (n >= 64 && (((const long)a1 ^ (const long)a2) & movsl_mask.mask)) + if (n >= 64 && ((a1 ^ a2) & movsl_mask.mask)) return 0; #endif return 1; } +#define movsl_is_ok(a1,a2,n) \ + __movsl_is_ok((unsigned long)(a1),(unsigned long)(a2),(n)) /* * Copy a null terminated string from userspace. @@ -71,7 +76,7 @@ * and returns @count. */ long -__strncpy_from_user(char *dst, const char *src, long count) +__strncpy_from_user(char *dst, const char __user *src, long count) { long res; __do_strncpy_from_user(dst, src, count, res); @@ -97,7 +102,7 @@ * and returns @count. */ long -strncpy_from_user(char *dst, const char *src, long count) +strncpy_from_user(char *dst, const char __user *src, long count) { long res = -EFAULT; if (access_ok(VERIFY_READ, src, 1)) @@ -142,7 +147,7 @@ * On success, this will be zero. */ unsigned long -clear_user(void *to, unsigned long n) +clear_user(void __user *to, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) __do_clear_user(to, n); @@ -161,7 +166,7 @@ * On success, this will be zero. */ unsigned long -__clear_user(void *to, unsigned long n) +__clear_user(void __user *to, unsigned long n) { __do_clear_user(to, n); return n; @@ -178,7 +183,7 @@ * On exception, returns 0. * If the string is too long, returns a value greater than @n. */ -long strnlen_user(const char *s, long n) +long strnlen_user(const char __user *s, long n) { unsigned long mask = -__addr_ok(s); unsigned long res, tmp; @@ -481,20 +486,67 @@ } while (0) -unsigned long __copy_to_user_ll(void *to, const void *from, unsigned long n) +unsigned long __copy_to_user_ll(void __user *to, const void *from, unsigned long n) { +#ifndef CONFIG_X86_WP_WORKS_OK + if (unlikely(boot_cpu_data.wp_works_ok == 0) && + ((unsigned long )to) < TASK_SIZE) { + /* + * CPU does not honor the WP bit when writing + * from supervisory mode, and due to preemption or SMP, + * the page tables can change at any time. + * Do it manually. Manfred + */ + while (n) { + unsigned long offset = ((unsigned long)to)%PAGE_SIZE; + unsigned long len = PAGE_SIZE - offset; + int retval; + struct page *pg; + void *maddr; + + if (len > n) + len = n; + +survive: + down_read(¤t->mm->mmap_sem); + retval = get_user_pages(current, current->mm, + (unsigned long )to, 1, 1, 0, &pg, NULL); + + if (retval == -ENOMEM && current->pid == 1) { + up_read(¤t->mm->mmap_sem); + blk_congestion_wait(WRITE, HZ/50); + goto survive; + } + + if (retval != 1) + break; + + maddr = kmap_atomic(pg, KM_USER0); + memcpy(maddr + offset, from, len); + kunmap_atomic(maddr, KM_USER0); + set_page_dirty_lock(pg); + put_page(pg); + up_read(¤t->mm->mmap_sem); + + from += len; + to += len; + n -= len; + } + return n; + } +#endif if (movsl_is_ok(to, from, n)) - __copy_user(to, from, n); + __copy_user((void *)to, from, n); else - n = __copy_user_intel(to, from, n); + n = __copy_user_intel((void *)to, from, n); return n; } -unsigned long __copy_from_user_ll(void *to, const void *from, unsigned long n) +unsigned long __copy_from_user_ll(void *to, const void __user *from, unsigned long n) { if (movsl_is_ok(to, from, n)) - __copy_user_zeroing(to, from, n); + __copy_user_zeroing(to, (const void *) from, n); else - n = __copy_user_zeroing_intel(to, from, n); + n = __copy_user_zeroing_intel(to, (const void *) from, n); return n; } diff -Nru a/arch/i386/mach-generic/Makefile b/arch/i386/mach-generic/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/mach-generic/Makefile Sat May 24 12:48:34 2003 @@ -0,0 +1,18 @@ +# +# Makefile for the generic architecture +# + +EXTRA_CFLAGS += -I../kernel + +obj-y := probe.o summit.o bigsmp.o default.o + + +# +# Makefile for the generic architecture +# + +EXTRA_CFLAGS += -I../kernel + +obj-y := probe.o summit.o bigsmp.o default.o + + diff -Nru a/arch/i386/mach-generic/bigsmp.c b/arch/i386/mach-generic/bigsmp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/mach-generic/bigsmp.c Sat May 24 12:48:34 2003 @@ -0,0 +1,23 @@ +/* + * APIC driver for "bigsmp" XAPIC machines with more than 8 virtual CPUs. + * Drives the local APIC in "clustered mode". + */ +#define APIC_DEFINITION 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int dmi_bigsmp; /* can be set by dmi scanners */ + +static __init int probe_bigsmp(void) +{ + return dmi_bigsmp; +} + +struct genapic apic_bigsmp = APIC_INIT("bigsmp", probe_bigsmp); diff -Nru a/arch/i386/mach-generic/default.c b/arch/i386/mach-generic/default.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/mach-generic/default.c Sat May 24 12:48:34 2003 @@ -0,0 +1,22 @@ +/* + * Default generic APIC driver. This handles upto 8 CPUs. + */ +#define APIC_DEFINITION 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* should be called last. */ +static __init int probe_default(void) +{ + return 1; +} + +struct genapic apic_default = APIC_INIT("default", probe_default); diff -Nru a/arch/i386/mach-generic/probe.c b/arch/i386/mach-generic/probe.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/mach-generic/probe.c Sat May 24 12:48:34 2003 @@ -0,0 +1,96 @@ +/* Copyright 2003 Andi Kleen, SuSE Labs. + * Subject to the GNU Public License, v.2 + * + * Generic x86 APIC driver probe layer. + */ +#include +#include +#include +#include +#include +#include +#include + +extern struct genapic apic_summit; +extern struct genapic apic_bigsmp; +extern struct genapic apic_default; + +struct genapic *genapic = &apic_default; + +struct genapic *apic_probe[] __initdata = { + &apic_summit, + &apic_bigsmp, + &apic_default, /* must be last */ + NULL, +}; + +void __init generic_apic_probe(char *command_line) +{ + char *s; + int i; + int changed = 0; + + s = strstr(command_line, "apic="); + if (s && (s == command_line || isspace(s[-1]))) { + char *p = strchr(s, ' '), old; + if (!p) + p = strchr(s, '\0'); + old = *p; + *p = 0; + for (i = 0; !changed && apic_probe[i]; i++) { + if (!strcmp(apic_probe[i]->name, s+5)) { + changed = 1; + genapic = apic_probe[i]; + } + } + if (!changed) + printk(KERN_ERR "Unknown genapic `%s' specified.\n", s); + *p = old; + } + for (i = 0; !changed && apic_probe[i]; i++) { + if (apic_probe[i]->probe()) { + changed = 1; + genapic = apic_probe[i]; + } + } + /* Not visible without early console */ + if (!changed) + panic("Didn't find an APIC driver"); + + printk(KERN_INFO "Using APIC driver %s\n", genapic->name); +} + +/* These functions can switch the APIC even after the initial ->probe() */ + +int __init mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid) +{ + int i; + for (i = 0; apic_probe[i]; ++i) { + if (apic_probe[i]->mps_oem_check(mpc,oem,productid)) { + genapic = apic_probe[i]; + printk(KERN_INFO "Switched to APIC driver `%s'.\n", + genapic->name); + return 1; + } + } + return 0; +} + +int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + int i; + for (i = 0; apic_probe[i]; ++i) { + if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) { + genapic = apic_probe[i]; + printk(KERN_INFO "Switched to APIC driver `%s'.\n", + genapic->name); + return 1; + } + } + return 0; +} + +int hard_smp_processor_id(void) +{ + return genapic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID)); +} diff -Nru a/arch/i386/mach-generic/summit.c b/arch/i386/mach-generic/summit.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/mach-generic/summit.c Sat May 24 12:48:34 2003 @@ -0,0 +1,22 @@ +/* + * APIC driver for the IBM "Summit" chipset. + */ +#define APIC_DEFINITION 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static __init int probe_summit(void) +{ + /* probed later in mptable/ACPI hooks */ + return 0; +} + +struct genapic apic_summit = APIC_INIT("summit", probe_summit); diff -Nru a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c --- a/arch/i386/mach-voyager/voyager_smp.c Sat May 24 12:48:23 2003 +++ b/arch/i386/mach-voyager/voyager_smp.c Sat May 24 12:48:23 2003 @@ -247,7 +247,7 @@ /* This is for the new dynamic CPU boot code */ volatile unsigned long cpu_callin_map = 0; -unsigned long cpu_callout_map = 0; +volatile unsigned long cpu_callout_map = 0; /* The per processor IRQ masks (these are usually kept in sync) */ static __u16 vic_irq_mask[NR_CPUS] __cacheline_aligned; @@ -531,7 +531,7 @@ struct pt_regs regs; /* don't care about the eip and regs settings since we'll * never reschedule the forked task. */ - return do_fork(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); + return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); } @@ -592,6 +592,8 @@ idle = fork_by_hand(); if(IS_ERR(idle)) panic("failed fork for CPU%d", cpu); + + wake_up_forked_process(idle); init_idle(idle, cpu); diff -Nru a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c --- a/arch/i386/mm/fault.c Sat May 24 12:48:19 2003 +++ b/arch/i386/mm/fault.c Sat May 24 12:48:19 2003 @@ -29,87 +29,6 @@ extern void die(const char *,struct pt_regs *,long); -#ifndef CONFIG_X86_WP_WORKS_OK -/* - * Ugly, ugly, but the goto's result in better assembly.. - */ -int __verify_write(const void * addr, unsigned long size) -{ - struct mm_struct *mm = current->mm; - struct vm_area_struct * vma; - unsigned long start = (unsigned long) addr; - - if (!size || segment_eq(get_fs(),KERNEL_DS)) - return 1; - - down_read(&mm->mmap_sem); - vma = find_vma(current->mm, start); - if (!vma) - goto bad_area; - if (vma->vm_start > start) - goto check_stack; - -good_area: - if (!(vma->vm_flags & VM_WRITE)) - goto bad_area; - size--; - size += start & ~PAGE_MASK; - size >>= PAGE_SHIFT; - start &= PAGE_MASK; - - for (;;) { - survive: - switch (handle_mm_fault(current->mm, vma, start, 1)) { - case VM_FAULT_SIGBUS: - goto bad_area; - case VM_FAULT_OOM: - goto out_of_memory; - case VM_FAULT_MINOR: - case VM_FAULT_MAJOR: - break; - default: - BUG(); - } - if (!size) - break; - size--; - start += PAGE_SIZE; - if (start < vma->vm_end) - continue; - vma = vma->vm_next; - if (!vma || vma->vm_start != start) - goto bad_area; - if (!(vma->vm_flags & VM_WRITE)) - goto bad_area;; - } - /* - * We really need to hold mmap_sem over the whole access to - * userspace, else another thread could change permissions. - * This is unfixable, so don't use i386-class machines for - * critical servers. - */ - up_read(&mm->mmap_sem); - return 1; - -check_stack: - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; - if (expand_stack(vma, start) == 0) - goto good_area; - -bad_area: - up_read(&mm->mmap_sem); - return 0; - -out_of_memory: - if (current->pid == 1) { - yield(); - goto survive; - } - goto bad_area; -} -#endif - /* * Unlock any spinlocks which will prevent us from getting the * message out @@ -405,8 +324,12 @@ if (!pgd_present(*pgd_k)) goto no_context; - set_pgd(pgd, *pgd_k); - + + /* + * set_pgd(pgd, *pgd_k); here would be useless on PAE + * and redundant with the set_pmd() on non-PAE. + */ + pmd = pmd_offset(pgd, address); pmd_k = pmd_offset(pgd_k, address); if (!pmd_present(*pmd_k)) diff -Nru a/arch/i386/mm/highmem.c b/arch/i386/mm/highmem.c --- a/arch/i386/mm/highmem.c Sat May 24 12:48:25 2003 +++ b/arch/i386/mm/highmem.c Sat May 24 12:48:25 2003 @@ -36,7 +36,7 @@ idx = type + KM_TYPE_NR*smp_processor_id(); vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); -#if CONFIG_DEBUG_HIGHMEM +#ifdef CONFIG_DEBUG_HIGHMEM if (!pte_none(*(kmap_pte-idx))) BUG(); #endif @@ -48,7 +48,7 @@ void kunmap_atomic(void *kvaddr, enum km_type type) { -#if CONFIG_DEBUG_HIGHMEM +#ifdef CONFIG_DEBUG_HIGHMEM unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); diff -Nru a/arch/i386/mm/hugetlbpage.c b/arch/i386/mm/hugetlbpage.c --- a/arch/i386/mm/hugetlbpage.c Sat May 24 12:48:31 2003 +++ b/arch/i386/mm/hugetlbpage.c Sat May 24 12:48:31 2003 @@ -20,8 +20,6 @@ #include #include -#include - static long htlbpagemem; int htlbpage_max; static long htlbzone_pages; @@ -398,8 +396,6 @@ { int lcount; struct page *page; - extern long htlbzone_pages; - extern struct list_head htlbpage_freelist; if (count < 0) lcount = count; diff -Nru a/arch/i386/mm/init.c b/arch/i386/mm/init.c --- a/arch/i386/mm/init.c Sat May 24 12:48:30 2003 +++ b/arch/i386/mm/init.c Sat May 24 12:48:30 2003 @@ -55,7 +55,7 @@ { pmd_t *pmd_table; -#if CONFIG_X86_PAE +#ifdef CONFIG_X86_PAE pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT)); if (pmd_table != pmd_offset(pgd, 0)) @@ -188,7 +188,7 @@ return 0; } -#if CONFIG_HIGHMEM +#ifdef CONFIG_HIGHMEM pte_t *kmap_pte; pgprot_t kmap_prot; @@ -265,7 +265,7 @@ unsigned long vaddr; pgd_t *pgd_base = swapper_pg_dir; -#if CONFIG_X86_PAE +#ifdef CONFIG_X86_PAE int i; /* Init entries of the first-level page table to the zero page */ for (i = 0; i < PTRS_PER_PGD; i++) @@ -295,7 +295,7 @@ permanent_kmaps_init(pgd_base); -#if CONFIG_X86_PAE +#ifdef CONFIG_X86_PAE /* * Add low memory identity-mappings - SMP needs it when * starting up on an AP from real-mode. In the non-PAE @@ -317,7 +317,7 @@ * us, because pgd_clear() is a no-op on i386. */ for (i = 0; i < USER_PTRS_PER_PGD; i++) -#if CONFIG_X86_PAE +#ifdef CONFIG_X86_PAE set_pgd(swapper_pg_dir+i, __pgd(1 + __pa(empty_zero_page))); #else set_pgd(swapper_pg_dir+i, __pgd(0)); @@ -363,7 +363,7 @@ load_cr3(swapper_pg_dir); -#if CONFIG_X86_PAE +#ifdef CONFIG_X86_PAE /* * We will bail out later - printk doesn't work right now so * the user would just see a hanging kernel. @@ -487,7 +487,7 @@ (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)) ); -#if CONFIG_X86_PAE +#ifdef CONFIG_X86_PAE if (!cpu_has_pae) panic("cannot execute a PAE-enabled kernel on a PAE-less CPU!"); #endif @@ -505,7 +505,7 @@ #endif } -#if CONFIG_X86_PAE +#ifdef CONFIG_X86_PAE struct kmem_cache_s *pae_pgd_cachep; void __init pgtable_cache_init(void) diff -Nru a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c --- a/arch/i386/mm/ioremap.c Sat May 24 12:48:22 2003 +++ b/arch/i386/mm/ioremap.c Sat May 24 12:48:22 2003 @@ -222,7 +222,6 @@ return; } - unmap_vm_area(p); if (p->flags && p->phys_addr < virt_to_phys(high_memory)) { change_page_attr(virt_to_page(__va(p->phys_addr)), p->size >> PAGE_SHIFT, diff -Nru a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c --- a/arch/i386/mm/pgtable.c Sat May 24 12:48:33 2003 +++ b/arch/i386/mm/pgtable.c Sat May 24 12:48:33 2003 @@ -141,7 +141,7 @@ { struct page *pte; -#if CONFIG_HIGHPTE +#ifdef CONFIG_HIGHPTE pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT, 0); #else pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT, 0); @@ -151,7 +151,7 @@ return pte; } -#if CONFIG_X86_PAE +#ifdef CONFIG_X86_PAE pgd_t *pgd_alloc(struct mm_struct *mm) { diff -Nru a/arch/i386/oprofile/init.c b/arch/i386/oprofile/init.c --- a/arch/i386/oprofile/init.c Sat May 24 12:48:25 2003 +++ b/arch/i386/oprofile/init.c Sat May 24 12:48:25 2003 @@ -9,6 +9,7 @@ #include #include +#include /* We support CPUs that have performance counters like the Pentium Pro * with the NMI mode driver. diff -Nru a/arch/i386/vmlinux.lds.S b/arch/i386/vmlinux.lds.S --- a/arch/i386/vmlinux.lds.S Sat May 24 12:48:21 2003 +++ b/arch/i386/vmlinux.lds.S Sat May 24 12:48:21 2003 @@ -85,7 +85,11 @@ __alt_instructions = .; .altinstructions : { *(.altinstructions) } __alt_instructions_end = .; - .altinstr_replacement : { *(.altinstr_replacement) } + .altinstr_replacement : { *(.altinstr_replacement) } + /* .exit.text is discard at runtime, not link time, to deal with references + from .altinstructions and .eh_frame */ + .exit.text : { *(.exit.text) } + .exit.data : { *(.exit.data) } . = ALIGN(4096); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } @@ -106,8 +110,6 @@ /* Sections to be discarded */ /DISCARD/ : { - *(.exit.text) - *(.exit.data) *(.exitcall.exit) } diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig --- a/arch/ia64/Kconfig Sat May 24 12:48:32 2003 +++ b/arch/ia64/Kconfig Sat May 24 12:48:32 2003 @@ -381,6 +381,10 @@ depends on MCKINLEY bool "4GB" +config HUGETLB_PAGE_SIZE_1GB + depends on MCKINLEY + bool "1GB" + config HUGETLB_PAGE_SIZE_256MB bool "256MB" diff -Nru a/arch/ia64/Makefile b/arch/ia64/Makefile --- a/arch/ia64/Makefile Sat May 24 12:48:19 2003 +++ b/arch/ia64/Makefile Sat May 24 12:48:19 2003 @@ -23,6 +23,7 @@ CFLAGS_KERNEL := -mconstant-gp GCC_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.') +GCC_MINOR_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f2 -d'.') GAS_STATUS=$(shell arch/ia64/scripts/check-gas $(CC) $(OBJDUMP)) @@ -35,7 +36,14 @@ endif ifneq ($(GCC_VERSION),2) - cflags-y += -frename-registers --param max-inline-insns=5000 + cflags-$(CONFIG_ITANIUM) += -frename-registers +endif + +ifeq ($(GCC_VERSION),3) + ifeq ($(GCC_MINOR_VERSION),4) + cflags-$(CONFIG_ITANIUM) += -mtune=merced + cflags-$(CONFIG_MCKINLEY) += -mtune=mckinley + endif endif cflags-$(CONFIG_ITANIUM_BSTEP_SPECIFIC) += -mb-step @@ -48,14 +56,14 @@ core-y += arch/ia64/kernel/ arch/ia64/mm/ core-$(CONFIG_IA32_SUPPORT) += arch/ia64/ia32/ core-$(CONFIG_IA64_DIG) += arch/ia64/dig/ -core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/ arch/ia64/hp/common/ arch/ia64/hp/zx1/ \ - arch/ia64/hp/sim/ +core-$(CONFIG_IA64_GENERIC) += arch/ia64/dig/ core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/ core-$(CONFIG_IA64_SGI_SN) += arch/ia64/sn/ drivers-$(CONFIG_PCI) += arch/ia64/pci/ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ +drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ boot := arch/ia64/boot tools := arch/ia64/tools diff -Nru a/arch/ia64/dig/machvec.c b/arch/ia64/dig/machvec.c --- a/arch/ia64/dig/machvec.c Sat May 24 12:48:25 2003 +++ b/arch/ia64/dig/machvec.c Sat May 24 12:48:25 2003 @@ -1,2 +1,3 @@ -#define MACHVEC_PLATFORM_NAME dig +#define MACHVEC_PLATFORM_NAME dig +#define MACHVEC_PLATFORM_HEADER #include 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 Sat May 24 12:48:21 2003 +++ b/arch/ia64/hp/common/sba_iommu.c Sat May 24 12:48:21 2003 @@ -1,9 +1,9 @@ /* ** IA64 System Bus Adapter (SBA) I/O MMU manager ** -** (c) Copyright 2002 Alex Williamson -** (c) Copyright 2002 Grant Grundler -** (c) Copyright 2002 Hewlett-Packard Company +** (c) Copyright 2002-2003 Alex Williamson +** (c) Copyright 2002-2003 Grant Grundler +** (c) Copyright 2002-2003 Hewlett-Packard Company ** ** Portions (c) 2000 Grant Grundler (from parisc I/O MMU code) ** Portions (c) 1999 Dave S. Miller (from sparc64 I/O MMU code) @@ -30,17 +30,39 @@ #include #include #include +#include +#include #include #include /* ia64_get_itc() */ #include #include /* PAGE_OFFSET */ +#include +#include /* wmb() */ +#include -#define DRIVER_NAME "SBA" +#define PFX "IOC: " +/* +** This option allows cards capable of 64bit DMA to bypass the IOMMU. If +** not defined, all DMA will be 32bit and go through the TLB. +*/ #define ALLOW_IOV_BYPASS + +/* +** If a device prefetches beyond the end of a valid pdir entry, it will cause +** a hard failure, ie. MCA. Version 3.0 and later of the zx1 LBA should +** disconnect on 4k boundaries and prevent such issues. If the device is +** particularly agressive, this option will keep the entire pdir valid such +** that prefetching will hit a valid address. This could severely impact +** error containment, and is therefore off by default. The page that is +** used for spill-over is poisoned, so that should help debugging somewhat. +*/ +#undef FULL_VALID_PDIR + #define ENABLE_MARK_CLEAN + /* ** The number of debug flags is a clue - this code is fragile. */ @@ -52,6 +74,10 @@ #undef DEBUG_LARGE_SG_ENTRIES #undef DEBUG_BYPASS +#if defined(FULL_VALID_PDIR) && defined(ASSERT_PDIR_SANITY) +#error FULL_VALID_PDIR and ASSERT_PDIR_SANITY are mutually exclusive +#endif + #define SBA_INLINE __inline__ /* #define SBA_INLINE */ @@ -96,12 +122,8 @@ #define ASSERT(expr) #endif -#define KB(x) ((x) * 1024) -#define MB(x) (KB (KB (x))) -#define GB(x) (MB (KB (x))) - /* -** The number of pdir entries to "free" before issueing +** The number of pdir entries to "free" before issuing ** a read to PCOM register to flush out PCOM writes. ** Interacts with allocation granularity (ie 4 or 8 entries ** allocated and free'd/purged at a time might make this @@ -109,30 +131,24 @@ */ #define DELAYED_RESOURCE_CNT 16 -#define DEFAULT_DMA_HINT_REG(d) 0 - -#define ZX1_FUNC_ID_VALUE ((PCI_DEVICE_ID_HP_ZX1_SBA << 16) | PCI_VENDOR_ID_HP) -#define ZX1_MC_ID ((PCI_DEVICE_ID_HP_ZX1_MC << 16) | PCI_VENDOR_ID_HP) +#define DEFAULT_DMA_HINT_REG 0 -#define SBA_FUNC_ID 0x0000 /* function id */ -#define SBA_FCLASS 0x0008 /* function class, bist, header, rev... */ +#define ZX1_IOC_ID ((PCI_DEVICE_ID_HP_ZX1_IOC << 16) | PCI_VENDOR_ID_HP) +#define REO_IOC_ID ((PCI_DEVICE_ID_HP_REO_IOC << 16) | PCI_VENDOR_ID_HP) +#define SX1000_IOC_ID ((PCI_DEVICE_ID_HP_SX1000_IOC << 16) | PCI_VENDOR_ID_HP) -#define SBA_FUNC_SIZE 0x10000 /* SBA configuration function reg set */ - -unsigned int __initdata zx1_func_offsets[] = {0x1000, 0x4000, 0x8000, - 0x9000, 0xa000, -1}; - -#define SBA_IOC_OFFSET 0x1000 - -#define MAX_IOC 1 /* we only have 1 for now*/ +#define ZX1_IOC_OFFSET 0x1000 /* ACPI reports SBA, we want IOC */ +#define IOC_FUNC_ID 0x000 +#define IOC_FCLASS 0x008 /* function class, bist, header, rev... */ #define IOC_IBASE 0x300 /* IO TLB */ #define IOC_IMASK 0x308 #define IOC_PCOM 0x310 #define IOC_TCNFG 0x318 #define IOC_PDIR_BASE 0x320 -#define IOC_IOVA_SPACE_BASE 0x40000000 /* IOVA ranges start at 1GB */ +/* AGP GART driver looks for this */ +#define ZX1_SBA_IOMMU_COOKIE 0x0000badbadc0ffeeUL /* ** IOC supports 4/8/16/64KB page sizes (see TCNFG register) @@ -152,7 +168,7 @@ #define IOVP_MASK PAGE_MASK struct ioc { - unsigned long ioc_hpa; /* I/O MMU base address */ + void *ioc_hpa; /* I/O MMU base address */ char *res_map; /* resource map, bit == pdir entry */ u64 *pdir_base; /* physical base address */ unsigned long ibase; /* pdir IOV Space base */ @@ -193,37 +209,37 @@ #endif #endif - /* STUFF We don't need in performance path */ + /* Stuff we don't need in performance path */ + struct ioc *next; /* list of IOC's in system */ + acpi_handle handle; /* for multiple IOC's */ + const char *name; + unsigned int func_id; + unsigned int rev; /* HW revision of chip */ + u32 iov_size; unsigned int pdir_size; /* in bytes, determined by IOV Space size */ + struct pci_dev *sac_only_dev; }; -struct sba_device { - struct sba_device *next; /* list of SBA's in system */ - const char *name; - unsigned long sba_hpa; /* base address */ - spinlock_t sba_lock; - unsigned int flags; /* state/functionality enabled */ - unsigned int hw_rev; /* HW revision of chip */ - - unsigned int num_ioc; /* number of on-board IOC's */ - struct ioc ioc[MAX_IOC]; -}; +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 -static struct sba_device *sba_list; -static int sba_count; -static int reserve_sba_gart = 1; -static struct pci_dev sac_only_dev; +#ifdef FULL_VALID_PDIR +static u64 prefetch_spill_page; +#endif -#define sba_sg_address(sg) (page_address((sg)->page) + (sg)->offset) -#define sba_sg_len(sg) (sg->length) -#define sba_sg_iova(sg) (sg->dma_address) -#define sba_sg_iova_len(sg) (sg->dma_length) - -/* REVISIT - fix me for multiple SBAs/IOCs */ -#define GET_IOC(dev) (sba_list->ioc) -#define SBA_SET_AGP(sba_dev) (sba_dev->flags |= 0x1) -#define SBA_GET_AGP(sba_dev) (sba_dev->flags & 0x1) +#ifdef CONFIG_PCI +# define GET_IOC(dev) (((dev)->bus == &pci_bus_type) \ + ? ((struct ioc *) PCI_CONTROLLER(to_pci_dev(dev))->iommu) : NULL) +#else +# define GET_IOC(dev) NULL +#endif /* ** DMA_CHUNK_SIZE is used by the SCSI mid-layer to break up @@ -232,10 +248,7 @@ ** rather than the HW. I/O MMU allocation alogorithms can be ** faster with smaller size is (to some degree). */ -#define DMA_CHUNK_SIZE (BITS_PER_LONG*IOVP_SIZE) - -/* Looks nice and keeps the compiler happy */ -#define SBA_DEV(d) ((struct sba_device *) (d)) +#define DMA_CHUNK_SIZE (BITS_PER_LONG*PAGE_SIZE) #define ROUNDUP(x,y) ((x + ((y)-1)) & ~((y)-1)) @@ -255,7 +268,7 @@ * sba_dump_tlb - debugging only - print IOMMU operating parameters * @hpa: base address of the IOMMU * - * Print the size/location of the IO MMU Pdir. + * Print the size/location of the IO MMU PDIR. */ static void sba_dump_tlb(char *hpa) @@ -273,19 +286,19 @@ #ifdef ASSERT_PDIR_SANITY /** - * sba_dump_pdir_entry - debugging only - print one IOMMU Pdir entry + * sba_dump_pdir_entry - debugging only - print one IOMMU PDIR entry * @ioc: IO MMU structure which owns the pdir we are interested in. * @msg: text to print ont the output line. * @pide: pdir index. * - * Print one entry of the IO MMU Pdir in human readable form. + * Print one entry of the IO MMU PDIR in human readable form. */ static void sba_dump_pdir_entry(struct ioc *ioc, char *msg, uint pide) { /* start printing from lowest pde in rval */ - u64 *ptr = &(ioc->pdir_base[pide & ~(BITS_PER_LONG - 1)]); - unsigned long *rptr = (unsigned long *) &(ioc->res_map[(pide >>3) & ~(sizeof(unsigned long) - 1)]); + u64 *ptr = &ioc->pdir_base[pide & ~(BITS_PER_LONG - 1)]; + unsigned long *rptr = (unsigned long *) &ioc->res_map[(pide >>3) & -sizeof(unsigned long)]; uint rcnt; printk(KERN_DEBUG "SBA: %s rp %p bit %d rval 0x%lx\n", @@ -296,7 +309,7 @@ printk(KERN_DEBUG "%s %2d %p %016Lx\n", (rcnt == (pide & (BITS_PER_LONG - 1))) ? " -->" : " ", - rcnt, ptr, *ptr ); + rcnt, ptr, (unsigned long long) *ptr ); rcnt++; ptr++; } @@ -359,17 +372,18 @@ * print the SG list so we can verify it's correct by hand. */ static void -sba_dump_sg(struct ioc *ioc, struct scatterlist *startsg, int nents) +sba_dump_sg( struct ioc *ioc, struct scatterlist *startsg, int nents) { while (nents-- > 0) { printk(KERN_DEBUG " %d : DMA %08lx/%05x CPU %p\n", nents, - (unsigned long) sba_sg_iova(startsg), sba_sg_iova_len(startsg), + startsg->dma_address, startsg->dma_length, sba_sg_address(startsg)); startsg++; } } + static void -sba_check_sg(struct ioc *ioc, struct scatterlist *startsg, int nents) +sba_check_sg( struct ioc *ioc, struct scatterlist *startsg, int nents) { struct scatterlist *the_sg = startsg; int the_nents = nents; @@ -398,9 +412,11 @@ #define PAGES_PER_RANGE 1 /* could increase this to 4 or 8 if needed */ /* Convert from IOVP to IOVA and vice versa. */ -#define SBA_IOVA(ioc,iovp,offset,hint_reg) ((ioc->ibase) | (iovp) | (offset) | ((hint_reg)<<(ioc->hint_shift_pdir))) +#define SBA_IOVA(ioc,iovp,offset,hint_reg) ((ioc->ibase) | (iovp) | (offset) | \ + ((hint_reg)<<(ioc->hint_shift_pdir))) #define SBA_IOVP(ioc,iova) (((iova) & ioc->hint_mask_pdir) & ~(ioc->ibase)) +/* FIXME : review these macros to verify correctness and usage */ #define PDIR_INDEX(iovp) ((iovp)>>IOVP_SHIFT) #define RESMAP_MASK(n) ~(~0UL << (n)) @@ -408,7 +424,7 @@ /** - * sba_search_bitmap - find free space in IO Pdir resource bitmap + * sba_search_bitmap - find free space in IO PDIR resource bitmap * @ioc: IO MMU structure which owns the pdir we are interested in. * @bits_wanted: number of entries we need. * @@ -445,7 +461,7 @@ ** We need the alignment to invalidate I/O TLB using ** SBA HW features in the unmap path. */ - unsigned long o = 1UL << get_order(bits_wanted << IOVP_SHIFT); + unsigned long o = 1 << get_order(bits_wanted << PAGE_SHIFT); uint bitshiftcnt = ROUNDUP(ioc->res_bitshift, o); unsigned long mask; @@ -491,7 +507,7 @@ /** - * sba_alloc_range - find free bits and mark them in IO Pdir resource bitmap + * sba_alloc_range - find free bits and mark them in IO PDIR resource bitmap * @ioc: IO MMU structure which owns the pdir we are interested in. * @size: number of bytes to create a mapping for * @@ -520,7 +536,8 @@ if (pide >= (ioc->res_size << 3)) { pide = sba_search_bitmap(ioc, pages_needed); if (pide >= (ioc->res_size << 3)) - panic(__FILE__ ": I/O MMU @ %lx is out of mapping resources\n", ioc->ioc_hpa); + panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n", + ioc->ioc_hpa); } #ifdef ASSERT_PDIR_SANITY @@ -553,7 +570,7 @@ /** - * sba_free_range - unmark bits in IO Pdir resource bitmap + * sba_free_range - unmark bits in IO PDIR resource bitmap * @ioc: IO MMU structure which owns the pdir we are interested in. * @iova: IO virtual address which was previously allocated. * @size: number of bytes to create a mapping for @@ -600,14 +617,14 @@ /** - * sba_io_pdir_entry - fill in one IO Pdir entry - * @pdir_ptr: pointer to IO Pdir entry - * @phys_page: phys CPU address of page to map + * sba_io_pdir_entry - fill in one IO PDIR entry + * @pdir_ptr: pointer to IO PDIR entry + * @vba: Virtual CPU address of buffer to map * * SBA Mapping Routine * - * Given a physical address (phys_page, arg1) sba_io_pdir_entry() - * loads the I/O Pdir entry pointed to by pdir_ptr (arg0). + * Given a virtual address (vba, arg1) sba_io_pdir_entry() + * loads the I/O PDIR entry pointed to by pdir_ptr (arg0). * Each IO Pdir entry consists of 8 bytes as shown below * (LSB == bit 0): * @@ -619,12 +636,21 @@ * V == Valid Bit * U == Unused * PPN == Physical Page Number + * + * The physical address fields are filled with the results of virt_to_phys() + * on the vba. */ -#define SBA_VALID_MASK 0x80000000000000FFULL -#define sba_io_pdir_entry(pdir_ptr, phys_page) *pdir_ptr = (phys_page | SBA_VALID_MASK) -#define sba_io_page(pdir_ptr) (*pdir_ptr & ~SBA_VALID_MASK) - +#if 1 +#define sba_io_pdir_entry(pdir_ptr, vba) *pdir_ptr = ((vba & ~0xE000000000000FFFULL) \ + | 0x8000000000000000ULL) +#else +void SBA_INLINE +sba_io_pdir_entry(u64 *pdir_ptr, unsigned long vba) +{ + *pdir_ptr = ((vba & ~0xE000000000000FFFULL) | 0x80000000000000FFULL); +} +#endif #ifdef ENABLE_MARK_CLEAN /** @@ -640,7 +666,7 @@ pg_addr = PAGE_ALIGN((unsigned long) addr); end = (unsigned long) addr + size; while (pg_addr + PAGE_SIZE <= end) { - struct page *page = virt_to_page(pg_addr); + struct page *page = virt_to_page((void *)pg_addr); set_bit(PG_arch_1, &page->flags); pg_addr += PAGE_SIZE; } @@ -648,12 +674,12 @@ #endif /** - * sba_mark_invalid - invalidate one or more IO Pdir entries + * sba_mark_invalid - invalidate one or more IO PDIR entries * @ioc: IO MMU structure which owns the pdir we are interested in. * @iova: IO Virtual Address mapped earlier * @byte_cnt: number of bytes this mapping covers. * - * Marking the IO Pdir entry(ies) as Invalid and invalidate + * Marking the IO PDIR entry(ies) as Invalid and invalidate * corresponding IO TLB entry. The PCOM (Purge Command Register) * is to purge stale entries in the IO TLB when unmapping entries. * @@ -687,15 +713,24 @@ iovp |= IOVP_SHIFT; /* set "size" field for PCOM */ +#ifndef FULL_VALID_PDIR /* - ** clear I/O Pdir entry "valid" bit + ** clear I/O PDIR entry "valid" bit ** Do NOT clear the rest - save it for debugging. ** We should only clear bits that have previously ** been enabled. */ - ioc->pdir_base[off] &= ~SBA_VALID_MASK; + ioc->pdir_base[off] &= ~(0x80000000000000FFULL); +#else + /* + ** If we want to maintain the PDIR as valid, put in + ** the spill page so devices prefetching won't + ** cause a hard fail. + */ + ioc->pdir_base[off] = (0x80000000000000FFULL | prefetch_spill_page); +#endif } else { - u32 t = get_order(byte_cnt) + IOVP_SHIFT; + u32 t = get_order(byte_cnt) + PAGE_SHIFT; iovp |= t; ASSERT(t <= 31); /* 2GB! Max value of "size" field */ @@ -703,14 +738,18 @@ do { /* verify this pdir entry is enabled */ ASSERT(ioc->pdir_base[off] >> 63); +#ifndef FULL_VALID_PDIR /* clear I/O Pdir entry "valid" bit first */ - ioc->pdir_base[off] &= ~SBA_VALID_MASK; + ioc->pdir_base[off] &= ~(0x80000000000000FFULL); +#else + ioc->pdir_base[off] = (0x80000000000000FFULL | prefetch_spill_page); +#endif off++; byte_cnt -= IOVP_SIZE; } while (byte_cnt > 0); } - WRITE_REG(iovp, ioc->ioc_hpa+IOC_PCOM); + WRITE_REG(iovp | ioc->ibase, ioc->ioc_hpa+IOC_PCOM); } /** @@ -718,26 +757,23 @@ * @dev: instance of PCI owned by the driver that's asking. * @addr: driver buffer to map. * @size: number of bytes to map in driver buffer. - * @direction: R/W or both. + * @dir: R/W or both. * * See Documentation/DMA-mapping.txt */ dma_addr_t -sba_map_single(struct pci_dev *dev, void *addr, size_t size, int direction) +sba_map_single(struct device *dev, void *addr, size_t size, int dir) { struct ioc *ioc; - unsigned long flags; + unsigned long flags; dma_addr_t iovp; dma_addr_t offset; u64 *pdir_start; int pide; #ifdef ALLOW_IOV_BYPASS - unsigned long phys_addr = virt_to_phys(addr); + unsigned long pci_addr = virt_to_phys(addr); #endif - if (!sba_list) - panic("sba_map_single: no SBA found!\n"); - ioc = GET_IOC(dev); ASSERT(ioc); @@ -745,7 +781,7 @@ /* ** Check if the PCI device can DMA to ptr... if so, just return ptr */ - if ((phys_addr & ~dev->dma_mask) == 0) { + if (dev && dev->dma_mask && (pci_addr & ~*dev->dma_mask) == 0) { /* ** Device is bit capable of DMA'ing to the buffer... ** just return the PCI address of ptr @@ -756,8 +792,8 @@ spin_unlock_irqrestore(&ioc->res_lock, flags); #endif DBG_BYPASS("sba_map_single() bypass mask/addr: 0x%lx/0x%lx\n", - dev->dma_mask, phys_addr); - return phys_addr; + *dev->dma_mask, pci_addr); + return pci_addr; } #endif @@ -790,8 +826,7 @@ while (size > 0) { ASSERT(((u8 *)pdir_start)[7] == 0); /* verify availability */ - - sba_io_pdir_entry(pdir_start, virt_to_phys(addr)); + sba_io_pdir_entry(pdir_start, (unsigned long) addr); DBG_RUN(" pdir 0x%p %lx\n", pdir_start, *pdir_start); @@ -799,12 +834,15 @@ size -= IOVP_SIZE; pdir_start++; } + /* force pdir update */ + wmb(); + /* form complete address */ #ifdef ASSERT_PDIR_SANITY sba_check_pdir(ioc,"Check after sba_map_single()"); #endif spin_unlock_irqrestore(&ioc->res_lock, flags); - return SBA_IOVA(ioc, iovp, offset, DEFAULT_DMA_HINT_REG(direction)); + return SBA_IOVA(ioc, iovp, offset, DEFAULT_DMA_HINT_REG); } /** @@ -812,23 +850,19 @@ * @dev: instance of PCI owned by the driver that's asking. * @iova: IOVA of driver buffer previously mapped. * @size: number of bytes mapped in driver buffer. - * @direction: R/W or both. + * @dir: R/W or both. * * See Documentation/DMA-mapping.txt */ -void sba_unmap_single(struct pci_dev *dev, dma_addr_t iova, size_t size, - int direction) +void sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, int dir) { struct ioc *ioc; #if DELAYED_RESOURCE_CNT > 0 struct sba_dma_pair *d; #endif - unsigned long flags; + unsigned long flags; dma_addr_t offset; - if (!sba_list) - panic("sba_map_single: no SBA found!\n"); - ioc = GET_IOC(dev); ASSERT(ioc); @@ -845,7 +879,7 @@ DBG_BYPASS("sba_unmap_single() bypass addr: 0x%lx\n", iova); #ifdef ENABLE_MARK_CLEAN - if (direction == PCI_DMA_FROMDEVICE) { + if (dir == DMA_FROM_DEVICE) { mark_clean(phys_to_virt(iova), size); } #endif @@ -861,29 +895,6 @@ size += offset; size = ROUNDUP(size, IOVP_SIZE); -#ifdef ENABLE_MARK_CLEAN - /* - ** Don't need to hold the spinlock while telling VM pages are "clean". - ** The pages are "busy" in the resource map until we mark them free. - ** But tell VM pages are clean *before* releasing the resource - ** in order to avoid race conditions. - */ - if (direction == PCI_DMA_FROMDEVICE) { - u32 iovp = (u32) SBA_IOVP(ioc,iova); - unsigned int pide = PDIR_INDEX(iovp); - u64 *pdirp = &(ioc->pdir_base[pide]); - size_t byte_cnt = size; - void *addr; - - do { - addr = phys_to_virt(sba_io_page(pdirp)); - mark_clean(addr, min(byte_cnt, IOVP_SIZE)); - pdirp++; - byte_cnt -= IOVP_SIZE; - } while (byte_cnt > 0); - } -#endif - spin_lock_irqsave(&ioc->res_lock, flags); #ifdef CONFIG_PROC_FS ioc->usingle_calls++; @@ -909,7 +920,40 @@ sba_free_range(ioc, iova, size); READ_REG(ioc->ioc_hpa+IOC_PCOM); /* flush purges */ #endif /* DELAYED_RESOURCE_CNT == 0 */ +#ifdef ENABLE_MARK_CLEAN + if (dir == DMA_FROM_DEVICE) { + u32 iovp = (u32) SBA_IOVP(ioc,iova); + int off = PDIR_INDEX(iovp); + void *addr; + + if (size <= IOVP_SIZE) { + addr = phys_to_virt(ioc->pdir_base[off] & + ~0xE000000000000FFFULL); + mark_clean(addr, size); + } else { + size_t byte_cnt = size; + + do { + addr = phys_to_virt(ioc->pdir_base[off] & + ~0xE000000000000FFFULL); + mark_clean(addr, min(byte_cnt, IOVP_SIZE)); + off++; + byte_cnt -= IOVP_SIZE; + + } while (byte_cnt > 0); + } + } +#endif spin_unlock_irqrestore(&ioc->res_lock, flags); + + /* XXX REVISIT for 2.5 Linux - need syncdma for zero-copy support. + ** For Astro based systems this isn't a big deal WRT performance. + ** As long as 2.4 kernels copyin/copyout data from/to userspace, + ** we don't need the syncdma. The issue here is I/O MMU cachelines + ** are *not* coherent in all cases. May be hwrev dependent. + ** Need to investigate more. + asm volatile("syncdma"); + */ } @@ -922,29 +966,25 @@ * See Documentation/DMA-mapping.txt */ void * -sba_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle) +sba_alloc_coherent (struct device *hwdev, size_t size, dma_addr_t *dma_handle, int flags) { - void *ret; - - if (!hwdev) { - /* only support PCI */ - *dma_handle = 0; - return 0; - } + struct ioc *ioc; + void *addr; - ret = (void *) __get_free_pages(GFP_ATOMIC, get_order(size)); + addr = (void *) __get_free_pages(flags, get_order(size)); + if (!addr) + return NULL; - if (ret) { - memset(ret, 0, size); - /* - * REVISIT: if sba_map_single starts needing more - * than dma_mask from the device, this needs to be - * updated. - */ - *dma_handle = sba_map_single(&sac_only_dev, ret, size, 0); - } + /* + * REVISIT: if sba_map_single starts needing more than dma_mask from the + * device, this needs to be updated. + */ + ioc = GET_IOC(hwdev); + ASSERT(ioc); + *dma_handle = sba_map_single(&ioc->sac_only_dev->dev, addr, size, 0); - return ret; + memset(addr, 0, size); + return addr; } @@ -957,117 +997,245 @@ * * See Documentation/DMA-mapping.txt */ -void sba_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, - dma_addr_t dma_handle) +void sba_free_coherent (struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) { sba_unmap_single(hwdev, dma_handle, size, 0); free_pages((unsigned long) vaddr, get_order(size)); } +/* +** Since 0 is a valid pdir_base index value, can't use that +** to determine if a value is valid or not. Use a flag to indicate +** the SG list entry contains a valid pdir index. +*/ +#define PIDE_FLAG 0x1UL + #ifdef DEBUG_LARGE_SG_ENTRIES int dump_run_sg = 0; #endif -#define SG_ENT_VIRT_PAGE(sg) page_address((sg)->page) -#define SG_ENT_PHYS_PAGE(SG) virt_to_phys(SG_ENT_VIRT_PAGE(SG)) - /** - * sba_coalesce_chunks - preprocess the SG list + * sba_fill_pdir - write allocated SG entries into IO PDIR * @ioc: IO MMU structure which owns the pdir we are interested in. - * @startsg: input=SG list output=DMA addr/len pairs filled in + * @startsg: list of IOVA/size pairs * @nents: number of entries in startsg list - * @direction: R/W or both. * - * Walk the SG list and determine where the breaks are in the DMA stream. - * Allocate IO Pdir resources and fill them in separate loop. - * Returns the number of DMA streams used for output IOVA list. - * Note each DMA stream can consume multiple IO Pdir entries. - * - * Code is written assuming some coalescing is possible. + * Take preprocessed SG list and write corresponding entries + * in the IO PDIR. */ + static SBA_INLINE int -sba_coalesce_chunks(struct ioc *ioc, struct scatterlist *startsg, - int nents, int direction) +sba_fill_pdir( + struct ioc *ioc, + struct scatterlist *startsg, + int nents) { - struct scatterlist *dma_sg = startsg; /* return array */ + struct scatterlist *dma_sg = startsg; /* pointer to current DMA */ int n_mappings = 0; + u64 *pdirp = 0; + unsigned long dma_offset = 0; - ASSERT(nents > 1); + dma_sg--; + while (nents-- > 0) { + int cnt = startsg->dma_length; + startsg->dma_length = 0; - do { - unsigned int dma_cnt = 1; /* number of pages in DMA stream */ - unsigned int pide; /* index into IO Pdir array */ - u64 *pdirp; /* pointer into IO Pdir array */ - unsigned long dma_offset, dma_len; /* cumulative DMA stream */ +#ifdef DEBUG_LARGE_SG_ENTRIES + if (dump_run_sg) + printk(" %2d : %08lx/%05x %p\n", + nents, startsg->dma_address, cnt, + sba_sg_address(startsg)); +#else + DBG_RUN_SG(" %d : %08lx/%05x %p\n", + nents, startsg->dma_address, cnt, + sba_sg_address(startsg)); +#endif + /* + ** Look for the start of a new DMA stream + */ + if (startsg->dma_address & PIDE_FLAG) { + u32 pide = startsg->dma_address & ~PIDE_FLAG; + dma_offset = (unsigned long) pide & ~IOVP_MASK; + startsg->dma_address = 0; + dma_sg++; + dma_sg->dma_address = pide | ioc->ibase; + pdirp = &(ioc->pdir_base[pide >> IOVP_SHIFT]); + n_mappings++; + } /* - ** Prepare for first/next DMA stream + ** Look for a VCONTIG chunk */ - dma_len = sba_sg_len(startsg); - dma_offset = (unsigned long) sba_sg_address(startsg); + if (cnt) { + unsigned long vaddr = (unsigned long) sba_sg_address(startsg); + ASSERT(pdirp); + + /* Since multiple Vcontig blocks could make up + ** one DMA stream, *add* cnt to dma_len. + */ + dma_sg->dma_length += cnt; + cnt += dma_offset; + dma_offset=0; /* only want offset on first chunk */ + cnt = ROUNDUP(cnt, IOVP_SIZE); +#ifdef CONFIG_PROC_FS + ioc->msg_pages += cnt >> IOVP_SHIFT; +#endif + do { + sba_io_pdir_entry(pdirp, vaddr); + vaddr += IOVP_SIZE; + cnt -= IOVP_SIZE; + pdirp++; + } while (cnt > 0); + } startsg++; - nents--; + } + /* force pdir update */ + wmb(); + +#ifdef DEBUG_LARGE_SG_ENTRIES + dump_run_sg = 0; +#endif + return(n_mappings); +} + + +/* +** Two address ranges are DMA contiguous *iff* "end of prev" and +** "start of next" are both on a page boundry. +** +** (shift left is a quick trick to mask off upper bits) +*/ +#define DMA_CONTIG(__X, __Y) \ + (((((unsigned long) __X) | ((unsigned long) __Y)) << (BITS_PER_LONG - PAGE_SHIFT)) == 0UL) + + +/** + * sba_coalesce_chunks - preprocess the SG list + * @ioc: IO MMU structure which owns the pdir we are interested in. + * @startsg: list of IOVA/size pairs + * @nents: number of entries in startsg list + * + * First pass is to walk the SG list and determine where the breaks are + * in the DMA stream. Allocates PDIR entries but does not fill them. + * Returns the number of DMA chunks. + * + * Doing the fill seperate from the coalescing/allocation keeps the + * code simpler. Future enhancement could make one pass through + * the sglist do both. + */ +static SBA_INLINE int +sba_coalesce_chunks( struct ioc *ioc, + struct scatterlist *startsg, + int nents) +{ + struct scatterlist *vcontig_sg; /* VCONTIG chunk head */ + unsigned long vcontig_len; /* len of VCONTIG chunk */ + unsigned long vcontig_end; + struct scatterlist *dma_sg; /* next DMA stream head */ + unsigned long dma_offset, dma_len; /* start/len of DMA stream */ + int n_mappings = 0; + + while (nents > 0) { + unsigned long vaddr = (unsigned long) sba_sg_address(startsg); /* - ** We want to know how many entries can be coalesced - ** before trying to allocate IO Pdir space. - ** IOVAs can then be allocated "naturally" aligned - ** to take advantage of the block IO TLB flush. + ** Prepare for first/next DMA stream */ - while (nents) { - unsigned long end_offset = dma_offset + dma_len; + dma_sg = vcontig_sg = startsg; + dma_len = vcontig_len = vcontig_end = startsg->length; + vcontig_end += vaddr; + dma_offset = vaddr & ~IOVP_MASK; - /* prev entry must end on a page boundary */ - if (end_offset & IOVP_MASK) - break; + /* PARANOID: clear entries */ + startsg->dma_address = startsg->dma_length = 0; - /* next entry start on a page boundary? */ - if (startsg->offset) - break; + /* + ** This loop terminates one iteration "early" since + ** it's always looking one "ahead". + */ + while (--nents > 0) { + unsigned long vaddr; /* tmp */ + + startsg++; + + /* PARANOID */ + startsg->dma_address = startsg->dma_length = 0; + + /* catch brokenness in SCSI layer */ + ASSERT(startsg->length <= DMA_CHUNK_SIZE); /* - ** make sure current dma stream won't exceed - ** DMA_CHUNK_SIZE if coalescing entries. + ** First make sure current dma stream won't + ** exceed DMA_CHUNK_SIZE if we coalesce the + ** next entry. */ - if (((end_offset + startsg->length + ~IOVP_MASK) - & IOVP_MASK) - > DMA_CHUNK_SIZE) + if (((dma_len + dma_offset + startsg->length + ~IOVP_MASK) & IOVP_MASK) + > DMA_CHUNK_SIZE) break; - dma_len += sba_sg_len(startsg); - startsg++; - nents--; - dma_cnt++; - } + /* + ** Then look for virtually contiguous blocks. + ** + ** append the next transaction? + */ + vaddr = (unsigned long) sba_sg_address(startsg); + if (vcontig_end == vaddr) + { + vcontig_len += startsg->length; + vcontig_end += startsg->length; + dma_len += startsg->length; + continue; + } - ASSERT(dma_len <= DMA_CHUNK_SIZE); +#ifdef DEBUG_LARGE_SG_ENTRIES + dump_run_sg = (vcontig_len > IOVP_SIZE); +#endif - /* allocate IO Pdir resource. - ** returns index into (u64) IO Pdir array. - ** IOVA is formed from this. - */ - pide = sba_alloc_range(ioc, dma_cnt << IOVP_SHIFT); - pdirp = &(ioc->pdir_base[pide]); + /* + ** Not virtually contigous. + ** Terminate prev chunk. + ** Start a new chunk. + ** + ** Once we start a new VCONTIG chunk, dma_offset + ** can't change. And we need the offset from the first + ** chunk - not the last one. Ergo Successive chunks + ** must start on page boundaries and dove tail + ** with it's predecessor. + */ + vcontig_sg->dma_length = vcontig_len; - /* fill_pdir: write stream into IO Pdir */ - while (dma_cnt--) { - sba_io_pdir_entry(pdirp, SG_ENT_PHYS_PAGE(startsg)); - startsg++; - pdirp++; - } + vcontig_sg = startsg; + vcontig_len = startsg->length; - /* "output" IOVA */ - sba_sg_iova(dma_sg) = SBA_IOVA(ioc, - ((dma_addr_t) pide << IOVP_SHIFT), - dma_offset, - DEFAULT_DMA_HINT_REG(direction)); - sba_sg_iova_len(dma_sg) = dma_len; + /* + ** 3) do the entries end/start on page boundaries? + ** Don't update vcontig_end until we've checked. + */ + if (DMA_CONTIG(vcontig_end, vaddr)) + { + vcontig_end = vcontig_len + vaddr; + dma_len += vcontig_len; + continue; + } else { + break; + } + } - dma_sg++; + /* + ** End of DMA Stream + ** Terminate last VCONTIG block. + ** Allocate space for DMA stream. + */ + vcontig_sg->dma_length = vcontig_len; + dma_len = (dma_len + dma_offset + ~IOVP_MASK) & IOVP_MASK; + ASSERT(dma_len <= DMA_CHUNK_SIZE); + dma_sg->dma_address = (dma_addr_t) (PIDE_FLAG + | (sba_alloc_range(ioc, dma_len) << IOVP_SHIFT) + | dma_offset); n_mappings++; - } while (nents); + } return n_mappings; } @@ -1075,60 +1243,51 @@ /** * sba_map_sg - map Scatter/Gather list - * @dev: instance of PCI device owned by the driver that's asking. + * @dev: instance of PCI owned by the driver that's asking. * @sglist: array of buffer/length pairs * @nents: number of entries in list - * @direction: R/W or both. + * @dir: R/W or both. * * See Documentation/DMA-mapping.txt */ -int sba_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, - int direction) +int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int dir) { struct ioc *ioc; - int filled = 0; + int coalesced, filled = 0; unsigned long flags; #ifdef ALLOW_IOV_BYPASS struct scatterlist *sg; #endif - DBG_RUN_SG("%s() START %d entries, 0x%p,0x%x\n", __FUNCTION__, nents, - sba_sg_address(sglist), sba_sg_len(sglist)); - - if (!sba_list) - panic("sba_map_single: no SBA found!\n"); - + DBG_RUN_SG("%s() START %d entries\n", __FUNCTION__, nents); ioc = GET_IOC(dev); ASSERT(ioc); #ifdef ALLOW_IOV_BYPASS - if (dev->dma_mask >= ioc->dma_mask) { - for (sg = sglist ; filled < nents ; filled++, sg++) { - sba_sg_iova(sg) = virt_to_phys(sba_sg_address(sg)); - sba_sg_iova_len(sg) = sba_sg_len(sg); + if (dev && dev->dma_mask && (ioc->dma_mask & ~*dev->dma_mask) == 0) { + for (sg = sglist ; filled < nents ; filled++, sg++){ + sg->dma_length = sg->length; + sg->dma_address = virt_to_phys(sba_sg_address(sg)); } #ifdef CONFIG_PROC_FS spin_lock_irqsave(&ioc->res_lock, flags); ioc->msg_bypass++; spin_unlock_irqrestore(&ioc->res_lock, flags); #endif - DBG_RUN_SG("%s() DONE %d mappings bypassed\n", __FUNCTION__, filled); return filled; } #endif /* Fast path single entry scatterlists. */ if (nents == 1) { - sba_sg_iova(sglist) = sba_map_single(dev, - (void *) sba_sg_iova(sglist), - sba_sg_len(sglist), direction); - sba_sg_iova_len(sglist) = sba_sg_len(sglist); + sglist->dma_length = sglist->length; + sglist->dma_address = sba_map_single(dev, sba_sg_address(sglist), sglist->length, + dir); #ifdef CONFIG_PROC_FS /* ** Should probably do some stats counting, but trying to ** be precise quickly starts wasting CPU time. */ #endif - DBG_RUN_SG("%s() DONE 1 mapping\n", __FUNCTION__); return 1; } @@ -1145,11 +1304,26 @@ #ifdef CONFIG_PROC_FS ioc->msg_calls++; #endif - + /* - ** coalesce and program the I/O Pdir + ** First coalesce the chunks and allocate I/O pdir space + ** + ** If this is one DMA stream, we can properly map using the + ** correct virtual address associated with each DMA page. + ** w/o this association, we wouldn't have coherent DMA! + ** Access to the virtual address is what forces a two pass algorithm. */ - filled = sba_coalesce_chunks(ioc, sglist, nents, direction); + coalesced = sba_coalesce_chunks(ioc, sglist, nents); + + /* + ** Program the I/O Pdir + ** + ** map the virtual addresses to the I/O Pdir + ** o dma_address will contain the pdir index + ** o dma_len will contain the number of bytes to map + ** o address contains the virtual address. + */ + filled = sba_fill_pdir(ioc, sglist, nents); #ifdef ASSERT_PDIR_SANITY if (sba_check_pdir(ioc,"Check after sba_map_sg()")) @@ -1161,6 +1335,7 @@ spin_unlock_irqrestore(&ioc->res_lock, flags); + ASSERT(coalesced == filled); DBG_RUN_SG("%s() DONE %d mappings\n", __FUNCTION__, filled); return filled; @@ -1172,23 +1347,19 @@ * @dev: instance of PCI owned by the driver that's asking. * @sglist: array of buffer/length pairs * @nents: number of entries in list - * @direction: R/W or both. + * @dir: R/W or both. * * See Documentation/DMA-mapping.txt */ -void sba_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, - int direction) +void sba_unmap_sg (struct device *dev, struct scatterlist *sglist, int nents, int dir) { struct ioc *ioc; #ifdef ASSERT_PDIR_SANITY unsigned long flags; #endif - DBG_RUN_SG("%s() START %d entries, 0x%p,0x%x\n", - __FUNCTION__, nents, sba_sg_address(sglist), sba_sg_len(sglist)); - - if (!sba_list) - panic("sba_map_single: no SBA found!\n"); + DBG_RUN_SG("%s() START %d entries, %p,%x\n", + __FUNCTION__, nents, sba_sg_address(sglist), sglist->length); ioc = GET_IOC(dev); ASSERT(ioc); @@ -1203,10 +1374,9 @@ spin_unlock_irqrestore(&ioc->res_lock, flags); #endif - while (sba_sg_len(sglist) && nents--) { + while (nents && sglist->dma_length) { - sba_unmap_single(dev, (dma_addr_t)sba_sg_iova(sglist), - sba_sg_iova_len(sglist), direction); + sba_unmap_single(dev, sglist->dma_address, sglist->dma_length, dir); #ifdef CONFIG_PROC_FS /* ** This leaves inconsistent data in the stats, but we can't @@ -1214,9 +1384,11 @@ ** were coalesced to a single entry. The stats are fun, ** but speed is more important. */ - ioc->usg_pages += (((u64)sba_sg_iova(sglist) & ~IOVP_MASK) + sba_sg_len(sglist) + IOVP_SIZE - 1) >> IOVP_SHIFT; + ioc->usg_pages += ((sglist->dma_address & ~IOVP_MASK) + sglist->dma_length + + IOVP_SIZE - 1) >> PAGE_SHIFT; #endif - ++sglist; + sglist++; + nents--; } DBG_RUN_SG("%s() DONE (nents %d)\n", __FUNCTION__, nents); @@ -1229,87 +1401,76 @@ } -unsigned long -sba_dma_address (struct scatterlist *sg) -{ - return ((unsigned long)sba_sg_iova(sg)); -} - -int -sba_dma_supported (struct pci_dev *dev, u64 mask) -{ - return 1; -} - /************************************************************** * * Initialization and claim * ***************************************************************/ - -static void -sba_ioc_init(struct sba_device *sba_dev, struct ioc *ioc, int ioc_num) +static void __init +ioc_iova_init(struct ioc *ioc) { - u32 iova_space_size, iova_space_mask; - void * pdir_base; - int pdir_size, iov_order, tcnfg; + u32 iova_space_mask; + int iov_order, tcnfg; + int agp_found = 0; + struct pci_dev *device; +#ifdef FULL_VALID_PDIR + unsigned long index; +#endif /* - ** Firmware programs the maximum IOV space size into the imask reg + ** Firmware programs the base and size of a "safe IOVA space" + ** (one that doesn't overlap memory or LMMIO space) in the + ** IBASE and IMASK registers. */ - iova_space_size = ~(READ_REG(ioc->ioc_hpa + IOC_IMASK) & 0xFFFFFFFFUL) + 1; + ioc->ibase = READ_REG(ioc->ioc_hpa + IOC_IBASE) & ~0x1UL; + ioc->iov_size = ~(READ_REG(ioc->ioc_hpa + IOC_IMASK) & 0xFFFFFFFFUL) + 1; /* ** iov_order is always based on a 1GB IOVA space since we want to ** turn on the other half for AGP GART. */ - iov_order = get_order(iova_space_size >> (IOVP_SHIFT-PAGE_SHIFT)); - ioc->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64); + iov_order = get_order(ioc->iov_size >> (IOVP_SHIFT - PAGE_SHIFT)); + ioc->pdir_size = (ioc->iov_size / IOVP_SIZE) * sizeof(u64); - DBG_INIT("%s() hpa 0x%lx IOV %dMB (%d bits) PDIR size 0x%0x\n", - __FUNCTION__, ioc->ioc_hpa, iova_space_size>>20, - iov_order + PAGE_SHIFT, ioc->pdir_size); + DBG_INIT("%s() hpa %p IOV %dMB (%d bits) PDIR size 0x%x\n", + __FUNCTION__, ioc->ioc_hpa, ioc->iov_size >> 20, + iov_order + PAGE_SHIFT, ioc->pdir_size); - /* XXX DMA HINTs not used */ + /* FIXME : DMA HINTs not used */ ioc->hint_shift_pdir = iov_order + PAGE_SHIFT; ioc->hint_mask_pdir = ~(0x3 << (iov_order + PAGE_SHIFT)); - ioc->pdir_base = pdir_base = - (void *) __get_free_pages(GFP_KERNEL, get_order(pdir_size)); - if (NULL == pdir_base) - { - panic(__FILE__ ":%s() could not allocate I/O Page Table\n", __FUNCTION__); - } - memset(pdir_base, 0, pdir_size); + ioc->pdir_base = (void *) __get_free_pages(GFP_KERNEL, + get_order(ioc->pdir_size)); + if (!ioc->pdir_base) + panic(PFX "Couldn't allocate I/O Page Table\n"); + + memset(ioc->pdir_base, 0, ioc->pdir_size); DBG_INIT("%s() pdir %p size %x hint_shift_pdir %x hint_mask_pdir %lx\n", - __FUNCTION__, pdir_base, pdir_size, + __FUNCTION__, ioc->pdir_base, ioc->pdir_size, ioc->hint_shift_pdir, ioc->hint_mask_pdir); - ASSERT((((unsigned long) pdir_base) & PAGE_MASK) == (unsigned long) pdir_base); - WRITE_REG(virt_to_phys(pdir_base), ioc->ioc_hpa + IOC_PDIR_BASE); + ASSERT((((unsigned long) ioc->pdir_base) & PAGE_MASK) == (unsigned long) ioc->pdir_base); + WRITE_REG(virt_to_phys(ioc->pdir_base), ioc->ioc_hpa + IOC_PDIR_BASE); - DBG_INIT(" base %p\n", pdir_base); + DBG_INIT(" base %p\n", ioc->pdir_base); /* build IMASK for IOC and Elroy */ iova_space_mask = 0xffffffff; - iova_space_mask <<= (iov_order + IOVP_SHIFT); - - ioc->ibase = READ_REG(ioc->ioc_hpa + IOC_IBASE) & 0xFFFFFFFEUL; - - ioc->imask = iova_space_mask; /* save it */ + iova_space_mask <<= (iov_order + PAGE_SHIFT); + ioc->imask = iova_space_mask; DBG_INIT("%s() IOV base 0x%lx mask 0x%0lx\n", __FUNCTION__, ioc->ibase, ioc->imask); /* - ** XXX DMA HINT registers are programmed with default hint + ** FIXME: Hint registers are programmed with default hint ** values during boot, so hints should be sane even if we ** can't reprogram them the way drivers want. */ - - WRITE_REG(ioc->imask, ioc->ioc_hpa+IOC_IMASK); + WRITE_REG(ioc->imask, ioc->ioc_hpa + IOC_IMASK); /* ** Setting the upper bits makes checking for bypass addresses @@ -1317,34 +1478,30 @@ */ ioc->imask |= 0xFFFFFFFF00000000UL; - /* Set I/O Pdir page size to system page size */ - switch (IOVP_SHIFT) { - case 12: /* 4K */ - tcnfg = 0; - break; - case 13: /* 8K */ - tcnfg = 1; - break; - case 14: /* 16K */ - tcnfg = 2; - break; - case 16: /* 64K */ - tcnfg = 3; + /* Set I/O PDIR Page size to system page size */ + switch (PAGE_SHIFT) { + case 12: tcnfg = 0; break; /* 4K */ + case 13: tcnfg = 1; break; /* 8K */ + case 14: tcnfg = 2; break; /* 16K */ + case 16: tcnfg = 3; break; /* 64K */ + default: + panic(PFX "Unsupported system page size %d", + 1 << PAGE_SHIFT); break; } - WRITE_REG(tcnfg, ioc->ioc_hpa+IOC_TCNFG); + WRITE_REG(tcnfg, ioc->ioc_hpa + IOC_TCNFG); /* ** Program the IOC's ibase and enable IOVA translation ** Bit zero == enable bit. */ - WRITE_REG(ioc->ibase | 1, ioc->ioc_hpa+IOC_IBASE); + WRITE_REG(ioc->ibase | 1, ioc->ioc_hpa + IOC_IBASE); /* ** Clear I/O TLB of any possible entries. ** (Yes. This is a bit paranoid...but so what) */ - WRITE_REG(0 | 31, ioc->ioc_hpa+IOC_PCOM); + WRITE_REG(ioc->ibase | (iov_order+PAGE_SHIFT), ioc->ioc_hpa + IOC_PCOM); /* ** If an AGP device is present, only use half of the IOV space @@ -1354,346 +1511,468 @@ ** We program the next pdir index after we stop w/ a key for ** the GART code to handshake on. */ - if (SBA_GET_AGP(sba_dev)) { - DBG_INIT("%s() AGP Device found, reserving 512MB for GART support\n", __FUNCTION__); + pci_for_each_dev(device) + agp_found |= pci_find_capability(device, PCI_CAP_ID_AGP); + + if (agp_found && reserve_sba_gart) { + DBG_INIT("%s: AGP device found, reserving half of IOVA for GART support\n", + __FUNCTION__); ioc->pdir_size /= 2; - ((u64 *)pdir_base)[PDIR_INDEX(iova_space_size/2)] = 0x0000badbadc0ffeeULL; + ((u64 *)ioc->pdir_base)[PDIR_INDEX(ioc->iov_size/2)] = ZX1_SBA_IOMMU_COOKIE; } +#ifdef FULL_VALID_PDIR + /* + ** Check to see if the spill page has been allocated, we don't need more than + ** one across multiple SBAs. + */ + if (!prefetch_spill_page) { + char *spill_poison = "SBAIOMMU POISON"; + int poison_size = 16; + void *poison_addr, *addr; + + addr = (void *)__get_free_pages(GFP_KERNEL, get_order(IOVP_SIZE)); + if (!addr) + panic(PFX "Couldn't allocate PDIR spill page\n"); + + poison_addr = addr; + for ( ; (u64) poison_addr < addr + IOVP_SIZE; poison_addr += poison_size) + memcpy(poison_addr, spill_poison, poison_size); + + prefetch_spill_page = virt_to_phys(addr); + + DBG_INIT("%s() prefetch spill addr: 0x%lx\n", __FUNCTION__, prefetch_spill_page); + } + /* + ** Set all the PDIR entries valid w/ the spill page as the target + */ + for (index = 0 ; index < (ioc->pdir_size / sizeof(u64)) ; index++) + ((u64 *)ioc->pdir_base)[index] = (0x80000000000000FF | prefetch_spill_page); +#endif - DBG_INIT("%s() DONE\n", __FUNCTION__); } +static void __init +ioc_resource_init(struct ioc *ioc) +{ + spin_lock_init(&ioc->res_lock); + /* resource map size dictated by pdir_size */ + ioc->res_size = ioc->pdir_size / sizeof(u64); /* entries */ + ioc->res_size >>= 3; /* convert bit count to byte count */ + DBG_INIT("%s() res_size 0x%x\n", __FUNCTION__, ioc->res_size); -/************************************************************************** -** -** SBA initialization code (HW and SW) -** -** o identify SBA chip itself -** o FIXME: initialize DMA hints for reasonable defaults -** -**************************************************************************/ + ioc->res_map = (char *) __get_free_pages(GFP_KERNEL, + get_order(ioc->res_size)); + if (!ioc->res_map) + panic(PFX "Couldn't allocate resource map\n"); -static void -sba_hw_init(struct sba_device *sba_dev) -{ - int i; - int num_ioc; - u64 dma_mask; - u32 func_id; + memset(ioc->res_map, 0, ioc->res_size); + /* next available IOVP - circular search */ + ioc->res_hint = (unsigned long *) ioc->res_map; - /* - ** Identify the SBA so we can set the dma_mask. We can make a virtual - ** dma_mask of the memory subsystem such that devices not implmenting - ** a full 64bit mask might still be able to bypass efficiently. - */ - func_id = READ_REG(sba_dev->sba_hpa + SBA_FUNC_ID); +#ifdef ASSERT_PDIR_SANITY + /* Mark first bit busy - ie no IOVA 0 */ + ioc->res_map[0] = 0x1; + ioc->pdir_base[0] = 0x8000000000000000ULL | ZX1_SBA_IOMMU_COOKIE; +#endif +#ifdef FULL_VALID_PDIR + /* Mark the last resource used so we don't prefetch beyond IOVA space */ + ioc->res_map[ioc->res_size - 1] |= 0x80UL; /* res_map is chars */ + ioc->pdir_base[(ioc->pdir_size / sizeof(u64)) - 1] = (0x80000000000000FF + | prefetch_spill_page); +#endif - if (func_id == ZX1_FUNC_ID_VALUE) { - dma_mask = 0xFFFFFFFFFFUL; - } else { - dma_mask = 0xFFFFFFFFFFFFFFFFUL; - } + DBG_INIT("%s() res_map %x %p\n", __FUNCTION__, + ioc->res_size, (void *) ioc->res_map); +} + +static void __init +ioc_sac_init(struct ioc *ioc) +{ + struct pci_dev *sac = NULL; + struct pci_controller *controller = NULL; - DBG_INIT("%s(): ioc->dma_mask == 0x%lx\n", __FUNCTION__, dma_mask); - /* - ** Leaving in the multiple ioc code from parisc for the future, - ** currently there are no muli-ioc mckinley sbas - */ - sba_dev->ioc[0].ioc_hpa = SBA_IOC_OFFSET; - num_ioc = 1; + * pci_alloc_coherent() must return a DMA address which is + * SAC (single address cycle) addressable, so allocate a + * pseudo-device to enforce that. + */ + sac = kmalloc(sizeof(*sac), GFP_KERNEL); + if (!sac) + panic(PFX "Couldn't allocate struct pci_dev"); + memset(sac, 0, sizeof(*sac)); - sba_dev->num_ioc = num_ioc; - for (i = 0; i < num_ioc; i++) { - sba_dev->ioc[i].dma_mask = dma_mask; - sba_dev->ioc[i].ioc_hpa += sba_dev->sba_hpa; - sba_ioc_init(sba_dev, &(sba_dev->ioc[i]), i); - } + controller = kmalloc(sizeof(*controller), GFP_KERNEL); + if (!controller) + panic(PFX "Couldn't allocate struct pci_controller"); + memset(controller, 0, sizeof(*controller)); + + controller->iommu = ioc; + sac->sysdata = controller; + sac->dma_mask = 0xFFFFFFFFUL; +#ifdef CONFIG_PCI + sac->dev.bus = &pci_bus_type; +#endif + ioc->sac_only_dev = sac; } -static void -sba_common_init(struct sba_device *sba_dev) +static void __init +ioc_zx1_init(struct ioc *ioc) { - int i; + if (ioc->rev < 0x20) + panic(PFX "IOC 2.0 or later required for IOMMU support\n"); - /* add this one to the head of the list (order doesn't matter) - ** This will be useful for debugging - especially if we get coredumps - */ - sba_dev->next = sba_list; - sba_list = sba_dev; - sba_count++; - - for(i=0; i< sba_dev->num_ioc; i++) { - int res_size; - - /* resource map size dictated by pdir_size */ - res_size = sba_dev->ioc[i].pdir_size/sizeof(u64); /* entries */ - res_size >>= 3; /* convert bit count to byte count */ - DBG_INIT("%s() res_size 0x%x\n", - __FUNCTION__, res_size); - - sba_dev->ioc[i].res_size = res_size; - sba_dev->ioc[i].res_map = (char *) __get_free_pages(GFP_KERNEL, get_order(res_size)); - - if (NULL == sba_dev->ioc[i].res_map) - { - panic(__FILE__ ":%s() could not allocate resource map\n", __FUNCTION__ ); - } + ioc->dma_mask = 0xFFFFFFFFFFUL; +} - memset(sba_dev->ioc[i].res_map, 0, res_size); - /* next available IOVP - circular search */ - if ((sba_dev->hw_rev & 0xFF) >= 0x20) { - sba_dev->ioc[i].res_hint = (unsigned long *) - sba_dev->ioc[i].res_map; - } else { - u64 reserved_iov; +typedef void (initfunc)(struct ioc *); - /* Yet another 1.x hack */ - printk(KERN_DEBUG "zx1 1.x: Starting resource hint offset into " - "IOV space to avoid initial zero value IOVA\n"); - sba_dev->ioc[i].res_hint = (unsigned long *) - &(sba_dev->ioc[i].res_map[L1_CACHE_BYTES]); - - sba_dev->ioc[i].res_map[0] = 0x1; - sba_dev->ioc[i].pdir_base[0] = 0x8000badbadc0ffeeULL; - - for (reserved_iov = 0xA0000 ; reserved_iov < 0xC0000 ; reserved_iov += IOVP_SIZE) { - u64 *res_ptr = (u64 *) sba_dev->ioc[i].res_map; - int index = PDIR_INDEX(reserved_iov); - int res_word; - u64 mask; - - res_word = (int)(index / BITS_PER_LONG); - mask = 0x1UL << (index - (res_word * BITS_PER_LONG)); - res_ptr[res_word] |= mask; - sba_dev->ioc[i].pdir_base[PDIR_INDEX(reserved_iov)] = (SBA_VALID_MASK | reserved_iov); +struct ioc_iommu { + u32 func_id; + char *name; + initfunc *init; +}; - } - } +static struct ioc_iommu ioc_iommu_info[] __initdata = { + { ZX1_IOC_ID, "zx1", ioc_zx1_init }, + { REO_IOC_ID, "REO" }, + { SX1000_IOC_ID, "sx1000" }, +}; -#ifdef ASSERT_PDIR_SANITY - /* Mark first bit busy - ie no IOVA 0 */ - sba_dev->ioc[i].res_map[0] = 0x1; - sba_dev->ioc[i].pdir_base[0] = 0x8000badbadc0ffeeULL; -#endif +static struct ioc * __init +ioc_init(u64 hpa, void *handle) +{ + struct ioc *ioc; + struct ioc_iommu *info; + + ioc = kmalloc(sizeof(*ioc), GFP_KERNEL); + if (!ioc) + return NULL; + + memset(ioc, 0, sizeof(*ioc)); - DBG_INIT("%s() %d res_map %x %p\n", __FUNCTION__, - i, res_size, (void *)sba_dev->ioc[i].res_map); + ioc->next = ioc_list; + ioc_list = ioc; + + ioc->handle = handle; + ioc->ioc_hpa = ioremap(hpa, 0x1000); + + ioc->func_id = READ_REG(ioc->ioc_hpa + IOC_FUNC_ID); + ioc->rev = READ_REG(ioc->ioc_hpa + IOC_FCLASS) & 0xFFUL; + ioc->dma_mask = 0xFFFFFFFFFFFFFFFFUL; /* conservative */ + + for (info = ioc_iommu_info; info < ioc_iommu_info + ARRAY_SIZE(ioc_iommu_info); info++) { + if (ioc->func_id == info->func_id) { + ioc->name = info->name; + if (info->init) + (info->init)(ioc); + } } - sba_dev->sba_lock = SPIN_LOCK_UNLOCKED; + if (!ioc->name) { + ioc->name = kmalloc(24, GFP_KERNEL); + if (ioc->name) + sprintf((char *) ioc->name, "Unknown (%04x:%04x)", + ioc->func_id & 0xFFFF, (ioc->func_id >> 16) & 0xFFFF); + else + ioc->name = "Unknown"; + } + + ioc_iova_init(ioc); + ioc_resource_init(ioc); + ioc_sac_init(ioc); + + printk(KERN_INFO PFX + "%s %d.%d HPA 0x%lx IOVA space %dMb at 0x%lx\n", + ioc->name, (ioc->rev >> 4) & 0xF, ioc->rev & 0xF, + hpa, ioc->iov_size >> 20, ioc->ibase); + + return ioc; } + + +/************************************************************************** +** +** SBA initialization code (HW and SW) +** +** o identify SBA chip itself +** o FIXME: initialize DMA hints for reasonable defaults +** +**************************************************************************/ + #ifdef CONFIG_PROC_FS -static int sba_proc_info(char *buf, char **start, off_t offset, int len) +static void * +ioc_start(struct seq_file *s, loff_t *pos) { - struct sba_device *sba_dev; struct ioc *ioc; - int total_pages; + loff_t n = *pos; + + for (ioc = ioc_list; ioc; ioc = ioc->next) + if (!n--) + return ioc; + + return NULL; +} + +static void * +ioc_next(struct seq_file *s, void *v, loff_t *pos) +{ + struct ioc *ioc = v; + + ++*pos; + return ioc->next; +} + +static void +ioc_stop(struct seq_file *s, void *v) +{ +} + +static int +ioc_show(struct seq_file *s, void *v) +{ + struct ioc *ioc = v; + int total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */ unsigned long i = 0, avg = 0, min, max; - for (sba_dev = sba_list; sba_dev; sba_dev = sba_dev->next) { - ioc = &sba_dev->ioc[0]; /* FIXME: Multi-IOC support! */ - total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */ - - sprintf(buf, "%s rev %d.%d\n", "Hewlett-Packard zx1 SBA", - ((sba_dev->hw_rev >> 4) & 0xF), (sba_dev->hw_rev & 0xF)); - sprintf(buf, "%sIO PDIR size : %d bytes (%d entries)\n", buf, - (int) ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits/byte */ total_pages); - - sprintf(buf, "%sIO PDIR entries : %ld free %ld used (%d%%)\n", buf, - total_pages - ioc->used_pages, ioc->used_pages, - (int) (ioc->used_pages * 100 / total_pages)); - - sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n", - buf, ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */ - - min = max = ioc->avg_search[0]; - for (i = 0; i < SBA_SEARCH_SAMPLE; i++) { - avg += ioc->avg_search[i]; - if (ioc->avg_search[i] > max) max = ioc->avg_search[i]; - if (ioc->avg_search[i] < min) min = ioc->avg_search[i]; - } - avg /= SBA_SEARCH_SAMPLE; - sprintf(buf, "%s Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", - buf, min, avg, max); - - sprintf(buf, "%spci_map_single(): %12ld calls %12ld pages (avg %d/1000)\n", - buf, ioc->msingle_calls, ioc->msingle_pages, - (int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls)); + seq_printf(s, "Hewlett Packard %s IOC rev %d.%d\n", + ioc->name, ((ioc->rev >> 4) & 0xF), (ioc->rev & 0xF)); + seq_printf(s, "IO PDIR size : %d bytes (%d entries)\n", + (int) ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits/byte */ + total_pages); + + seq_printf(s, "IO PDIR entries : %ld free %ld used (%d%%)\n", + total_pages - ioc->used_pages, ioc->used_pages, + (int) (ioc->used_pages * 100 / total_pages)); + + seq_printf(s, "Resource bitmap : %d bytes (%d pages)\n", + ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */ + + min = max = ioc->avg_search[0]; + for (i = 0; i < SBA_SEARCH_SAMPLE; i++) { + avg += ioc->avg_search[i]; + if (ioc->avg_search[i] > max) max = ioc->avg_search[i]; + if (ioc->avg_search[i] < min) min = ioc->avg_search[i]; + } + avg /= SBA_SEARCH_SAMPLE; + seq_printf(s, " Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", min, avg, max); + + seq_printf(s, "pci_map_single(): %12ld calls %12ld pages (avg %d/1000)\n", + ioc->msingle_calls, ioc->msingle_pages, + (int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls)); #ifdef ALLOW_IOV_BYPASS - sprintf(buf, "%spci_map_single(): %12ld bypasses\n", - buf, ioc->msingle_bypass); + seq_printf(s, "pci_map_single(): %12ld bypasses\n", ioc->msingle_bypass); #endif - sprintf(buf, "%spci_unmap_single: %12ld calls %12ld pages (avg %d/1000)\n", - buf, ioc->usingle_calls, ioc->usingle_pages, - (int) ((ioc->usingle_pages * 1000)/ioc->usingle_calls)); + seq_printf(s, "pci_unmap_single: %12ld calls %12ld pages (avg %d/1000)\n", + ioc->usingle_calls, ioc->usingle_pages, + (int) ((ioc->usingle_pages * 1000)/ioc->usingle_calls)); #ifdef ALLOW_IOV_BYPASS - sprintf(buf, "%spci_unmap_single: %12ld bypasses\n", - buf, ioc->usingle_bypass); + seq_printf(s, "pci_unmap_single: %12ld bypasses\n", ioc->usingle_bypass); #endif - sprintf(buf, "%spci_map_sg() : %12ld calls %12ld pages (avg %d/1000)\n", - buf, ioc->msg_calls, ioc->msg_pages, - (int) ((ioc->msg_pages * 1000)/ioc->msg_calls)); + seq_printf(s, "pci_map_sg() : %12ld calls %12ld pages (avg %d/1000)\n", + ioc->msg_calls, ioc->msg_pages, + (int) ((ioc->msg_pages * 1000)/ioc->msg_calls)); #ifdef ALLOW_IOV_BYPASS - sprintf(buf, "%spci_map_sg() : %12ld bypasses\n", - buf, ioc->msg_bypass); + seq_printf(s, "pci_map_sg() : %12ld bypasses\n", ioc->msg_bypass); #endif - sprintf(buf, "%spci_unmap_sg() : %12ld calls %12ld pages (avg %d/1000)\n", - buf, ioc->usg_calls, ioc->usg_pages, - (int) ((ioc->usg_pages * 1000)/ioc->usg_calls)); - } - return strlen(buf); + seq_printf(s, "pci_unmap_sg() : %12ld calls %12ld pages (avg %d/1000)\n", + ioc->usg_calls, ioc->usg_pages, (int) ((ioc->usg_pages * 1000)/ioc->usg_calls)); + + return 0; } +static struct seq_operations ioc_seq_ops = { + .start = ioc_start, + .next = ioc_next, + .stop = ioc_stop, + .show = ioc_show +}; + static int -sba_resource_map(char *buf, char **start, off_t offset, int len) +ioc_open(struct inode *inode, struct file *file) { - struct ioc *ioc = sba_list->ioc; /* FIXME: Multi-IOC support! */ - unsigned int *res_ptr; - int i; + return seq_open(file, &ioc_seq_ops); +} - if (!ioc) - return 0; +static struct file_operations ioc_fops = { + .open = ioc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release +}; - res_ptr = (unsigned int *)ioc->res_map; - buf[0] = '\0'; - for(i = 0; i < (ioc->res_size / sizeof(unsigned int)); ++i, ++res_ptr) { - if ((i & 7) == 0) - strcat(buf,"\n "); - sprintf(buf, "%s %08x", buf, *res_ptr); - } - strcat(buf, "\n"); +static int +ioc_map_show(struct seq_file *s, void *v) +{ + struct ioc *ioc = v; + unsigned int i, *res_ptr = (unsigned int *)ioc->res_map; - return strlen(buf); + for (i = 0; i < ioc->res_size / sizeof(unsigned int); ++i, ++res_ptr) + seq_printf(s, "%s%08x", (i & 7) ? " " : "\n ", *res_ptr); + seq_printf(s, "\n"); + + return 0; } -#endif -/* -** Determine if sba should claim this chip (return 0) or not (return 1). -** If so, initialize the chip and tell other partners in crime they -** have work to do. -*/ -void __init sba_init(void) +static struct seq_operations ioc_map_ops = { + .start = ioc_start, + .next = ioc_next, + .stop = ioc_stop, + .show = ioc_map_show +}; + +static int +ioc_map_open(struct inode *inode, struct file *file) { - struct sba_device *sba_dev; - u32 func_id, hw_rev; - u32 *func_offset = NULL; - int i, agp_found = 0; - static char sba_rev[6]; - struct pci_dev *device = NULL; - u64 hpa = 0; + return seq_open(file, &ioc_map_ops); +} - if (!(device = pci_find_device(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_ZX1_SBA, NULL))) - return; +static struct file_operations ioc_map_fops = { + .open = ioc_map_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release +}; - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - if (pci_resource_flags(device, i) == IORESOURCE_MEM) { - hpa = (u64) ioremap(pci_resource_start(device, i), - pci_resource_len(device, i)); - break; - } +static void __init +ioc_proc_init(void) +{ + if (ioc_list) { + struct proc_dir_entry *dir, *entry; + + dir = proc_mkdir("bus/mckinley", 0); + entry = create_proc_entry(ioc_list->name, 0, dir); + if (entry) + entry->proc_fops = &ioc_fops; + + entry = create_proc_entry("bitmap", 0, dir); + if (entry) + entry->proc_fops = &ioc_map_fops; } +} +#endif - func_id = READ_REG(hpa + SBA_FUNC_ID); - if (func_id != ZX1_FUNC_ID_VALUE) - return; +void +sba_connect_bus(struct pci_bus *bus) +{ + acpi_handle handle, parent; + acpi_status status; + struct ioc *ioc; - strcpy(sba_rev, "zx1"); - func_offset = zx1_func_offsets; + if (!PCI_CONTROLLER(bus)) + panic(PFX "no sysdata on bus %d!\n",bus->number); - /* Read HW Rev First */ - hw_rev = READ_REG(hpa + SBA_FCLASS) & 0xFFUL; + if (PCI_CONTROLLER(bus)->iommu) + return; + + handle = PCI_CONTROLLER(bus)->acpi_handle; + if (!handle) + return; /* - * Not all revision registers of the chipset are updated on every - * turn. Must scan through all functions looking for the highest rev + * The IOC scope encloses PCI root bridges in the ACPI + * namespace, so work our way out until we find an IOC we + * claimed previously. */ - if (func_offset) { - for (i = 0 ; func_offset[i] != -1 ; i++) { - u32 func_rev; - - func_rev = READ_REG(hpa + SBA_FCLASS + func_offset[i]) & 0xFFUL; - DBG_INIT("%s() func offset: 0x%x rev: 0x%x\n", - __FUNCTION__, func_offset[i], func_rev); - if (func_rev > hw_rev) - hw_rev = func_rev; - } - } - - printk(KERN_INFO "%s found %s %d.%d at %s, HPA 0x%lx\n", DRIVER_NAME, - sba_rev, ((hw_rev >> 4) & 0xF), (hw_rev & 0xF), - device->slot_name, hpa); + do { + for (ioc = ioc_list; ioc; ioc = ioc->next) + if (ioc->handle == handle) { + PCI_CONTROLLER(bus)->iommu = ioc; + return; + } - if ((hw_rev & 0xFF) < 0x20) { - printk(KERN_INFO "%s: SBA rev less than 2.0 not supported", DRIVER_NAME); - return; - } + status = acpi_get_parent(handle, &parent); + handle = parent; + } while (ACPI_SUCCESS(status)); - sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL); - if (NULL == sba_dev) { - printk(KERN_ERR DRIVER_NAME " - couldn't alloc sba_device\n"); - return; - } + printk(KERN_WARNING "No IOC for PCI Bus %02x:%02x in ACPI\n", PCI_SEGMENT(bus), bus->number); +} - memset(sba_dev, 0, sizeof(struct sba_device)); +static int __init +acpi_sba_ioc_add(struct acpi_device *device) +{ + struct ioc *ioc; + acpi_status status; + u64 hpa, length; + struct acpi_device_info dev_info; - for(i=0; iioc[i].res_lock)); + status = hp_acpi_csr_space(device->handle, &hpa, &length); + if (ACPI_FAILURE(status)) + return 1; - sba_dev->hw_rev = hw_rev; - sba_dev->sba_hpa = hpa; + status = acpi_get_object_info(device->handle, &dev_info); + if (ACPI_FAILURE(status)) + return 1; /* - * We pass this fake device from alloc_consistent to ensure - * we only use SAC for alloc_consistent mappings. + * For HWP0001, only SBA appears in ACPI namespace. It encloses the PCI + * root bridges, and its CSR space includes the IOC function. */ - sac_only_dev.dma_mask = 0xFFFFFFFFUL; + if (strncmp("HWP0001", dev_info.hardware_id, 7) == 0) + hpa += ZX1_IOC_OFFSET; - /* - * We need to check for an AGP device, if we find one, then only - * use part of the IOVA space for PCI DMA, the rest is for GART. - * REVISIT for multiple IOC. - */ - pci_for_each_dev(device) - agp_found |= pci_find_capability(device, PCI_CAP_ID_AGP); + ioc = ioc_init(hpa, device->handle); + if (!ioc) + return 1; - if (agp_found && reserve_sba_gart) - SBA_SET_AGP(sba_dev); + return 0; +} - sba_hw_init(sba_dev); - sba_common_init(sba_dev); +static struct acpi_driver acpi_sba_ioc_driver = { + name: "IOC IOMMU Driver", + ids: "HWP0001,HWP0004", + ops: { + add: acpi_sba_ioc_add, + }, +}; -#ifdef CONFIG_PROC_FS - { - struct proc_dir_entry * proc_mckinley_root; +static int __init +sba_init(void) +{ + MAX_DMA_ADDRESS = ~0UL; + + acpi_bus_register_driver(&acpi_sba_ioc_driver); - proc_mckinley_root = proc_mkdir("bus/mckinley",0); - create_proc_info_entry(sba_rev, 0, proc_mckinley_root, sba_proc_info); - create_proc_info_entry("bitmap", 0, proc_mckinley_root, sba_resource_map); +#ifdef CONFIG_PCI + { + struct pci_bus *b; + pci_for_each_bus(b) + sba_connect_bus(b); } #endif + +#ifdef CONFIG_PROC_FS + ioc_proc_init(); +#endif + return 0; } +subsys_initcall(sba_init); /* must be initialized after ACPI etc., but before any drivers... */ + static int __init -nosbagart (char *str) +nosbagart(char *str) { reserve_sba_gart = 0; return 1; } -__setup("nosbagart",nosbagart); +int +sba_dma_supported (struct device *dev, u64 mask) +{ + /* make sure it's at least 32bit capable */ + return ((mask & 0xFFFFFFFFUL) == 0xFFFFFFFFUL); +} + +__setup("nosbagart", nosbagart); -EXPORT_SYMBOL(sba_init); EXPORT_SYMBOL(sba_map_single); EXPORT_SYMBOL(sba_unmap_single); EXPORT_SYMBOL(sba_map_sg); EXPORT_SYMBOL(sba_unmap_sg); -EXPORT_SYMBOL(sba_dma_address); EXPORT_SYMBOL(sba_dma_supported); -EXPORT_SYMBOL(sba_alloc_consistent); -EXPORT_SYMBOL(sba_free_consistent); +EXPORT_SYMBOL(sba_alloc_coherent); +EXPORT_SYMBOL(sba_free_coherent); diff -Nru a/arch/ia64/hp/sim/hpsim_console.c b/arch/ia64/hp/sim/hpsim_console.c --- a/arch/ia64/hp/sim/hpsim_console.c Sat May 24 12:48:31 2003 +++ b/arch/ia64/hp/sim/hpsim_console.c Sat May 24 12:48:31 2003 @@ -59,7 +59,7 @@ static struct tty_driver *simcons_console_device (struct console *c, int *index) { - extern struct tty_driver hp_serial_driver; + extern struct tty_driver hp_simserial_driver; *index = c->index; - return &hp_serial_driver; + return &hp_simserial_driver; } diff -Nru a/arch/ia64/hp/sim/hpsim_machvec.c b/arch/ia64/hp/sim/hpsim_machvec.c --- a/arch/ia64/hp/sim/hpsim_machvec.c Sat May 24 12:48:25 2003 +++ b/arch/ia64/hp/sim/hpsim_machvec.c Sat May 24 12:48:25 2003 @@ -1,2 +1,3 @@ -#define MACHVEC_PLATFORM_NAME hpsim +#define MACHVEC_PLATFORM_NAME hpsim +#define MACHVEC_PLATFORM_HEADER #include diff -Nru a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c --- a/arch/ia64/hp/sim/simeth.c Sat May 24 12:48:26 2003 +++ b/arch/ia64/hp/sim/simeth.c Sat May 24 12:48:26 2003 @@ -55,7 +55,7 @@ static int simeth_tx(struct sk_buff *skb, struct net_device *dev); static int simeth_rx(struct net_device *dev); static struct net_device_stats *simeth_get_stats(struct net_device *dev); -static void simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs); +static irqreturn_t simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs); static void set_multicast_list(struct net_device *dev); static int simeth_device_event(struct notifier_block *this,unsigned long event, void *ptr); @@ -494,20 +494,21 @@ /* * Interrupt handler (Yes, we can do it too !!!) */ -static void +static irqreturn_t simeth_interrupt(int irq, void *dev_id, struct pt_regs * regs) { struct net_device *dev = dev_id; if ( dev == NULL ) { printk(KERN_WARNING "simeth: irq %d for unknown device\n", irq); - return; + return IRQ_NONE; } /* - * very simple loop because we get interrupts only when receving + * very simple loop because we get interrupts only when receiving */ while (simeth_rx(dev)); + return IRQ_HANDLED; } static struct net_device_stats * diff -Nru a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c --- a/arch/ia64/hp/sim/simscsi.c Sat May 24 12:48:24 2003 +++ b/arch/ia64/hp/sim/simscsi.c Sat May 24 12:48:24 2003 @@ -386,6 +386,19 @@ return 0; } -static Scsi_Host_Template driver_template = SIMSCSI; - +static Scsi_Host_Template driver_template = { + .name = "simscsi", + .detect = simscsi_detect, + .release = simscsi_release, + .info = simscsi_info, + .queuecommand = simscsi_queuecommand, + .eh_host_reset_handler = simscsi_host_reset, + .bios_param = simscsi_biosparam, + .can_queue = SIMSCSI_REQ_QUEUE_LEN, + .this_id = -1, + .sg_tablesize = SG_ALL, + .max_sectors = 1024, + .cmd_per_lun = SIMSCSI_REQ_QUEUE_LEN, + .use_clustering = DISABLE_CLUSTERING, +}; #include "../drivers/scsi/scsi_module.c" diff -Nru a/arch/ia64/hp/sim/simscsi.h b/arch/ia64/hp/sim/simscsi.h --- a/arch/ia64/hp/sim/simscsi.h Sat May 24 12:48:19 2003 +++ b/arch/ia64/hp/sim/simscsi.h Sat May 24 12:48:19 2003 @@ -20,22 +20,4 @@ extern int simscsi_biosparam (struct scsi_device *, struct block_device *, sector_t, int[]); -#define SIMSCSI { \ - .name = "simscsi", \ - .detect = simscsi_detect, \ - .release = simscsi_release, \ - .info = simscsi_info, \ - .queuecommand = simscsi_queuecommand, \ - .eh_host_reset_handler = simscsi_host_reset, \ - .bios_param = simscsi_biosparam, \ - .can_queue = SIMSCSI_REQ_QUEUE_LEN, \ - .this_id = -1, \ - .sg_tablesize = SG_ALL, \ - .max_sectors = 1024, \ - .cmd_per_lun = SIMSCSI_REQ_QUEUE_LEN, \ - .present = 0, \ - .unchecked_isa_dma = 0, \ - .use_clustering = DISABLE_CLUSTERING \ -} - #endif /* SIMSCSI_H */ diff -Nru a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c --- a/arch/ia64/hp/sim/simserial.c Sat May 24 12:48:24 2003 +++ b/arch/ia64/hp/sim/simserial.c Sat May 24 12:48:24 2003 @@ -103,7 +103,8 @@ { 0, 0} }; -static struct tty_driver hp_serial_driver, callout_driver; +struct tty_driver hp_simserial_driver; +static struct tty_driver callout_driver; static int serial_refcount; static struct async_struct *IRQ_ports[NR_IRQS]; @@ -184,7 +185,7 @@ /* * This is the serial driver's interrupt routine for a single port */ -static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs) +static irqreturn_t rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs) { struct async_struct * info; @@ -195,13 +196,14 @@ info = IRQ_ports[irq]; if (!info || !info->tty) { printk(KERN_INFO "simrs_interrupt_single: info|tty=0 info=%p problem\n", info); - return; + return IRQ_NONE; } /* * pretty simple in our case, because we only get interrupts * on inbound traffic */ receive_chars(info->tty, regs); + return IRQ_HANDLED; } /* @@ -768,7 +770,7 @@ { unsigned long flags; int retval=0; - void (*handler)(int, void *, struct pt_regs *); + irqreturn_t (*handler)(int, void *, struct pt_regs *); struct serial_state *state= info->state; unsigned long page; @@ -808,8 +810,7 @@ } else handler = rs_interrupt_single; - retval = request_irq(state->irq, handler, IRQ_T(info), - "simserial", NULL); + retval = request_irq(state->irq, handler, IRQ_T(info), "simserial", NULL); if (retval) { if (capable(CAP_SYS_ADMIN)) { if (info->tty) @@ -1028,43 +1029,43 @@ /* Initialize the tty_driver structure */ - memset(&hp_serial_driver, 0, sizeof(struct tty_driver)); - hp_serial_driver.magic = TTY_DRIVER_MAGIC; - hp_serial_driver.driver_name = "simserial"; - hp_serial_driver.name = "ttyS"; - hp_serial_driver.major = TTY_MAJOR; - hp_serial_driver.minor_start = 64; - hp_serial_driver.num = 1; - hp_serial_driver.type = TTY_DRIVER_TYPE_SERIAL; - hp_serial_driver.subtype = SERIAL_TYPE_NORMAL; - hp_serial_driver.init_termios = tty_std_termios; - hp_serial_driver.init_termios.c_cflag = + memset(&hp_simserial_driver, 0, sizeof(struct tty_driver)); + hp_simserial_driver.magic = TTY_DRIVER_MAGIC; + hp_simserial_driver.driver_name = "simserial"; + hp_simserial_driver.name = "ttyS"; + hp_simserial_driver.major = TTY_MAJOR; + hp_simserial_driver.minor_start = 64; + hp_simserial_driver.num = 1; + hp_simserial_driver.type = TTY_DRIVER_TYPE_SERIAL; + hp_simserial_driver.subtype = SERIAL_TYPE_NORMAL; + hp_simserial_driver.init_termios = tty_std_termios; + hp_simserial_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - hp_serial_driver.flags = TTY_DRIVER_REAL_RAW; - hp_serial_driver.refcount = &serial_refcount; - hp_serial_driver.table = serial_table; - hp_serial_driver.termios = serial_termios; - hp_serial_driver.termios_locked = serial_termios_locked; - - hp_serial_driver.open = rs_open; - hp_serial_driver.close = rs_close; - hp_serial_driver.write = rs_write; - hp_serial_driver.put_char = rs_put_char; - hp_serial_driver.flush_chars = rs_flush_chars; - hp_serial_driver.write_room = rs_write_room; - hp_serial_driver.chars_in_buffer = rs_chars_in_buffer; - hp_serial_driver.flush_buffer = rs_flush_buffer; - hp_serial_driver.ioctl = rs_ioctl; - hp_serial_driver.throttle = rs_throttle; - hp_serial_driver.unthrottle = rs_unthrottle; - hp_serial_driver.send_xchar = rs_send_xchar; - hp_serial_driver.set_termios = rs_set_termios; - hp_serial_driver.stop = rs_stop; - hp_serial_driver.start = rs_start; - hp_serial_driver.hangup = rs_hangup; - hp_serial_driver.break_ctl = rs_break; - hp_serial_driver.wait_until_sent = rs_wait_until_sent; - hp_serial_driver.read_proc = rs_read_proc; + hp_simserial_driver.flags = TTY_DRIVER_REAL_RAW; + hp_simserial_driver.refcount = &serial_refcount; + hp_simserial_driver.table = serial_table; + hp_simserial_driver.termios = serial_termios; + hp_simserial_driver.termios_locked = serial_termios_locked; + + hp_simserial_driver.open = rs_open; + hp_simserial_driver.close = rs_close; + hp_simserial_driver.write = rs_write; + hp_simserial_driver.put_char = rs_put_char; + hp_simserial_driver.flush_chars = rs_flush_chars; + hp_simserial_driver.write_room = rs_write_room; + hp_simserial_driver.chars_in_buffer = rs_chars_in_buffer; + hp_simserial_driver.flush_buffer = rs_flush_buffer; + hp_simserial_driver.ioctl = rs_ioctl; + hp_simserial_driver.throttle = rs_throttle; + hp_simserial_driver.unthrottle = rs_unthrottle; + hp_simserial_driver.send_xchar = rs_send_xchar; + hp_simserial_driver.set_termios = rs_set_termios; + hp_simserial_driver.stop = rs_stop; + hp_simserial_driver.start = rs_start; + hp_simserial_driver.hangup = rs_hangup; + hp_simserial_driver.break_ctl = rs_break; + hp_simserial_driver.wait_until_sent = rs_wait_until_sent; + hp_simserial_driver.read_proc = rs_read_proc; /* * Let's have a little bit of fun ! @@ -1087,14 +1088,14 @@ * The callout device is just like normal device except for * major number and the subtype code. */ - callout_driver = hp_serial_driver; + callout_driver = hp_simserial_driver; callout_driver.name = "cua"; callout_driver.major = TTYAUX_MAJOR; callout_driver.subtype = SERIAL_TYPE_CALLOUT; callout_driver.read_proc = 0; callout_driver.proc_entry = 0; - if (tty_register_driver(&hp_serial_driver)) + if (tty_register_driver(&hp_simserial_driver)) panic("Couldn't register simserial driver\n"); if (tty_register_driver(&callout_driver)) diff -Nru a/arch/ia64/hp/zx1/Makefile b/arch/ia64/hp/zx1/Makefile --- a/arch/ia64/hp/zx1/Makefile Sat May 24 12:48:32 2003 +++ b/arch/ia64/hp/zx1/Makefile Sat May 24 12:48:32 2003 @@ -5,5 +5,4 @@ # Copyright (C) Alex Williamson (alex_williamson@hp.com) # -obj-y := hpzx1_misc.o obj-$(CONFIG_IA64_GENERIC) += hpzx1_machvec.o diff -Nru a/arch/ia64/hp/zx1/hpzx1_machvec.c b/arch/ia64/hp/zx1/hpzx1_machvec.c --- a/arch/ia64/hp/zx1/hpzx1_machvec.c Sat May 24 12:48:23 2003 +++ b/arch/ia64/hp/zx1/hpzx1_machvec.c Sat May 24 12:48:23 2003 @@ -1,2 +1,3 @@ -#define MACHVEC_PLATFORM_NAME hpzx1 +#define MACHVEC_PLATFORM_NAME hpzx1 +#define MACHVEC_PLATFORM_HEADER #include diff -Nru a/arch/ia64/hp/zx1/hpzx1_misc.c b/arch/ia64/hp/zx1/hpzx1_misc.c --- a/arch/ia64/hp/zx1/hpzx1_misc.c Sat May 24 12:48:24 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,348 +0,0 @@ -/* - * Misc. support for HP zx1 chipset support - * - * Copyright (C) 2002-2003 Hewlett-Packard Co - * Alex Williamson - * Bjorn Helgaas - */ - - -#include -#include -#include -#include -#include -#include - -#include -#include - -extern acpi_status acpi_evaluate_integer (acpi_handle, acpi_string, struct acpi_object_list *, - unsigned long *); - -#define PFX "hpzx1: " - -static int hpzx1_devices; - -struct fake_pci_dev { - struct fake_pci_dev *next; - struct pci_dev *pci_dev; - unsigned long csr_base; - unsigned long csr_size; - unsigned long mapped_csrs; // ioremapped - int sizing; // in middle of BAR sizing operation? -} *fake_pci_dev_list; - -static struct pci_ops *orig_pci_ops; - -struct fake_pci_dev * -lookup_fake_dev (struct pci_bus *bus, unsigned int devfn) -{ - struct fake_pci_dev *fake_dev; - - for (fake_dev = fake_pci_dev_list; fake_dev; fake_dev = fake_dev->next) - if (fake_dev->pci_dev->bus == bus && fake_dev->pci_dev->devfn == devfn) - return fake_dev; - return NULL; -} - -static int -hp_cfg_read (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) -{ - struct fake_pci_dev *fake_dev = lookup_fake_dev(bus, devfn); - - if (!fake_dev) - return (*orig_pci_ops->read)(bus, devfn, where, size, value); - - if (where == PCI_BASE_ADDRESS_0) { - if (fake_dev->sizing) - *value = ~(fake_dev->csr_size - 1); - else - *value = ((fake_dev->csr_base & PCI_BASE_ADDRESS_MEM_MASK) - | PCI_BASE_ADDRESS_SPACE_MEMORY); - fake_dev->sizing = 0; - return PCIBIOS_SUCCESSFUL; - } - switch (size) { - case 1: *value = readb(fake_dev->mapped_csrs + where); break; - case 2: *value = readw(fake_dev->mapped_csrs + where); break; - case 4: *value = readl(fake_dev->mapped_csrs + where); break; - default: - printk(KERN_WARNING"hp_cfg_read: bad size = %d bytes", size); - break; - } - if (where == PCI_COMMAND) - *value |= PCI_COMMAND_MEMORY; /* SBA omits this */ - return PCIBIOS_SUCCESSFUL; -} - -static int -hp_cfg_write (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) -{ - struct fake_pci_dev *fake_dev = lookup_fake_dev(bus, devfn); - - if (!fake_dev) - return (*orig_pci_ops->write)(bus, devfn, where, size, value); - - if (where == PCI_BASE_ADDRESS_0) { - if (value == ((1UL << 8*size) - 1)) - fake_dev->sizing = 1; - return PCIBIOS_SUCCESSFUL; - } - switch (size) { - case 1: writeb(value, fake_dev->mapped_csrs + where); break; - case 2: writew(value, fake_dev->mapped_csrs + where); break; - case 4: writel(value, fake_dev->mapped_csrs + where); break; - default: - printk(KERN_WARNING"hp_cfg_write: bad size = %d bytes", size); - break; - } - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops hp_pci_conf = { - .read = hp_cfg_read, - .write = hp_cfg_write -}; - -static void -hpzx1_fake_pci_dev(char *name, unsigned int busnum, unsigned long addr, unsigned int size) -{ - struct fake_pci_dev *fake; - int slot, ret; - struct pci_dev *dev; - struct pci_bus *b, *bus = NULL; - u8 hdr; - - fake = kmalloc(sizeof(*fake), GFP_KERNEL); - if (!fake) { - printk(KERN_ERR PFX "No memory for %s (0x%p) sysdata\n", name, (void *) addr); - return; - } - - memset(fake, 0, sizeof(*fake)); - fake->csr_base = addr; - fake->csr_size = size; - fake->mapped_csrs = (unsigned long) ioremap(addr, size); - fake->sizing = 0; - - pci_for_each_bus(b) - if (busnum == b->number) { - bus = b; - break; - } - - if (!bus) { - printk(KERN_ERR PFX "No host bus 0x%02x for %s (0x%p)\n", - busnum, name, (void *) addr); - kfree(fake); - return; - } - - for (slot = 0x1e; slot; slot--) - if (!pci_find_slot(busnum, PCI_DEVFN(slot, 0))) - break; - - if (slot < 0) { - printk(KERN_ERR PFX "No space for %s (0x%p) on bus 0x%02x\n", - name, (void *) addr, busnum); - kfree(fake); - return; - } - - dev = kmalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) { - printk(KERN_ERR PFX "No memory for %s (0x%p)\n", name, (void *) addr); - kfree(fake); - return; - } - - bus->ops = &hp_pci_conf; // replace pci ops for this bus - - fake->pci_dev = dev; - fake->next = fake_pci_dev_list; - fake_pci_dev_list = fake; - - memset(dev, 0, sizeof(*dev)); - dev->bus = bus; - dev->sysdata = fake; - dev->dev.parent = bus->dev; - dev->dev.bus = &pci_bus_type; - dev->devfn = PCI_DEVFN(slot, 0); - pci_read_config_word(dev, PCI_VENDOR_ID, &dev->vendor); - pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device); - pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr); - dev->hdr_type = hdr & 0x7f; - - pci_setup_device(dev); - - // pci_insert_device() without running /sbin/hotplug - list_add_tail(&dev->bus_list, &bus->devices); - list_add_tail(&dev->global_list, &pci_devices); - - strcpy(dev->dev.bus_id, dev->slot_name); - ret = device_register(&dev->dev); - if (ret < 0) - printk(KERN_INFO PFX "fake device registration failed (%d)\n", ret); - - printk(KERN_INFO PFX "%s at 0x%lx; pci dev %s\n", name, addr, dev->slot_name); - - hpzx1_devices++; -} - -struct acpi_hp_vendor_long { - u8 guid_id; - u8 guid[16]; - u8 csr_base[8]; - u8 csr_length[8]; -}; - -#define HP_CCSR_LENGTH 0x21 -#define HP_CCSR_TYPE 0x2 -#define HP_CCSR_GUID EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, \ - 0xf6, 0x4a, 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad) - -extern acpi_status acpi_get_crs(acpi_handle, struct acpi_buffer *); -extern struct acpi_resource *acpi_get_crs_next(struct acpi_buffer *, int *); -extern union acpi_resource_data *acpi_get_crs_type(struct acpi_buffer *, int *, int); -extern void acpi_dispose_crs(struct acpi_buffer *); - -static acpi_status -hp_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length) -{ - int i, offset = 0; - acpi_status status; - struct acpi_buffer buf; - struct acpi_resource_vendor *res; - struct acpi_hp_vendor_long *hp_res; - efi_guid_t vendor_guid; - - *csr_base = 0; - *csr_length = 0; - - status = acpi_get_crs(obj, &buf); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PFX "Unable to get _CRS data on object\n"); - return status; - } - - res = (struct acpi_resource_vendor *)acpi_get_crs_type(&buf, &offset, ACPI_RSTYPE_VENDOR); - if (!res) { - printk(KERN_ERR PFX "Failed to find config space for device\n"); - acpi_dispose_crs(&buf); - return AE_NOT_FOUND; - } - - hp_res = (struct acpi_hp_vendor_long *)(res->reserved); - - if (res->length != HP_CCSR_LENGTH || hp_res->guid_id != HP_CCSR_TYPE) { - printk(KERN_ERR PFX "Unknown Vendor data\n"); - acpi_dispose_crs(&buf); - return AE_TYPE; /* Revisit error? */ - } - - memcpy(&vendor_guid, hp_res->guid, sizeof(efi_guid_t)); - if (efi_guidcmp(vendor_guid, HP_CCSR_GUID) != 0) { - printk(KERN_ERR PFX "Vendor GUID does not match\n"); - acpi_dispose_crs(&buf); - return AE_TYPE; /* Revisit error? */ - } - - for (i = 0 ; i < 8 ; i++) { - *csr_base |= ((u64)(hp_res->csr_base[i]) << (i * 8)); - *csr_length |= ((u64)(hp_res->csr_length[i]) << (i * 8)); - } - - acpi_dispose_crs(&buf); - - return AE_OK; -} - -static acpi_status -hpzx1_sba_probe(acpi_handle obj, u32 depth, void *context, void **ret) -{ - u64 csr_base = 0, csr_length = 0; - acpi_status status; - char *name = context; - char fullname[16]; - - status = hp_csr_space(obj, &csr_base, &csr_length); - if (ACPI_FAILURE(status)) - return status; - - /* - * Only SBA shows up in ACPI namespace, so its CSR space - * includes both SBA and IOC. Make SBA and IOC show up - * separately in PCI space. - */ - sprintf(fullname, "%s SBA", name); - hpzx1_fake_pci_dev(fullname, 0, csr_base, 0x1000); - sprintf(fullname, "%s IOC", name); - hpzx1_fake_pci_dev(fullname, 0, csr_base + 0x1000, 0x1000); - - return AE_OK; -} - -static acpi_status -hpzx1_lba_probe(acpi_handle obj, u32 depth, void *context, void **ret) -{ - u64 csr_base = 0, csr_length = 0; - acpi_status status; - acpi_native_uint busnum; - char *name = context; - char fullname[32]; - - status = hp_csr_space(obj, &csr_base, &csr_length); - if (ACPI_FAILURE(status)) - return status; - - status = acpi_evaluate_integer(obj, METHOD_NAME__BBN, NULL, &busnum); - if (ACPI_FAILURE(status)) { - printk(KERN_WARNING PFX "evaluate _BBN fail=0x%x\n", status); - busnum = 0; // no _BBN; stick it on bus 0 - } - - sprintf(fullname, "%s _BBN 0x%02x", name, (unsigned int) busnum); - hpzx1_fake_pci_dev(fullname, busnum, csr_base, csr_length); - - return AE_OK; -} - -static void -hpzx1_acpi_dev_init(void) -{ - extern struct pci_ops *pci_root_ops; - - orig_pci_ops = pci_root_ops; - - /* - * Make fake PCI devices for the following hardware in the - * ACPI namespace. This makes it more convenient for drivers - * because they can claim these devices based on PCI - * information, rather than needing to know about ACPI. The - * 64-bit "HPA" space for this hardware is available as BAR - * 0/1. - * - * HWP0001: Single IOC SBA w/o IOC in namespace - * HWP0002: LBA device - * HWP0003: AGP LBA device - */ - acpi_get_devices("HWP0001", hpzx1_sba_probe, "HWP0001", NULL); - acpi_get_devices("HWP0002", hpzx1_lba_probe, "HWP0002 PCI LBA", NULL); - acpi_get_devices("HWP0003", hpzx1_lba_probe, "HWP0003 AGP LBA", NULL); -} - -extern void sba_init(void); - -static int -hpzx1_init (void) -{ - /* zx1 has a hardware I/O TLB which lets us DMA from any device to any address */ - MAX_DMA_ADDRESS = ~0UL; - - hpzx1_acpi_dev_init(); - sba_init(); - return 0; -} - -subsys_initcall(hpzx1_init); diff -Nru a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c --- a/arch/ia64/ia32/binfmt_elf32.c Sat May 24 12:48:32 2003 +++ b/arch/ia64/ia32/binfmt_elf32.c Sat May 24 12:48:32 2003 @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -40,7 +41,6 @@ #define CLOCKS_PER_SEC IA32_CLOCKS_PER_SEC extern void ia64_elf32_init (struct pt_regs *regs); -extern void put_dirty_page (struct task_struct * tsk, struct page *page, unsigned long address); static void elf32_set_personality (void); @@ -200,7 +200,7 @@ struct page *page = bprm->page[i]; if (page) { bprm->page[i] = NULL; - put_dirty_page(current, page, stack_base); + put_dirty_page(current, page, stack_base, PAGE_COPY); } stack_base += PAGE_SIZE; } diff -Nru a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S --- a/arch/ia64/ia32/ia32_entry.S Sat May 24 12:48:25 2003 +++ b/arch/ia64/ia32/ia32_entry.S Sat May 24 12:48:25 2003 @@ -273,9 +273,9 @@ data8 sys32_sigsuspend data8 compat_sys_sigpending data8 sys_sethostname - data8 sys32_setrlimit /* 75 */ - data8 sys32_old_getrlimit - data8 sys32_getrusage + data8 compat_sys_setrlimit /* 75 */ + data8 compat_sys_old_getrlimit + data8 compat_sys_getrusage data8 sys32_gettimeofday data8 sys32_settimeofday data8 sys32_getgroups16 /* 80 */ @@ -312,7 +312,7 @@ data8 sys_vhangup data8 sys32_ni_syscall /* used to be sys_idle */ data8 sys32_ni_syscall - data8 sys32_wait4 + data8 compat_sys_wait4 data8 sys_swapoff /* 115 */ data8 sys32_sysinfo data8 sys32_ipc @@ -389,7 +389,7 @@ data8 sys32_ni_syscall /* streams1 */ data8 sys32_ni_syscall /* streams2 */ data8 sys32_vfork /* 190 */ - data8 sys32_getrlimit + data8 compat_sys_getrlimit data8 sys32_mmap2 data8 sys32_truncate64 data8 sys32_ftruncate64 diff -Nru a/arch/ia64/ia32/ia32_ioctl.c b/arch/ia64/ia32/ia32_ioctl.c --- a/arch/ia64/ia32/ia32_ioctl.c Sat May 24 12:48:29 2003 +++ b/arch/ia64/ia32/ia32_ioctl.c Sat May 24 12:48:29 2003 @@ -3,13 +3,16 @@ * * Copyright (C) 2000 VA Linux Co * Copyright (C) 2000 Don Dugger - * Copyright (C) 2001-2002 Hewlett-Packard Co + * Copyright (C) 2001-2003 Hewlett-Packard Co * David Mosberger-Tang */ #include #include #include /* argh, msdos_fs.h isn't self-contained... */ +#include /* argh, msdos_fs.h isn't self-contained... */ + +#include #include #include @@ -32,8 +35,6 @@ #include #define __KERNEL__ #include - -#include #include <../drivers/char/drm/drm.h> #include <../drivers/char/drm/mga_drm.h> diff -Nru a/arch/ia64/ia32/ia32_traps.c b/arch/ia64/ia32/ia32_traps.c --- a/arch/ia64/ia32/ia32_traps.c Sat May 24 12:48:23 2003 +++ b/arch/ia64/ia32/ia32_traps.c Sat May 24 12:48:23 2003 @@ -103,7 +103,7 @@ * C1 reg you need in case of a stack fault, 0x040 is the stack * fault bit. We should only be taking one exception at a time, * so if this combination doesn't produce any single exception, - * then we have a bad program that isn't syncronizing its FPU usage + * then we have a bad program that isn't synchronizing its FPU usage * and it will suffer the consequences since we won't be able to * fully reproduce the context of the exception */ diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c --- a/arch/ia64/ia32/sys_ia32.c Sat May 24 12:48:26 2003 +++ b/arch/ia64/ia32/sys_ia32.c Sat May 24 12:48:26 2003 @@ -53,10 +53,10 @@ #include #include #include +#include #include #include -#include #define DEBUG 0 @@ -177,7 +177,7 @@ { int err; - if (stat->size > MAX_NON_LFS) + if ((u64) stat->size > MAX_NON_LFS) return -EOVERFLOW; if (clear_user(ubuf, sizeof(*ubuf))) @@ -243,8 +243,7 @@ return -ENOMEM; if (old_prot) - if (copy_from_user(page, (void *) PAGE_START(start), PAGE_SIZE)) - return -EFAULT; + copy_from_user(page, (void *) PAGE_START(start), PAGE_SIZE); down_write(¤t->mm->mmap_sem); { @@ -837,8 +836,9 @@ } } + size = FDS_BYTES(n); ret = -EINVAL; - if (n < 0) + if (n < 0 || size < n) goto out_nofds; if (n > current->files->max_fdset) @@ -850,7 +850,6 @@ * long-words. */ ret = -ENOMEM; - size = FDS_BYTES(n); bits = kmalloc(6 * size, GFP_KERNEL); if (!bits) goto out_nofds; @@ -928,8 +927,7 @@ static struct iovec * get_compat_iovec (struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type) { - int i; - u32 buf, len; + u32 i, buf, len; struct iovec *ivp, *iov; /* Get the "struct iovec" from user memory */ @@ -1005,77 +1003,6 @@ return ret; } -#define RLIM_INFINITY32 0x7fffffff -#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) - -struct rlimit32 { - int rlim_cur; - int rlim_max; -}; - -extern asmlinkage long sys_getrlimit (unsigned int resource, struct rlimit *rlim); - -asmlinkage long -sys32_old_getrlimit (unsigned int resource, struct rlimit32 *rlim) -{ - mm_segment_t old_fs = get_fs(); - struct rlimit r; - int ret; - - set_fs(KERNEL_DS); - ret = sys_getrlimit(resource, &r); - set_fs(old_fs); - if (!ret) { - ret = put_user(RESOURCE32(r.rlim_cur), &rlim->rlim_cur); - ret |= put_user(RESOURCE32(r.rlim_max), &rlim->rlim_max); - } - return ret; -} - -asmlinkage long -sys32_getrlimit (unsigned int resource, struct rlimit32 *rlim) -{ - mm_segment_t old_fs = get_fs(); - struct rlimit r; - int ret; - - set_fs(KERNEL_DS); - ret = sys_getrlimit(resource, &r); - set_fs(old_fs); - if (!ret) { - if (r.rlim_cur >= 0xffffffff) - r.rlim_cur = 0xffffffff; - if (r.rlim_max >= 0xffffffff) - r.rlim_max = 0xffffffff; - ret = put_user(r.rlim_cur, &rlim->rlim_cur); - ret |= put_user(r.rlim_max, &rlim->rlim_max); - } - return ret; -} - -extern asmlinkage long sys_setrlimit (unsigned int resource, struct rlimit *rlim); - -asmlinkage long -sys32_setrlimit (unsigned int resource, struct rlimit32 *rlim) -{ - struct rlimit r; - int ret; - mm_segment_t old_fs = get_fs(); - - if (resource >= RLIM_NLIMITS) - return -EINVAL; - if (get_user(r.rlim_cur, &rlim->rlim_cur) || get_user(r.rlim_max, &rlim->rlim_max)) - return -EFAULT; - if (r.rlim_cur == RLIM_INFINITY32) - r.rlim_cur = RLIM_INFINITY; - if (r.rlim_max == RLIM_INFINITY32) - r.rlim_max = RLIM_INFINITY; - set_fs(KERNEL_DS); - ret = sys_setrlimit(resource, &r); - set_fs(old_fs); - return ret; -} - /* * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation.. * @@ -1648,19 +1575,35 @@ return err; } +extern int sem_ctls[]; +#define sc_semopm (sem_ctls[2]) + static long -semtimedop32(int semid, struct sembuf *tsems, int nsems, - const struct compat_timespec *timeout32) +semtimedop32(int semid, struct sembuf *tsops, int nsops, + struct compat_timespec *timeout32) { struct timespec t; - if (get_user (t.tv_sec, &timeout32->tv_sec) || - get_user (t.tv_nsec, &timeout32->tv_nsec)) + mm_segment_t oldfs; + long ret; + + /* parameter checking precedence should mirror sys_semtimedop() */ + if (nsops < 1 || semid < 0) + return -EINVAL; + if (nsops > sc_semopm) + return -E2BIG; + if (!access_ok(VERIFY_READ, tsops, nsops * sizeof(struct sembuf)) || + get_compat_timespec(&t, timeout32)) return -EFAULT; - return sys_semtimedop(semid, tsems, nsems, &t); + + oldfs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_semtimedop(semid, tsops, nsops, &t); + set_fs(oldfs); + return ret; } asmlinkage long -sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) +sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth) { int version; @@ -1668,12 +1611,15 @@ call &= 0xffff; switch (call) { + case SEMTIMEDOP: + if (fifth) + return semtimedop32(first, (struct sembuf *)AA(ptr), + second, (struct compat_timespec *)AA(fifth)); + /* else fall through for normal semop() */ case SEMOP: /* struct sembuf is the same on 32 and 64bit :)) */ - return sys_semtimedop(first, (struct sembuf *)AA(ptr), second, NULL); - case SEMTIMEDOP: - return semtimedop32(first, (struct sembuf *)AA(ptr), second, - (const struct compat_timespec *)AA(fifth)); + return sys_semtimedop(first, (struct sembuf *)AA(ptr), second, + NULL); case SEMGET: return sys_semget(first, second, third); case SEMCTL: @@ -1724,98 +1670,10 @@ return i; } -struct rusage32 { - struct compat_timeval ru_utime; - struct compat_timeval ru_stime; - int ru_maxrss; - int ru_ixrss; - int ru_idrss; - int ru_isrss; - int ru_minflt; - int ru_majflt; - int ru_nswap; - int ru_inblock; - int ru_oublock; - int ru_msgsnd; - int ru_msgrcv; - int ru_nsignals; - int ru_nvcsw; - int ru_nivcsw; -}; - -static int -put_rusage (struct rusage32 *ru, struct rusage *r) -{ - int err; - - if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru))) - return -EFAULT; - - err = __put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec); - err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec); - err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec); - err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec); - err |= __put_user (r->ru_maxrss, &ru->ru_maxrss); - err |= __put_user (r->ru_ixrss, &ru->ru_ixrss); - err |= __put_user (r->ru_idrss, &ru->ru_idrss); - err |= __put_user (r->ru_isrss, &ru->ru_isrss); - err |= __put_user (r->ru_minflt, &ru->ru_minflt); - err |= __put_user (r->ru_majflt, &ru->ru_majflt); - err |= __put_user (r->ru_nswap, &ru->ru_nswap); - err |= __put_user (r->ru_inblock, &ru->ru_inblock); - err |= __put_user (r->ru_oublock, &ru->ru_oublock); - err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd); - err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv); - err |= __put_user (r->ru_nsignals, &ru->ru_nsignals); - err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw); - err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw); - return err; -} - -asmlinkage long -sys32_wait4 (int pid, unsigned int *stat_addr, int options, struct rusage32 *ru) -{ - if (!ru) - return sys_wait4(pid, stat_addr, options, NULL); - else { - struct rusage r; - int ret; - unsigned int status; - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r); - set_fs(old_fs); - if (put_rusage(ru, &r)) - return -EFAULT; - if (stat_addr && put_user(status, stat_addr)) - return -EFAULT; - return ret; - } -} - asmlinkage long sys32_waitpid (int pid, unsigned int *stat_addr, int options) { - return sys32_wait4(pid, stat_addr, options, NULL); -} - - -extern asmlinkage long sys_getrusage (int who, struct rusage *ru); - -asmlinkage long -sys32_getrusage (int who, struct rusage32 *ru) -{ - struct rusage r; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - ret = sys_getrusage(who, &r); - set_fs(old_fs); - if (put_rusage (ru, &r)) - return -EFAULT; - return ret; + return compat_sys_wait4(pid, stat_addr, options, NULL); } static unsigned int @@ -2211,7 +2069,7 @@ ret = -EIO; break; } - for (i = 0; i < 17*sizeof(int); i += sizeof(int) ) { + for (i = 0; i < (int) (17*sizeof(int)); i += sizeof(int) ) { put_user(getreg(child, i), (unsigned int *) A(data)); data += sizeof(int); } @@ -2223,7 +2081,7 @@ ret = -EIO; break; } - for (i = 0; i < 17*sizeof(int); i += sizeof(int) ) { + for (i = 0; i < (int) (17*sizeof(int)); i += sizeof(int) ) { get_user(tmp, (unsigned int *) A(data)); putreg(child, i, tmp); data += sizeof(int); @@ -2299,7 +2157,7 @@ return(-EINVAL); /* Trying to gain more privileges? */ asm volatile ("mov %0=ar.eflag ;;" : "=r"(old)); - if (level > ((old >> 12) & 3)) { + if ((unsigned int) level > ((old >> 12) & 3)) { if (!capable(CAP_SYS_RAWIO)) return -EPERM; } diff -Nru a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile --- a/arch/ia64/kernel/Makefile Sat May 24 12:48:33 2003 +++ b/arch/ia64/kernel/Makefile Sat May 24 12:48:33 2003 @@ -11,6 +11,8 @@ obj-$(CONFIG_EFI_VARS) += efivars.o obj-$(CONFIG_FSYS) += fsys.o obj-$(CONFIG_IA64_BRL_EMU) += brl_emu.o +obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o +obj-$(CONFIG_IA64_HP_ZX1) += acpi-ext.o obj-$(CONFIG_IA64_MCA) += mca.o mca_asm.o obj-$(CONFIG_IA64_PALINFO) += palinfo.o obj-$(CONFIG_IOSAPIC) += iosapic.o diff -Nru a/arch/ia64/kernel/acpi-ext.c b/arch/ia64/kernel/acpi-ext.c --- a/arch/ia64/kernel/acpi-ext.c Sat May 24 12:48:33 2003 +++ b/arch/ia64/kernel/acpi-ext.c Sat May 24 12:48:33 2003 @@ -3,69 +3,99 @@ * * Copyright (C) 2003 Hewlett-Packard * Copyright (C) Alex Williamson + * Copyright (C) Bjorn Helgaas * - * Vendor specific extensions to ACPI. These are used by both - * HP and NEC. + * Vendor specific extensions to ACPI. */ #include +#include #include #include #include #include -/* - * Note: Strictly speaking, this is only needed for HP and NEC machines. - * However, NEC machines identify themselves as DIG-compliant, so there is - * no easy way to #ifdef this out. - */ +struct acpi_vendor_descriptor { + u8 guid_id; + efi_guid_t guid; +}; + +struct acpi_vendor_info { + struct acpi_vendor_descriptor *descriptor; + u8 *data; + u32 length; +}; + acpi_status -hp_acpi_csr_space (acpi_handle obj, u64 *csr_base, u64 *csr_length) +acpi_vendor_resource_match(struct acpi_resource *resource, void *context) { - int i, offset = 0; - acpi_status status; - struct acpi_buffer buf; - struct acpi_resource_vendor *res; - struct acpi_hp_vendor_long *hp_res; - efi_guid_t vendor_guid; - - *csr_base = 0; - *csr_length = 0; - - status = acpi_get_crs(obj, &buf); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Unable to get _CRS data on object\n"); - return status; - } - - res = (struct acpi_resource_vendor *)acpi_get_crs_type(&buf, &offset, ACPI_RSTYPE_VENDOR); - if (!res) { - printk(KERN_ERR PREFIX "Failed to find config space for device\n"); - acpi_dispose_crs(&buf); + struct acpi_vendor_info *info = (struct acpi_vendor_info *) context; + struct acpi_resource_vendor *vendor; + struct acpi_vendor_descriptor *descriptor; + u32 length; + + if (resource->id != ACPI_RSTYPE_VENDOR) + return AE_OK; + + vendor = (struct acpi_resource_vendor *) &resource->data; + descriptor = (struct acpi_vendor_descriptor *) vendor->reserved; + if (vendor->length <= sizeof(*info->descriptor) || + descriptor->guid_id != info->descriptor->guid_id || + efi_guidcmp(descriptor->guid, info->descriptor->guid)) + return AE_OK; + + length = vendor->length - sizeof(struct acpi_vendor_descriptor); + info->data = acpi_os_allocate(length); + if (!info->data) + return AE_NO_MEMORY; + + memcpy(info->data, vendor->reserved + sizeof(struct acpi_vendor_descriptor), length); + info->length = length; + return AE_CTRL_TERMINATE; +} + +acpi_status +acpi_find_vendor_resource(acpi_handle obj, struct acpi_vendor_descriptor *id, + u8 **data, u32 *length) +{ + struct acpi_vendor_info info; + + info.descriptor = id; + info.data = 0; + + acpi_walk_resources(obj, METHOD_NAME__CRS, acpi_vendor_resource_match, &info); + if (!info.data) return AE_NOT_FOUND; - } - hp_res = (struct acpi_hp_vendor_long *)(res->reserved); + *data = info.data; + *length = info.length; + return AE_OK; +} + +struct acpi_vendor_descriptor hp_ccsr_descriptor = { + .guid_id = 2, + .guid = EFI_GUID(0x69e9adf9, 0x924f, 0xab5f, 0xf6, 0x4a, 0x24, 0xd2, 0x01, 0x37, 0x0e, 0xad) +}; + +acpi_status +hp_acpi_csr_space(acpi_handle obj, u64 *csr_base, u64 *csr_length) +{ + acpi_status status; + u8 *data; + u32 length; + int i; + + status = acpi_find_vendor_resource(obj, &hp_ccsr_descriptor, &data, &length); - if (res->length != HP_CCSR_LENGTH || hp_res->guid_id != HP_CCSR_TYPE) { - printk(KERN_ERR PREFIX "Unknown Vendor data\n"); - acpi_dispose_crs(&buf); - return AE_TYPE; /* Revisit error? */ - } - - memcpy(&vendor_guid, hp_res->guid, sizeof(efi_guid_t)); - if (efi_guidcmp(vendor_guid, HP_CCSR_GUID) != 0) { - printk(KERN_ERR PREFIX "Vendor GUID does not match\n"); - acpi_dispose_crs(&buf); - return AE_TYPE; /* Revisit error? */ - } - - for (i = 0 ; i < 8 ; i++) { - *csr_base |= ((u64)(hp_res->csr_base[i]) << (i * 8)); - *csr_length |= ((u64)(hp_res->csr_length[i]) << (i * 8)); - } + if (ACPI_FAILURE(status) || length != 16) + return AE_NOT_FOUND; + + memcpy(csr_base, data, sizeof(*csr_base)); + memcpy(csr_length, data + 8, sizeof(*csr_length)); + acpi_os_free(data); - acpi_dispose_crs(&buf); return AE_OK; } + +EXPORT_SYMBOL(hp_acpi_csr_space); diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c --- a/arch/ia64/kernel/acpi.c Sat May 24 12:48:24 2003 +++ b/arch/ia64/kernel/acpi.c Sat May 24 12:48:24 2003 @@ -115,134 +115,6 @@ #endif } -#ifdef CONFIG_ACPI - -/** - * acpi_get_crs - Return the current resource settings for a device - * obj: A handle for this device - * buf: A buffer to be populated by this call. - * - * Pass a valid handle, typically obtained by walking the namespace and a - * pointer to an allocated buffer, and this function will fill in the buffer - * with a list of acpi_resource structures. - */ -acpi_status -acpi_get_crs (acpi_handle obj, struct acpi_buffer *buf) -{ - acpi_status result; - buf->length = 0; - buf->pointer = NULL; - - result = acpi_get_current_resources(obj, buf); - if (result != AE_BUFFER_OVERFLOW) - return result; - buf->pointer = kmalloc(buf->length, GFP_KERNEL); - if (!buf->pointer) - return -ENOMEM; - - return acpi_get_current_resources(obj, buf); -} - -struct acpi_resource * -acpi_get_crs_next (struct acpi_buffer *buf, int *offset) -{ - struct acpi_resource *res; - - if (*offset >= buf->length) - return NULL; - - res = buf->pointer + *offset; - *offset += res->length; - return res; -} - -union acpi_resource_data * -acpi_get_crs_type (struct acpi_buffer *buf, int *offset, int type) -{ - for (;;) { - struct acpi_resource *res = acpi_get_crs_next(buf, offset); - if (!res) - return NULL; - if (res->id == type) - return &res->data; - } -} - -void -acpi_dispose_crs (struct acpi_buffer *buf) -{ - kfree(buf->pointer); -} - -void -acpi_get_crs_addr (struct acpi_buffer *buf, int type, u64 *base, u64 *size, u64 *tra) -{ - int offset = 0; - struct acpi_resource_address16 *addr16; - struct acpi_resource_address32 *addr32; - struct acpi_resource_address64 *addr64; - - for (;;) { - struct acpi_resource *res = acpi_get_crs_next(buf, &offset); - if (!res) - return; - switch (res->id) { - case ACPI_RSTYPE_ADDRESS16: - addr16 = (struct acpi_resource_address16 *) &res->data; - - if (type == addr16->resource_type) { - *base = addr16->min_address_range; - *size = addr16->address_length; - *tra = addr16->address_translation_offset; - return; - } - break; - case ACPI_RSTYPE_ADDRESS32: - addr32 = (struct acpi_resource_address32 *) &res->data; - if (type == addr32->resource_type) { - *base = addr32->min_address_range; - *size = addr32->address_length; - *tra = addr32->address_translation_offset; - return; - } - break; - case ACPI_RSTYPE_ADDRESS64: - addr64 = (struct acpi_resource_address64 *) &res->data; - if (type == addr64->resource_type) { - *base = addr64->min_address_range; - *size = addr64->address_length; - *tra = addr64->address_translation_offset; - return; - } - break; - } - } -} - -int -acpi_get_addr_space(void *obj, u8 type, u64 *base, u64 *length, u64 *tra) -{ - acpi_status status; - struct acpi_buffer buf; - - *base = 0; - *length = 0; - *tra = 0; - - status = acpi_get_crs((acpi_handle)obj, &buf); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Unable to get _CRS data on object\n"); - return status; - } - - acpi_get_crs_addr(&buf, type, base, length, tra); - - acpi_dispose_crs(&buf); - - return AE_OK; -} -#endif /* CONFIG_ACPI */ - #ifdef CONFIG_ACPI_BOOT #define ACPI_MAX_PLATFORM_INTERRUPTS 256 @@ -324,7 +196,8 @@ printk(" enabled"); #ifdef CONFIG_SMP smp_boot_data.cpu_phys_id[total_cpus] = (lsapic->id << 8) | lsapic->eid; - if (hard_smp_processor_id() == smp_boot_data.cpu_phys_id[total_cpus]) + if (hard_smp_processor_id() + == (unsigned int) smp_boot_data.cpu_phys_id[total_cpus]) printk(" (BSP)"); #endif } @@ -918,8 +791,7 @@ return 0; /* Turn it on */ - vector = iosapic_register_intr (gsi, polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, - trigger ? IOSAPIC_EDGE : IOSAPIC_LEVEL); + vector = iosapic_register_intr (gsi, polarity, trigger); return vector; } diff -Nru a/arch/ia64/kernel/brl_emu.c b/arch/ia64/kernel/brl_emu.c --- a/arch/ia64/kernel/brl_emu.c Sat May 24 12:48:30 2003 +++ b/arch/ia64/kernel/brl_emu.c Sat May 24 12:48:30 2003 @@ -59,7 +59,7 @@ unsigned long next_ip; struct siginfo siginfo; struct illegal_op_return rv; - int tmp_taken, unimplemented_address; + long tmp_taken, unimplemented_address; rv.fkt = (unsigned long) -1; diff -Nru a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c --- a/arch/ia64/kernel/efi.c Sat May 24 12:48:19 2003 +++ b/arch/ia64/kernel/efi.c Sat May 24 12:48:19 2003 @@ -203,16 +203,16 @@ STUB_RESET_SYSTEM(virt, ) void -efi_gettimeofday (struct timeval *tv) +efi_gettimeofday (struct timespec *ts) { efi_time_t tm; - memset(tv, 0, sizeof(tv)); + memset(ts, 0, sizeof(ts)); if ((*efi.get_time)(&tm, 0) != EFI_SUCCESS) return; - tv->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second); - tv->tv_usec = tm.nanosecond / 1000; + ts->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second); + ts->tv_nsec = tm.nanosecond; } static int @@ -512,7 +512,7 @@ /* Show what we know for posterity */ c16 = __va(efi.systab->fw_vendor); if (c16) { - for (i = 0;i < sizeof(vendor) && *c16; ++i) + for (i = 0;i < (int) sizeof(vendor) && *c16; ++i) vendor[i] = *c16++; vendor[i] = '\0'; } @@ -520,7 +520,7 @@ printk(KERN_INFO "EFI v%u.%.02u by %s:", efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor); - for (i = 0; i < efi.systab->nr_tables; i++) { + for (i = 0; i < (int) efi.systab->nr_tables; i++) { if (efi_guidcmp(config_tables[i].guid, MPS_TABLE_GUID) == 0) { efi.mps = __va(config_tables[i].table); printk(" MPS=0x%lx", config_tables[i].table); diff -Nru a/arch/ia64/kernel/efivars.c b/arch/ia64/kernel/efivars.c --- a/arch/ia64/kernel/efivars.c Sat May 24 12:48:24 2003 +++ b/arch/ia64/kernel/efivars.c Sat May 24 12:48:24 2003 @@ -138,8 +138,7 @@ static inline unsigned long utf8_strsize(efi_char16_t *data, unsigned long maxlength) { - return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) * - sizeof(efi_char16_t); + return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t); } @@ -170,8 +169,7 @@ efi_guid_t *vendor_guid) { - int i, short_name_size = variable_name_size / - sizeof(efi_char16_t) + 38; + int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38; char *short_name; efivar_entry_t *new_efivar; @@ -192,7 +190,7 @@ /* Convert Unicode to normal chars (assume top bits are 0), ala UTF-8 */ - for (i=0; i diff -Nru a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S --- a/arch/ia64/kernel/head.S Sat May 24 12:48:28 2003 +++ b/arch/ia64/kernel/head.S Sat May 24 12:48:28 2003 @@ -733,3 +733,82 @@ SET_REG(b5); #endif /* CONFIG_IA64_BRL_EMU */ + +#ifdef CONFIG_SMP + /* + * This routine handles spinlock contention. It uses a non-standard calling + * convention to avoid converting leaf routines into interior routines. Because + * of this special convention, there are several restrictions: + * + * - do not use gp relative variables, this code is called from the kernel + * and from modules, r1 is undefined. + * - do not use stacked registers, the caller owns them. + * - do not use the scratch stack space, the caller owns it. + * - do not use any registers other than the ones listed below + * + * Inputs: + * ar.pfs - saved CFM of caller + * ar.ccv - 0 (and available for use) + * r28 - available for use. + * r29 - available for use. + * r30 - available for use. + * r31 - address of lock, available for use. + * b7 - return address + * p14 - available for use. + * + * If you patch this code to use more registers, do not forget to update + * the clobber lists for spin_lock() in include/asm-ia64/spinlock.h. + */ + +#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) + +GLOBAL_ENTRY(ia64_spinlock_contention_pre3_4) + .prologue + .save ar.pfs, r0 // this code effectively has a zero frame size + .save rp, r28 + .body + nop 0 + nop 0 + .restore sp // pop existing prologue after next insn + mov b6 = r28 + .prologue + .save ar.pfs, r0 + .altrp b6 + .body +.wait: + // exponential backoff, kdb, lockmeter etc. go in here + hint @pause + ld4.bias r30=[r31] + nop 0 + ;; + cmp4.eq p14,p0=r30,r0 +(p14) br.cond.sptk.few b6 // lock is now free, try to acquire + br.cond.sptk.few .wait +END(ia64_spinlock_contention_pre3_4) + +#else + +GLOBAL_ENTRY(ia64_spinlock_contention) + .prologue + .altrp b6 + .body +.wait: + // exponential backoff, kdb, lockmeter etc. go in here + hint @pause + ld4.bias r30=[r31] + ;; + cmp4.ne p14,p0=r30,r0 + mov r30 = 1 +(p14) br.cond.sptk.few .wait + ;; + cmpxchg4.acq r30=[r31], r30, ar.ccv + ;; + cmp4.ne p14,p0=r0,r30 +(p14) br.cond.sptk.few .wait + + br.ret.sptk.many b6 // lock is now taken +END(ia64_spinlock_contention) + +#endif + +#endif /* CONFIG_SMP */ diff -Nru a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c --- a/arch/ia64/kernel/ia64_ksyms.c Sat May 24 12:48:24 2003 +++ b/arch/ia64/kernel/ia64_ksyms.c Sat May 24 12:48:24 2003 @@ -46,6 +46,7 @@ EXPORT_SYMBOL(__ia64_memcpy_fromio); EXPORT_SYMBOL(__ia64_memcpy_toio); EXPORT_SYMBOL(__ia64_memset_c_io); +EXPORT_SYMBOL(io_space); #include EXPORT_SYMBOL_NOVERS(__down); @@ -56,6 +57,12 @@ #include EXPORT_SYMBOL(clear_page); +#ifdef CONFIG_VIRTUAL_MEM_MAP +#include +EXPORT_SYMBOL(vmalloc_end); +EXPORT_SYMBOL(ia64_pfn_valid); +#endif + #include EXPORT_SYMBOL(cpu_info__per_cpu); EXPORT_SYMBOL(kernel_thread); @@ -161,3 +168,11 @@ EXPORT_SYMBOL(unw_access_fr); EXPORT_SYMBOL(unw_access_ar); EXPORT_SYMBOL(unw_access_pr); + +#if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 4) +extern void ia64_spinlock_contention_pre3_4 (void); +EXPORT_SYMBOL(ia64_spinlock_contention_pre3_4); +#else +extern void ia64_spinlock_contention (void); +EXPORT_SYMBOL(ia64_spinlock_contention); +#endif diff -Nru a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c --- a/arch/ia64/kernel/iosapic.c Sat May 24 12:48:24 2003 +++ b/arch/ia64/kernel/iosapic.c Sat May 24 12:48:24 2003 @@ -581,9 +581,8 @@ register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger); DBG("ISA: IRQ %u -> GSI 0x%x (%s,%s) -> CPU 0x%04x vector %d\n", - isa_irq, gsi, - polarity == IOSAPIC_POL_HIGH ? "high" : "low", trigger == IOSAPIC_EDGE ? "edge" : "level", - dest, vector); + isa_irq, gsi, polarity == IOSAPIC_POL_HIGH ? "high" : "low", + trigger == IOSAPIC_EDGE ? "edge" : "level", dest, vector); /* program the IOSAPIC routing table */ set_rte(vector, dest); @@ -635,7 +634,6 @@ (ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, gsi_base, gsi_base + num_rte - 1); if ((gsi_base == 0) && pcat_compat) { - /* * Map the legacy ISA devices into the IOSAPIC data. Some of these may * get reprogrammed later on with data from the ACPI Interrupt Source @@ -646,20 +644,11 @@ } } -static void __init -fixup_vector (int vector, unsigned int gsi, const char *pci_id) +void +iosapic_enable_intr (unsigned int vector) { - struct hw_interrupt_type *irq_type = &irq_type_iosapic_level; - irq_desc_t *idesc; unsigned int dest; - idesc = irq_desc(vector); - if (idesc->handler != irq_type) { - if (idesc->handler != &no_irq_type) - printk(KERN_INFO "IOSAPIC: changing vector %d from %s to %s\n", - vector, idesc->handler->typename, irq_type->typename); - idesc->handler = irq_type; - } #ifdef CONFIG_SMP /* * For platforms that do not support interrupt redirect via the XTP interface, we @@ -687,10 +676,12 @@ #endif set_rte(vector, dest); - printk(KERN_INFO "IOSAPIC: %s -> GSI 0x%x -> CPU 0x%04x vector %d\n", - pci_id, gsi, dest, vector); + printk(KERN_INFO "IOSAPIC: vector %d -> CPU 0x%04x, enabled\n", + vector, dest); } +#ifdef CONFIG_ACPI_PCI + void __init iosapic_parse_prt (void) { @@ -699,6 +690,8 @@ unsigned int gsi; int vector; char pci_id[16]; + struct hw_interrupt_type *irq_type = &irq_type_iosapic_level; + irq_desc_t *idesc; list_for_each(node, &acpi_prt.entries) { entry = list_entry(node, struct acpi_prt_entry, node); @@ -711,6 +704,9 @@ vector = gsi_to_vector(gsi); if (vector < 0) { + if (find_iosapic(gsi) < 0) + continue; + /* allocate a vector for this interrupt line */ if (pcat_compat && (gsi < 16)) vector = isa_irq_to_vector(gsi); @@ -718,11 +714,22 @@ /* new GSI; allocate a vector for it */ vector = ia64_alloc_vector(); - register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW, IOSAPIC_LEVEL); + register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW, + IOSAPIC_LEVEL); } snprintf(pci_id, sizeof(pci_id), "%02x:%02x:%02x[%c]", entry->id.segment, entry->id.bus, entry->id.device, 'A' + entry->pin); - fixup_vector(vector, gsi, pci_id); + /* + * If vector was previously initialized to a different + * handler, re-initialize. + */ + idesc = irq_desc(vector); + if (idesc->handler != irq_type) + register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW, + IOSAPIC_LEVEL); + } } + +#endif /* CONFIG_ACPI */ diff -Nru a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c --- a/arch/ia64/kernel/irq.c Sat May 24 12:48:31 2003 +++ b/arch/ia64/kernel/irq.c Sat May 24 12:48:31 2003 @@ -18,7 +18,6 @@ */ #include -#include #include #include #include @@ -33,6 +32,7 @@ #include #include #include +#include #include #include @@ -50,7 +50,7 @@ * Linux has a controller-independent x86 interrupt architecture. * every controller has a 'controller-template', that is used * by the main code to do the right thing. Each driver-visible - * interrupt source is transparently wired to the apropriate + * interrupt source is transparently wired to the appropriate * controller. Thus drivers need not be aware of the * interrupt-controller. * @@ -91,7 +91,8 @@ * Special irq handlers. */ -void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } +irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) +{ return IRQ_NONE; } /* * Generic no controller code @@ -107,7 +108,7 @@ * each architecture has to answer this themselves, it doesn't deserve * a generic callback i think. */ -#if CONFIG_X86 +#ifdef CONFIG_X86 printk(KERN_ERR "unexpected IRQ trap at vector %02x\n", irq); #ifdef CONFIG_X86_LOCAL_APIC /* @@ -121,7 +122,7 @@ ack_APIC_irq(); #endif #endif -#if CONFIG_IA64 +#ifdef CONFIG_IA64 printk(KERN_ERR "Unexpected irq vector 0x%x on CPU %u!\n", irq, smp_processor_id()); #endif } @@ -141,9 +142,11 @@ }; atomic_t irq_err_count; -#if defined(CONFIG_X86) && defined(CONFIG_X86_IO_APIC) && defined(APIC_MISMATCH_DEBUG) +#ifdef CONFIG_X86_IO_APIC +#ifdef APIC_MISMATCH_DEBUG atomic_t irq_mis_count; #endif +#endif /* * Generic, controller-independent functions: @@ -178,9 +181,10 @@ #endif seq_printf(p, " %14s", idesc->handler->typename); seq_printf(p, " %s", action->name); + for (action=action->next; action; action = action->next) seq_printf(p, ", %s", action->name); - + seq_putc(p, '\n'); skip: spin_unlock_irqrestore(&idesc->lock, flags); @@ -190,21 +194,23 @@ if (cpu_online(j)) seq_printf(p, "%10u ", nmi_count(j)); seq_putc(p, '\n'); -#if defined(CONFIG_SMP) && defined(CONFIG_X86) +#ifdef CONFIG_X86_LOCAL_APIC seq_puts(p, "LOC: "); for (j = 0; j < NR_CPUS; j++) if (cpu_online(j)) - seq_printf(p, "%10u ", apic_timer_irqs[j]); + seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs); seq_putc(p, '\n'); #endif seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); -#if defined(CONFIG_X86) && defined(CONFIG_X86_IO_APIC) && defined(APIC_MISMATCH_DEBUG) +#ifdef CONFIG_X86_IO_APIC +#ifdef APIC_MISMATCH_DEBUG seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count)); #endif +#endif return 0; } -#if CONFIG_SMP +#ifdef CONFIG_SMP inline void synchronize_irq(unsigned int irq) { while (irq_desc(irq)->status & IRQ_INPROGRESS) @@ -219,21 +225,46 @@ * waste of time and is not what some drivers would * prefer. */ -int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action) +int handle_IRQ_event(unsigned int irq, + struct pt_regs *regs, struct irqaction *action) { int status = 1; /* Force the "do bottom halves" bit */ + int retval = 0; + struct irqaction *first_action = action; if (!(action->flags & SA_INTERRUPT)) local_irq_enable(); do { status |= action->flags; - action->handler(irq, action->dev_id, regs); + retval |= action->handler(irq, action->dev_id, regs); action = action->next; } while (action); if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); local_irq_disable(); + if (retval != 1) { + static int count = 100; + 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); + print_symbol(" (%s)", + (unsigned long)action->handler); + printk("\n"); + action = action->next; + } while (action); + } + } return status; } @@ -455,7 +486,7 @@ */ int request_irq(unsigned int irq, - void (*handler)(int, void *, struct pt_regs *), + irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id) @@ -482,7 +513,7 @@ return -EINVAL; action = (struct irqaction *) - kmalloc(sizeof(struct irqaction), GFP_KERNEL); + kmalloc(sizeof(struct irqaction), GFP_ATOMIC); if (!action) return -ENOMEM; @@ -511,10 +542,7 @@ * does not return until any executing interrupts for this IRQ * have completed. * - * This function may be called from interrupt context. - * - * Bugs: Attempting to free an irq in a handler for the same irq hangs - * the machine. + * This function must not be called from interrupt context. */ void free_irq(unsigned int irq, void *dev_id) @@ -545,11 +573,8 @@ } spin_unlock_irqrestore(&desc->lock,flags); -#ifdef CONFIG_SMP /* Wait to make sure it's not being used on another CPU */ - while (desc->status & IRQ_INPROGRESS) - synchronize_irq(irq); -#endif + synchronize_irq(irq); kfree(action); return; } @@ -664,7 +689,6 @@ * only return ISA irq numbers - just so that we reset them * all to a known state. */ - unsigned int probe_irq_mask(unsigned long val) { int i; @@ -705,7 +729,7 @@ * The interrupt probe logic state is returned to its previous * value. * - * BUGS: When used in a module (which arguably shouldnt happen) + * BUGS: When used in a module (which arguably shouldn't happen) * nothing prevents two IRQ probe callers from overlapping. The * results of this are non-optimal. */ @@ -748,6 +772,8 @@ struct irqaction *old, **p; irq_desc_t *desc = irq_desc(irq); + if (desc->handler == &no_irq_type) + return -ENOSYS; /* * Some drivers like serial.c use request_irq() heavily, * so we have to be careful not to interfere with a @@ -808,11 +834,11 @@ #define HEX_DIGITS 8 -static int parse_hex_value (const char *buffer, unsigned long count, unsigned long *ret) +static unsigned int parse_hex_value (const char *buffer, + unsigned long count, unsigned long *ret) { unsigned char hexnum [HEX_DIGITS]; - unsigned long value; - int i; + unsigned long value, i; if (!count) return -EINVAL; @@ -844,7 +870,7 @@ return 0; } -#if CONFIG_SMP +#ifdef CONFIG_SMP static struct proc_dir_entry * smp_affinity_entry [NR_IRQS]; @@ -947,15 +973,16 @@ /* create /proc/irq/1234 */ irq_dir[irq] = proc_mkdir(name, root_irq_dir); -#if CONFIG_SMP +#ifdef CONFIG_SMP { struct proc_dir_entry *entry; + /* create /proc/irq/1234/smp_affinity */ entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); if (entry) { entry->nlink = 1; - entry->data = (void *)(unsigned long)irq; + entry->data = (void *)(long)irq; entry->read_proc = irq_affinity_read_proc; entry->write_proc = irq_affinity_write_proc; } diff -Nru a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c --- a/arch/ia64/kernel/irq_ia64.c Sat May 24 12:48:23 2003 +++ b/arch/ia64/kernel/irq_ia64.c Sat May 24 12:48:23 2003 @@ -145,7 +145,7 @@ } #ifdef CONFIG_SMP -extern void handle_IPI (int irq, void *dev_id, struct pt_regs *regs); +extern irqreturn_t handle_IPI (int irq, void *dev_id, struct pt_regs *regs); static struct irqaction ipi_irqaction = { .handler = handle_IPI, diff -Nru a/arch/ia64/kernel/machvec.c b/arch/ia64/kernel/machvec.c --- a/arch/ia64/kernel/machvec.c Sat May 24 12:48:24 2003 +++ b/arch/ia64/kernel/machvec.c Sat May 24 12:48:24 2003 @@ -1,12 +1,14 @@ #include +#include + #ifdef CONFIG_IA64_GENERIC #include #include -#include #include +#include struct ia64_machine_vector ia64_mv; @@ -42,4 +44,10 @@ void machvec_noop (void) { +} + +void +machvec_memory_fence (void) +{ + mb(); } diff -Nru a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c --- a/arch/ia64/kernel/mca.c Sat May 24 12:48:24 2003 +++ b/arch/ia64/kernel/mca.c Sat May 24 12:48:24 2003 @@ -3,6 +3,9 @@ * Purpose: Generic MCA handling layer * * Updated for latest kernel + * Copyright (C) 2003 Hewlett-Packard Co + * David Mosberger-Tang + * * Copyright (C) 2002 Dell Computer Corporation * Copyright (C) Matt Domsch (Matt_Domsch@dell.com) * @@ -18,6 +21,7 @@ * Copyright (C) 1999 Silicon Graphics, Inc. * Copyright (C) Vijay Chander(vijay@engr.sgi.com) * + * 03/04/15 D. Mosberger Added INIT backtrace support. * 02/03/25 M. Domsch GUID cleanups * * 02/01/04 J. Hall Aligned MCA stack to 16 bytes, added platform vs. CPU @@ -39,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +52,7 @@ #include #include +#include #include #include #include @@ -139,7 +145,7 @@ /* Get the MCA error record */ if (!ia64_log_get(sal_info_type, (prfunc_t)printk)) - return platform_err; // no record retrieved + return platform_err; /* no record retrieved */ /* TODO: * 1. analyze error logs to determine recoverability @@ -166,7 +172,7 @@ } -void +irqreturn_t ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs) { IA64_MCA_DEBUG("ia64_mca_cpe_int_handler: received interrupt. CPU:%d vector = %#x\n", @@ -174,20 +180,186 @@ /* Get the CMC error record and log it */ ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE, 0); + return IRQ_HANDLED; +} + +static void +show_min_state (pal_min_state_area_t *minstate) +{ + u64 iip = minstate->pmsa_iip + ((struct ia64_psr *)(&minstate->pmsa_ipsr))->ri; + u64 xip = minstate->pmsa_xip + ((struct ia64_psr *)(&minstate->pmsa_xpsr))->ri; + + printk("NaT bits\t%016lx\n", minstate->pmsa_nat_bits); + printk("pr\t\t%016lx\n", minstate->pmsa_pr); + printk("b0\t\t%016lx ", minstate->pmsa_br0); print_symbol("%s\n", minstate->pmsa_br0); + printk("ar.rsc\t\t%016lx\n", minstate->pmsa_rsc); + printk("cr.iip\t\t%016lx ", iip); print_symbol("%s\n", iip); + printk("cr.ipsr\t\t%016lx\n", minstate->pmsa_ipsr); + printk("cr.ifs\t\t%016lx\n", minstate->pmsa_ifs); + printk("xip\t\t%016lx ", xip); print_symbol("%s\n", xip); + printk("xpsr\t\t%016lx\n", minstate->pmsa_xpsr); + printk("xfs\t\t%016lx\n", minstate->pmsa_xfs); + printk("b1\t\t%016lx ", minstate->pmsa_br1); + print_symbol("%s\n", minstate->pmsa_br1); + + printk("\nstatic registers r0-r15:\n"); + printk(" r0- 3 %016lx %016lx %016lx %016lx\n", + 0UL, minstate->pmsa_gr[0], minstate->pmsa_gr[1], minstate->pmsa_gr[2]); + printk(" r4- 7 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_gr[3], minstate->pmsa_gr[4], + minstate->pmsa_gr[5], minstate->pmsa_gr[6]); + printk(" r8-11 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_gr[7], minstate->pmsa_gr[8], + minstate->pmsa_gr[9], minstate->pmsa_gr[10]); + printk("r12-15 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_gr[11], minstate->pmsa_gr[12], + minstate->pmsa_gr[13], minstate->pmsa_gr[14]); + + printk("\nbank 0:\n"); + printk("r16-19 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank0_gr[0], minstate->pmsa_bank0_gr[1], + minstate->pmsa_bank0_gr[2], minstate->pmsa_bank0_gr[3]); + printk("r20-23 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank0_gr[4], minstate->pmsa_bank0_gr[5], + minstate->pmsa_bank0_gr[6], minstate->pmsa_bank0_gr[7]); + printk("r24-27 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank0_gr[8], minstate->pmsa_bank0_gr[9], + minstate->pmsa_bank0_gr[10], minstate->pmsa_bank0_gr[11]); + printk("r28-31 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank0_gr[12], minstate->pmsa_bank0_gr[13], + minstate->pmsa_bank0_gr[14], minstate->pmsa_bank0_gr[15]); + + printk("\nbank 1:\n"); + printk("r16-19 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank1_gr[0], minstate->pmsa_bank1_gr[1], + minstate->pmsa_bank1_gr[2], minstate->pmsa_bank1_gr[3]); + printk("r20-23 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank1_gr[4], minstate->pmsa_bank1_gr[5], + minstate->pmsa_bank1_gr[6], minstate->pmsa_bank1_gr[7]); + printk("r24-27 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank1_gr[8], minstate->pmsa_bank1_gr[9], + minstate->pmsa_bank1_gr[10], minstate->pmsa_bank1_gr[11]); + printk("r28-31 %016lx %016lx %016lx %016lx\n", + minstate->pmsa_bank1_gr[12], minstate->pmsa_bank1_gr[13], + minstate->pmsa_bank1_gr[14], minstate->pmsa_bank1_gr[15]); +} + +static void +fetch_min_state (pal_min_state_area_t *ms, struct pt_regs *pt, struct switch_stack *sw) +{ + u64 *dst_banked, *src_banked, bit, shift, nat_bits; + int i; + + /* + * First, update the pt-regs and switch-stack structures with the contents stored + * in the min-state area: + */ + if (((struct ia64_psr *) &ms->pmsa_ipsr)->ic == 0) { + pt->cr_ipsr = ms->pmsa_xpsr; + pt->cr_iip = ms->pmsa_xip; + pt->cr_ifs = ms->pmsa_xfs; + } else { + pt->cr_ipsr = ms->pmsa_ipsr; + pt->cr_iip = ms->pmsa_iip; + pt->cr_ifs = ms->pmsa_ifs; + } + pt->ar_rsc = ms->pmsa_rsc; + pt->pr = ms->pmsa_pr; + pt->r1 = ms->pmsa_gr[0]; + pt->r2 = ms->pmsa_gr[1]; + pt->r3 = ms->pmsa_gr[2]; + sw->r4 = ms->pmsa_gr[3]; + sw->r5 = ms->pmsa_gr[4]; + sw->r6 = ms->pmsa_gr[5]; + sw->r7 = ms->pmsa_gr[6]; + pt->r8 = ms->pmsa_gr[7]; + pt->r9 = ms->pmsa_gr[8]; + pt->r10 = ms->pmsa_gr[9]; + pt->r11 = ms->pmsa_gr[10]; + pt->r12 = ms->pmsa_gr[11]; + pt->r13 = ms->pmsa_gr[12]; + pt->r14 = ms->pmsa_gr[13]; + pt->r15 = ms->pmsa_gr[14]; + dst_banked = &pt->r16; /* r16-r31 are contiguous in struct pt_regs */ + src_banked = ms->pmsa_bank1_gr; + for (i = 0; i < 16; ++i) + dst_banked[i] = src_banked[i]; + pt->b0 = ms->pmsa_br0; + sw->b1 = ms->pmsa_br1; + + /* construct the NaT bits for the pt-regs structure: */ +# define PUT_NAT_BIT(dst, addr) \ + do { \ + bit = nat_bits & 1; nat_bits >>= 1; \ + shift = ((unsigned long) addr >> 3) & 0x3f; \ + dst = ((dst) & ~(1UL << shift)) | (bit << shift); \ + } while (0) + + /* Rotate the saved NaT bits such that bit 0 corresponds to pmsa_gr[0]: */ + shift = ((unsigned long) &ms->pmsa_gr[0] >> 3) & 0x3f; + nat_bits = (ms->pmsa_nat_bits >> shift) | (ms->pmsa_nat_bits << (64 - shift)); + + PUT_NAT_BIT(sw->caller_unat, &pt->r1); + PUT_NAT_BIT(sw->caller_unat, &pt->r2); + PUT_NAT_BIT(sw->caller_unat, &pt->r3); + PUT_NAT_BIT(sw->ar_unat, &sw->r4); + PUT_NAT_BIT(sw->ar_unat, &sw->r5); + PUT_NAT_BIT(sw->ar_unat, &sw->r6); + PUT_NAT_BIT(sw->ar_unat, &sw->r7); + PUT_NAT_BIT(sw->caller_unat, &pt->r8); PUT_NAT_BIT(sw->caller_unat, &pt->r9); + PUT_NAT_BIT(sw->caller_unat, &pt->r10); PUT_NAT_BIT(sw->caller_unat, &pt->r11); + PUT_NAT_BIT(sw->caller_unat, &pt->r12); PUT_NAT_BIT(sw->caller_unat, &pt->r13); + PUT_NAT_BIT(sw->caller_unat, &pt->r14); PUT_NAT_BIT(sw->caller_unat, &pt->r15); + nat_bits >>= 16; /* skip over bank0 NaT bits */ + PUT_NAT_BIT(sw->caller_unat, &pt->r16); PUT_NAT_BIT(sw->caller_unat, &pt->r17); + PUT_NAT_BIT(sw->caller_unat, &pt->r18); PUT_NAT_BIT(sw->caller_unat, &pt->r19); + PUT_NAT_BIT(sw->caller_unat, &pt->r20); PUT_NAT_BIT(sw->caller_unat, &pt->r21); + PUT_NAT_BIT(sw->caller_unat, &pt->r22); PUT_NAT_BIT(sw->caller_unat, &pt->r23); + PUT_NAT_BIT(sw->caller_unat, &pt->r24); PUT_NAT_BIT(sw->caller_unat, &pt->r25); + PUT_NAT_BIT(sw->caller_unat, &pt->r26); PUT_NAT_BIT(sw->caller_unat, &pt->r27); + PUT_NAT_BIT(sw->caller_unat, &pt->r28); PUT_NAT_BIT(sw->caller_unat, &pt->r29); + PUT_NAT_BIT(sw->caller_unat, &pt->r30); PUT_NAT_BIT(sw->caller_unat, &pt->r31); } -/* - * This routine will be used to deal with platform specific handling - * of the init, i.e. drop into the kernel debugger on server machine, - * or if the processor is part of some parallel machine without a - * console, then we would call the appropriate debug hooks here. - */ void -init_handler_platform (struct pt_regs *regs) +init_handler_platform (sal_log_processor_info_t *proc_ptr, + struct pt_regs *pt, struct switch_stack *sw) { + struct unw_frame_info info; + /* if a kernel debugger is available call it here else just dump the registers */ - show_regs(regs); /* dump the state info */ + /* + * Wait for a bit. On some machines (e.g., HP's zx2000 and zx6000, INIT can be + * generated via the BMC's command-line interface, but since the console is on the + * same serial line, the user will need some time to switch out of the BMC before + * the dump begins. + */ + printk("Delaying for 5 seconds...\n"); + udelay(5*1000000); + show_min_state(&SAL_LPI_PSI_INFO(proc_ptr)->min_state_area); + + printk("Backtrace of current task (pid %d, %s)\n", current->pid, current->comm); + fetch_min_state(&SAL_LPI_PSI_INFO(proc_ptr)->min_state_area, pt, sw); + unw_init_from_interruption(&info, current, pt, sw); + ia64_do_show_stack(&info, NULL); + + if (!tasklist_lock.write_lock) + read_lock(&tasklist_lock); + { + struct task_struct *g, *t; + do_each_thread (g, t) { + if (t == current) + continue; + + printk("\nBacktrace of pid %d (%s)\n", t->pid, t->comm); + show_stack(t); + } while_each_thread (g, t); + } + if (!tasklist_lock.write_lock) + read_unlock(&tasklist_lock); + + printk("\nINIT dump complete. Please reboot now.\n"); while (1); /* hang city if no debugger */ } @@ -263,7 +435,6 @@ /* * routine to process and prepare to dump min_state_save * information for debugging purposes. - * */ void ia64_process_min_state_save (pal_min_state_area_t *pmss) @@ -272,8 +443,6 @@ u64 *tpmss_ptr = (u64 *)pmss; u64 *return_min_state_ptr = ia64_mca_min_state_save_info; - /* dump out the min_state_area information */ - for (i=0;i>=1; } p += sprintf(p, "\n\tLoad hints : "); for(k=0; k < 8; k++ ) { - if ( cci.pcci_ld_hints & 0x1) p += sprintf(p, "[%s]", cache_ld_hints[k]); + if (cci.pcci_ld_hints & 0x1) + p += sprintf(p, "[%s]", cache_ld_hints[k]); cci.pcci_ld_hints >>=1; } - p += sprintf(p, "\n\tAlias boundary : %d byte(s)\n" \ - "\tTag LSB : %d\n" \ - "\tTag MSB : %d\n", - 1<0 ; j--) { @@ -379,15 +380,14 @@ continue; } - p += sprintf(p, "\n%s Translation Cache Level %d:\n" \ - "\tHash sets : %d\n" \ - "\tAssociativity : %d\n" \ - "\tNumber of entries : %d\n" \ - "\tFlags : ", - cache_types[j+tc_info.tc_unified], i+1, - tc_info.tc_num_sets, - tc_info.tc_associativity, - tc_info.tc_num_entries); + p += sprintf(p, + "\n%s Translation Cache Level %d:\n" + "\tHash sets : %d\n" + "\tAssociativity : %d\n" + "\tNumber of entries : %d\n" + "\tFlags : ", + cache_types[j+tc_info.tc_unified], i+1, tc_info.tc_num_sets, + tc_info.tc_associativity, tc_info.tc_num_entries); if (tc_info.tc_pf) p += sprintf(p, "PreferredPageSizeOptimized "); if (tc_info.tc_unified) p += sprintf(p, "Unified "); @@ -436,17 +436,18 @@ if (ia64_pal_rse_info(&phys_stacked, &hints) != 0) return 0; - p += sprintf(p, "RSE stacked physical registers : %ld\n" \ - "RSE load/store hints : %ld (%s)\n", - phys_stacked, - hints.ph_data, - hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(\?\?)"); - - if (ia64_pal_debug_info(&iregs, &dregs)) return 0; - - p += sprintf(p, "Instruction debug register pairs : %ld\n" \ - "Data debug register pairs : %ld\n", - iregs, dregs); + p += sprintf(p, + "RSE stacked physical registers : %ld\n" + "RSE load/store hints : %ld (%s)\n", + phys_stacked, hints.ph_data, + hints.ph_data < RSE_HINTS_COUNT ? rse_hints[hints.ph_data]: "(\?\?)"); + + if (ia64_pal_debug_info(&iregs, &dregs)) + return 0; + + p += sprintf(p, + "Instruction debug register pairs : %ld\n" + "Data debug register pairs : %ld\n", iregs, dregs); return p - page; } @@ -563,26 +564,21 @@ */ if (ia64_pal_version(&min_ver, &cur_ver) != 0) return 0; - p += sprintf(p, "PAL_vendor : 0x%02x (min=0x%02x)\n" \ - "PAL_A : %x.%x.%x (min=%x.%x.%x)\n" \ - "PAL_B : %x.%x.%x (min=%x.%x.%x)\n", - cur_ver.pal_version_s.pv_pal_vendor, - min_ver.pal_version_s.pv_pal_vendor, - - cur_ver.pal_version_s.pv_pal_a_model>>4, - cur_ver.pal_version_s.pv_pal_a_model&0xf, - cur_ver.pal_version_s.pv_pal_a_rev, - min_ver.pal_version_s.pv_pal_a_model>>4, - min_ver.pal_version_s.pv_pal_a_model&0xf, - min_ver.pal_version_s.pv_pal_a_rev, - - cur_ver.pal_version_s.pv_pal_b_model>>4, - cur_ver.pal_version_s.pv_pal_b_model&0xf, - cur_ver.pal_version_s.pv_pal_b_rev, - min_ver.pal_version_s.pv_pal_b_model>>4, - min_ver.pal_version_s.pv_pal_b_model&0xf, - min_ver.pal_version_s.pv_pal_b_rev); - + p += sprintf(p, + "PAL_vendor : 0x%02x (min=0x%02x)\n" + "PAL_A : %x.%x.%x (min=%x.%x.%x)\n" + "PAL_B : %x.%x.%x (min=%x.%x.%x)\n", + cur_ver.pal_version_s.pv_pal_vendor, min_ver.pal_version_s.pv_pal_vendor, + + cur_ver.pal_version_s.pv_pal_a_model>>4, + cur_ver.pal_version_s.pv_pal_a_model&0xf, cur_ver.pal_version_s.pv_pal_a_rev, + min_ver.pal_version_s.pv_pal_a_model>>4, + min_ver.pal_version_s.pv_pal_a_model&0xf, min_ver.pal_version_s.pv_pal_a_rev, + + cur_ver.pal_version_s.pv_pal_b_model>>4, + cur_ver.pal_version_s.pv_pal_b_model&0xf, cur_ver.pal_version_s.pv_pal_b_rev, + min_ver.pal_version_s.pv_pal_b_model>>4, + min_ver.pal_version_s.pv_pal_b_model&0xf, min_ver.pal_version_s.pv_pal_b_rev); return p - page; } @@ -595,26 +591,20 @@ if (ia64_pal_perf_mon_info(pm_buffer, &pm_info) != 0) return 0; - p += sprintf(p, "PMC/PMD pairs : %d\n" \ - "Counter width : %d bits\n" \ - "Cycle event number : %d\n" \ - "Retired event number : %d\n" \ - "Implemented PMC : ", - pm_info.pal_perf_mon_info_s.generic, - pm_info.pal_perf_mon_info_s.width, - pm_info.pal_perf_mon_info_s.cycles, - pm_info.pal_perf_mon_info_s.retired); + p += sprintf(p, + "PMC/PMD pairs : %d\n" + "Counter width : %d bits\n" + "Cycle event number : %d\n" + "Retired event number : %d\n" + "Implemented PMC : ", + pm_info.pal_perf_mon_info_s.generic, pm_info.pal_perf_mon_info_s.width, + pm_info.pal_perf_mon_info_s.cycles, pm_info.pal_perf_mon_info_s.retired); p = bitregister_process(p, pm_buffer, 256); - p += sprintf(p, "\nImplemented PMD : "); - p = bitregister_process(p, pm_buffer+4, 256); - p += sprintf(p, "\nCycles count capable : "); - p = bitregister_process(p, pm_buffer+8, 256); - p += sprintf(p, "\nRetired bundles count capable : "); #ifdef CONFIG_ITANIUM @@ -646,12 +636,11 @@ if (ia64_pal_freq_ratios(&proc, &bus, &itc) != 0) return 0; - p += sprintf(p, "Processor/Clock ratio : %ld/%ld\n" \ - "Bus/Clock ratio : %ld/%ld\n" \ - "ITC/Clock ratio : %ld/%ld\n", - proc.num, proc.den, - bus.num, bus.den, - itc.num, itc.den); + p += sprintf(p, + "Processor/Clock ratio : %ld/%ld\n" + "Bus/Clock ratio : %ld/%ld\n" + "ITC/Clock ratio : %ld/%ld\n", + proc.num, proc.den, bus.num, bus.den, itc.num, itc.den); return p - page; } @@ -665,7 +654,7 @@ u64 tr_buffer[4]; pal_vm_info_1_u_t vm_info_1; pal_vm_info_2_u_t vm_info_2; - int i, j; + u64 i, j; u64 max[3], pgm; struct ifa_reg { u64 valid:1; @@ -711,7 +700,7 @@ status = ia64_pal_tr_read(j, i, tr_buffer, &tr_valid); if (status != 0) { - printk(KERN_ERR "palinfo: pal call failed on tr[%d:%d]=%ld\n", + printk(KERN_ERR "palinfo: pal call failed on tr[%lu:%lu]=%ld\n", i, j, status); continue; } @@ -725,34 +714,29 @@ rid_reg = (struct rid_reg *)&tr_buffer[3]; pgm = -1 << (itir_reg->ps - 12); - p += sprintf(p, "%cTR%d: av=%d pv=%d dv=%d mv=%d\n" \ - "\tppn : 0x%lx\n" \ - "\tvpn : 0x%lx\n" \ - "\tps : ", - - "ID"[i], - j, - tr_valid.pal_tr_valid_s.access_rights_valid, - tr_valid.pal_tr_valid_s.priv_level_valid, - tr_valid.pal_tr_valid_s.dirty_bit_valid, - tr_valid.pal_tr_valid_s.mem_attr_valid, - (gr_reg->ppn & pgm)<< 12, - (ifa_reg->vpn & pgm)<< 12); + p += sprintf(p, + "%cTR%lu: av=%d pv=%d dv=%d mv=%d\n" + "\tppn : 0x%lx\n" + "\tvpn : 0x%lx\n" + "\tps : ", + "ID"[i], j, + tr_valid.pal_tr_valid_s.access_rights_valid, + tr_valid.pal_tr_valid_s.priv_level_valid, + tr_valid.pal_tr_valid_s.dirty_bit_valid, + tr_valid.pal_tr_valid_s.mem_attr_valid, + (gr_reg->ppn & pgm)<< 12, (ifa_reg->vpn & pgm)<< 12); p = bitvector_process(p, 1<< itir_reg->ps); - p += sprintf(p, "\n\tpl : %d\n" \ - "\tar : %d\n" \ - "\trid : %x\n" \ - "\tp : %d\n" \ - "\tma : %d\n" \ - "\td : %d\n", - gr_reg->pl, - gr_reg->ar, - rid_reg->rid, - gr_reg->p, - gr_reg->ma, - gr_reg->d); + p += sprintf(p, + "\n\tpl : %d\n" + "\tar : %d\n" + "\trid : %x\n" + "\tp : %d\n" + "\tma : %d\n" + "\td : %d\n", + gr_reg->pl, gr_reg->ar, rid_reg->rid, gr_reg->p, gr_reg->ma, + gr_reg->d); } } return p - page; @@ -776,7 +760,7 @@ { "tr_info", tr_info, } }; -#define NR_PALINFO_ENTRIES (sizeof(palinfo_entries)/sizeof(palinfo_entry_t)) +#define NR_PALINFO_ENTRIES (int) ARRAY_SIZE(palinfo_entries) /* * this array is used to keep track of the proc entries we create. This is diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c --- a/arch/ia64/kernel/perfmon.c Sat May 24 12:48:32 2003 +++ b/arch/ia64/kernel/perfmon.c Sat May 24 12:48:32 2003 @@ -2,7 +2,7 @@ * This file implements the perfmon subsystem which is used * to program the IA-64 Performance Monitoring Unit (PMU). * - * Originaly Written by Ganesh Venkitachalam, IBM Corp. + * Originally Written by Ganesh Venkitachalam, IBM Corp. * Copyright (C) 1999 Ganesh Venkitachalam * * Modifications by Stephane Eranian, Hewlett-Packard Co. @@ -224,8 +224,9 @@ unsigned int protected:1; /* allow access to creator of context only */ unsigned int using_dbreg:1; /* using range restrictions (debug registers) */ unsigned int excl_idle:1; /* exclude idle task in system wide session */ + unsigned int unsecure:1; /* sp = 0 for non self-monitored task */ unsigned int trap_reason:2; /* reason for going into pfm_block_ovfl_reset() */ - unsigned int reserved:21; + unsigned int reserved:20; } pfm_context_flags_t; #define PFM_TRAP_REASON_NONE 0x0 /* default value */ @@ -278,6 +279,7 @@ #define ctx_fl_using_dbreg ctx_flags.using_dbreg #define ctx_fl_excl_idle ctx_flags.excl_idle #define ctx_fl_trap_reason ctx_flags.trap_reason +#define ctx_fl_unsecure ctx_flags.unsecure /* * global information about all sessions @@ -362,8 +364,9 @@ #define PFM_CMD_IDX(cmd) (cmd) -#define PFM_CMD_IS_VALID(cmd) ((PFM_CMD_IDX(cmd) >= 0) && (PFM_CMD_IDX(cmd) < PFM_CMD_COUNT) \ - && pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_func != NULL) +#define PFM_CMD_IS_VALID(cmd) ((PFM_CMD_IDX(cmd) >= 0) \ + && (PFM_CMD_IDX(cmd) < (int) PFM_CMD_COUNT) \ + && pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_func != NULL) #define PFM_CMD_USE_PID(cmd) ((pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_PID) != 0) #define PFM_CMD_READ_ARG(cmd) ((pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_ARG_READ) != 0) @@ -646,7 +649,7 @@ /* * This function is called from pfm_destroy_context() and also from pfm_inherit() - * to explicitely remove the sampling buffer mapping from the user level address space. + * to explicitly remove the sampling buffer mapping from the user level address space. */ static int pfm_remove_smpl_mapping(struct task_struct *task) @@ -724,8 +727,7 @@ static unsigned long pfm_smpl_entry_size(unsigned long *which, unsigned long size) { - unsigned long res = 0; - int i; + unsigned long i, res = 0; for (i=0; i < size; i++, which++) res += hweight64(*which); @@ -1076,10 +1078,15 @@ * and it must be a valid CPU */ cpu = ffz(~pfx->ctx_cpu_mask); +#ifdef CONFIG_SMP if (cpu_online(cpu) == 0) { +#else + if (cpu != 0) { +#endif DBprintk(("CPU%d is not online\n", cpu)); return -EINVAL; } + /* * check for pre-existing pinning, if conflicting reject */ @@ -1225,6 +1232,7 @@ ctx->ctx_fl_block = (ctx_flags & PFM_FL_NOTIFY_BLOCK) ? 1 : 0; ctx->ctx_fl_system = (ctx_flags & PFM_FL_SYSTEM_WIDE) ? 1: 0; ctx->ctx_fl_excl_idle = (ctx_flags & PFM_FL_EXCL_IDLE) ? 1: 0; + ctx->ctx_fl_unsecure = (ctx_flags & PFM_FL_UNSECURE) ? 1: 0; ctx->ctx_fl_frozen = 0; ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE; @@ -1251,9 +1259,11 @@ DBprintk(("context=%p, pid=%d notify_task=%p\n", (void *)ctx, task->pid, ctx->ctx_notify_task)); - DBprintk(("context=%p, pid=%d flags=0x%x inherit=%d block=%d system=%d excl_idle=%d\n", + DBprintk(("context=%p, pid=%d flags=0x%x inherit=%d block=%d system=%d excl_idle=%d unsecure=%d\n", (void *)ctx, task->pid, ctx_flags, ctx->ctx_fl_inherit, - ctx->ctx_fl_block, ctx->ctx_fl_system, ctx->ctx_fl_excl_idle)); + ctx->ctx_fl_block, ctx->ctx_fl_system, + ctx->ctx_fl_excl_idle, + ctx->ctx_fl_unsecure)); /* * when no notification is required, we can make this visible at the last moment @@ -1659,7 +1669,7 @@ if (!PMD_IS_IMPL(cnum)) goto abort_mission; /* * we can only read the register that we use. That includes - * the one we explicitely initialize AND the one we want included + * the one we explicitly initialize AND the one we want included * in the sampling buffer (smpl_regs). * * Having this restriction allows optimization in the ctxsw routine @@ -1871,7 +1881,7 @@ * if blocking, then post the semaphore. * if non-blocking, then we ensure that the task will go into * pfm_overflow_must_block() before returning to user mode. - * We cannot explicitely reset another task, it MUST always + * We cannot explicitly reset another task, it MUST always * be done by the task itself. This works for system wide because * the tool that is controlling the session is doing "self-monitoring". * @@ -1882,7 +1892,10 @@ DBprintk(("unblocking %d \n", task->pid)); up(sem); } else { + struct thread_info *info = (struct thread_info *) ((char *) task + IA64_TASK_SIZE); task->thread.pfm_ovfl_block_reset = 1; + ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_RESET; + set_bit(TIF_NOTIFY_RESUME, &info->flags); } #if 0 /* @@ -2051,7 +2064,7 @@ /* * reinforce secure monitoring: cannot toggle psr.up */ - ia64_psr(regs)->sp = 1; + if (ctx->ctx_fl_unsecure == 0) ia64_psr(regs)->sp = 1; return 0; } @@ -2159,11 +2172,11 @@ * never leaves the current CPU and the state * is shared by all processes running on it */ - for (i=0; i < pmu_conf.num_ibrs; i++) { + for (i=0; i < (int) pmu_conf.num_ibrs; i++) { ia64_set_ibr(i, 0UL); } ia64_srlz_i(); - for (i=0; i < pmu_conf.num_dbrs; i++) { + for (i=0; i < (int) pmu_conf.num_dbrs; i++) { ia64_set_dbr(i, 0UL); } ia64_srlz_d(); @@ -2505,7 +2518,7 @@ /* 33 */{ pfm_write_dbrs, PFM_CMD_PID|PFM_CMD_CTX|PFM_CMD_ARG_RW, PFM_CMD_ARG_MANY, sizeof(pfarg_dbreg_t)} #endif }; -#define PFM_CMD_COUNT (sizeof(pfm_cmd_tab)/sizeof(pfm_cmd_desc_t)) +#define PFM_CMD_COUNT ARRAY_SIZE(pfm_cmd_tab) static int check_task_state(struct task_struct *task) @@ -2732,12 +2745,13 @@ * again */ th->pfm_ovfl_block_reset = 0; + clear_thread_flag(TIF_NOTIFY_RESUME); /* * do some sanity checks first */ if (!ctx) { - printk(KERN_DEBUG "perfmon: [%d] has no PFM context\n", current->pid); + printk(KERN_ERR "perfmon: [%d] has no PFM context\n", current->pid); return; } /* @@ -2899,15 +2913,18 @@ /* * main overflow processing routine. - * it can be called from the interrupt path or explicitely during the context switch code + * it can be called from the interrupt path or explicitly during the context switch code + * Arguments: + * mode: 0=coming from PMU interrupt, 1=coming from ctxsw + * * Return: * new value of pmc[0]. if 0x0 then unfreeze, else keep frozen */ static unsigned long -pfm_overflow_handler(struct task_struct *task, pfm_context_t *ctx, u64 pmc0, struct pt_regs *regs) +pfm_overflow_handler(int mode, struct task_struct *task, pfm_context_t *ctx, u64 pmc0, struct pt_regs *regs) { - unsigned long mask; struct thread_struct *t; + unsigned long mask; unsigned long old_val; unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL; int i; @@ -2998,10 +3015,10 @@ /* * check for sampling buffer * - * if present, record sample. We propagate notification ONLY when buffer - * becomes full. + * if present, record sample only when a 64-bit counter has overflowed. + * We propagate notification ONLY when buffer becomes full. */ - if(CTX_HAS_SMPL(ctx)) { + if(CTX_HAS_SMPL(ctx) && ovfl_pmds) { ret = pfm_record_sample(task, ctx, ovfl_pmds, regs); if (ret == 1) { /* @@ -3046,12 +3063,55 @@ * ctx_notify_task could already be NULL, checked in pfm_notify_user() */ if (CTX_OVFL_NOBLOCK(ctx) == 0 && ctx->ctx_notify_task != task) { - t->pfm_ovfl_block_reset = 1; /* will cause blocking */ ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_BLOCKSIG; } else { - t->pfm_ovfl_block_reset = 1; /* will cause blocking */ ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_SIG; } + /* + * we cannot block in system wide mode and we do not go + * through the PMU ctxsw code. Therefore we can generate + * the notification here. In system wide mode, the current + * task maybe different from the task controlling the session + * on this CPU, therefore owner can be different from current. + * + * In per-process mode, this function gets called from + * the interrupt handler or pfm_load_regs(). The mode argument + * tells where we are coming from. When coming from the interrupt + * handler, it is safe to notify (send signal) right here because + * we do not hold any runqueue locks needed by send_sig_info(). + * + * However when coming from ctxsw, we cannot send the signal here. + * It must be deferred until we are sure we do not hold any runqueue + * related locks. The current task maybe different from the owner + * only in UP mode. The deferral is implemented using the + * TIF_NOTIFY_RESUME mechanism. In this case, the pending work + * is checked when the task is about to leave the kernel (see + * entry.S). As of this version of perfmon, a kernel only + * task cannot be monitored in per-process mode. Therefore, + * when this function gets called from pfm_load_regs(), we know + * we have a user level task which will eventually either exit + * or leave the kernel, and thereby go through the checkpoint + * for TIF_*. + */ + if (ctx->ctx_fl_system || mode == 0) { + pfm_notify_user(ctx); + ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE; + } else { + struct thread_info *info; + + /* + * given that TIF_NOTIFY_RESUME is not specific to + * perfmon, we need to have a second level check to + * verify the source of the notification. + */ + task->thread.pfm_ovfl_block_reset = 1; + /* + * when coming from ctxsw, current still points to the + * previous task, therefore we must work with task and not current. + */ + info = ((struct thread_info *) ((char *) task + IA64_TASK_SIZE)); + set_bit(TIF_NOTIFY_RESUME, &info->flags); + } /* * keep the PMU frozen until either pfm_restart() or @@ -3059,7 +3119,10 @@ */ ctx->ctx_fl_frozen = 1; - DBprintk_ovfl(("return pmc0=0x%x must_block=%ld reason=%d\n", + DBprintk_ovfl(("current [%d] owner [%d] mode=%d return pmc0=0x%x must_block=%ld reason=%d\n", + current->pid, + PMU_OWNER() ? PMU_OWNER()->pid : -1, + mode, ctx->ctx_fl_frozen ? 0x1 : 0x0, t->pfm_ovfl_block_reset, ctx->ctx_fl_trap_reason)); @@ -3068,7 +3131,7 @@ return 0x1UL; } -static void +static irqreturn_t pfm_interrupt_handler(int irq, void *arg, struct pt_regs *regs) { u64 pmc0; @@ -3083,7 +3146,7 @@ if (pfm_alternate_intr_handler) { (*pfm_alternate_intr_handler->handler)(irq, arg, regs); put_cpu(); - return; + return IRQ_HANDLED; } /* @@ -3108,19 +3171,21 @@ printk(KERN_DEBUG "perfmon: Spurious overflow interrupt: process %d has " "no PFM context\n", task->pid); put_cpu(); - return; + return IRQ_HANDLED; } /* * assume PMC[0].fr = 1 at this point */ - pmc0 = pfm_overflow_handler(task, ctx, pmc0, regs); + pmc0 = pfm_overflow_handler(0, task, ctx, pmc0, regs); /* * we can only update pmc0 when the overflow - * is for the current context. In UP the current - * task may not be the one owning the PMU + * is for the current context or we are in system + * wide mode. In UP (per-task) the current + * task may not be the one owning the PMU, + * same thing for system-wide. */ - if (task == current) { + if (task == current || ctx->ctx_fl_system) { /* * We always clear the overflow status bits and either unfreeze * or keep the PMU frozen. @@ -3134,6 +3199,7 @@ pfm_stats[smp_processor_id()].pfm_spurious_ovfl_intr_count++; } put_cpu_no_resched(); + return IRQ_HANDLED; } /* for debug only */ @@ -3387,11 +3453,11 @@ * in the next version of perfmon. */ if (ctx->ctx_fl_using_dbreg) { - for (i=0; i < pmu_conf.num_ibrs; i++) { + for (i=0; i < (int) pmu_conf.num_ibrs; i++) { ia64_set_ibr(i, t->ibr[i]); } ia64_srlz_i(); - for (i=0; i < pmu_conf.num_dbrs; i++) { + for (i=0; i < (int) pmu_conf.num_dbrs; i++) { ia64_set_dbr(i, t->dbr[i]); } ia64_srlz_d(); @@ -3402,7 +3468,7 @@ * this path cannot be used in SMP */ if (owner == task) { - if (atomic_read(&ctx->ctx_last_cpu) != smp_processor_id()) + if ((unsigned int) atomic_read(&ctx->ctx_last_cpu) != smp_processor_id()) DBprintk(("invalid last_cpu=%d for [%d]\n", atomic_read(&ctx->ctx_last_cpu), task->pid)); @@ -3454,7 +3520,7 @@ * Side effect on ctx_fl_frozen is possible. */ if (t->pmc[0] & ~0x1) { - t->pmc[0] = pfm_overflow_handler(task, ctx, t->pmc[0], NULL); + t->pmc[0] = pfm_overflow_handler(1, task, ctx, t->pmc[0], NULL); } /* @@ -3676,7 +3742,7 @@ * */ - if (atomic_read(&ctx->ctx_last_cpu) != smp_processor_id()) + if ((unsigned int) atomic_read(&ctx->ctx_last_cpu) != smp_processor_id()) printk(KERN_DEBUG "perfmon: [%d] last_cpu=%d\n", task->pid, atomic_read(&ctx->ctx_last_cpu)); @@ -3754,16 +3820,20 @@ preempt_disable(); /* - * make sure child cannot mess up the monitoring session + * for secure sessions, make sure child cannot mess up + * the monitoring session. */ - ia64_psr(regs)->sp = 1; - DBprintk(("enabling psr.sp for [%d]\n", task->pid)); - + if (ctx->ctx_fl_unsecure == 0) { + ia64_psr(regs)->sp = 1; + DBprintk(("enabling psr.sp for [%d]\n", task->pid)); + } else { + DBprintk(("psr.sp=%d [%d]\n", ia64_psr(regs)->sp, task->pid)); + } /* * if there was a virtual mapping for the sampling buffer * the mapping is NOT inherited across fork() (see VM_DONTCOPY), - * so we don't have to explicitely remove it here. + * so we don't have to explicitly remove it here. * * * Part of the clearing of fields is also done in diff -Nru a/arch/ia64/kernel/perfmon_mckinley.h b/arch/ia64/kernel/perfmon_mckinley.h --- a/arch/ia64/kernel/perfmon_mckinley.h Sat May 24 12:48:29 2003 +++ b/arch/ia64/kernel/perfmon_mckinley.h Sat May 24 12:48:29 2003 @@ -25,8 +25,8 @@ /* pmc5 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(5),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc6 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(6),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc7 */ { PFM_REG_COUNTING, 6, 0x0UL, 0xfffff7fUL, NULL, pfm_mck_reserved, {RDEP(7),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc8 */ { PFM_REG_CONFIG , 0, 0xffffffff3fffffffUL, 0xffffffff9fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, -/* pmc9 */ { PFM_REG_CONFIG , 0, 0xffffffff3ffffffcUL, 0xffffffff9fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc8 */ { PFM_REG_CONFIG , 0, 0xffffffff3fffffffUL, 0xffffffff3fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, +/* pmc9 */ { PFM_REG_CONFIG , 0, 0xffffffff3ffffffcUL, 0xffffffff3fffffffUL, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc10 */ { PFM_REG_MONITOR , 4, 0x0UL, 0xffffUL, NULL, pfm_mck_reserved, {RDEP(0)|RDEP(1),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc11 */ { PFM_REG_MONITOR , 6, 0x0UL, 0x30f01cf, NULL, pfm_mck_reserved, {RDEP(2)|RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc12 */ { PFM_REG_MONITOR , 6, 0x0UL, 0xffffUL, NULL, pfm_mck_reserved, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, @@ -143,10 +143,7 @@ case 8: val8 = *val; val13 = th->pmc[13]; val14 = th->pmc[14]; - *val |= 1UL << 2; /* bit 2 must always be 1 */ check_case1 = 1; - break; - case 9: *val |= 1UL << 2; /* bit 2 must always be 1 */ break; case 13: val8 = th->pmc[8]; val13 = *val; diff -Nru a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c --- a/arch/ia64/kernel/process.c Sat May 24 12:48:24 2003 +++ b/arch/ia64/kernel/process.c Sat May 24 12:48:24 2003 @@ -43,8 +43,8 @@ #include "sigframe.h" -static void -do_show_stack (struct unw_frame_info *info, void *arg) +void +ia64_do_show_stack (struct unw_frame_info *info, void *arg) { unsigned long ip, sp, bsp; char buf[80]; /* don't make it so big that it overflows the stack! */ @@ -57,7 +57,7 @@ unw_get_sp(info, &sp); unw_get_bsp(info, &bsp); - snprintf(buf, sizeof(buf), " [<%016lx>] %%s sp=0x%016lx bsp=0x%016lx\n", + snprintf(buf, sizeof(buf), " [<%016lx>] %%s\n\t\t\t\tsp=%016lx bsp=%016lx\n", ip, sp, bsp); print_symbol(buf, ip); } while (unw_unwind(info) >= 0); @@ -73,12 +73,12 @@ show_stack (struct task_struct *task) { if (!task) - unw_init_running(do_show_stack, 0); + unw_init_running(ia64_do_show_stack, 0); else { struct unw_frame_info info; unw_init_from_blocked_task(&info, task); - do_show_stack(&info, 0); + ia64_do_show_stack(&info, 0); } } @@ -123,8 +123,8 @@ if (user_mode(regs)) { /* print the stacked registers */ - unsigned long val, sof, *bsp, ndirty; - int i, is_nat = 0; + unsigned long val, *bsp, ndirty; + int i, sof, is_nat = 0; sof = regs->cr_ifs & 0x7f; /* size of frame */ ndirty = (regs->loadrs >> 19); @@ -135,7 +135,7 @@ ((i == sof - 1) || (i % 3) == 2) ? "\n" : " "); } } else - show_stack(0); + show_stack(NULL); } void @@ -379,6 +379,7 @@ # define THREAD_FLAGS_TO_SET 0 p->thread.flags = ((current->thread.flags & ~THREAD_FLAGS_TO_CLEAR) | THREAD_FLAGS_TO_SET); + p->thread.last_fph_cpu = -1; #ifdef CONFIG_IA32_SUPPORT /* * If we're cloning an IA32 task then save the IA32 extra diff -Nru a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c --- a/arch/ia64/kernel/ptrace.c Sat May 24 12:48:33 2003 +++ b/arch/ia64/kernel/ptrace.c Sat May 24 12:48:33 2003 @@ -202,17 +202,16 @@ get_rnat (struct pt_regs *pt, struct switch_stack *sw, unsigned long *krbs, unsigned long *urnat_addr) { - unsigned long rnat0 = 0, rnat1 = 0, urnat = 0, *slot0_kaddr, kmask = ~0UL; + unsigned long rnat0 = 0, rnat1 = 0, urnat = 0, *slot0_kaddr, umask = 0UL; unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift; long num_regs; kbsp = (unsigned long *) sw->ar_bspstore; ubspstore = (unsigned long *) pt->ar_bspstore; /* - * First, figure out which bit number slot 0 in user-land maps - * to in the kernel rnat. Do this by figuring out how many - * register slots we're beyond the user's backingstore and - * then computing the equivalent address in kernel space. + * First, figure out which bit number slot 0 in user-land maps to in the kernel + * rnat. Do this by figuring out how many register slots we're beyond the user's + * backingstore and then computing the equivalent address in kernel space. */ num_regs = ia64_rse_num_regs(ubspstore, urnat_addr + 1); slot0_kaddr = ia64_rse_skip_regs(krbs, num_regs); @@ -222,8 +221,8 @@ if (ubspstore + 63 > urnat_addr) { /* some bits need to be merged in from pt->ar_rnat */ - kmask = ~((1UL << ia64_rse_slot_num(ubspstore)) - 1); - urnat = (pt->ar_rnat & ~kmask); + umask = ((1UL << ia64_rse_slot_num(ubspstore)) - 1); + urnat = (pt->ar_rnat & umask); } if (rnat0_kaddr >= kbsp) { rnat0 = sw->ar_rnat; @@ -235,7 +234,7 @@ } else if (rnat1_kaddr > krbs) { rnat1 = *rnat1_kaddr; } - urnat |= ((rnat1 << (63 - shift)) | (rnat0 >> shift)) & kmask; + urnat |= ((rnat1 << (63 - shift)) | (rnat0 >> shift)) & ~umask; return urnat; } @@ -246,17 +245,19 @@ put_rnat (struct pt_regs *pt, struct switch_stack *sw, unsigned long *krbs, unsigned long *urnat_addr, unsigned long urnat) { - unsigned long rnat0 = 0, rnat1 = 0, rnat = 0, *slot0_kaddr, kmask = ~0UL, mask; - unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift; - long num_regs; + unsigned long rnat0 = 0, rnat1 = 0, *slot0_kaddr, umask = 0, mask, m; + unsigned long *kbsp, *ubspstore, *rnat0_kaddr, *rnat1_kaddr, shift, slot, ndirty; + long num_regs, nbits; + + ndirty = ia64_rse_num_regs(krbs, krbs + (pt->loadrs >> 19)); + nbits = ndirty % 63; kbsp = (unsigned long *) sw->ar_bspstore; ubspstore = (unsigned long *) pt->ar_bspstore; /* - * First, figure out which bit number slot 0 in user-land maps - * to in the kernel rnat. Do this by figuring out how many - * register slots we're beyond the user's backingstore and - * then computing the equivalent address in kernel space. + * First, figure out which bit number slot 0 in user-land maps to in the kernel + * rnat. Do this by figuring out how many register slots we're beyond the user's + * backingstore and then computing the equivalent address in kernel space. */ num_regs = (long) ia64_rse_num_regs(ubspstore, urnat_addr + 1); slot0_kaddr = ia64_rse_skip_regs(krbs, num_regs); @@ -264,29 +265,37 @@ rnat1_kaddr = ia64_rse_rnat_addr(slot0_kaddr); rnat0_kaddr = rnat1_kaddr - 64; +printk("%s: ubspstore=%p urnat_addr=%p\n", __FUNCTION__, ubspstore, urnat_addr); if (ubspstore + 63 > urnat_addr) { /* some bits need to be place in pt->ar_rnat: */ - kmask = ~((1UL << ia64_rse_slot_num(ubspstore)) - 1); - pt->ar_rnat = (pt->ar_rnat & kmask) | (rnat & ~kmask); + slot = ia64_rse_slot_num(ubspstore); + umask = ((1UL << slot) - 1); + pt->ar_rnat = (pt->ar_rnat & ~umask) | (urnat & umask); + nbits -= slot; + if (nbits <= 0) + return; } + mask = (1UL << nbits) - 1; /* * Note: Section 11.1 of the EAS guarantees that bit 63 of an * rnat slot is ignored. so we don't have to clear it here. */ rnat0 = (urnat << shift); - mask = ~0UL << shift; + m = mask << shift; +printk("%s: rnat0=%016lx, m=%016lx, rnat0_kaddr=%p kbsp=%p\n", __FUNCTION__, rnat0, m, rnat0_kaddr, kbsp); if (rnat0_kaddr >= kbsp) { - sw->ar_rnat = (sw->ar_rnat & ~mask) | (rnat0 & mask); + sw->ar_rnat = (sw->ar_rnat & ~m) | (rnat0 & m); } else if (rnat0_kaddr > krbs) { - *rnat0_kaddr = ((*rnat0_kaddr & ~mask) | (rnat0 & mask)); + *rnat0_kaddr = ((*rnat0_kaddr & ~m) | (rnat0 & m)); } rnat1 = (urnat >> (63 - shift)); - mask = ~0UL >> (63 - shift); + m = mask >> (63 - shift); +printk("%s: rnat1=%016lx, m=%016lx, rnat1_kaddr=%p kbsp=%p\n", __FUNCTION__, rnat1, m, rnat1_kaddr, kbsp); if (rnat1_kaddr >= kbsp) { - sw->ar_rnat = (sw->ar_rnat & ~mask) | (rnat1 & mask); + sw->ar_rnat = (sw->ar_rnat & ~m) | (rnat1 & m); } else if (rnat1_kaddr > krbs) { - *rnat1_kaddr = ((*rnat1_kaddr & ~mask) | (rnat1 & mask)); + *rnat1_kaddr = ((*rnat1_kaddr & ~m) | (rnat1 & m)); } } @@ -589,6 +598,7 @@ psr->mfh = 0; ia64_save_fpu(&task->thread.fph[0]); task->thread.flags |= IA64_THREAD_FPH_VALID; + task->thread.last_fph_cpu = smp_processor_id(); } } @@ -608,12 +618,11 @@ ia64_flush_fph(task); if (!(task->thread.flags & IA64_THREAD_FPH_VALID)) { task->thread.flags |= IA64_THREAD_FPH_VALID; + task->thread.last_fph_cpu = -1; /* force reload */ memset(&task->thread.fph, 0, sizeof(task->thread.fph)); } -#ifndef CONFIG_SMP if (ia64_get_fpu_owner() == task) ia64_set_fpu_owner(0); -#endif psr->dfh = 1; } @@ -702,7 +711,9 @@ case PT_R4: case PT_R5: case PT_R6: case PT_R7: if (write_access) { /* read NaT bit first: */ - ret = unw_get_gr(&info, (addr - PT_R4)/8 + 4, data, &nat); + unsigned long dummy; + + ret = unw_get_gr(&info, (addr - PT_R4)/8 + 4, &dummy, &nat); if (ret < 0) return ret; } diff -Nru a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c --- a/arch/ia64/kernel/sal.c Sat May 24 12:48:32 2003 +++ b/arch/ia64/kernel/sal.c Sat May 24 12:48:32 2003 @@ -116,7 +116,7 @@ p = (char *) (systab + 1); for (i = 0; i < systab->entry_count; i++) { /* - * The first byte of each entry type contains the type desciptor. + * The first byte of each entry type contains the type descriptor. */ switch (*p) { case SAL_DESC_ENTRY_POINT: diff -Nru a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c --- a/arch/ia64/kernel/salinfo.c Sat May 24 12:48:29 2003 +++ b/arch/ia64/kernel/salinfo.c Sat May 24 12:48:29 2003 @@ -38,7 +38,7 @@ { "itc_drift", IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT, }, }; -#define NR_SALINFO_ENTRIES (sizeof(salinfo_entries)/sizeof(salinfo_entry_t)) +#define NR_SALINFO_ENTRIES ARRAY_SIZE(salinfo_entries) /* * One for each feature and one more for the directory entry... diff -Nru a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c --- a/arch/ia64/kernel/setup.c Sat May 24 12:48:20 2003 +++ b/arch/ia64/kernel/setup.c Sat May 24 12:48:20 2003 @@ -59,7 +59,10 @@ struct ia64_boot_param *ia64_boot_param; struct screen_info screen_info; +unsigned long ia64_max_cacheline_size; unsigned long ia64_iobase; /* virtual address for I/O accesses */ +struct io_space io_space[MAX_IO_SPACES]; +unsigned int num_io_spaces; unsigned char aux_device_present = 0xaa; /* XXX remove this when legacy I/O is gone */ @@ -412,6 +415,11 @@ } ia64_iobase = (unsigned long) ioremap(phys_iobase, 0); + /* setup legacy IO port space */ + io_space[0].mmio_base = ia64_iobase; + io_space[0].sparse = 1; + num_io_spaces = 1; + #ifdef CONFIG_SMP cpu_physical_id(0) = hard_smp_processor_id(); #endif @@ -421,7 +429,7 @@ #ifdef CONFIG_ACPI_BOOT acpi_boot_init(); #endif -#ifdef CONFIG_SERIAL_HCDP +#ifdef CONFIG_SERIAL_8250_HCDP if (efi.hcdp) { void setup_serial_hcdp(void *); @@ -494,7 +502,7 @@ memcpy(features, " standard", 10); cp = features; sep = 0; - for (i = 0; i < sizeof(feature_bits)/sizeof(feature_bits[0]); ++i) { + for (i = 0; i < (int) ARRAY_SIZE(feature_bits); ++i) { if (mask & feature_bits[i].mask) { if (sep) *cp++ = sep; @@ -625,6 +633,39 @@ /* start_kernel() requires this... */ } +static void +get_max_cacheline_size (void) +{ + unsigned long line_size, max = 1; + u64 l, levels, unique_caches; + pal_cache_config_info_t cci; + s64 status; + + status = ia64_pal_cache_summary(&levels, &unique_caches); + if (status != 0) { + printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n", + __FUNCTION__, status); + max = SMP_CACHE_BYTES; + goto out; + } + + for (l = 0; l < levels; ++l) { + status = ia64_pal_cache_config_info(l, /* cache_type (data_or_unified)= */ 2, + &cci); + if (status != 0) { + printk(KERN_ERR + "%s: ia64_pal_cache_config_info(l=%lu) failed (status=%ld)\n", + __FUNCTION__, l, status); + max = SMP_CACHE_BYTES; + } + line_size = 1 << cci.pcci_line_size; + if (line_size > max) + max = line_size; + } + out: + if (max > ia64_max_cacheline_size) + ia64_max_cacheline_size = max; +} /* * cpu_init() initializes state that is per-CPU. This function acts @@ -667,6 +708,8 @@ #ifdef CONFIG_NUMA cpu_info->node_data = get_node_data_ptr(); #endif + + get_max_cacheline_size(); /* * We can't pass "local_cpu_data" to identify_cpu() because we haven't called diff -Nru a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c --- a/arch/ia64/kernel/signal.c Sat May 24 12:48:26 2003 +++ b/arch/ia64/kernel/signal.c Sat May 24 12:48:26 2003 @@ -142,8 +142,13 @@ __copy_from_user(current->thread.fph, &sc->sc_fr[32], 96*16); psr->mfh = 0; /* drop signal handler's fph contents... */ - if (!psr->dfh) + if (psr->dfh) + current->thread.last_fph_cpu = -1; + else { __ia64_load_fpu(current->thread.fph); + ia64_set_fpu_owner(current); + current->thread.last_fph_cpu = smp_processor_id(); + } } return err; } @@ -523,7 +528,7 @@ else errno = -errno; } - } else if (scr->pt.r10 != -1) + } else if ((long) scr->pt.r10 != -1) /* * A system calls has to be restarted only if one of the error codes * ERESTARTNOHAND, ERESTARTSYS, or ERESTARTNOINTR is returned. If r10 diff -Nru a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c --- a/arch/ia64/kernel/smp.c Sat May 24 12:48:33 2003 +++ b/arch/ia64/kernel/smp.c Sat May 24 12:48:33 2003 @@ -2,7 +2,7 @@ * SMP Support * * Copyright (C) 1999 Walt Drummond - * Copyright (C) 1999, 2001 David Mosberger-Tang + * Copyright (C) 1999, 2001, 2003 David Mosberger-Tang * * Lots of stuff stolen from arch/alpha/kernel/smp.c * @@ -87,7 +87,7 @@ cpu_halt(); } -void +irqreturn_t handle_IPI (int irq, void *dev_id, struct pt_regs *regs) { int this_cpu = get_cpu(); @@ -147,10 +147,11 @@ mb(); /* Order data access and bit testing. */ } put_cpu(); + return IRQ_HANDLED; } /* - * Called with preeemption disabled + * Called with preeemption disabled. */ static inline void send_IPI_single (int dest_cpu, int op) @@ -160,12 +161,12 @@ } /* - * Called with preeemption disabled + * Called with preeemption disabled. */ static inline void send_IPI_allbutself (int op) { - int i; + unsigned int i; for (i = 0; i < NR_CPUS; i++) { if (cpu_online(i) && i != smp_processor_id()) @@ -174,7 +175,7 @@ } /* - * Called with preeemption disabled + * Called with preeemption disabled. */ static inline void send_IPI_all (int op) @@ -187,7 +188,7 @@ } /* - * Called with preeemption disabled + * Called with preeemption disabled. */ static inline void send_IPI_self (int op) @@ -196,7 +197,7 @@ } /* - * Called with preeemption disabled + * Called with preeemption disabled. */ void smp_send_reschedule (int cpu) diff -Nru a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c --- a/arch/ia64/kernel/smpboot.c Sat May 24 12:48:21 2003 +++ b/arch/ia64/kernel/smpboot.c Sat May 24 12:48:21 2003 @@ -192,6 +192,7 @@ { long i, delta, adj, adjust_latency = 0, done = 0; unsigned long flags, rt, master_time_stamp, bound; + extern void ia64_cpu_local_tick (void); #if DEBUG_ITC_SYNC struct { long rt; /* roundtrip time */ @@ -246,6 +247,16 @@ printk(KERN_INFO "CPU %d: synchronized ITC with CPU %u (last diff %ld cycles, " "maxerr %lu cycles)\n", smp_processor_id(), master, delta, rt); + + /* + * Check whether we sync'd the itc ahead of the next timer interrupt. If so, just + * reset it. + */ + if (time_after(ia64_get_itc(), local_cpu_data->itm_next)) { + Dprintk("CPU %d: oops, jumped a timer tick; resetting timer.\n", + smp_processor_id()); + ia64_cpu_local_tick(); + } } /* @@ -279,15 +290,6 @@ smp_setup_percpu_timer(); - if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) { - /* - * Synchronize the ITC with the BP - */ - Dprintk("Going to syncup ITC with BP.\n"); - - ia64_sync_itc(0); - } - /* * Get our bogomips. */ @@ -310,6 +312,18 @@ local_irq_enable(); calibrate_delay(); local_cpu_data->loops_per_jiffy = loops_per_jiffy; + + if (!(sal_platform_features & IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT)) { + /* + * Synchronize the ITC with the BP. Need to do this after irqs are + * enabled because ia64_sync_itc() calls smp_call_function_single(), which + * calls spin_unlock_bh(), which calls spin_unlock_bh(), which calls + * local_bh_enable(), which bugs out if irqs are not enabled... + */ + Dprintk("Going to syncup ITC with BP.\n"); + ia64_sync_itc(0); + } + /* * Allow the master to continue. */ @@ -394,13 +408,26 @@ return 0; } -unsigned long cache_decay_ticks; /* # of ticks an idle task is considered cache-hot */ +static int __init +decay (char *str) +{ + int ticks; + get_option (&str, &ticks); + cache_decay_ticks = ticks; + return 1; +} + +__setup("decay=", decay); + +/* + * # of ticks an idle task is considered cache-hot. Highly application-dependent. There + * are apps out there which are known to suffer significantly with values >= 4. + */ +unsigned long cache_decay_ticks = 10; /* equal to MIN_TIMESLICE */ static void smp_tune_scheduling (void) { - cache_decay_ticks = 10; /* XXX base this on PAL info and cache-bandwidth estimate */ - printk(KERN_INFO "task migration cache decay timeout: %ld msecs.\n", (cache_decay_ticks + 1) * 1000 / HZ); } diff -Nru a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c --- a/arch/ia64/kernel/time.c Sat May 24 12:48:21 2003 +++ b/arch/ia64/kernel/time.c Sat May 24 12:48:21 2003 @@ -83,11 +83,26 @@ return (elapsed_cycles*local_cpu_data->nsec_per_cyc) >> IA64_NSEC_PER_CYC_SHIFT; } +static inline void +set_normalized_timespec (struct timespec *ts, time_t sec, long nsec) +{ + while (nsec > NSEC_PER_SEC) { + nsec -= NSEC_PER_SEC; + ++sec; + } + while (nsec < 0) { + nsec += NSEC_PER_SEC; + --sec; + } + ts->tv_sec = sec; + ts->tv_nsec = nsec; +} + void do_settimeofday (struct timeval *tv) { - time_t sec = tv->tv_sec; - long nsec = tv->tv_usec * 1000; + time_t wtm_sec, sec = tv->tv_sec; + long wtm_nsec, nsec = tv->tv_usec * 1000; write_seqlock_irq(&xtime_lock); { @@ -99,13 +114,12 @@ */ nsec -= gettimeoffset(); - while (nsec < 0) { - nsec += 1000000000; - sec--; - } + wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); + wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); + + set_normalized_timespec(&xtime, sec, nsec); + set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); - xtime.tv_sec = sec; - xtime.tv_nsec = nsec; time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; @@ -166,8 +180,8 @@ usec = (nsec + offset) / 1000; - while (unlikely(usec >= 1000000)) { - usec -= 1000000; + while (unlikely(usec >= USEC_PER_SEC)) { + usec -= USEC_PER_SEC; ++sec; } @@ -175,8 +189,8 @@ tv->tv_usec = usec; } -static void -timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t +timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) { unsigned long new_itm; @@ -221,7 +235,7 @@ do { /* * If we're too close to the next clock tick for comfort, we increase the - * saftey margin by intentionally dropping the next tick(s). We do NOT update + * safety margin by intentionally dropping the next tick(s). We do NOT update * itm.next because that would force us to call do_timer() which in turn would * let our clock run too fast (with the potentially devastating effect of * losing monotony of time). @@ -231,12 +245,13 @@ ia64_set_itm(new_itm); /* double check, in case we got hit by a (slow) PMI: */ } while (time_after_eq(ia64_get_itc(), new_itm)); + return IRQ_HANDLED; } /* * Encapsulate access to the itm structure for SMP. */ -void __init +void ia64_cpu_local_tick (void) { int cpu = smp_processor_id(); @@ -281,7 +296,7 @@ if (status != 0) { /* invent "random" values */ printk(KERN_ERR - "SAL/PAL failed to obtain frequency info---inventing reasonably values\n"); + "SAL/PAL failed to obtain frequency info---inventing reasonable values\n"); platform_base_freq = 100000000; itc_ratio.num = 3; itc_ratio.den = 1; @@ -305,8 +320,8 @@ local_cpu_data->proc_freq = (platform_base_freq*proc_ratio.num)/proc_ratio.den; local_cpu_data->itc_freq = itc_freq; - local_cpu_data->cyc_per_usec = (itc_freq + 500000) / 1000000; - local_cpu_data->nsec_per_cyc = ((1000000000UL<cyc_per_usec = (itc_freq + USEC_PER_SEC/2) / USEC_PER_SEC; + local_cpu_data->nsec_per_cyc = ((NSEC_PER_SEC<curr.reg + unw.save_order[i]; if (reg->where == UNW_WHERE_GR_SAVE) { reg->where = UNW_WHERE_GR; @@ -698,7 +698,7 @@ */ if (sr->imask) { unsigned char kind, mask = 0, *cp = sr->imask; - unsigned long t; + int t; static const unsigned char limit[3] = { UNW_REG_F31, UNW_REG_R7, UNW_REG_B5 }; @@ -1214,13 +1214,13 @@ spin_unlock(&unw.lock); /* - * XXX We'll deadlock here if we interrupt a thread that is - * holding a read lock on script->lock. A try_write_lock() - * might be mighty handy here... Alternatively, we could - * disable interrupts whenever we hold a read-lock, but that - * seems silly. + * We'd deadlock here if we interrupted a thread that is holding a read lock on + * script->lock. Thus, if the write_trylock() fails, we simply bail out. The + * alternative would be to disable interrupts whenever we hold a read-lock, but + * that seems silly. */ - write_lock(&script->lock); + if (!write_trylock(&script->lock)) + return NULL; spin_lock(&unw.lock); { @@ -1888,22 +1888,21 @@ return -1; } -void -unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t, struct switch_stack *sw) +static void +init_frame_info (struct unw_frame_info *info, struct task_struct *t, + struct switch_stack *sw, unsigned long stktop) { - unsigned long rbslimit, rbstop, stklimit, stktop, sol; + unsigned long rbslimit, rbstop, stklimit; STAT(unsigned long start, flags;) STAT(local_irq_save(flags); ++unw.stat.api.inits; start = ia64_get_itc()); /* - * Subtle stuff here: we _could_ unwind through the - * switch_stack frame but we don't want to do that because it - * would be slow as each preserved register would have to be - * processed. Instead, what we do here is zero out the frame - * info and start the unwind process at the function that - * created the switch_stack frame. When a preserved value in - * switch_stack needs to be accessed, run_script() will + * Subtle stuff here: we _could_ unwind through the switch_stack frame but we + * don't want to do that because it would be slow as each preserved register would + * have to be processed. Instead, what we do here is zero out the frame info and + * start the unwind process at the function that created the switch_stack frame. + * When a preserved value in switch_stack needs to be accessed, run_script() will * initialize the appropriate pointer on demand. */ memset(info, 0, sizeof(*info)); @@ -1914,7 +1913,6 @@ rbstop = rbslimit; stklimit = (unsigned long) t + IA64_STK_OFFSET; - stktop = (unsigned long) sw - 16; if (stktop <= rbstop) stktop = rbstop; @@ -1924,34 +1922,58 @@ info->memstk.top = stktop; info->task = t; info->sw = sw; - info->sp = info->psp = (unsigned long) (sw + 1) - 16; - info->pt = 0; + info->sp = info->psp = stktop; + info->pr = sw->pr; + UNW_DPRINT(3, "unwind.%s:\n" + " task 0x%lx\n" + " rbs = [0x%lx-0x%lx)\n" + " stk = [0x%lx-0x%lx)\n" + " pr 0x%lx\n" + " sw 0x%lx\n" + " sp 0x%lx\n", + __FUNCTION__, (unsigned long) t, rbslimit, rbstop, stktop, stklimit, + info->pr, (unsigned long) info->sw, info->sp); + STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags)); +} + +void +unw_init_from_interruption (struct unw_frame_info *info, struct task_struct *t, + struct pt_regs *pt, struct switch_stack *sw) +{ + unsigned long sof; + + init_frame_info(info, t, sw, pt->r12); + info->cfm_loc = &pt->cr_ifs; + info->unat_loc = &pt->ar_unat; + info->pfs_loc = &pt->ar_pfs; + sof = *info->cfm_loc & 0x7f; + info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sof); + info->ip = pt->cr_iip + ia64_psr(pt)->ri; + info->pt = (unsigned long) pt; + UNW_DPRINT(3, "unwind.%s:\n" + " bsp 0x%lx\n" + " sof 0x%lx\n" + " ip 0x%lx\n", + __FUNCTION__, info->bsp, sof, info->ip); + find_save_locs(info); +} + +void +unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t, struct switch_stack *sw) +{ + unsigned long sol; + + init_frame_info(info, t, sw, (unsigned long) (sw + 1) - 16); info->cfm_loc = &sw->ar_pfs; sol = (*info->cfm_loc >> 7) & 0x7f; info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sol); info->ip = sw->b0; - info->pr = sw->pr; - UNW_DPRINT(3, - "unwind.%s\n" - " rbslimit 0x%lx\n" - " rbstop 0x%lx\n" - " stklimit 0x%lx\n" - " stktop 0x%lx\n" - " task 0x%lx\n" - " sw 0x%lx\n", - __FUNCTION__, rbslimit, rbstop, stklimit, stktop, - (unsigned long)(info->task), - (unsigned long)(info->sw)); - UNW_DPRINT(3, - " sp/psp 0x%lx\n" - " sol 0x%lx\n" - " bsp 0x%lx\n" - " ip 0x%lx\n" - " pr 0x%lx\n", - info->sp, sol, info->bsp, info->ip, info->pr); - + UNW_DPRINT(3, "unwind.%s:\n" + " bsp 0x%lx\n" + " sol 0x%lx\n" + " ip 0x%lx\n", + __FUNCTION__, info->bsp, sol, info->ip); find_save_locs(info); - STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags)); } void diff -Nru a/arch/ia64/lib/copy_user.S b/arch/ia64/lib/copy_user.S --- a/arch/ia64/lib/copy_user.S Sat May 24 12:48:21 2003 +++ b/arch/ia64/lib/copy_user.S Sat May 24 12:48:21 2003 @@ -316,7 +316,7 @@ // Beginning of long mempcy (i.e. > 16 bytes) // .long_copy_user: - tbit.nz p6,p7=src1,0 // odd alignement + tbit.nz p6,p7=src1,0 // odd alignment and tmp=7,tmp ;; cmp.eq p10,p8=r0,tmp diff -Nru a/arch/ia64/lib/do_csum.S b/arch/ia64/lib/do_csum.S --- a/arch/ia64/lib/do_csum.S Sat May 24 12:48:21 2003 +++ b/arch/ia64/lib/do_csum.S Sat May 24 12:48:21 2003 @@ -137,7 +137,7 @@ mov saved_pr=pr // preserve predicates (rotation) (p6) br.ret.spnt.many rp // return if zero or negative length - mov hmask=-1 // intialize head mask + mov hmask=-1 // initialize head mask tbit.nz p15,p0=buf,0 // is buf an odd address? and first1=-8,buf // 8-byte align down address of first1 element diff -Nru a/arch/ia64/lib/io.c b/arch/ia64/lib/io.c --- a/arch/ia64/lib/io.c Sat May 24 12:48:19 2003 +++ b/arch/ia64/lib/io.c Sat May 24 12:48:19 2003 @@ -51,84 +51,79 @@ #ifdef CONFIG_IA64_GENERIC +#undef __ia64_inb +#undef __ia64_inw +#undef __ia64_inl +#undef __ia64_outb +#undef __ia64_outw +#undef __ia64_outl +#undef __ia64_readb +#undef __ia64_readw +#undef __ia64_readl +#undef __ia64_readq +#undef __ia64_writeb +#undef __ia64_writew +#undef __ia64_writel +#undef __ia64_writeq + unsigned int -ia64_inb (unsigned long port) +__ia64_inb (unsigned long port) { - return __ia64_inb(port); + return ___ia64_inb(port); } unsigned int -ia64_inw (unsigned long port) +__ia64_inw (unsigned long port) { - return __ia64_inw(port); + return ___ia64_inw(port); } unsigned int -ia64_inl (unsigned long port) +__ia64_inl (unsigned long port) { - return __ia64_inl(port); + return ___ia64_inl(port); } void -ia64_outb (unsigned char val, unsigned long port) +__ia64_outb (unsigned char val, unsigned long port) { - __ia64_outb(val, port); + ___ia64_outb(val, port); } void -ia64_outw (unsigned short val, unsigned long port) +__ia64_outw (unsigned short val, unsigned long port) { - __ia64_outw(val, port); + ___ia64_outw(val, port); } void -ia64_outl (unsigned int val, unsigned long port) +__ia64_outl (unsigned int val, unsigned long port) { - __ia64_outl(val, port); + ___ia64_outl(val, port); } unsigned char -ia64_readb (void *addr) +__ia64_readb (void *addr) { - return __ia64_readb (addr); + return ___ia64_readb (addr); } unsigned short -ia64_readw (void *addr) +__ia64_readw (void *addr) { - return __ia64_readw (addr); + return ___ia64_readw (addr); } unsigned int -ia64_readl (void *addr) +__ia64_readl (void *addr) { - return __ia64_readl (addr); + return ___ia64_readl (addr); } unsigned long -ia64_readq (void *addr) +__ia64_readq (void *addr) { - return __ia64_readq (addr) + return ___ia64_readq (addr); } - - -/* define aliases: */ - -asm (".global __ia64_inb, __ia64_inw, __ia64_inl"); -asm ("__ia64_inb = ia64_inb"); -asm ("__ia64_inw = ia64_inw"); -asm ("__ia64_inl = ia64_inl"); - -asm (".global __ia64_outb, __ia64_outw, __ia64_outl"); -asm ("__ia64_outb = ia64_outb"); -asm ("__ia64_outw = ia64_outw"); -asm ("__ia64_outl = ia64_outl"); - -asm (".global __ia64_readb, __ia64_readw, __ia64_readl, __ia64_readq"); -asm ("__ia64_readb = ia64_readb"); -asm ("__ia64_readw = ia64_readw"); -asm ("__ia64_readl = ia64_readl"); -asm ("__ia64_readq = ia64_readq"); - #endif /* CONFIG_IA64_GENERIC */ diff -Nru a/arch/ia64/lib/swiotlb.c b/arch/ia64/lib/swiotlb.c --- a/arch/ia64/lib/swiotlb.c Sat May 24 12:48:29 2003 +++ b/arch/ia64/lib/swiotlb.c Sat May 24 12:48:29 2003 @@ -5,7 +5,10 @@ * I/O TLBs (aka DMA address translation hardware). * Copyright (C) 2000 Asit Mallick * Copyright (C) 2000 Goutham Rao + * Copyright (C) 2000, 2003 Hewlett-Packard Co + * David Mosberger-Tang * + * 03/05/07 davidm Switch from PCI-DMA to generic device DMA API. * 00/12/13 davidm Rename to swiotlb.c and add mark_clean() to avoid * unnecessary i-cache flushing. */ @@ -92,7 +95,7 @@ void swiotlb_init (void) { - int i; + unsigned long i; /* * Get IO TLB memory from the low pages @@ -121,7 +124,7 @@ * Allocates bounce buffer and returns its kernel virtual address. */ static void * -map_single (struct pci_dev *hwdev, char *buffer, size_t size, int direction) +map_single (struct device *hwdev, char *buffer, size_t size, int dir) { unsigned long flags; char *dma_addr; @@ -161,7 +164,7 @@ if (io_tlb_list[index] >= nslots) { int count = 0; - for (i = index; i < index + nslots; i++) + for (i = index; i < (int) (index + nslots); i++) io_tlb_list[i] = 0; for (i = index - 1; (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE -1) && io_tlb_list[i]; i--) @@ -195,7 +198,7 @@ * needed when we sync the memory. Then we sync the buffer if needed. */ io_tlb_orig_addr[index] = buffer; - if (direction == PCI_DMA_TODEVICE || direction == PCI_DMA_BIDIRECTIONAL) + if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) memcpy(dma_addr, buffer, size); return dma_addr; @@ -205,7 +208,7 @@ * dma_addr is the kernel virtual address of the bounce buffer to unmap. */ static void -unmap_single (struct pci_dev *hwdev, char *dma_addr, size_t size, int direction) +unmap_single (struct device *hwdev, char *dma_addr, size_t size, int dir) { unsigned long flags; int i, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT; @@ -215,7 +218,7 @@ /* * First, sync the memory before unmapping the entry */ - if ((direction == PCI_DMA_FROMDEVICE) || (direction == PCI_DMA_BIDIRECTIONAL)) + if ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)) /* * bounce... copy the data back into the original buffer * and delete the * bounce buffer. @@ -239,7 +242,7 @@ for (i = index + nslots - 1; i >= index; i--) io_tlb_list[i] = ++count; /* - * Step 2: merge the returned slots with the preceeding slots, if + * Step 2: merge the returned slots with the preceding slots, if * available (non zero) */ for (i = index - 1; (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE -1) && @@ -250,49 +253,46 @@ } static void -sync_single (struct pci_dev *hwdev, char *dma_addr, size_t size, int direction) +sync_single (struct device *hwdev, char *dma_addr, size_t size, int dir) { int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; char *buffer = io_tlb_orig_addr[index]; /* * bounce... copy the data back into/from the original buffer - * XXX How do you handle PCI_DMA_BIDIRECTIONAL here ? + * XXX How do you handle DMA_BIDIRECTIONAL here ? */ - if (direction == PCI_DMA_FROMDEVICE) + if (dir == DMA_FROM_DEVICE) memcpy(buffer, dma_addr, size); - else if (direction == PCI_DMA_TODEVICE) + else if (dir == DMA_TO_DEVICE) memcpy(dma_addr, buffer, size); else BUG(); } void * -swiotlb_alloc_consistent (struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle) +swiotlb_alloc_coherent (struct device *hwdev, size_t size, dma_addr_t *dma_handle, int flags) { - unsigned long pci_addr; - int gfp = GFP_ATOMIC; + unsigned long dev_addr; void *ret; - /* - * Alloc_consistent() is defined to return memory < 4GB, no matter what the DMA - * mask says. - */ - gfp |= GFP_DMA; /* XXX fix me: should change this to GFP_32BIT or ZONE_32BIT */ - ret = (void *)__get_free_pages(gfp, get_order(size)); + /* XXX fix me: the DMA API should pass us an explicit DMA mask instead: */ + flags |= GFP_DMA; + + ret = (void *)__get_free_pages(flags, get_order(size)); if (!ret) return NULL; memset(ret, 0, size); - pci_addr = virt_to_phys(ret); - if (hwdev && (pci_addr & ~hwdev->dma_mask) != 0) - panic("swiotlb_alloc_consistent: allocated memory is out of range for PCI device"); - *dma_handle = pci_addr; + dev_addr = virt_to_phys(ret); + if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0) + panic("swiotlb_alloc_consistent: allocated memory is out of range for device"); + *dma_handle = dev_addr; return ret; } void -swiotlb_free_consistent (struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) +swiotlb_free_coherent (struct device *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) { free_pages((unsigned long) vaddr, get_order(size)); } @@ -305,34 +305,34 @@ * swiotlb_unmap_single or swiotlb_dma_sync_single is performed. */ dma_addr_t -swiotlb_map_single (struct pci_dev *hwdev, void *ptr, size_t size, int direction) +swiotlb_map_single (struct device *hwdev, void *ptr, size_t size, int dir) { - unsigned long pci_addr = virt_to_phys(ptr); + unsigned long dev_addr = virt_to_phys(ptr); - if (direction == PCI_DMA_NONE) + if (dir == DMA_NONE) BUG(); /* * Check if the PCI device can DMA to ptr... if so, just return ptr */ - if ((pci_addr & ~hwdev->dma_mask) == 0) + if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) == 0) /* * Device is bit capable of DMA'ing to the buffer... just return the PCI * address of ptr */ - return pci_addr; + return dev_addr; /* * get a bounce buffer: */ - pci_addr = virt_to_phys(map_single(hwdev, ptr, size, direction)); + dev_addr = virt_to_phys(map_single(hwdev, ptr, size, dir)); /* * Ensure that the address returned is DMA'ble: */ - if ((pci_addr & ~hwdev->dma_mask) != 0) + if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0) panic("map_single: bounce buffer is not DMA'ble"); - return pci_addr; + return dev_addr; } /* @@ -363,15 +363,15 @@ * device wrote there. */ void -swiotlb_unmap_single (struct pci_dev *hwdev, dma_addr_t pci_addr, size_t size, int direction) +swiotlb_unmap_single (struct device *hwdev, dma_addr_t dev_addr, size_t size, int dir) { - char *dma_addr = phys_to_virt(pci_addr); + char *dma_addr = phys_to_virt(dev_addr); - if (direction == PCI_DMA_NONE) + if (dir == DMA_NONE) BUG(); if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end) - unmap_single(hwdev, dma_addr, size, direction); - else if (direction == PCI_DMA_FROMDEVICE) + unmap_single(hwdev, dma_addr, size, dir); + else if (dir == DMA_FROM_DEVICE) mark_clean(dma_addr, size); } @@ -385,21 +385,21 @@ * again owns the buffer. */ void -swiotlb_sync_single (struct pci_dev *hwdev, dma_addr_t pci_addr, size_t size, int direction) +swiotlb_sync_single (struct device *hwdev, dma_addr_t dev_addr, size_t size, int dir) { - char *dma_addr = phys_to_virt(pci_addr); + char *dma_addr = phys_to_virt(dev_addr); - if (direction == PCI_DMA_NONE) + if (dir == DMA_NONE) BUG(); if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end) - sync_single(hwdev, dma_addr, size, direction); - else if (direction == PCI_DMA_FROMDEVICE) + sync_single(hwdev, dma_addr, size, dir); + else if (dir == DMA_FROM_DEVICE) mark_clean(dma_addr, size); } /* * Map a set of buffers described by scatterlist in streaming mode for DMA. This is the - * scather-gather version of the above swiotlb_map_single interface. Here the scatter + * scatter-gather version of the above swiotlb_map_single interface. Here the scatter * gather list elements are each tagged with the appropriate dma address and length. They * are obtained via sg_dma_{address,length}(SG). * @@ -412,23 +412,22 @@ * Device ownership issues as mentioned above for swiotlb_map_single are the same here. */ int -swiotlb_map_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction) +swiotlb_map_sg (struct device *hwdev, struct scatterlist *sg, int nelems, int dir) { void *addr; - unsigned long pci_addr; + unsigned long dev_addr; int i; - if (direction == PCI_DMA_NONE) + if (dir == DMA_NONE) BUG(); for (i = 0; i < nelems; i++, sg++) { addr = SG_ENT_VIRT_ADDRESS(sg); - pci_addr = virt_to_phys(addr); - if ((pci_addr & ~hwdev->dma_mask) != 0) - sg->dma_address = (dma_addr_t) - map_single(hwdev, addr, sg->length, direction); + dev_addr = virt_to_phys(addr); + if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0) + sg->dma_address = (dma_addr_t) map_single(hwdev, addr, sg->length, dir); else - sg->dma_address = pci_addr; + sg->dma_address = dev_addr; sg->dma_length = sg->length; } return nelems; @@ -439,17 +438,17 @@ * here are the same as for swiotlb_unmap_single() above. */ void -swiotlb_unmap_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction) +swiotlb_unmap_sg (struct device *hwdev, struct scatterlist *sg, int nelems, int dir) { int i; - if (direction == PCI_DMA_NONE) + if (dir == DMA_NONE) BUG(); for (i = 0; i < nelems; i++, sg++) if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg)) - unmap_single(hwdev, (void *) sg->dma_address, sg->dma_length, direction); - else if (direction == PCI_DMA_FROMDEVICE) + unmap_single(hwdev, (void *) sg->dma_address, sg->dma_length, dir); + else if (dir == DMA_FROM_DEVICE) mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length); } @@ -461,16 +460,16 @@ * usage. */ void -swiotlb_sync_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction) +swiotlb_sync_sg (struct device *hwdev, struct scatterlist *sg, int nelems, int dir) { int i; - if (direction == PCI_DMA_NONE) + if (dir == DMA_NONE) BUG(); for (i = 0; i < nelems; i++, sg++) if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg)) - sync_single(hwdev, (void *) sg->dma_address, sg->dma_length, direction); + sync_single(hwdev, (void *) sg->dma_address, sg->dma_length, dir); } /* @@ -479,7 +478,7 @@ * you would pass 0x00ffffff as the mask to this function. */ int -swiotlb_pci_dma_supported (struct pci_dev *hwdev, u64 mask) +swiotlb_dma_supported (struct device *hwdev, u64 mask) { return 1; } @@ -491,6 +490,6 @@ EXPORT_SYMBOL(swiotlb_unmap_sg); EXPORT_SYMBOL(swiotlb_sync_single); EXPORT_SYMBOL(swiotlb_sync_sg); -EXPORT_SYMBOL(swiotlb_alloc_consistent); -EXPORT_SYMBOL(swiotlb_free_consistent); -EXPORT_SYMBOL(swiotlb_pci_dma_supported); +EXPORT_SYMBOL(swiotlb_alloc_coherent); +EXPORT_SYMBOL(swiotlb_free_coherent); +EXPORT_SYMBOL(swiotlb_dma_supported); diff -Nru a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c --- a/arch/ia64/mm/fault.c Sat May 24 12:48:32 2003 +++ b/arch/ia64/mm/fault.c Sat May 24 12:48:32 2003 @@ -58,6 +58,18 @@ if (in_atomic() || !mm) goto no_context; +#ifdef CONFIG_VIRTUAL_MEM_MAP + /* + * If fault is in region 5 and we are in the kernel, we may already + * have the mmap_sem (pfn_valid macro is called during mmap). There + * is no vma for region 5 addr's anyway, so skip getting the semaphore + * and go directly to the exception handling code. + */ + + if ((REGION_NUMBER(address) == 5) && !user_mode(regs)) + goto bad_area_no_up; +#endif + down_read(&mm->mmap_sem); vma = find_vma_prev(mm, address, &prev_vma); @@ -139,6 +151,9 @@ bad_area: up_read(&mm->mmap_sem); +#ifdef CONFIG_VIRTUAL_MEM_MAP + bad_area_no_up: +#endif if ((isr & IA64_ISR_SP) || ((isr & IA64_ISR_NA) && (isr & IA64_ISR_CODE_MASK) == IA64_ISR_CODE_LFETCH)) { diff -Nru a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c --- a/arch/ia64/mm/hugetlbpage.c Sat May 24 12:48:25 2003 +++ b/arch/ia64/mm/hugetlbpage.c Sat May 24 12:48:25 2003 @@ -12,13 +12,12 @@ #include #include #include +#include #include #include #include #include -#include - #define TASK_HPAGE_BASE (REGION_HPAGE << REGION_SHIFT) static long htlbpagemem; @@ -392,8 +391,6 @@ { int lcount; struct page *page ; - extern long htlbzone_pages; - extern struct list_head htlbpage_freelist; if (count < 0) lcount = count; diff -Nru a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c --- a/arch/ia64/mm/init.c Sat May 24 12:48:23 2003 +++ b/arch/ia64/mm/init.c Sat May 24 12:48:23 2003 @@ -38,6 +38,13 @@ unsigned long MAX_DMA_ADDRESS = PAGE_OFFSET + 0x100000000UL; +#ifdef CONFIG_VIRTUAL_MEM_MAP +# define LARGE_GAP 0x40000000 /* Use virtual mem map if hole is > than this */ + unsigned long vmalloc_end = VMALLOC_END_INIT; + static struct page *vmem_map; + static unsigned long num_dma_physpages; +#endif + static int pgt_cache_water[2] = { 25, 50 }; void @@ -48,13 +55,13 @@ low = pgt_cache_water[0]; high = pgt_cache_water[1]; - if (pgtable_cache_size > high) { + if (pgtable_cache_size > (u64) high) { do { if (pgd_quicklist) free_page((unsigned long)pgd_alloc_one_fast(0)); if (pmd_quicklist) free_page((unsigned long)pmd_alloc_one_fast(0, 0)); - } while (pgtable_cache_size > low); + } while (pgtable_cache_size > (u64) low); } } @@ -337,6 +344,139 @@ ia64_tlb_init(); } +#ifdef CONFIG_VIRTUAL_MEM_MAP + +static int +create_mem_map_page_table (u64 start, u64 end, void *arg) +{ + unsigned long address, start_page, end_page; + struct page *map_start, *map_end; + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + + map_start = vmem_map + (__pa(start) >> PAGE_SHIFT); + map_end = vmem_map + (__pa(end) >> PAGE_SHIFT); + + start_page = (unsigned long) map_start & PAGE_MASK; + end_page = PAGE_ALIGN((unsigned long) map_end); + + for (address = start_page; address < end_page; address += PAGE_SIZE) { + pgd = pgd_offset_k(address); + if (pgd_none(*pgd)) + pgd_populate(&init_mm, pgd, alloc_bootmem_pages(PAGE_SIZE)); + pmd = pmd_offset(pgd, address); + + if (pmd_none(*pmd)) + pmd_populate_kernel(&init_mm, pmd, alloc_bootmem_pages(PAGE_SIZE)); + pte = pte_offset_kernel(pmd, address); + + if (pte_none(*pte)) + set_pte(pte, pfn_pte(__pa(alloc_bootmem_pages(PAGE_SIZE)) >> PAGE_SHIFT, + PAGE_KERNEL)); + } + return 0; +} + +struct memmap_init_callback_data { + struct page *start; + struct page *end; + int nid; + unsigned long zone; +}; + +static int +virtual_memmap_init (u64 start, u64 end, void *arg) +{ + struct memmap_init_callback_data *args; + struct page *map_start, *map_end; + + args = (struct memmap_init_callback_data *) arg; + + map_start = vmem_map + (__pa(start) >> PAGE_SHIFT); + map_end = vmem_map + (__pa(end) >> PAGE_SHIFT); + + if (map_start < args->start) + map_start = args->start; + if (map_end > args->end) + map_end = args->end; + + /* + * We have to initialize "out of bounds" struct page elements that fit completely + * on the same pages that were allocated for the "in bounds" elements because they + * may be referenced later (and found to be "reserved"). + */ + map_start -= ((unsigned long) map_start & (PAGE_SIZE - 1)) / sizeof(struct page); + map_end += ((PAGE_ALIGN((unsigned long) map_end) - (unsigned long) map_end) + / sizeof(struct page)); + + if (map_start < map_end) + memmap_init_zone(map_start, (unsigned long) (map_end - map_start), + args->nid, args->zone, page_to_pfn(map_start)); + return 0; +} + +void +memmap_init (struct page *start, unsigned long size, int nid, + unsigned long zone, unsigned long start_pfn) +{ + if (!vmem_map) + memmap_init_zone(start, size, nid, zone, start_pfn); + else { + struct memmap_init_callback_data args; + + args.start = start; + args.end = start + size; + args.nid = nid; + args.zone = zone; + + efi_memmap_walk(virtual_memmap_init, &args); + } +} + +int +ia64_pfn_valid (unsigned long pfn) +{ + char byte; + + return __get_user(byte, (char *) pfn_to_page(pfn)) == 0; +} + +static int +count_dma_pages (u64 start, u64 end, void *arg) +{ + unsigned long *count = arg; + + if (end <= MAX_DMA_ADDRESS) + *count += (end - start) >> PAGE_SHIFT; + return 0; +} + +static int +find_largest_hole (u64 start, u64 end, void *arg) +{ + u64 *max_gap = arg; + + static u64 last_end = PAGE_OFFSET; + + /* NOTE: this algorithm assumes efi memmap table is ordered */ + + if (*max_gap < (start - last_end)) + *max_gap = start - last_end; + last_end = end; + return 0; +} +#endif /* CONFIG_VIRTUAL_MEM_MAP */ + +static int +count_pages (u64 start, u64 end, void *arg) +{ + unsigned long *count = arg; + + *count += (end - start) >> PAGE_SHIFT; + return 0; +} + /* * Set up the page tables. */ @@ -348,18 +488,70 @@ extern void discontig_paging_init(void); discontig_paging_init(); + efi_memmap_walk(count_pages, &num_physpages); } #else /* !CONFIG_DISCONTIGMEM */ void paging_init (void) { - unsigned long max_dma, zones_size[MAX_NR_ZONES]; + unsigned long max_dma; + unsigned long zones_size[MAX_NR_ZONES]; +# ifdef CONFIG_VIRTUAL_MEM_MAP + unsigned long zholes_size[MAX_NR_ZONES]; + unsigned long max_gap; +# endif /* initialize mem_map[] */ memset(zones_size, 0, sizeof(zones_size)); + num_physpages = 0; + efi_memmap_walk(count_pages, &num_physpages); + max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT; + +# ifdef CONFIG_VIRTUAL_MEM_MAP + memset(zholes_size, 0, sizeof(zholes_size)); + + num_dma_physpages = 0; + efi_memmap_walk(count_dma_pages, &num_dma_physpages); + + if (max_low_pfn < max_dma) { + zones_size[ZONE_DMA] = max_low_pfn; + zholes_size[ZONE_DMA] = max_low_pfn - num_dma_physpages; + } else { + zones_size[ZONE_DMA] = max_dma; + zholes_size[ZONE_DMA] = max_dma - num_dma_physpages; + if (num_physpages > num_dma_physpages) { + zones_size[ZONE_NORMAL] = max_low_pfn - max_dma; + zholes_size[ZONE_NORMAL] = ((max_low_pfn - max_dma) + - (num_physpages - num_dma_physpages)); + } + } + + max_gap = 0; + efi_memmap_walk(find_largest_hole, (u64 *)&max_gap); + if (max_gap < LARGE_GAP) { + vmem_map = (struct page *) 0; + free_area_init_node(0, &contig_page_data, NULL, zones_size, 0, zholes_size); + mem_map = contig_page_data.node_mem_map; + } + else { + unsigned long map_size; + + /* allocate virtual_mem_map */ + + map_size = PAGE_ALIGN(max_low_pfn * sizeof(struct page)); + vmalloc_end -= map_size; + vmem_map = (struct page *) vmalloc_end; + efi_memmap_walk(create_mem_map_page_table, 0); + + free_area_init_node(0, &contig_page_data, vmem_map, zones_size, 0, zholes_size); + + mem_map = contig_page_data.node_mem_map; + printk("Virtual mem_map starts at 0x%p\n", mem_map); + } +# else /* !CONFIG_VIRTUAL_MEM_MAP */ if (max_low_pfn < max_dma) zones_size[ZONE_DMA] = max_low_pfn; else { @@ -367,19 +559,11 @@ zones_size[ZONE_NORMAL] = max_low_pfn - max_dma; } free_area_init(zones_size); +# endif /* !CONFIG_VIRTUAL_MEM_MAP */ } #endif /* !CONFIG_DISCONTIGMEM */ static int -count_pages (u64 start, u64 end, void *arg) -{ - unsigned long *count = arg; - - *count += (end - start) >> PAGE_SHIFT; - return 0; -} - -static int count_reserved_pages (u64 start, u64 end, void *arg) { unsigned long num_reserved = 0; @@ -406,7 +590,7 @@ * any drivers that may need the PCI DMA interface are initialized or bootmem has * been freed. */ - platform_pci_dma_init(); + platform_dma_init(); #endif #ifndef CONFIG_DISCONTIGMEM @@ -415,9 +599,6 @@ max_mapnr = max_low_pfn; #endif - num_physpages = 0; - efi_memmap_walk(count_pages, &num_physpages); - high_memory = __va(max_low_pfn * PAGE_SIZE); for_each_pgdat(pgdat) @@ -445,7 +626,7 @@ num_pgt_pages = nr_free_pages() / PTRS_PER_PGD + NUM_TASKS; if (num_pgt_pages > nr_free_pages() / 10) num_pgt_pages = nr_free_pages() / 10; - if (num_pgt_pages > pgt_cache_water[1]) + if (num_pgt_pages > (u64) pgt_cache_water[1]) pgt_cache_water[1] = num_pgt_pages; /* install the gate page in the global page table: */ diff -Nru a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c --- a/arch/ia64/pci/pci.c Sat May 24 12:48:24 2003 +++ b/arch/ia64/pci/pci.c Sat May 24 12:48:24 2003 @@ -5,6 +5,7 @@ * * Copyright (C) 2002 Hewlett-Packard Co * David Mosberger-Tang + * Bjorn Helgaas * * Note: Above list of copyright holders is incomplete... */ @@ -116,31 +117,10 @@ subsys_initcall(pci_acpi_init); -static void __init -pcibios_fixup_resource(struct resource *res, u64 offset) -{ - res->start += offset; - res->end += offset; -} - -void __init -pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus) -{ - int i; - - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - if (!dev->resource[i].start) - continue; - if (dev->resource[i].flags & IORESOURCE_MEM) - pcibios_fixup_resource(&dev->resource[i], - PCI_CONTROLLER(dev)->mem_offset); - } -} - /* Called by ACPI when it finds a new root bus. */ static struct pci_controller * -alloc_pci_controller(int seg) +alloc_pci_controller (int seg) { struct pci_controller *controller; @@ -153,8 +133,8 @@ return controller; } -struct pci_bus * -scan_root_bus(int bus, struct pci_ops *ops, void *sysdata) +static struct pci_bus * +scan_root_bus (int bus, struct pci_ops *ops, void *sysdata) { struct pci_bus *b; @@ -184,23 +164,185 @@ return b; } +static int +alloc_resource (char *name, struct resource *root, unsigned long start, unsigned long end, unsigned long flags) +{ + struct resource *res; + + res = kmalloc(sizeof(*res), GFP_KERNEL); + if (!res) + return -ENOMEM; + + memset(res, 0, sizeof(*res)); + res->name = name; + res->start = start; + res->end = end; + res->flags = flags; + + if (request_resource(root, res)) + return -EBUSY; + + return 0; +} + +static u64 +add_io_space (struct acpi_resource_address64 *addr) +{ + u64 offset; + int sparse = 0; + int i; + + if (addr->address_translation_offset == 0) + return IO_SPACE_BASE(0); /* part of legacy IO space */ + + if (addr->attribute.io.translation_attribute == ACPI_SPARSE_TRANSLATION) + sparse = 1; + + offset = (u64) ioremap(addr->address_translation_offset, 0); + for (i = 0; i < num_io_spaces; i++) + if (io_space[i].mmio_base == offset && + io_space[i].sparse == sparse) + return IO_SPACE_BASE(i); + + if (num_io_spaces == MAX_IO_SPACES) { + printk("Too many IO port spaces\n"); + return ~0; + } + + i = num_io_spaces++; + io_space[i].mmio_base = offset; + io_space[i].sparse = sparse; + + return IO_SPACE_BASE(i); +} + +static acpi_status +count_window (struct acpi_resource *resource, void *data) +{ + unsigned int *windows = (unsigned int *) data; + struct acpi_resource_address64 addr; + acpi_status status; + + status = acpi_resource_to_address64(resource, &addr); + if (ACPI_SUCCESS(status)) + if (addr.resource_type == ACPI_MEMORY_RANGE || + addr.resource_type == ACPI_IO_RANGE) + (*windows)++; + + return AE_OK; +} + +struct pci_root_info { + struct pci_controller *controller; + char *name; +}; + +static acpi_status +add_window (struct acpi_resource *res, void *data) +{ + struct pci_root_info *info = (struct pci_root_info *) data; + struct pci_window *window; + struct acpi_resource_address64 addr; + acpi_status status; + unsigned long flags, offset = 0; + struct resource *root; + + status = acpi_resource_to_address64(res, &addr); + if (ACPI_SUCCESS(status)) { + if (addr.resource_type == ACPI_MEMORY_RANGE) { + flags = IORESOURCE_MEM; + root = &iomem_resource; + offset = addr.address_translation_offset; + } else if (addr.resource_type == ACPI_IO_RANGE) { + flags = IORESOURCE_IO; + root = &ioport_resource; + offset = add_io_space(&addr); + if (offset == ~0) + return AE_OK; + } else + return AE_OK; + + window = &info->controller->window[info->controller->windows++]; + window->resource.flags |= flags; + window->resource.start = addr.min_address_range; + window->resource.end = addr.max_address_range; + window->offset = offset; + + if (alloc_resource(info->name, root, addr.min_address_range + offset, + addr.max_address_range + offset, flags)) + printk(KERN_ERR "alloc 0x%lx-0x%lx from %s for %s failed\n", + addr.min_address_range + offset, addr.max_address_range + offset, + root->name, info->name); + } + + return AE_OK; +} + struct pci_bus * -pcibios_scan_root(void *handle, int seg, int bus) +pcibios_scan_root (void *handle, int seg, int bus) { + struct pci_root_info info; struct pci_controller *controller; - u64 base, size, offset; + unsigned int windows = 0; + char *name; printk("PCI: Probing PCI hardware on bus (%02x:%02x)\n", seg, bus); controller = alloc_pci_controller(seg); if (!controller) - return NULL; + goto out1; controller->acpi_handle = handle; - acpi_get_addr_space(handle, ACPI_MEMORY_RANGE, &base, &size, &offset); - controller->mem_offset = offset; + acpi_walk_resources(handle, METHOD_NAME__CRS, count_window, &windows); + controller->window = kmalloc(sizeof(*controller->window) * windows, GFP_KERNEL); + if (!controller->window) + goto out2; + + name = kmalloc(16, GFP_KERNEL); + if (!name) + goto out3; + + sprintf(name, "PCI Bus %02x:%02x", seg, bus); + info.controller = controller; + info.name = name; + acpi_walk_resources(handle, METHOD_NAME__CRS, add_window, &info); return scan_root_bus(bus, pci_root_ops, controller); + +out3: + kfree(controller->window); +out2: + kfree(controller); +out1: + return NULL; +} + +void __init +pcibios_fixup_device_resources (struct pci_dev *dev, struct pci_bus *bus) +{ + struct pci_controller *controller = PCI_CONTROLLER(dev); + struct pci_window *window; + int i, j; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + if (!dev->resource[i].start) + continue; + +#define contains(win, res) ((res)->start >= (win)->start && \ + (res)->end <= (win)->end) + + for (j = 0; j < controller->windows; j++) { + window = &controller->window[j]; + if (((dev->resource[i].flags & IORESOURCE_MEM && + window->resource.flags & IORESOURCE_MEM) || + (dev->resource[i].flags & IORESOURCE_IO && + window->resource.flags & IORESOURCE_IO)) && + contains(&window->resource, &dev->resource[i])) { + dev->resource[i].start += window->offset; + dev->resource[i].end += window->offset; + } + } + } } /* diff -Nru a/arch/ia64/sn/kernel/machvec.c b/arch/ia64/sn/kernel/machvec.c --- a/arch/ia64/sn/kernel/machvec.c Sat May 24 12:48:25 2003 +++ b/arch/ia64/sn/kernel/machvec.c Sat May 24 12:48:25 2003 @@ -33,9 +33,11 @@ #include #ifdef CONFIG_IA64_SGI_SN1 -#define MACHVEC_PLATFORM_NAME sn1 +#define MACHVEC_PLATFORM_NAME sn1 +#define MACHVEC_PLATFORM_HEADER #else CONFIG_IA64_SGI_SN1 -#define MACHVEC_PLATFORM_NAME sn2 +#define MACHVEC_PLATFORM_NAME sn2 +#define MACHVEC_PLATFORM_HEADER #else #error "unknown platform" #endif diff -Nru a/arch/ia64/tools/print_offsets.c b/arch/ia64/tools/print_offsets.c --- a/arch/ia64/tools/print_offsets.c Sat May 24 12:48:31 2003 +++ b/arch/ia64/tools/print_offsets.c Sat May 24 12:48:31 2003 @@ -193,7 +193,7 @@ printf ("/*\n * DO NOT MODIFY\n *\n * This file was generated by " "arch/ia64/tools/print_offsets.\n *\n */\n\n"); - for (i = 0; i < sizeof (tab) / sizeof (tab[0]); ++i) + for (i = 0; i < (int) (sizeof (tab) / sizeof (tab[0])); ++i) { if (tab[i].name[0] == '\0') printf ("\n"); diff -Nru a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S --- a/arch/m68k/kernel/entry.S Sat May 24 12:48:19 2003 +++ b/arch/m68k/kernel/entry.S Sat May 24 12:48:19 2003 @@ -188,7 +188,7 @@ #if 0 -#if CONFIG_AMIGA +#ifdef CONFIG_AMIGA ami_inthandler: addql #1,irq_stat+CPUSTAT_LOCAL_IRQ_COUNT SAVE_ALL_INT diff -Nru a/arch/m68k/sun3/prom/init.c b/arch/m68k/sun3/prom/init.c --- a/arch/m68k/sun3/prom/init.c Sat May 24 12:48:31 2003 +++ b/arch/m68k/sun3/prom/init.c Sat May 24 12:48:31 2003 @@ -32,7 +32,7 @@ void __init prom_init(struct linux_romvec *rp) { -#if CONFIG_AP1000 +#ifdef CONFIG_AP1000 extern struct linux_romvec *ap_prom_init(void); rp = ap_prom_init(); #endif diff -Nru a/arch/m68k/sun3/prom/printf.c b/arch/m68k/sun3/prom/printf.c --- a/arch/m68k/sun3/prom/printf.c Sat May 24 12:48:19 2003 +++ b/arch/m68k/sun3/prom/printf.c Sat May 24 12:48:19 2003 @@ -38,7 +38,7 @@ bptr = ppbuf; -#if CONFIG_AP1000 +#ifdef CONFIG_AP1000 ap_write(1,bptr,strlen(bptr)); #else diff -Nru a/arch/m68knommu/platform/5249/MOTOROLA/crt0_ram.S b/arch/m68knommu/platform/5249/MOTOROLA/crt0_ram.S --- a/arch/m68knommu/platform/5249/MOTOROLA/crt0_ram.S Sat May 24 12:48:31 2003 +++ b/arch/m68knommu/platform/5249/MOTOROLA/crt0_ram.S Sat May 24 12:48:31 2003 @@ -93,7 +93,7 @@ move.l %d0, 0x180(%a1) /* Set PLL register */ nop -#if CONFIG_CLOCK_140MHz +#ifdef CONFIG_CLOCK_140MHz /* * Set initial clock frequency. This assumes M5249C3 board * is fitted with 11.2896MHz crystal. It will program the diff -Nru a/arch/mips/arc/misc.c b/arch/mips/arc/misc.c --- a/arch/mips/arc/misc.c Sat May 24 12:48:21 2003 +++ b/arch/mips/arc/misc.c Sat May 24 12:48:21 2003 @@ -19,7 +19,7 @@ { bc_disable(); cli(); -#if CONFIG_SCSI_SGIWD93 +#ifdef CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); #endif romvec->halt(); @@ -29,7 +29,7 @@ { bc_disable(); cli(); -#if CONFIG_SCSI_SGIWD93 +#ifdef CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); #endif romvec->pdown(); @@ -40,7 +40,7 @@ { bc_disable(); cli(); -#if CONFIG_SCSI_SGIWD93 +#ifdef CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); #endif romvec->restart(); @@ -50,7 +50,7 @@ { bc_disable(); cli(); -#if CONFIG_SCSI_SGIWD93 +#ifdef CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); #endif romvec->reboot(); @@ -60,7 +60,7 @@ { bc_disable(); cli(); -#if CONFIG_SCSI_SGIWD93 +#ifdef CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); #endif romvec->imode(); diff -Nru a/arch/mips/au1000/common/serial.c b/arch/mips/au1000/common/serial.c --- a/arch/mips/au1000/common/serial.c Sat May 24 12:48:22 2003 +++ b/arch/mips/au1000/common/serial.c Sat May 24 12:48:22 2003 @@ -2681,8 +2681,8 @@ (state->flags & ASYNC_FOURPORT) ? " FourPort" : "", state->port, state->irq, uart_config[state->type].name); - tty_register_device(&serial_driver, state->line); - tty_register_device(&callout_driver, state->line); + tty_register_device(&serial_driver, state->line, NULL); + tty_register_device(&callout_driver, state->line, NULL); } return 0; } @@ -2769,8 +2769,8 @@ state->iomem_base ? "iomem" : "port", state->iomem_base ? (unsigned long)state->iomem_base : state->port, state->irq, uart_config[state->type].name); - tty_register_device(&serial_driver, state->line); - tty_register_device(&callout_driver, state->line); + tty_register_device(&serial_driver, state->line, NULL); + tty_register_device(&callout_driver, state->line, NULL); return state->line + SERIAL_DEV_OFFSET; } diff -Nru a/arch/mips64/arc/misc.c b/arch/mips64/arc/misc.c --- a/arch/mips64/arc/misc.c Sat May 24 12:48:28 2003 +++ b/arch/mips64/arc/misc.c Sat May 24 12:48:28 2003 @@ -29,7 +29,7 @@ { bc_disable(); cli(); -#if CONFIG_SCSI_SGIWD93 +#ifdef CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); #endif ARC_CALL0(halt); @@ -41,7 +41,7 @@ { bc_disable(); cli(); -#if CONFIG_SCSI_SGIWD93 +#ifdef CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); #endif ARC_CALL0(pdown); @@ -54,7 +54,7 @@ { bc_disable(); cli(); -#if CONFIG_SCSI_SGIWD93 +#ifdef CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); #endif ARC_CALL0(restart); @@ -66,7 +66,7 @@ { bc_disable(); cli(); -#if CONFIG_SCSI_SGIWD93 +#ifdef CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); #endif ARC_CALL0(reboot); @@ -78,7 +78,7 @@ { bc_disable(); cli(); -#if CONFIG_SCSI_SGIWD93 +#ifdef CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); #endif ARC_CALL0(imode); diff -Nru a/arch/parisc/hpux/wrappers.S b/arch/parisc/hpux/wrappers.S --- a/arch/parisc/hpux/wrappers.S Sat May 24 12:48:31 2003 +++ b/arch/parisc/hpux/wrappers.S Sat May 24 12:48:31 2003 @@ -129,7 +129,7 @@ /* Set the return value for the child */ hpux_child_return: -#if CONFIG_SMP || CONFIG_PREEMPT +#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) bl schedule_tail, %r2 nop #endif diff -Nru a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c --- a/arch/parisc/kernel/module.c Sat May 24 12:48:33 2003 +++ b/arch/parisc/kernel/module.c Sat May 24 12:48:33 2003 @@ -568,3 +568,7 @@ #endif return 0; } + +void module_arch_cleanup(struct module *mod) +{ +} diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig --- a/arch/ppc/Kconfig Sat May 24 12:48:33 2003 +++ b/arch/ppc/Kconfig Sat May 24 12:48:33 2003 @@ -1111,7 +1111,7 @@ config LOWMEM_SIZE_BOOL bool "Set maximum low memory" - depends on ADVANCED_OPTIONS && HIGHMEM + depends on ADVANCED_OPTIONS help This option allows you to set the maximum amount of memory which will be used as "low memory", that is, memory which the kernel can diff -Nru a/arch/ppc/Makefile b/arch/ppc/Makefile --- a/arch/ppc/Makefile Sat May 24 12:48:20 2003 +++ b/arch/ppc/Makefile Sat May 24 12:48:20 2003 @@ -11,10 +11,10 @@ # # This must match PAGE_OFFSET in include/asm-ppc/page.h. -KERNELLOAD =$(CONFIG_KERNEL_START) +KERNELLOAD := $(CONFIG_KERNEL_START) LDFLAGS_BLOB := --format binary --oformat elf32-powerpc -LDFLAGS_vmlinux = -Ttext $(KERNELLOAD) -Bstatic +LDFLAGS_vmlinux := -Ttext $(KERNELLOAD) -Bstatic CPPFLAGS += -Iarch/$(ARCH) AFLAGS += -Iarch/$(ARCH) cflags-y += -Iarch/$(ARCH) -msoft-float -pipe \ diff -Nru a/arch/ppc/boot/Makefile b/arch/ppc/boot/Makefile --- a/arch/ppc/boot/Makefile Sat May 24 12:48:26 2003 +++ b/arch/ppc/boot/Makefile Sat May 24 12:48:26 2003 @@ -13,28 +13,17 @@ CFLAGS += -fno-builtin -D__BOOTER__ -Iarch/$(ARCH)/boot/include HOSTCFLAGS += -Iarch/$(ARCH)/boot/include -BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd +BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd bootdir-y := simple bootdir-$(CONFIG_ALL_PPC) := openfirmware prep -subdir-y := lib common images -subdir-$(CONFIG_ALL_PPC) += of1275 +subdir-y := lib/ common/ images/ +subdir-$(CONFIG_ALL_PPC) += of1275/ # for cleaning subdir- += simple/ openfirmware/ prep/ -tools-$(CONFIG_ALL_PPC) := addnote mknote hack-coff mkprep -tools-$(CONFIG_PPLUS) := mkbugboot mkprep -tools-$(CONFIG_4xx) := mktree -tools-$(CONFIG_LOPEC) := mkbugboot mkprep -tools-$(CONFIG_MCPN765) := mkbugboot mkprep -tools-$(CONFIG_MENF1) := mkprep -tools-$(CONFIG_MVME5100) := mkbugboot mkprep -tools-$(CONFIG_PRPMC750) := mkbugboot mkprep -tools-$(CONFIG_PRPMC800) := mkbugboot mkprep -tools-$(CONFIG_SPRUCE) := mktree - -host-progs := $(addprefix utils/,$(tools-y)) +host-progs := $(addprefix utils/, addnote mknote hack-coff mkprep mkbugboot mktree) .PHONY: $(BOOT_TARGETS) $(bootdir-y) diff -Nru a/arch/ppc/boot/common/dummy.c b/arch/ppc/boot/common/dummy.c --- a/arch/ppc/boot/common/dummy.c Sat May 24 12:48:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,4 +0,0 @@ -int main(void) -{ - return 0; -} diff -Nru a/arch/ppc/boot/images/Makefile b/arch/ppc/boot/images/Makefile --- a/arch/ppc/boot/images/Makefile Sat May 24 12:48:20 2003 +++ b/arch/ppc/boot/images/Makefile Sat May 24 12:48:20 2003 @@ -2,12 +2,14 @@ # This dir holds all of the images for PPC machines. # Tom Rini January 2001 -extra-y := vmlinux.gz -GZIP_FLAGS := -v9f +extra-y := vmlinux.bin vmlinux.gz -$(obj)/vmlinux.gz: vmlinux - $(OBJCOPY) -O binary $< $(@:.gz=) - gzip $(GZIP_FLAGS) $(@:.gz=) +OBJCOPYFLAGS_vmlinux.bin := -O binary +$(obj)/vmlinux.bin: vmlinux FORCE + $(call if_changed,objcopy) + +$(obj)/vmlinux.gz: $(obj)/vmlinux.bin FORCE + $(call if_changed,gzip) # Files generated that shall be removed upon make clean clean-files := sImage vmapus vmlinux* miboot* zImage* diff -Nru a/arch/ppc/boot/openfirmware/Makefile b/arch/ppc/boot/openfirmware/Makefile --- a/arch/ppc/boot/openfirmware/Makefile Sat May 24 12:48:22 2003 +++ b/arch/ppc/boot/openfirmware/Makefile Sat May 24 12:48:22 2003 @@ -10,36 +10,34 @@ # Merged 'chrp' and 'pmac' into 'openfirmware', and cleaned up the # rules. -clean-files := note coffboot coffboot.initrd +zImage.initrd znetboot.initrd: del-ramdisk-sec := -R .ramdisk +zImage.initrd znetboot.initrd: initrd := .initrd -boot: zImage -boot := arch/ppc/boot -common := $(boot)/common -utils := $(boot)/utils -bootlib := $(boot)/lib -of1275 := $(boot)/of1275 -images := $(boot)/images - -OBJCOPY_ARGS = -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment -COFF_LD_ARGS = -T $(boot)/ld.script -e _start -Ttext 0x00700000 -Bstatic -CHRP_LD_ARGS = -T $(boot)/ld.script -e _start -Ttext 0x00800000 -NEWWORLD_LD_ARGS = -T $(boot)/ld.script -e _start -Ttext 0x01000000 +boot := arch/ppc/boot +common := $(boot)/common +utils := $(boot)/utils +bootlib := $(boot)/lib +of1275 := $(boot)/of1275 +images := $(boot)/images + +OBJCOPY_ARGS := -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment +COFF_LD_ARGS := -T $(boot)/ld.script -e _start -Ttext 0x00700000 -Bstatic +CHRP_LD_ARGS := -T $(boot)/ld.script -e _start -Ttext 0x00800000 +NEWWORLD_LD_ARGS:= -T $(boot)/ld.script -e _start -Ttext 0x01000000 COMMONOBJS := start.o misc.o common.o COFFOBJS := coffcrt0.o $(COMMONOBJS) coffmain.o -CHRPOBJS := crt0.o $(COMMONOBJS) chrpmain.o -NEWWORLDOBJS := crt0.o $(COMMONOBJS) newworldmain.o +CHRPOBJS := crt0.o $(COMMONOBJS) chrpmain.o +NEWWORLDOBJS := crt0.o $(COMMONOBJS) newworldmain.o -EXTRA_TARGETS := $(COFFOBJS) $(CHRPOBJS) $(NEWWORLDOBJS) +targets := $(COFFOBJS) $(CHRPOBJS) $(NEWWORLDOBJS) dummy.o COFFOBJS := $(addprefix $(obj)/, $(COFFOBJS)) CHRPOBJS := $(addprefix $(obj)/, $(CHRPOBJS)) NEWWORLDOBJS := $(addprefix $(obj)/, $(NEWWORLDOBJS)) -LIBS = lib/lib.a $(bootlib)/lib.a $(of1275)/lib.a $(common)/lib.a +LIBS := lib/lib.a $(bootlib)/lib.a $(of1275)/lib.a $(common)/lib.a -ADDNOTE := $(utils)/addnote -MKNOTE := $(utils)/mknote HACKCOFF := $(utils)/hack-coff ifdef CONFIG_SMP @@ -49,108 +47,136 @@ END += .64 endif -TFTPIMAGE=/tftpboot/zImage. -$(obj)/dummy.o: $(common)/dummy.c - $(CC) -c -o $@ $(common)/dummy.c - -$(obj)/image.o: $(images)/vmlinux.gz $(obj)/dummy.o - $(OBJCOPY) $(obj)/dummy.o $@ -R .comment \ - --add-section=.image=$(images)/vmlinux.gz \ - --set-section-flags=.image=contents,alloc,load,readonly,data -ifdef CONFIG_XMON - $(OBJCOPY) $@ $@ \ - --add-section=.sysmap=$(TOPDIR)/System.map \ - --set-section-flags=.sysmap=contents,alloc,load,readonly,data -endif +$(images)/ramdisk.image.gz: + @echo ' MISSING $@' + @echo ' RAM disk image must be provided seperatly' + @/bin/false + +objcpxmon-$(CONFIG_XMON) := --add-section=.sysmap=System.map \ + --set-section-flags=.sysmap=contents,alloc,load,readonly,data +quiet_cmd_genimage = GEN $@ + cmd_genimage = $(OBJCOPY) -R .comment \ + --add-section=.image=$(images)/vmlinux.gz \ + --set-section-flags=.image=contents,alloc,load,readonly,data \ + $(objcpxmon-y) $< $@ + +targets += image.o +$(obj)/image.o: $(obj)/dummy.o $(images)/vmlinux.gz FORCE + $(call if_changed,genimage) # Place the ramdisk in the initrd image. -$(obj)/image-initrd.o: $(obj)/image.o $(images)/ramdisk.image.gz - $(OBJCOPY) $(obj)/image.o $@ \ - --add-section=.ramdisk=$(images)/ramdisk.image.gz \ - --set-section-flags=.ramdisk=contents,alloc,load,readonly,data +quiet_cmd_genimage-initrd = GEN $@ + cmd_genimage-initrd = $(OBJCOPY) $< $@ \ + --add-section=.ramdisk=$(images)/ramdisk.image.gz \ + --set-section-flags=.ramdisk=contents,alloc,load,readonly,data +targets += image.initrd.o +$(obj)/image.initrd.o: $(obj)/image.o $(images)/ramdisk.image.gz FORCE + $(call if_changed,genimage-initrd) # Create the note section for New-World PowerMacs. -$(obj)/note: $(MKNOTE) - $(MKNOTE) > $(obj)/note - -znetboot: $(images)/vmlinux.coff $(images)/vmlinux.elf-pmac $(images)/zImage.chrp - cp $(images)/vmlinux.coff $(TFTPIMAGE).pmac$(END) - cp $(images)/vmlinux.elf-pmac $(TFTPIMAGE).pmac$(END)elf - cp $(images)/zImage.chrp $(TFTPIMAGE).chrp$(END) - -znetboot.initrd: $(images)/vmlinux.initrd.coff \ - $(images)/vmlinux.initrd.elf-pmac \ - $(images)/zImage.initrd.chrp - cp $(images)/vmlinux.initrd.coff $(TFTPIMAGE).pmac$(END) - cp $(images)/vmlinux.initrd.elf-pmac $(TFTPIMAGE).pmac$(END).elf - cp $(images)/zImage.initrd.chrp $(TFTPIMAGE).chrp$(END) +quit_cmd_mknote = MKNOTE $@ + cmd_mknote = $(utils)/mknote > $@ +targets += note +$(obj)/note: $(utils)/mknote FORCE + $(call if_changed,mknote) + + +$(obj)/coffcrt0.o: EXTRA_AFLAGS := -traditional -DXCOFF +$(obj)/crt0.o: EXTRA_AFLAGS := -traditional +targets += coffcrt0.o crt0.o +$(obj)/coffcrt0.o $(obj)/crt0.o: $(common)/crt0.S FORCE + $(call if_changed_dep,as_o_S) + +quiet_cmd_gencoffb = COFF $@ + cmd_gencoffb = $(LD) -o $@ $(COFF_LD_ARGS) $(filter-out FORCE,$^) && \ + $(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec) +targets += coffboot +$(obj)/coffboot: $(COFFOBJS) $(obj)/image.o $(LIBS) FORCE + $(call if_changed,gencoffb) +targets += coffboot.initrd +$(obj)/coffboot.initrd: $(COFFOBJS) $(obj)/image.initrd.o $(LIBS) FORCE + $(call if_changed,gencoffb) + + +quiet_cmd_gen-coff = COFF $@ + cmd_gen-coff = $(OBJCOPY) $(OBJCOPY_ARGS) $< $@ && \ + $(HACKCOFF) $@ && \ + ln -sf $(notdir $@) $(images)/zImage$(initrd).pmac + +$(images)/vmlinux.coff: $(obj)/coffboot + $(call cmd,gen-coff) + +$(images)/vmlinux.initrd.coff: $(obj)/coffboot.initrd + $(call cmd,gen-coff) + +quiet_cmd_gen-elf-pmac = ELF $@ + cmd_gen-elf-pmac = $(LD) $(NEWWORLD_LD_ARGS) -o $@ \ + $(NEWWORLDOBJS) $(LIBS) $< && \ + $(OBJCOPY) $@ $@ --add-section=.note=$(obj)/note \ + -R .comment $(del-ramdisk-sec) + +$(images)/vmlinux.elf-pmac: $(obj)/image.o $(NEWWORLDOBJS) $(LIBS) $(obj)/note + $(call cmd,gen-elf-pmac) +$(images)/vmlinux.initrd.elf-pmac: $(obj)/image.initrd.o $(NEWWORLDOBJS) \ + $(LIBS) $(obj)/note + $(call cmd,gen-elf-pmac) + +quiet_cmd_gen-chrp = CHRP $@ + cmd_gen-chrp = $(LD) $(CHRP_LD_ARGS) -o $@ $^ && \ + $(OBJCOPY) $@ $@ -R .comment $(del-ramdisk-sec) +$(images)/zImage.chrp: $(CHRPOBJS) $(obj)/image.o $(LIBS) + $(call cmd,gen-chrp) +$(images)/zImage.initrd.chrp: $(CHRPOBJS) $(obj)/image.initrd.o $(LIBS) + $(call cmd,gen-chrp) + +quiet_cmd_addnote = ADDNOTE $@ + cmd_addnote = cat $< > $@ && $(utils)/addnote $@ +$(images)/zImage.chrp-rs6k $(images)/zImage.initrd.chrp-rs6k: \ + %-rs6k: % + $(call cmd,addnote) + +quiet_cmd_gen-miboot = GEN $@ + cmd_gen-miboot = $(OBJCOPY) $(OBJCOPY_ARGS) \ + --add-section=$1=$(word 2, $^) $< $@ $(images)/miboot.image: $(obj)/dummy.o $(images)/vmlinux.gz - $(OBJCOPY) $(OBJCOPY_ARGS) --add-section=image=$(images)/vmlinux.gz \ - $(obj)/dummy.o $@ + $(call cmd,gen-miboot,image) $(images)/miboot.initrd.image: $(images)/miboot.image $(images)/ramdisk.image.gz - $(OBJCOPY) $(OBJCOPY_ARGS) \ - --add-section=initrd=$(images)/ramdisk.image.gz \ - $(images)/miboot.image $@ - -$(obj)/coffcrt0.o: $(common)/crt0.S - $(CC) $(AFLAGS) -DXCOFF -traditional -c -o $@ $(common)/crt0.S - -$(obj)/crt0.o: $(common)/crt0.S - $(CC) $(AFLAGS) -traditional -c -o $@ $(common)/crt0.S - -$(obj)/coffboot: $(COFFOBJS) $(obj)/image.o $(LIBS) - $(LD) -o $@ $(COFF_LD_ARGS) $^ - $(OBJCOPY) $@ $@ -R .comment -R .ramdisk - -$(obj)/coffboot.initrd: $(COFFOBJS) $(obj)/image-initrd.o $(LIBS) - $(LD) -o $@ $(COFF_LD_ARGS) $^ - $(OBJCOPY) $@ $@ -R .comment - -$(images)/vmlinux.coff: $(obj)/coffboot $(HACKCOFF) - $(OBJCOPY) $(OBJCOPY_ARGS) $(obj)/coffboot $@ - $(HACKCOFF) $@ - ln -sf vmlinux.coff $(images)/zImage.pmac - -$(images)/vmlinux.initrd.coff: $(obj)/coffboot.initrd $(HACKCOFF) - $(OBJCOPY) $(OBJCOPY_ARGS) $(obj)/coffboot.initrd $@ - $(HACKCOFF) $@ - ln -sf vmlinux.initrd.coff $(images)/zImage.initrd.pmac - -$(images)/vmlinux.elf-pmac: $(NEWWORLDOBJS) $(LIBS) $(obj)/image.o $(obj)/note - $(LD) $(NEWWORLD_LD_ARGS) -o $@ $(NEWWORLDOBJS) $(LIBS) $(obj)/image.o - $(OBJCOPY) $@ $@ \ - --add-section=.note=$(obj)/note -R .comment -R .ramdisk - -$(images)/vmlinux.initrd.elf-pmac: $(NEWWORLDOBJS) $(LIBS) \ - $(obj)/image-initrd.o $(obj)/note - $(LD) $(NEWWORLD_LD_ARGS) -o $@ $(NEWWORLDOBJS) $(LIBS) \ - $(obj)/image-initrd.o - $(OBJCOPY) $@ $@ \ - --add-section=.note=$(obj)/note -R .comment + $(call cmd,gen-miboot,initrd) -$(images)/zImage.chrp: $(CHRPOBJS) $(obj)/image.o $(LIBS) - $(LD) $(CHRP_LD_ARGS) -o $@ $^ - $(OBJCOPY) $@ $@ -R .comment -R .ramdisk +# The targets used on the make command-line + +.PHONY: zImage zImage.initrd +zImage: $(images)/vmlinux.coff \ + $(images)/vmlinux.elf-pmac \ + $(images)/zImage.chrp \ + $(images)/zImage.chrp-rs6k \ + $(images)/miboot.image + @echo ' kernel: $@ is ready ($<)' +zImage.initrd: $(images)/vmlinux.initrd.coff \ + $(images)/vmlinux.initrd.elf-pmac \ + $(images)/zImage.initrd.chrp \ + $(images)/zImage.initrd.chrp-rs6k \ + $(images)/miboot.initrd.image + @echo ' kernel: $@ is ready ($<)' + +TFTPIMAGE := /tftpboot/zImage. + +.PHONY: znetboot znetboot.initrd +znetboot: $(images)/vmlinux.coff \ + $(images)/vmlinux.elf-pmac \ + $(images)/zImage.chrp + cp $(images)/vmlinux.coff $(TFTPIMAGE).pmac$(END) + cp $(images)/vmlinux.elf-pmac $(TFTPIMAGE).pmac$(END).elf + cp $(images)/zImage.chrp $(TFTPIMAGE).chrp$(END) + @echo ' kernel: $@ is ready ($<)' +znetboot.initrd:$(images)/vmlinux.initrd.coff \ + $(images)/vmlinux.initrd.elf-pmac \ + $(images)/zImage.initrd.chrp + cp $(images)/vmlinux.initrd.coff $(TFTPIMAGE).pmac$(END) + cp $(images)/vmlinux.initrd.elf-pmac $(TFTPIMAGE).pmac$(END).elf + cp $(images)/zImage.initrd.chrp $(TFTPIMAGE).chrp$(END) + @echo ' kernel: $@ is ready ($<)' -$(images)/zImage.initrd.chrp: $(CHRPOBJS) $(obj)/image-initrd.o $(LIBS) - $(LD) $(CHRP_LD_ARGS) -o $@ $^ - $(OBJCOPY) $@ $@ -R .comment - -$(images)/zImage.chrp-rs6k: $(images)/zImage.chrp $(ADDNOTE) - cp $(images)/zImage.chrp $@ - $(ADDNOTE) $@ - -$(images)/zImage.initrd.chrp-rs6k: $(images)/zImage.initrd.chrp $(ADDNOTE) - cp $(images)/zImage.initrd.chrp $@ - $(ADDNOTE) $@ - -zImage: $(images)/vmlinux.coff $(images)/vmlinux.elf-pmac \ - $(images)/zImage.chrp $(images)/zImage.chrp-rs6k \ - $(images)/miboot.image - -zImage.initrd: $(images)/vmlinux.initrd.coff $(images)/vmlinux.initrd.elf-pmac\ - $(images)/zImage.initrd.chrp $(images)/zImage.initrd.chrp-rs6k\ - $(images)/miboot.initrd.image diff -Nru a/arch/ppc/boot/openfirmware/dummy.c b/arch/ppc/boot/openfirmware/dummy.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc/boot/openfirmware/dummy.c Sat May 24 12:48:34 2003 @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff -Nru a/arch/ppc/boot/prep/Makefile b/arch/ppc/boot/prep/Makefile --- a/arch/ppc/boot/prep/Makefile Sat May 24 12:48:31 2003 +++ b/arch/ppc/boot/prep/Makefile Sat May 24 12:48:31 2003 @@ -13,74 +13,96 @@ # modified by Cort (cort@cs.nmt.edu) # -boot: zImage - -TFTPIMAGE = /tftpboot/zImage.prep +TFTPIMAGE := /tftpboot/zImage.prep ifeq ($(CONFIG_SMP),y) -TFTPIMAGE = $(TFTPBOOT).smp +TFTPIMAGE := $(TFTPBOOT).smp endif -LD_ARGS = -T $(boot)/ld.script -Ttext 0x00800000 -Bstatic -OBJCOPY_ARGS = -O elf32-powerpc -LIBS = $(common)/lib.a $(bootlib)/lib.a - boot-y := head.o misc.o boot-$(CONFIG_VGA_CONSOLE) += vreset.o kbd.o -boot := arch/ppc/boot -common := $(boot)/common -utils := $(boot)/utils -bootlib := $(boot)/lib -of1275 := $(boot)/of1275 -images := $(boot)/images -simple := $(boot)/simple +boot := arch/ppc/boot +common := $(boot)/common +utils := $(boot)/utils +bootlib := $(boot)/lib +images := $(boot)/images +simple := $(boot)/simple -EXTRA_TARGETS := $(boot-y) ../simple/legacy.o -OBJS := $(addprefix $(obj)/,$(boot-y)) $(simple)/legacy.o +OBJCOPYFLAGS := -O elf32-powerpc +LIBS := $(common)/lib.a $(bootlib)/lib.a -# Tools -MKPREP := $(utils)/mkprep +targets := $(boot-y) dummy.o ../simple/legacy.o +OBJS := $(addprefix $(obj)/,$(boot-y)) $(simple)/legacy.o # Extra include search dirs CFLAGS_kbd.o += -Idrivers/char +zImage: initrd := zImage: $(images)/zImage.prep -zImage.initrd: $(images)/zImage.initrd.prep - -$(obj)/dummy.o: $(common)/dummy.c - $(CC) -c -o $@ $(common)/dummy.c + @echo ' kernel: $@ is ready ($<)' -$(images)/zImage.prep: $(OBJS) $(LIBS) $(boot)/ld.script $(images)/vmlinux.gz \ - $(obj)/dummy.o $(MKPREP) - $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ - --add-section=.image=$(images)/vmlinux.gz \ - --set-section-flags=.image=contents,alloc,load,readonly,data \ - $(obj)/dummy.o $(obj)/image.o - $(LD) $(LD_ARGS) -o $(obj)/zImage $(OBJS) $(obj)/image.o $(LIBS) - $(OBJCOPY) $(OBJCOPY_ARGS) $(obj)/zImage $(obj)/zImage \ - -R .comment -R .stab -R .stabstr - $(MKPREP) -pbp $(obj)/zImage $@ - rm -f $(obj)/zImage - -$(images)/zImage.initrd.prep: $(OBJS) $(LIBS) $(boot)/ld.script \ - $(images)/vmlinux.gz $(obj)/dummy.o $(MKPREP) - $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ - --add-section=.ramdisk=$(images)/ramdisk.image.gz \ - --set-section-flags=.ramdisk=contents,alloc,load,readonly,data \ - --add-section=.image=$(images)/vmlinux.gz \ - --set-section-flags=.image=contents,alloc,load,readonly,data \ - $(obj)/dummy.o $(obj)/image.o - $(LD) $(LD_ARGS) -o $(obj)/zImage.initrd $(OBJS) $(obj)/image.o $(LIBS) - $(OBJCOPY) $(OBJCOPY_ARGS) $(obj)/zImage.initrd $(obj)/zImage.initrd \ - -R .comment -R .stab -R .stabstr - $(MKPREP) -pbp $(obj)/zImage.initrd $@ - rm -f $(obj)/zImage.initrd +zImage.initrd: initrd := .initrd +zImage.initrd: $(images)/zImage.initrd.prep + @echo ' kernel: $@ is ready ($<)' +$(images)/ramdisk.image.gz: + @echo ' MISSING $@' + @echo ' RAM disk image must be provided separatly' + @/bin/false + +OBJCOPYFLAGS_image.o := \ + --add-section=.image=$(images)/vmlinux.gz \ + --set-section-flags=.image=contents,alloc,load,readonly,data +targets += image.o +$(obj)/image.o: $(obj)/dummy.o $(images)/vmlinux.gz + $(call if_changed,objcopy) + +OBJCOPYFLAGS_image.initrd.o := \ + --add-section=.ramdisk=$(images)/ramdisk.image.gz \ + --set-section-flags=.ramdisk=contents,alloc,load,readonly,data \ + --add-section=.image=$(images)/vmlinux.gz \ + --set-section-flags=.image=contents,alloc,load,readonly,data +targets += image.initrd.o +$(obj)/image.initrd.o: $(obj)/dummy.o $(images)/vmlinux.gz $(images)/ramdisk.image.gz + $(call if_changed,objcopy) + +LDFLAGS_zImage.bin := -Ttext 0x00800000 -Bstatic -T +LDFLAGS_zImage.initrd.bin := -Ttext 0x00800000 -Bstatic -T +targets += zImage.bin +$(obj)/zImage.bin: $(boot)/ld.script $(OBJS) $(obj)/image.o $(LIBS) + $(call if_changed,ld) +targets += zImage.initrd.bin +$(obj)/zImage.initrd.bin: $(boot)/ld.script $(OBJS) $(obj)/image.initrd.o $(LIBS) + $(call if_changed,ld) + +OBJCOPYFLAGS_zImage := -R .comment -R .stab -R .stabstr +OBJCOPYFLAGS_zImage.initrd := -R .comment -R .stab -R .stabstr +targets += zImage +$(obj)/zImage: %: %.bin FORCE + $(call if_changed,objcopy) +targets += zImage.initrd +$(obj)/zImage.initrd: %: %.bin FORCE + $(call if_changed,objcopy) + +quiet_cmd_mkprep = MKPREP $@ + cmd_mkprep = $(utils)/mkprep -pbp $< $@ + +$(images)/zImage.prep: $(obj)/zImage $(utils)/mkprep + $(call cmd,mkprep) +$(images)/zImage.initrd.prep: $(obj)/zImage.initrd $(utils)/mkprep + $(call cmd,mkprep) + +# +# Convinient shorthands for various targets +# floppy: zImage dd if=$(images)/zImage.prep of=/dev/fd0H1440 bs=64b znetboot : zImage cp $(images)/zImage.prep $(TFTPIMAGE) + @echo ' kernel: $@ is ready ($<)' znetboot.initrd : zImage.initrd cp $(images)/zImage.initrd.prep $(TFTPIMAGE) + @echo ' kernel: $@ is ready ($<)' + diff -Nru a/arch/ppc/boot/prep/dummy.c b/arch/ppc/boot/prep/dummy.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc/boot/prep/dummy.c Sat May 24 12:48:34 2003 @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff -Nru a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile --- a/arch/ppc/boot/simple/Makefile Sat May 24 12:48:19 2003 +++ b/arch/ppc/boot/simple/Makefile Sat May 24 12:48:19 2003 @@ -160,8 +160,7 @@ MKPREP := $(utils)/mkprep MKTREE := $(utils)/mktree -$(obj)/dummy.o: $(common)/dummy.c - $(CC) -c -o $@ $(common)/dummy.c +targets := dummy.o $(obj)/zvmlinux: $(OBJS) $(LIBS) $(boot)/ld.script $(images)/vmlinux.gz \ $(obj)/dummy.o diff -Nru a/arch/ppc/boot/simple/dummy.c b/arch/ppc/boot/simple/dummy.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc/boot/simple/dummy.c Sat May 24 12:48:34 2003 @@ -0,0 +1,4 @@ +int main(void) +{ + return 0; +} diff -Nru a/arch/ppc/boot/utils/Makefile b/arch/ppc/boot/utils/Makefile --- a/arch/ppc/boot/utils/Makefile Sat May 24 12:48:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,20 +0,0 @@ -# -# arch/ppc/boot/utils/Makefile -# -# 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. - -HOSTCFLAGS += -I$(TOPDIR)/arch/$(ARCH)/boot/include - -all: FORCE - -# Simple programs with 1 file and no extra CFLAGS -UTILS = addnote hack-coff mkprep mknote mkbugboot mktree \ - addSystemMap addRamdDisk - -$(UTILS): - $(HOSTCC) $(HOSTCFLAGS) -o $@ $@.c - -clean: - rm -f $(UTILS) diff -Nru a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile --- a/arch/ppc/kernel/Makefile Sat May 24 12:48:31 2003 +++ b/arch/ppc/kernel/Makefile Sat May 24 12:48:31 2003 @@ -10,12 +10,10 @@ endif # Start off with 'head.o', change as needed. -HEAD-y := head.o -HEAD-$(CONFIG_40x) := head_4xx.o -HEAD-$(CONFIG_8xx) := head_8xx.o -HEAD-$(CONFIG_6xx) += idle_6xx.o - -extra-y := $(HEAD-y) +extra-y := head.o +extra-$(CONFIG_40x) := head_4xx.o +extra-$(CONFIG_8xx) := head_8xx.o +extra-$(CONFIG_6xx) += idle_6xx.o obj-y := entry.o traps.o irq.o idle.o time.o misc.o \ process.o signal.o ptrace.o align.o \ diff -Nru a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S --- a/arch/ppc/kernel/entry.S Sat May 24 12:48:31 2003 +++ b/arch/ppc/kernel/entry.S Sat May 24 12:48:31 2003 @@ -531,12 +531,27 @@ resume_kernel: /* check current_thread_info->preempt_count */ rlwinm r9,r1,0,0,18 - lwz r3,TI_PREEMPT(r9) - cmpwi 0,r3,0 /* if non-zero, just restore regs and return */ + lwz r0,TI_PREEMPT(r9) + cmpwi 0,r0,0 /* if non-zero, just restore regs and return */ bne restore - lwz r9,TI_FLAGS(r9) - andi. r0,r9,_TIF_NEED_RESCHED - bne do_resched + lwz r0,TI_FLAGS(r9) + andi. r0,r0,_TIF_NEED_RESCHED + beq+ restore + andi. r0,r3,MSR_EE /* interrupts off? */ + beq restore /* don't schedule if so */ +1: lis r0,PREEMPT_ACTIVE@h + stw r0,TI_PREEMPT(r9) + ori r10,r10,MSR_EE + SYNC + MTMSRD(r10) /* hard-enable interrupts */ + bl schedule + LOAD_MSR_KERNEL(r10,MSR_KERNEL) + SYNC + MTMSRD(r10) /* disable interrupts */ + rlwinm r9,r1,0,0,18 + lwz r0,TI_FLAGS(r9) + andi. r0,r0,_TIF_NEED_RESCHED + bne- 1b #else resume_kernel: #endif /* CONFIG_PREEMPT */ @@ -740,13 +755,6 @@ lwz r9,TI_FLAGS(r9) andi. r0,r9,_TIF_NEED_RESCHED bne- do_resched - -#ifdef CONFIG_PREEMPT - lwz r0,_MSR(r1) - andi. r0,r0,MSR_PR - beq restore -#endif - andi. r0,r9,_TIF_SIGPENDING beq restore_user do_user_signal: /* r10 contains MSR_KERNEL here */ diff -Nru a/arch/ppc/kernel/l2cr.S b/arch/ppc/kernel/l2cr.S --- a/arch/ppc/kernel/l2cr.S Sat May 24 12:48:25 2003 +++ b/arch/ppc/kernel/l2cr.S Sat May 24 12:48:25 2003 @@ -272,10 +272,6 @@ blr END_FTR_SECTION_IFCLR(CPU_FTR_L3CR) - /* Stop DST streams */ - DSSALL - sync - /* Turn off interrupts and data relocation. */ mfmsr r7 /* Save MSR in r7 */ rlwinm r4,r7,0,17,15 @@ -284,6 +280,10 @@ mtmsr r4 isync + /* Stop DST streams */ + DSSALL + sync + /* Get the current enable bit of the L3CR into r4 */ mfspr r4,SPRN_L3CR diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S --- a/arch/ppc/kernel/misc.S Sat May 24 12:48:31 2003 +++ b/arch/ppc/kernel/misc.S Sat May 24 12:48:31 2003 @@ -534,7 +534,7 @@ isync lis r5, IDC_INVALL@h mtspr IC_CST, r5 -#elif defined(CONFIG_40x) +#elif defined(CONFIG_4xx) #ifdef CONFIG_403GCX li r3, 512 mtctr r3 @@ -1365,13 +1365,13 @@ .long sys_epoll_create .long sys_epoll_ctl .long sys_epoll_wait - .long sys_remap_file_pages - .long sys_timer_create /* 240 */ - .long sys_timer_settime - .long sys_timer_gettime - .long sys_timer_getoverrun - .long sys_timer_delete - .long sys_clock_settime /* 245 */ - .long sys_clock_gettime - .long sys_clock_getres - .long sys_clock_nanosleep + .long sys_remap_file_pages + .long sys_timer_create /* 240 */ + .long sys_timer_settime + .long sys_timer_gettime + .long sys_timer_getoverrun + .long sys_timer_delete + .long sys_clock_settime /* 245 */ + .long sys_clock_gettime + .long sys_clock_getres + .long sys_clock_nanosleep diff -Nru a/arch/ppc/kernel/module.c b/arch/ppc/kernel/module.c --- a/arch/ppc/kernel/module.c Sat May 24 12:48:22 2003 +++ b/arch/ppc/kernel/module.c Sat May 24 12:48:22 2003 @@ -269,3 +269,7 @@ { return 0; } + +void module_arch_cleanup(struct module *mod) +{ +} diff -Nru a/arch/ppc/kernel/pci-dma.c b/arch/ppc/kernel/pci-dma.c --- a/arch/ppc/kernel/pci-dma.c Sat May 24 12:48:21 2003 +++ b/arch/ppc/kernel/pci-dma.c Sat May 24 12:48:21 2003 @@ -22,6 +22,7 @@ if (hwdev == NULL || hwdev->dma_mask != 0xffffffff) gfp |= GFP_DMA; + #ifdef CONFIG_NOT_COHERENT_CACHE ret = consistent_alloc(gfp, size, dma_handle); #else @@ -30,7 +31,9 @@ if (ret != NULL) { memset(ret, 0, size); +#ifndef CONFIG_NOT_COHERENT_CACHE *dma_handle = virt_to_bus(ret); +#endif } return ret; } diff -Nru a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c --- a/arch/ppc/kernel/ppc_ksyms.c Sat May 24 12:48:31 2003 +++ b/arch/ppc/kernel/ppc_ksyms.c Sat May 24 12:48:31 2003 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -156,6 +157,7 @@ EXPORT_SYMBOL(ioremap); EXPORT_SYMBOL(__ioremap); EXPORT_SYMBOL(iounmap); +EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */ #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) EXPORT_SYMBOL(ppc_ide_md); @@ -197,6 +199,7 @@ EXPORT_SYMBOL(flush_dcache_range); EXPORT_SYMBOL(flush_icache_user_range); EXPORT_SYMBOL(flush_dcache_page); +EXPORT_SYMBOL(flush_tlb_kernel_range); #ifdef CONFIG_ALTIVEC EXPORT_SYMBOL(last_task_used_altivec); EXPORT_SYMBOL(giveup_altivec); diff -Nru a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c --- a/arch/ppc/kernel/process.c Sat May 24 12:48:24 2003 +++ b/arch/ppc/kernel/process.c Sat May 24 12:48:24 2003 @@ -445,33 +445,26 @@ void *child_threadptr, int *child_tidp, int p6, struct pt_regs *regs) { - struct task_struct *p; - CHECK_FULL_REGS(regs); if (usp == 0) usp = regs->gpr[1]; /* stack pointer for child */ - p = do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0, - parent_tidp, child_tidp); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0, + parent_tidp, child_tidp); } int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs) { - struct task_struct *p; CHECK_FULL_REGS(regs); - p = do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); } int sys_vfork(int p1, int p2, int p3, int p4, int p5, int p6, struct pt_regs *regs) { - struct task_struct *p; CHECK_FULL_REGS(regs); - p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, - 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], + regs, 0, NULL, NULL); } int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, @@ -524,7 +517,7 @@ while (count < 16 && sp > prev_sp && sp < stack_top && (sp & 3) == 0) { if (count == 0) { printk("Call trace:"); -#if CONFIG_KALLSYMS +#ifdef CONFIG_KALLSYMS printk("\n"); #endif } else { @@ -534,7 +527,7 @@ } else ret = *(unsigned long *)(sp + 4); printk(" [%08lx] ", ret); -#if CONFIG_KALLSYMS +#ifdef CONFIG_KALLSYMS print_symbol("%s", ret); printk("\n"); #endif diff -Nru a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c --- a/arch/ppc/kernel/smp.c Sat May 24 12:48:32 2003 +++ b/arch/ppc/kernel/smp.c Sat May 24 12:48:32 2003 @@ -403,9 +403,10 @@ /* create a process for the processor */ /* only regs.msr is actually used, and 0 is OK for it */ memset(®s, 0, sizeof(struct pt_regs)); - p = do_fork(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); + p = copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); if (IS_ERR(p)) panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); + wake_up_forked_process(p); init_idle(p, cpu); unhash_process(p); diff -Nru a/arch/ppc/mm/cachemap.c b/arch/ppc/mm/cachemap.c --- a/arch/ppc/mm/cachemap.c Sat May 24 12:48:33 2003 +++ b/arch/ppc/mm/cachemap.c Sat May 24 12:48:33 2003 @@ -2,7 +2,7 @@ * PowerPC version derived from arch/arm/mm/consistent.c * Copyright (C) 2001 Dan Malek (dmalek@jlc.net) * - * arch/arm/mm/consistent.c + * arch/ppc/mm/cachemap.c * * Copyright (C) 2000 Russell King * @@ -59,57 +59,69 @@ */ void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle) { - int order, err, i; - unsigned long page, va, pa, flags; - struct vm_struct *area; - void *ret; + int order, err; + struct page *page, *free, *end; + unsigned long pa, flags, offset; + struct vm_struct *area = NULL; + unsigned long va = 0; - if (in_interrupt()) - BUG(); + BUG_ON(in_interrupt()); - /* Only allocate page size areas. - */ + /* Only allocate page size areas */ size = PAGE_ALIGN(size); order = get_order(size); - page = __get_free_pages(gfp, order); - if (!page) { - BUG(); + free = page = alloc_pages(gfp, order); + if (! page) return NULL; - } + + pa = page_to_phys(page); + *dma_handle = page_to_bus(page); + end = page + (1 << order); /* * we need to ensure that there are no cachelines in use, * or worse dirty in this area. */ - invalidate_dcache_range(page, page + size); + invalidate_dcache_range((unsigned long)page_address(page), + (unsigned long)page_address(page) + size); - /* Allocate some common virtual space to map the new pages. - */ + /* + * alloc_pages() expects the block to be handled as a unit, so + * it only sets the page count on the first page. We set the + * counts on each page so they can be freed individually + */ + for (; page < end; page++) + set_page_count(page, 1); + + + /* Allocate some common virtual space to map the new pages*/ area = get_vm_area(size, VM_ALLOC); - if (area == 0) { - free_pages(page, order); - return NULL; - } - va = VMALLOC_VMADDR(area->addr); - ret = (void *)va; + if (! area) + goto out; - /* This gives us the real physical address of the first page. - */ - *dma_handle = pa = virt_to_bus((void *)page); + va = VMALLOC_VMADDR(area->addr); flags = _PAGE_KERNEL | _PAGE_NO_CACHE; - - err = 0; - for (i = 0; i < size && err == 0; i += PAGE_SIZE) - err = map_page(va+i, pa+i, flags); - if (err) { - vfree((void *)va); - return NULL; + for (offset = 0; offset < size; offset += PAGE_SIZE) { + err = map_page(va+offset, pa+offset, flags); + if (err) { + vfree((void *)va); + va = 0; + goto out; + } + + free++; + } + + out: + /* Free pages which weren't mapped */ + for (; free < end; free++) { + __free_page(free); } - return ret; + return (void *)va; } /* @@ -117,8 +129,7 @@ */ void consistent_free(void *vaddr) { - if (in_interrupt()) - BUG(); + BUG_ON(in_interrupt()); vfree(vaddr); } @@ -155,6 +166,6 @@ { unsigned long start; - start = page_address(page) + offset; + start = (unsigned long)page_address(page) + offset; consistent_sync((void *)start, size, direction); } diff -Nru a/arch/ppc/ocp/Makefile b/arch/ppc/ocp/Makefile --- a/arch/ppc/ocp/Makefile Sat May 24 12:48:22 2003 +++ b/arch/ppc/ocp/Makefile Sat May 24 12:48:22 2003 @@ -1,13 +1,6 @@ # # Makefile for the linux kernel. # -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -# Note 2! The CFLAGS definitions are now in the main makefile... -# -# NB: cribbed from the drivers/sbus/Makefile -- PMM -obj-y += ocp.o ocp-driver.o ocp-probe.o +obj-y := ocp.o ocp-driver.o ocp-probe.o diff -Nru a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c --- a/arch/ppc/syslib/open_pic.c Sat May 24 12:48:26 2003 +++ b/arch/ppc/syslib/open_pic.c Sat May 24 12:48:26 2003 @@ -55,7 +55,7 @@ #ifdef CONFIG_SMP /* Interprocessor Interrupts */ static void openpic_initipi(u_int ipi, u_int pri, u_int vector); -static void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs); +static irqreturn_t openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *); #endif /* Timer Interrupts */ diff -Nru a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c --- a/arch/ppc64/kernel/LparData.c Sat May 24 12:48:22 2003 +++ b/arch/ppc64/kernel/LparData.c Sat May 24 12:48:22 2003 @@ -61,7 +61,7 @@ 0xc8a5d9c4, /* desc = "HvRD" ebcdic */ sizeof(struct HvReleaseData), offsetof(struct naca_struct, xItVpdAreas), - (struct naca_struct *)(KERNELBASE+0x4000), /* 64-bit Naca address */ + (struct naca_struct *)(NACA_VIRT_ADDR), /* 64-bit Naca address */ 0x6000, /* offset of LparMap within loadarea (see head.S) */ 0, 1, /* tags inactive */ diff -Nru a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile Sat May 24 12:48:32 2003 +++ b/arch/ppc64/kernel/Makefile Sat May 24 12:48:32 2003 @@ -15,7 +15,7 @@ iSeries_IoMmTable.o iSeries_irq.o \ iSeries_VpdInfo.o XmPciLpEvent.o \ HvCall.o HvLpConfig.o LparData.o mf_proc.o \ - proc_pmc.o iSeries_setup.o ItLpQueue.o hvCall.o \ + iSeries_setup.o ItLpQueue.o hvCall.o \ mf.o HvLpEvent.o iSeries_proc.o obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \ @@ -25,6 +25,7 @@ obj-y += open_pic.o xics.o pSeries_htab.o rtas.o \ chrp_setup.o i8259.o ras.o prom.o +obj-$(CONFIG_PROC_FS) += proc_ppc64.o obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o diff -Nru a/arch/ppc64/kernel/align.c b/arch/ppc64/kernel/align.c --- a/arch/ppc64/kernel/align.c Sat May 24 12:48:33 2003 +++ b/arch/ppc64/kernel/align.c Sat May 24 12:48:33 2003 @@ -237,7 +237,7 @@ dsisr = regs->dsisr; /* Power4 doesn't set DSISR for an alignment interrupt */ - if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) { + if (!cpu_alignexc_sets_dsisr()) { unsigned int real_instr; if (__get_user(real_instr, (unsigned int *)regs->nip)) return 0; @@ -309,6 +309,7 @@ /* Doing stfs, have to convert to single */ enable_kernel_fp(); cvt_df(¤t->thread.fpr[reg], (float *)&data.v[4], ¤t->thread.fpscr); + disable_kernel_fp(); } else data.dd = current->thread.fpr[reg]; @@ -342,6 +343,7 @@ /* Doing lfs, have to convert to double */ enable_kernel_fp(); cvt_fd((float *)&data.v[4], ¤t->thread.fpr[reg], ¤t->thread.fpscr); + disable_kernel_fp(); } else current->thread.fpr[reg] = data.dd; diff -Nru a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c --- a/arch/ppc64/kernel/asm-offsets.c Sat May 24 12:48:28 2003 +++ b/arch/ppc64/kernel/asm-offsets.c Sat May 24 12:48:28 2003 @@ -59,14 +59,14 @@ /* naca */ DEFINE(PACA, offsetof(struct naca_struct, paca)); - DEFINE(DCACHEL1LINESIZE, offsetof(struct naca_struct, dCacheL1LineSize)); + DEFINE(DCACHEL1LINESIZE, offsetof(struct systemcfg, dCacheL1LineSize)); DEFINE(DCACHEL1LOGLINESIZE, offsetof(struct naca_struct, dCacheL1LogLineSize)); DEFINE(DCACHEL1LINESPERPAGE, offsetof(struct naca_struct, dCacheL1LinesPerPage)); - DEFINE(ICACHEL1LINESIZE, offsetof(struct naca_struct, iCacheL1LineSize)); + DEFINE(ICACHEL1LINESIZE, offsetof(struct systemcfg, iCacheL1LineSize)); DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct naca_struct, iCacheL1LogLineSize)); DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct naca_struct, iCacheL1LinesPerPage)); DEFINE(SLBSIZE, offsetof(struct naca_struct, slb_size)); - DEFINE(PLATFORM, offsetof(struct naca_struct, platform)); + DEFINE(PLATFORM, offsetof(struct systemcfg, platform)); /* paca */ DEFINE(PACA_SIZE, sizeof(struct paca_struct)); diff -Nru a/arch/ppc64/kernel/chrp_setup.c b/arch/ppc64/kernel/chrp_setup.c --- a/arch/ppc64/kernel/chrp_setup.c Sat May 24 12:48:20 2003 +++ b/arch/ppc64/kernel/chrp_setup.c Sat May 24 12:48:20 2003 @@ -263,6 +263,8 @@ char *os; static int display_character, set_indicator; static int max_width; + static spinlock_t progress_lock = SPIN_LOCK_UNLOCKED; + static int pending_newline = 0; /* did last write end with unprinted newline? */ if (!rtas.base) return; @@ -278,34 +280,79 @@ display_character = rtas_token("display-character"); set_indicator = rtas_token("set-indicator"); } - if (display_character == RTAS_UNKNOWN_SERVICE) { - /* use hex display */ - if (set_indicator == RTAS_UNKNOWN_SERVICE) - return; - rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex); + + if(display_character == RTAS_UNKNOWN_SERVICE) { + /* use hex display if available */ + if(set_indicator != RTAS_UNKNOWN_SERVICE) + rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex); return; } - rtas_call(display_character, 1, 1, NULL, '\r'); + spin_lock(&progress_lock); + /* Last write ended with newline, but we didn't print it since + * it would just clear the bottom line of output. Print it now + * instead. + * + * If no newline is pending, print a CR to start output at the + * beginning of the line. + */ + if(pending_newline) { + rtas_call(display_character, 1, 1, NULL, '\r'); + rtas_call(display_character, 1, 1, NULL, '\n'); + pending_newline = 0; + } else + rtas_call(display_character, 1, 1, NULL, '\r'); + width = max_width; os = s; - while ( *os ) - { - if ( (*os == '\n') || (*os == '\r') ) + while (*os) { + if(*os == '\n' || *os == '\r') { + /* Blank to end of line. */ + while(width-- > 0) + rtas_call(display_character, 1, 1, NULL, ' '); + + /* If newline is the last character, save it + * until next call to avoid bumping up the + * display output. + */ + if(*os == '\n' && !os[1]) { + pending_newline = 1; + spin_unlock(&progress_lock); + return; + } + + /* RTAS wants CR-LF, not just LF */ + + if(*os == '\n') { + rtas_call(display_character, 1, 1, NULL, '\r'); + rtas_call(display_character, 1, 1, NULL, '\n'); + } else { + /* CR might be used to re-draw a line, so we'll + * leave it alone and not add LF. + */ + rtas_call(display_character, 1, 1, NULL, *os); + } + width = max_width; - else + } else { width--; - rtas_call(display_character, 1, 1, NULL, *os++ ); + rtas_call(display_character, 1, 1, NULL, *os); + } + + os++; + /* if we overwrite the screen length */ - if ( width == 0 ) + if ( width <= 0 ) while ( (*os != 0) && (*os != '\n') && (*os != '\r') ) os++; } - + /* Blank to end of line. */ while ( width-- > 0 ) rtas_call(display_character, 1, 1, NULL, ' ' ); + + spin_unlock(&progress_lock); } extern void setup_default_decr(void); diff -Nru a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S --- a/arch/ppc64/kernel/entry.S Sat May 24 12:48:19 2003 +++ b/arch/ppc64/kernel/entry.S Sat May 24 12:48:19 2003 @@ -225,10 +225,6 @@ bl .sys32_rt_sigreturn b 80f -_GLOBAL(ppc64_sigreturn) - bl .sys_sigreturn - b 80f - _GLOBAL(ppc64_rt_sigreturn) bl .sys_rt_sigreturn @@ -412,11 +408,6 @@ ld r4,GPR4(r1) ld r1,GPR1(r1) - /* - * What if we took an exception and stole this segment, we may - * fault on the above addresses and globber SRR0/1. Should check RI - * bit and repeat - Anton - */ rfid /* Note: this must change if we start using the TIF_NOTIFY_RESUME bit */ diff -Nru a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S --- a/arch/ppc64/kernel/head.S Sat May 24 12:48:25 2003 +++ b/arch/ppc64/kernel/head.S Sat May 24 12:48:25 2003 @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include #include @@ -49,8 +51,9 @@ * 0x0100 - 0x2fff : pSeries Interrupt prologs * 0x3000 - 0x3fff : Interrupt support * 0x4000 - 0x4fff : NACA - * 0x5000 - 0x5fff : Initial segment table + * 0x5000 - 0x5fff : SystemCfg * 0x6000 : iSeries and common interrupt prologs + * 0x9000 - 0x9fff : Initial segment table */ /* @@ -123,6 +126,10 @@ * All of it must fit below the first exception vector at 0x100. */ _GLOBAL(__secondary_hold) + mfmsr r24 + ori r24,r24,MSR_RI + mtmsrd r24 /* RI on */ + /* Grab our linux cpu number */ mr r24,r3 @@ -362,11 +369,11 @@ STD_EXCEPTION_PSERIES( 0x1300, InstructionBreakpoint ) /* Space for the naca. Architected to be located at real address - * 0x4000. Various tools rely on this location being fixed. + * NACA_PHYS_ADDR. Various tools rely on this location being fixed. * The first dword of the naca is required by iSeries LPAR to * point to itVpdAreas. On pSeries native, this value is not used. */ - . = 0x4000 + . = NACA_PHYS_ADDR .globl __end_interrupts .globl __start_naca __end_interrupts: @@ -380,21 +387,14 @@ .llong 0x0 .llong paca - /* - * Space for the initial segment table - * For LPAR, the hypervisor must fill in at least one entry - * before we get control (with relocate on) - */ - . = 0x5000 + . = SYSTEMCFG_PHYS_ADDR .globl __end_naca - .globl __start_stab + .globl __start_systemcfg __end_naca: -__start_stab: - - - . = 0x6000 - .globl __end_stab -__end_stab: +__start_systemcfg: + . = (SYSTEMCFG_PHYS_ADDR + PAGE_SIZE) + .globl __end_systemcfg +__end_systemcfg: #ifdef CONFIG_PPC_ISERIES /* @@ -408,7 +408,7 @@ .llong 1 /* # ESIDs to be mapped by hypervisor */ .llong 1 /* # memory ranges to be mapped by hypervisor */ - .llong 5 /* Page # of segment table within load area */ + .llong STAB0_PAGE /* Page # of segment table within load area */ .llong 0 /* Reserved */ .llong 0 /* Reserved */ .llong 0 /* Reserved */ @@ -529,6 +529,20 @@ MachineCheck_FWNMI: EXCEPTION_PROLOG_PSERIES(0x200, MachineCheck_common) + /* + * Space for the initial segment table + * For LPAR, the hypervisor must fill in at least one entry + * before we get control (with relocate on) + */ + . = STAB0_PHYS_ADDR + .globl __start_stab +__start_stab: + + . = (STAB0_PHYS_ADDR + PAGE_SIZE) + .globl __end_stab +__end_stab: + + /*** Common interrupt handlers ***/ STD_EXCEPTION_COMMON( 0x100, SystemReset, .SystemResetException ) @@ -782,11 +796,16 @@ FPUnavailable_common: EXCEPTION_PROLOG_COMMON bne .load_up_fpu /* if from user, just load it up */ - li r20,0 + addi r3,r1,STACK_FRAME_OVERHEAD +#ifdef DO_SOFT_DISABLE + ld r20,SOFTE(r1) +#else + rldicl r20,r23,49,63 /* copy EE bit from saved MSR */ +#endif li r6,0x800 - bl .save_remaining_regs /* if from kernel, take a trap */ - bl .KernelFP - b .ret_from_except + bl .save_remaining_regs + bl .KernelFPUnavailableException + BUG_OPCODE .globl SystemCall_common SystemCall_common: @@ -1032,7 +1051,7 @@ slbmfee r23,r22 rldicl r23,r23,37,63 cmpwi r23,0 - beq 3f /* Found an invalid entry */ + beq 4f /* Found an invalid entry */ addi r22,r22,1 cmpldi r22,64 @@ -1041,18 +1060,37 @@ /* No free entry - just take the next entry, round-robin */ /* XXX we should get the number of SLB entries from the naca */ SLB_NUM_ENTRIES = 64 - mfspr r21,SPRG3 +2: mfspr r21,SPRG3 ld r22,PACASTABRR(r21) addi r23,r22,1 cmpdi r23,SLB_NUM_ENTRIES - blt 2f + blt 3f li r23,1 -2: std r23,PACASTABRR(r21) +3: std r23,PACASTABRR(r21) /* r20 = vsid, r22 = entry */ -3: + + /* + * Never cast out the segment for our kernel stack. Since we + * dont invalidate the ERAT we could have a valid translation + * for the kernel stack during the first part of exception exit + * which gets invalidated due to a tlbie from another cpu at a + * non recoverable point (after setting srr0/1) - Anton + */ + slbmfee r23,r22 + srdi r23,r23,28 + /* + * This is incorrect (r1 is not the kernel stack) if we entered + * from userspace but there is no critical window from userspace + * so this should be OK. Also if we cast out the userspace stack + * segment while in userspace we will fault it straight back in. + */ + srdi r21,r1,28 + cmpd r21,r23 + beq- 2b + /* Put together the vsid portion of the entry. */ - li r21,0 +4: li r21,0 rldimi r21,r20,12,0 ori r20,r21,1024 ori r20,r20,128 /* set class bit for kernel region */ @@ -1060,17 +1098,6 @@ ori r20,r20,256 /* map kernel region with large ptes */ #endif - /* - * XXX we should handle this in the exception exit path in 2.5, - * we need to make this path quick - Anton - */ - /* Invalidate the old entry */ - slbmfee r21,r22 - lis r23,-2049 - ori r23,r23,65535 - and r21,r21,r23 - slbie r21 - /* Put together the esid portion of the entry. */ mfspr r21,DAR /* Get the new esid */ rldicl r21,r21,36,28 /* Permits a full 36b of ESID */ @@ -1252,9 +1279,12 @@ addi r2,r2,0x4000 addi r2,r2,0x4000 + LOADADDR(r9,systemcfg) + SET_REG_TO_CONST(r4, SYSTEMCFG_VIRT_ADDR) + std r4,0(r9) /* set the systemcfg pointer */ + LOADADDR(r9,naca) - SET_REG_TO_CONST(r4, KERNELBASE) - addi r4,r4,0x4000 + SET_REG_TO_CONST(r4, NACA_VIRT_ADDR) std r4,0(r9) /* set the naca pointer */ /* Get the pointer to the segment table */ @@ -1285,13 +1315,18 @@ /* Relocate the TOC from a virt addr to a real addr */ sub r2,r2,r3 + /* setup the systemcfg pointer which is needed by prom_init */ + LOADADDR(r9,systemcfg) + sub r9,r9,r3 /* addr of the variable systemcfg */ + SET_REG_TO_CONST(r4, SYSTEMCFG_VIRT_ADDR) + sub r4,r4,r3 + std r4,0(r9) /* set the value of systemcfg */ + /* setup the naca pointer which is needed by prom_init */ LOADADDR(r9,naca) sub r9,r9,r3 /* addr of the variable naca */ - - SET_REG_TO_CONST(r4, KERNELBASE) + SET_REG_TO_CONST(r4, NACA_VIRT_ADDR) sub r4,r4,r3 - addi r4,r4,0x4000 std r4,0(r9) /* set the value of naca */ /* DRENG / PPPBBB Fix the following comment!!! -Peter */ @@ -1410,11 +1445,13 @@ copy_to_here: /* + * load_up_fpu(unused, unused, tsk) * Disable FP for the task which had the FPU previously, * and save its floating-point registers in its thread_struct. * Enables the FPU for use in the kernel on return. * On SMP we know the fpu is free, since we give it up every - * switch. -- Cort + * switch (ie, no lazy save of the FP registers). + * On entry: r13 == 'current' && last_task_used_math != 'current' */ _STATIC(load_up_fpu) mfmsr r5 /* grab the current MSR */ @@ -1432,27 +1469,30 @@ ld r4,last_task_used_math@l(r3) cmpi 0,r4,0 beq 1f - addi r4,r4,THREAD /* want THREAD of last_task_used_math */ + /* Save FP state to last_task_used_math's THREAD struct */ + addi r4,r4,THREAD SAVE_32FPRS(0, r4) mffs fr0 stfd fr0,THREAD_FPSCR(r4) + /* Disable FP for last_task_used_math */ ld r5,PT_REGS(r4) ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) li r20,MSR_FP|MSR_FE0|MSR_FE1 - andc r4,r4,r20 /* disable FP for previous task */ + andc r4,r4,r20 std r4,_MSR-STACK_FRAME_OVERHEAD(r5) 1: #endif /* CONFIG_SMP */ /* enable use of FP after return */ ld r4,PACACURRENT(r13) addi r5,r4,THREAD /* Get THREAD */ - lwz r4,THREAD_FPEXC_MODE(r5) + ld r4,THREAD_FPEXC_MODE(r5) ori r23,r23,MSR_FP or r23,r23,r4 lfd fr0,THREAD_FPSCR(r5) mtfsf 0xff,fr0 REST_32FPRS(0, r5) #ifndef CONFIG_SMP + /* Update last_task_used_math to 'current' */ subi r4,r5,THREAD /* Back to 'current' */ std r4,last_task_used_math@l(r3) #endif /* CONFIG_SMP */ @@ -1460,19 +1500,16 @@ b fast_exception_return /* - * FP unavailable trap from kernel - print a message, but let - * the task use FP in the kernel until it returns to user mode. + * disable_kernel_fp() + * Disable the FPU. */ -_GLOBAL(KernelFP) - ld r3,_MSR(r1) - ori r3,r3,MSR_FP - std r3,_MSR(r1) /* enable use of FP after return */ - LOADADDR(r3,86f) - ld r4,PACACURRENT(r13) /* current */ - ld r5,_NIP(r1) - b .ret_from_except -86: .string "floating point used in kernel (task=%p, pc=%x)\n" - .align 4 +_GLOBAL(disable_kernel_fp) + mfmsr r3 + rldicl r0,r3,(63-MSR_FP_LG),1 + rldicl r3,r0,(MSR_FP_LG+1),0 + mtmsrd r3 /* disable use of fpu now */ + isync + blr /* * giveup_fpu(tsk) @@ -1562,8 +1599,8 @@ sc /* HvCall_setASR */ #else /* set the ASR */ - addi r3,0,0x4000 /* r3 = ptr to naca */ - lhz r3,PLATFORM(r3) /* r3 = platform flags */ + li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */ + lwz r3,PLATFORM(r3) /* r3 = platform flags */ cmpldi r3,PLATFORM_PSERIES_LPAR bne 98f mfspr r3,PVR @@ -1642,10 +1679,20 @@ bl .reloc_offset mr r26,r3 + mfmsr r6 + ori r6,r6,MSR_RI + mtmsrd r6 /* RI on */ + + /* setup the systemcfg pointer which is needed by *tab_initialize */ + LOADADDR(r6,systemcfg) + sub r6,r6,r26 /* addr of the variable systemcfg */ + li r27,SYSTEMCFG_PHYS_ADDR + std r27,0(r6) /* set the value of systemcfg */ + /* setup the naca pointer which is needed by *tab_initialize */ LOADADDR(r6,naca) sub r6,r6,r26 /* addr of the variable naca */ - li r27,0x4000 + li r27,NACA_PHYS_ADDR std r27,0(r6) /* set the value of naca */ #ifdef CONFIG_HMT @@ -1709,15 +1756,12 @@ sub r13,r13,r26 /* convert to physical addr */ mtspr SPRG3,r13 /* PPPBBB: Temp... -Peter */ - li r3,0x5000 - std r3,PACASTABREAL(r13) - LOADADDR(r24, __start_stab) - std r24,PACASTABVIRT(r13) + ld r3,PACASTABREAL(r13) ori r4,r3,1 /* turn on valid bit */ /* set the ASR */ - addi r3,0,0x4000 /* r3 = ptr to naca */ - lhz r3,PLATFORM(r3) /* r3 = platform flags */ + li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */ + lwz r3,PLATFORM(r3) /* r3 = platform flags */ cmpldi r3,PLATFORM_PSERIES_LPAR bne 98f mfspr r3,PVR @@ -1741,8 +1785,8 @@ bl .stab_initialize bl .htab_initialize - addi r3,0,0x4000 /* r3 = ptr to naca */ - lhz r3,PLATFORM(r3) /* r3 = platform flags */ + li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */ + lwz r3,PLATFORM(r3) /* r3 = platform flags */ cmpldi r3,PLATFORM_PSERIES bne 98f LOADADDR(r6,_SDR1) /* Only if NOT LPAR */ @@ -1791,11 +1835,14 @@ addi r2,r2,0x4000 addi r2,r2,0x4000 - /* setup the naca pointer */ - LOADADDR(r9,naca) + /* setup the systemcfg pointer */ + LOADADDR(r9,systemcfg) + SET_REG_TO_CONST(r8, SYSTEMCFG_VIRT_ADDR) + std r8,0(r9) - SET_REG_TO_CONST(r8, KERNELBASE) - addi r8,r8,0x4000 + /* setup the naca pointer */ + LOADADDR(r9,naca) + SET_REG_TO_CONST(r8, NACA_VIRT_ADDR) std r8,0(r9) /* set the value of the naca ptr */ LOADADDR(r26, boot_cpuid) @@ -1946,7 +1993,7 @@ hardware_int_paca0: .space 8*4096 -/* 1 page segment table per cpu (max 48) */ +/* 1 page segment table per cpu (max 48, cpu0 allocated at STAB0_PHYS_ADDR) */ .globl stab_array stab_array: .space 4096 * 48 diff -Nru a/arch/ppc64/kernel/htab.c b/arch/ppc64/kernel/htab.c --- a/arch/ppc64/kernel/htab.c Sat May 24 12:48:26 2003 +++ b/arch/ppc64/kernel/htab.c Sat May 24 12:48:26 2003 @@ -101,7 +101,7 @@ hpteg = ((hash & htab_data.htab_hash_mask)*HPTES_PER_GROUP); - if (naca->platform == PLATFORM_PSERIES_LPAR) + if (systemcfg->platform == PLATFORM_PSERIES_LPAR) ret = pSeries_lpar_hpte_insert(hpteg, va, (unsigned long)__v2a(addr) >> PAGE_SHIFT, 0, mode, 1, large); @@ -140,7 +140,7 @@ htab_data.htab_num_ptegs = pteg_count; htab_data.htab_hash_mask = pteg_count - 1; - if (naca->platform == PLATFORM_PSERIES) { + if (systemcfg->platform == PLATFORM_PSERIES) { /* Find storage for the HPT. Must be contiguous in * the absolute address space. */ @@ -165,15 +165,15 @@ mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX; /* XXX we currently map kernel text rw, should fix this */ - if (cpu_has_largepage() && naca->physicalMemorySize > 256*MB) { + if (cpu_has_largepage() && systemcfg->physicalMemorySize > 256*MB) { create_pte_mapping((unsigned long)KERNELBASE, KERNELBASE + 256*MB, mode_rw, 0); create_pte_mapping((unsigned long)KERNELBASE + 256*MB, - KERNELBASE + (naca->physicalMemorySize), + KERNELBASE + (systemcfg->physicalMemorySize), mode_rw, 1); } else { create_pte_mapping((unsigned long)KERNELBASE, - KERNELBASE+(naca->physicalMemorySize), + KERNELBASE+(systemcfg->physicalMemorySize), mode_rw, 0); } } diff -Nru a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c --- a/arch/ppc64/kernel/iSeries_setup.c Sat May 24 12:48:29 2003 +++ b/arch/ppc64/kernel/iSeries_setup.c Sat May 24 12:48:29 2003 @@ -561,13 +561,13 @@ * which should be equal to * nextPhysChunk */ - naca->physicalMemorySize = chunk_to_addr(nextPhysChunk); + systemcfg->physicalMemorySize = chunk_to_addr(nextPhysChunk); /* Bolt kernel mappings for all of memory */ - iSeries_bolt_kernel( 0, naca->physicalMemorySize ); + iSeries_bolt_kernel( 0, systemcfg->physicalMemorySize ); lmb_init(); - lmb_add( 0, naca->physicalMemorySize ); + lmb_add( 0, systemcfg->physicalMemorySize ); lmb_analyze(); /* ?? */ lmb_reserve( 0, __pa(klimit)); @@ -584,29 +584,28 @@ static void __init setup_iSeries_cache_sizes(void) { - unsigned i,n; - unsigned procIx = get_paca()->xLpPaca.xDynHvPhysicalProcIndex; + unsigned int i, n; + unsigned int procIx = get_paca()->xLpPaca.xDynHvPhysicalProcIndex; + + systemcfg->iCacheL1Size = xIoHriProcessorVpd[procIx].xInstCacheSize * 1024; + systemcfg->iCacheL1LineSize = xIoHriProcessorVpd[procIx].xInstCacheOperandSize; + systemcfg->dCacheL1Size = xIoHriProcessorVpd[procIx].xDataL1CacheSizeKB * 1024; + systemcfg->dCacheL1LineSize = xIoHriProcessorVpd[procIx].xDataCacheOperandSize; + naca->iCacheL1LinesPerPage = PAGE_SIZE / systemcfg->iCacheL1LineSize; + naca->dCacheL1LinesPerPage = PAGE_SIZE / systemcfg->dCacheL1LineSize; - naca->iCacheL1LineSize = xIoHriProcessorVpd[procIx].xInstCacheOperandSize; - naca->dCacheL1LineSize = xIoHriProcessorVpd[procIx].xDataCacheOperandSize; - naca->iCacheL1LinesPerPage = PAGE_SIZE / naca->iCacheL1LineSize; - naca->dCacheL1LinesPerPage = PAGE_SIZE / naca->dCacheL1LineSize; - i = naca->iCacheL1LineSize; + i = systemcfg->iCacheL1LineSize; n = 0; while ((i=(i/2))) ++n; naca->iCacheL1LogLineSize = n; - i = naca->dCacheL1LineSize; + + i = systemcfg->dCacheL1LineSize; n = 0; while ((i=(i/2))) ++n; naca->dCacheL1LogLineSize = n; - printk( "D-cache line size = %d (log = %d)\n", - (unsigned)naca->dCacheL1LineSize, - (unsigned)naca->dCacheL1LogLineSize ); - printk( "I-cache line size = %d (log = %d)\n", - (unsigned)naca->iCacheL1LineSize, - (unsigned)naca->iCacheL1LogLineSize ); - + printk( "D-cache line size = %d\n", (unsigned int)systemcfg->dCacheL1LineSize); + printk( "I-cache line size = %d\n", (unsigned int)systemcfg->iCacheL1LineSize); } /* @@ -648,6 +647,11 @@ void * eventStack; unsigned procIx = get_paca()->xLpPaca.xDynHvPhysicalProcIndex; + /* Add an eye catcher and the systemcfg layout version number */ + strcpy(systemcfg->eye_catcher, "SYSTEMCFG:PPC64"); + systemcfg->version.major = SYSTEMCFG_MAJOR; + systemcfg->version.minor = SYSTEMCFG_MINOR; + /* Setup the Lp Event Queue */ /* Allocate a page for the Event Stack @@ -696,8 +700,8 @@ printk("Time base frequency = %lu.%02lu\n", tbFreqMhz, tbFreqMhzHundreths ); - printk("Processor version = %x\n", - xIoHriProcessorVpd[procIx].xPVR ); + systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR; + printk("Processor version = %x\n", systemcfg->processor); } @@ -726,9 +730,9 @@ seq_printf(m,"time base\t: %lu.%02luMHz\n", tbFreqMhz, tbFreqMhzHundreths ); seq_printf(m,"i-cache\t\t: %d\n", - naca->iCacheL1LineSize); + systemcfg->iCacheL1LineSize); seq_printf(m,"d-cache\t\t: %d\n", - naca->dCacheL1LineSize); + systemcfg->dCacheL1LineSize); } diff -Nru a/arch/ppc64/kernel/ioctl32.c b/arch/ppc64/kernel/ioctl32.c --- a/arch/ppc64/kernel/ioctl32.c Sat May 24 12:48:33 2003 +++ b/arch/ppc64/kernel/ioctl32.c Sat May 24 12:48:33 2003 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -577,6 +579,17 @@ len += sizeof(struct ethtool_regs); break; } + case ETHTOOL_GEEPROM: + case ETHTOOL_SEEPROM: { + struct ethtool_eeprom *promaddr = (struct ethtool_eeprom *)A(data); + /* darned variable size arguments */ + if (get_user(len, (u32 *)&promaddr->len)) { + err = -EFAULT; + goto out; + } + len += sizeof(struct ethtool_eeprom); + break; + } case ETHTOOL_GSET: case ETHTOOL_SSET: len = sizeof(struct ethtool_cmd); break; default: @@ -659,6 +672,32 @@ return err; } +int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct ifreq *u_ifreq64; + struct ifreq32 *u_ifreq32 = (struct ifreq32 *) arg; + char tmp_buf[IFNAMSIZ]; + void __user *data64; + u32 data32; + + if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]), + IFNAMSIZ)) + return -EFAULT; + if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data)) + return -EFAULT; + data64 = A(data32); + + u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64)); + + /* Don't check these user accesses, just let that get trapped + * in the ioctl handler instead. + */ + copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], IFNAMSIZ); + __put_user(data64, &u_ifreq64->ifr_ifru.ifru_data); + + return sys_ioctl(fd, cmd, (unsigned long) u_ifreq64); +} + static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg) { struct ifreq ifr; @@ -3643,670 +3682,32 @@ #define BNEPGETCONNLIST _IOR('B', 210, int) #define BNEPGETCONNINFO _IOR('B', 211, int) -struct ioctl_trans { - unsigned long cmd; - unsigned long handler; - unsigned long next; -}; - -#define COMPATIBLE_IOCTL(cmd) { cmd, (unsigned long)sys_ioctl, 0 }, +#define HANDLE_IOCTL(cmd,handler) { cmd, (ioctl_trans_handler_t)handler, 0 }, +#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd,sys_ioctl) -#define HANDLE_IOCTL(cmd,handler) { cmd, (unsigned long)handler, 0 }, +#define IOCTL_TABLE_START \ + struct ioctl_trans ioctl_start[] = { +#define IOCTL_TABLE_END \ + }; struct ioctl_trans ioctl_end[0]; #define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int) #define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t) -static struct ioctl_trans ioctl_translations[] = { - /* List here explicitly which ioctl's need translation, - * all others default to calling sys_ioctl(). - */ -/* Big T */ -COMPATIBLE_IOCTL(TCGETA) -COMPATIBLE_IOCTL(TCSETA) -COMPATIBLE_IOCTL(TCSETAW) -COMPATIBLE_IOCTL(TCSETAF) -COMPATIBLE_IOCTL(TCSBRK) +IOCTL_TABLE_START +#include COMPATIBLE_IOCTL(TCSBRKP) -COMPATIBLE_IOCTL(TCXONC) -COMPATIBLE_IOCTL(TCFLSH) -COMPATIBLE_IOCTL(TCGETS) -COMPATIBLE_IOCTL(TCSETS) -COMPATIBLE_IOCTL(TCSETSW) -COMPATIBLE_IOCTL(TCSETSF) -COMPATIBLE_IOCTL(TIOCLINUX) COMPATIBLE_IOCTL(TIOCSTART) COMPATIBLE_IOCTL(TIOCSTOP) -/* Little t */ -COMPATIBLE_IOCTL(TIOCGETD) -COMPATIBLE_IOCTL(TIOCSETD) -COMPATIBLE_IOCTL(TIOCEXCL) -COMPATIBLE_IOCTL(TIOCNXCL) -COMPATIBLE_IOCTL(TIOCCONS) -COMPATIBLE_IOCTL(TIOCGSOFTCAR) -COMPATIBLE_IOCTL(TIOCSSOFTCAR) -COMPATIBLE_IOCTL(TIOCSWINSZ) -COMPATIBLE_IOCTL(TIOCGWINSZ) -COMPATIBLE_IOCTL(TIOCMGET) -COMPATIBLE_IOCTL(TIOCMBIC) -COMPATIBLE_IOCTL(TIOCMBIS) -COMPATIBLE_IOCTL(TIOCMSET) -COMPATIBLE_IOCTL(TIOCPKT) -COMPATIBLE_IOCTL(TIOCNOTTY) -COMPATIBLE_IOCTL(TIOCSTI) -COMPATIBLE_IOCTL(TIOCOUTQ) -COMPATIBLE_IOCTL(TIOCSPGRP) -COMPATIBLE_IOCTL(TIOCGPGRP) -COMPATIBLE_IOCTL(TIOCSCTTY) -COMPATIBLE_IOCTL(TIOCGPTN) -COMPATIBLE_IOCTL(TIOCSPTLCK) COMPATIBLE_IOCTL(TIOCGSERIAL) COMPATIBLE_IOCTL(TIOCSSERIAL) -COMPATIBLE_IOCTL(TIOCSERGETLSR) COMPATIBLE_IOCTL(TIOCSLTC) -/* Big F */ -COMPATIBLE_IOCTL(FBIOGET_VSCREENINFO) -COMPATIBLE_IOCTL(FBIOPUT_VSCREENINFO) -COMPATIBLE_IOCTL(FBIOPAN_DISPLAY) -COMPATIBLE_IOCTL(FBIOGET_CON2FBMAP) -COMPATIBLE_IOCTL(FBIOPUT_CON2FBMAP) #if 0 COMPATIBLE_IOCTL(FBIOBLANK) #endif -/* Little f */ -COMPATIBLE_IOCTL(FIOCLEX) -COMPATIBLE_IOCTL(FIONCLEX) -COMPATIBLE_IOCTL(FIOASYNC) -COMPATIBLE_IOCTL(FIONBIO) -COMPATIBLE_IOCTL(FIONREAD) /* This is also TIOCINQ */ -/* 0x00 */ -COMPATIBLE_IOCTL(FIBMAP) -COMPATIBLE_IOCTL(FIGETBSZ) -/* 0x03 -- HD/IDE ioctl's used by hdparm and friends. - * Some need translations, these do not. - */ -COMPATIBLE_IOCTL(HDIO_GET_IDENTITY) -COMPATIBLE_IOCTL(HDIO_SET_DMA) -COMPATIBLE_IOCTL(HDIO_SET_UNMASKINTR) -COMPATIBLE_IOCTL(HDIO_SET_NOWERR) -COMPATIBLE_IOCTL(HDIO_SET_32BIT) -COMPATIBLE_IOCTL(HDIO_SET_MULTCOUNT) -COMPATIBLE_IOCTL(HDIO_DRIVE_CMD) -COMPATIBLE_IOCTL(HDIO_SET_PIO_MODE) -COMPATIBLE_IOCTL(HDIO_SET_NICE) -/* 0x02 -- Floppy ioctls */ -COMPATIBLE_IOCTL(FDMSGON) -COMPATIBLE_IOCTL(FDMSGOFF) -COMPATIBLE_IOCTL(FDSETEMSGTRESH) -COMPATIBLE_IOCTL(FDFLUSH) -COMPATIBLE_IOCTL(FDWERRORCLR) -COMPATIBLE_IOCTL(FDSETMAXERRS) -COMPATIBLE_IOCTL(FDGETMAXERRS) -COMPATIBLE_IOCTL(FDGETDRVTYP) -COMPATIBLE_IOCTL(FDEJECT) -COMPATIBLE_IOCTL(FDCLRPRM) -COMPATIBLE_IOCTL(FDFMTBEG) -COMPATIBLE_IOCTL(FDFMTEND) -COMPATIBLE_IOCTL(FDRESET) -COMPATIBLE_IOCTL(FDTWADDLE) -COMPATIBLE_IOCTL(FDFMTTRK) -COMPATIBLE_IOCTL(FDRAWCMD) -/* 0x12 */ -COMPATIBLE_IOCTL(BLKROSET) -COMPATIBLE_IOCTL(BLKROGET) -COMPATIBLE_IOCTL(BLKRRPART) -COMPATIBLE_IOCTL(BLKFLSBUF) -COMPATIBLE_IOCTL(BLKSECTSET) -COMPATIBLE_IOCTL(BLKSSZGET) -COMPATIBLE_IOCTL(BLKRASET) -COMPATIBLE_IOCTL(BLKFRASET) -/* RAID */ -COMPATIBLE_IOCTL(RAID_VERSION) -COMPATIBLE_IOCTL(GET_ARRAY_INFO) -COMPATIBLE_IOCTL(GET_DISK_INFO) -COMPATIBLE_IOCTL(PRINT_RAID_DEBUG) -COMPATIBLE_IOCTL(CLEAR_ARRAY) -COMPATIBLE_IOCTL(ADD_NEW_DISK) -COMPATIBLE_IOCTL(HOT_REMOVE_DISK) -COMPATIBLE_IOCTL(SET_ARRAY_INFO) -COMPATIBLE_IOCTL(SET_DISK_INFO) -COMPATIBLE_IOCTL(WRITE_RAID_INFO) -COMPATIBLE_IOCTL(UNPROTECT_ARRAY) -COMPATIBLE_IOCTL(PROTECT_ARRAY) -COMPATIBLE_IOCTL(HOT_ADD_DISK) -COMPATIBLE_IOCTL(SET_DISK_FAULTY) -COMPATIBLE_IOCTL(RUN_ARRAY) -COMPATIBLE_IOCTL(START_ARRAY) -COMPATIBLE_IOCTL(STOP_ARRAY) -COMPATIBLE_IOCTL(STOP_ARRAY_RO) -COMPATIBLE_IOCTL(RESTART_ARRAY_RW) -/* Big K */ -COMPATIBLE_IOCTL(PIO_FONT) -COMPATIBLE_IOCTL(GIO_FONT) -COMPATIBLE_IOCTL(KDSIGACCEPT) -COMPATIBLE_IOCTL(KDGETKEYCODE) -COMPATIBLE_IOCTL(KDSETKEYCODE) -COMPATIBLE_IOCTL(KIOCSOUND) -COMPATIBLE_IOCTL(KDMKTONE) -COMPATIBLE_IOCTL(KDGKBTYPE) -COMPATIBLE_IOCTL(KDSETMODE) -COMPATIBLE_IOCTL(KDGETMODE) -COMPATIBLE_IOCTL(KDSKBMODE) -COMPATIBLE_IOCTL(KDGKBMODE) -COMPATIBLE_IOCTL(KDSKBMETA) -COMPATIBLE_IOCTL(KDGKBMETA) -COMPATIBLE_IOCTL(KDGKBENT) -COMPATIBLE_IOCTL(KDSKBENT) -COMPATIBLE_IOCTL(KDGKBSENT) -COMPATIBLE_IOCTL(KDSKBSENT) -COMPATIBLE_IOCTL(KDGKBDIACR) -COMPATIBLE_IOCTL(KDKBDREP) -COMPATIBLE_IOCTL(KDSKBDIACR) -COMPATIBLE_IOCTL(KDGKBLED) -COMPATIBLE_IOCTL(KDSKBLED) -COMPATIBLE_IOCTL(KDGETLED) -COMPATIBLE_IOCTL(KDSETLED) -COMPATIBLE_IOCTL(GIO_SCRNMAP) -COMPATIBLE_IOCTL(PIO_SCRNMAP) -COMPATIBLE_IOCTL(GIO_UNISCRNMAP) -COMPATIBLE_IOCTL(PIO_UNISCRNMAP) -COMPATIBLE_IOCTL(PIO_FONTRESET) -COMPATIBLE_IOCTL(PIO_UNIMAPCLR) -/* Big S */ -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN) -COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST) -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI) -COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK) -COMPATIBLE_IOCTL(SCSI_IOCTL_DOORUNLOCK) -COMPATIBLE_IOCTL(SCSI_IOCTL_TEST_UNIT_READY) -COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_ENABLE) -COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_DISABLE) -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER) -COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND) -/* Big T */ -COMPATIBLE_IOCTL(TUNSETNOCSUM) -COMPATIBLE_IOCTL(TUNSETDEBUG) -COMPATIBLE_IOCTL(TUNSETIFF) -COMPATIBLE_IOCTL(TUNSETPERSIST) -COMPATIBLE_IOCTL(TUNSETOWNER) -/* Big V */ -COMPATIBLE_IOCTL(VT_SETMODE) -COMPATIBLE_IOCTL(VT_GETMODE) -COMPATIBLE_IOCTL(VT_GETSTATE) -COMPATIBLE_IOCTL(VT_OPENQRY) -COMPATIBLE_IOCTL(VT_ACTIVATE) -COMPATIBLE_IOCTL(VT_WAITACTIVE) -COMPATIBLE_IOCTL(VT_RELDISP) -COMPATIBLE_IOCTL(VT_DISALLOCATE) -COMPATIBLE_IOCTL(VT_RESIZE) -COMPATIBLE_IOCTL(VT_RESIZEX) -COMPATIBLE_IOCTL(VT_LOCKSWITCH) -COMPATIBLE_IOCTL(VT_UNLOCKSWITCH) -/* Little v, the video4linux ioctls */ -COMPATIBLE_IOCTL(VIDIOCGCAP) -COMPATIBLE_IOCTL(VIDIOCGCHAN) -COMPATIBLE_IOCTL(VIDIOCSCHAN) -COMPATIBLE_IOCTL(VIDIOCGPICT) -COMPATIBLE_IOCTL(VIDIOCSPICT) -COMPATIBLE_IOCTL(VIDIOCCAPTURE) -COMPATIBLE_IOCTL(VIDIOCKEY) -COMPATIBLE_IOCTL(VIDIOCGAUDIO) -COMPATIBLE_IOCTL(VIDIOCSAUDIO) -COMPATIBLE_IOCTL(VIDIOCSYNC) -COMPATIBLE_IOCTL(VIDIOCMCAPTURE) -COMPATIBLE_IOCTL(VIDIOCGMBUF) -COMPATIBLE_IOCTL(VIDIOCGUNIT) -COMPATIBLE_IOCTL(VIDIOCGCAPTURE) -COMPATIBLE_IOCTL(VIDIOCSCAPTURE) -/* BTTV specific... */ -COMPATIBLE_IOCTL(_IOW('v', BASE_VIDIOCPRIVATE+0, char [256])) -COMPATIBLE_IOCTL(_IOR('v', BASE_VIDIOCPRIVATE+1, char [256])) -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int)) -COMPATIBLE_IOCTL(_IOW('v' , BASE_VIDIOCPRIVATE+3, char [16])) /* struct bttv_pll_info */ -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+4, int)) -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+5, int)) -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+6, int)) -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+7, int)) /* Little p (/dev/rtc, /dev/envctrl, etc.) */ COMPATIBLE_IOCTL(_IOR('p', 20, int[7])) /* RTCGET */ COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */ -COMPATIBLE_IOCTL(RTC_AIE_ON) -COMPATIBLE_IOCTL(RTC_AIE_OFF) -COMPATIBLE_IOCTL(RTC_UIE_ON) -COMPATIBLE_IOCTL(RTC_UIE_OFF) -COMPATIBLE_IOCTL(RTC_PIE_ON) -COMPATIBLE_IOCTL(RTC_PIE_OFF) -COMPATIBLE_IOCTL(RTC_WIE_ON) -COMPATIBLE_IOCTL(RTC_WIE_OFF) -COMPATIBLE_IOCTL(RTC_ALM_SET) -COMPATIBLE_IOCTL(RTC_ALM_READ) -COMPATIBLE_IOCTL(RTC_RD_TIME) -COMPATIBLE_IOCTL(RTC_SET_TIME) -COMPATIBLE_IOCTL(RTC_WKALM_SET) -COMPATIBLE_IOCTL(RTC_WKALM_RD) -/* Little m */ -COMPATIBLE_IOCTL(MTIOCTOP) -/* Socket level stuff */ -COMPATIBLE_IOCTL(FIOSETOWN) -COMPATIBLE_IOCTL(SIOCSPGRP) -COMPATIBLE_IOCTL(FIOGETOWN) -COMPATIBLE_IOCTL(SIOCGPGRP) -COMPATIBLE_IOCTL(SIOCATMARK) -COMPATIBLE_IOCTL(SIOCSIFLINK) -COMPATIBLE_IOCTL(SIOCSIFENCAP) -COMPATIBLE_IOCTL(SIOCGIFENCAP) -COMPATIBLE_IOCTL(SIOCSIFBR) -COMPATIBLE_IOCTL(SIOCGIFBR) -COMPATIBLE_IOCTL(SIOCSARP) -COMPATIBLE_IOCTL(SIOCGARP) -COMPATIBLE_IOCTL(SIOCDARP) -COMPATIBLE_IOCTL(SIOCSRARP) -COMPATIBLE_IOCTL(SIOCGRARP) -COMPATIBLE_IOCTL(SIOCDRARP) -COMPATIBLE_IOCTL(SIOCADDDLCI) -COMPATIBLE_IOCTL(SIOCDELDLCI) -COMPATIBLE_IOCTL(SIOCGMIIPHY) -COMPATIBLE_IOCTL(SIOCGMIIREG) -COMPATIBLE_IOCTL(SIOCSMIIREG) -COMPATIBLE_IOCTL(SIOCGIFVLAN) -COMPATIBLE_IOCTL(SIOCSIFVLAN) -/* SG stuff */ -COMPATIBLE_IOCTL(SG_SET_TIMEOUT) -COMPATIBLE_IOCTL(SG_GET_TIMEOUT) -COMPATIBLE_IOCTL(SG_EMULATED_HOST) -COMPATIBLE_IOCTL(SG_SET_TRANSFORM) -COMPATIBLE_IOCTL(SG_GET_TRANSFORM) -COMPATIBLE_IOCTL(SG_SET_RESERVED_SIZE) -COMPATIBLE_IOCTL(SG_GET_RESERVED_SIZE) -COMPATIBLE_IOCTL(SG_GET_SCSI_ID) -COMPATIBLE_IOCTL(SG_SET_FORCE_LOW_DMA) -COMPATIBLE_IOCTL(SG_GET_LOW_DMA) -COMPATIBLE_IOCTL(SG_SET_FORCE_PACK_ID) -COMPATIBLE_IOCTL(SG_GET_PACK_ID) -COMPATIBLE_IOCTL(SG_GET_NUM_WAITING) -COMPATIBLE_IOCTL(SG_SET_DEBUG) -COMPATIBLE_IOCTL(SG_GET_SG_TABLESIZE) -COMPATIBLE_IOCTL(SG_GET_COMMAND_Q) -COMPATIBLE_IOCTL(SG_SET_COMMAND_Q) -COMPATIBLE_IOCTL(SG_GET_VERSION_NUM) -COMPATIBLE_IOCTL(SG_NEXT_CMD_LEN) -COMPATIBLE_IOCTL(SG_SCSI_RESET) -COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE) -COMPATIBLE_IOCTL(SG_SET_KEEP_ORPHAN) -COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN) -/* PPP stuff */ -COMPATIBLE_IOCTL(PPPIOCGFLAGS) -COMPATIBLE_IOCTL(PPPIOCSFLAGS) -COMPATIBLE_IOCTL(PPPIOCGASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCSASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCGUNIT) -COMPATIBLE_IOCTL(PPPIOCGRASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCSRASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCGMRU) -COMPATIBLE_IOCTL(PPPIOCSMRU) -COMPATIBLE_IOCTL(PPPIOCSMAXCID) -COMPATIBLE_IOCTL(PPPIOCGXASYNCMAP) -COMPATIBLE_IOCTL(LPGETSTATUS) -COMPATIBLE_IOCTL(PPPIOCSXASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCXFERUNIT) -COMPATIBLE_IOCTL(PPPIOCGNPMODE) -COMPATIBLE_IOCTL(PPPIOCSNPMODE) -COMPATIBLE_IOCTL(PPPIOCGDEBUG) -COMPATIBLE_IOCTL(PPPIOCSDEBUG) -COMPATIBLE_IOCTL(PPPIOCNEWUNIT) -COMPATIBLE_IOCTL(PPPIOCATTACH) -COMPATIBLE_IOCTL(PPPIOCDETACH) -COMPATIBLE_IOCTL(PPPIOCSMRRU) -COMPATIBLE_IOCTL(PPPIOCCONNECT) -COMPATIBLE_IOCTL(PPPIOCDISCONN) -COMPATIBLE_IOCTL(PPPIOCATTCHAN) -COMPATIBLE_IOCTL(PPPIOCGCHAN) -/* PPPOX */ -COMPATIBLE_IOCTL(PPPOEIOCSFWD) -COMPATIBLE_IOCTL(PPPOEIOCDFWD) -/* CDROM stuff */ -COMPATIBLE_IOCTL(CDROMPAUSE) -COMPATIBLE_IOCTL(CDROMRESUME) -COMPATIBLE_IOCTL(CDROMPLAYMSF) -COMPATIBLE_IOCTL(CDROMPLAYTRKIND) -COMPATIBLE_IOCTL(CDROMREADTOCHDR) -COMPATIBLE_IOCTL(CDROMREADTOCENTRY) -COMPATIBLE_IOCTL(CDROMSTOP) -COMPATIBLE_IOCTL(CDROMSTART) -COMPATIBLE_IOCTL(CDROMEJECT) -COMPATIBLE_IOCTL(CDROMVOLCTRL) -COMPATIBLE_IOCTL(CDROMSUBCHNL) -COMPATIBLE_IOCTL(CDROMEJECT_SW) -COMPATIBLE_IOCTL(CDROMMULTISESSION) -COMPATIBLE_IOCTL(CDROM_GET_MCN) -COMPATIBLE_IOCTL(CDROMRESET) -COMPATIBLE_IOCTL(CDROMVOLREAD) -COMPATIBLE_IOCTL(CDROMSEEK) -COMPATIBLE_IOCTL(CDROMPLAYBLK) -COMPATIBLE_IOCTL(CDROMCLOSETRAY) -COMPATIBLE_IOCTL(CDROM_SET_OPTIONS) -COMPATIBLE_IOCTL(CDROM_CLEAR_OPTIONS) -COMPATIBLE_IOCTL(CDROM_SELECT_SPEED) -COMPATIBLE_IOCTL(CDROM_SELECT_DISC) -COMPATIBLE_IOCTL(CDROM_MEDIA_CHANGED) -COMPATIBLE_IOCTL(CDROM_DRIVE_STATUS) -COMPATIBLE_IOCTL(CDROM_DISC_STATUS) -COMPATIBLE_IOCTL(CDROM_CHANGER_NSLOTS) -COMPATIBLE_IOCTL(CDROM_LOCKDOOR) -COMPATIBLE_IOCTL(CDROM_DEBUG) -COMPATIBLE_IOCTL(CDROM_GET_CAPABILITY) -/* DVD ioctls */ -COMPATIBLE_IOCTL(DVD_READ_STRUCT) -COMPATIBLE_IOCTL(DVD_WRITE_STRUCT) -COMPATIBLE_IOCTL(DVD_AUTH) -/* Big L */ -COMPATIBLE_IOCTL(LOOP_SET_FD) -COMPATIBLE_IOCTL(LOOP_CLR_FD) -/* Big Q for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_SEQ_RESET) -COMPATIBLE_IOCTL(SNDCTL_SEQ_SYNC) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_INFO) -COMPATIBLE_IOCTL(SNDCTL_SEQ_CTRLRATE) -COMPATIBLE_IOCTL(SNDCTL_SEQ_GETOUTCOUNT) -COMPATIBLE_IOCTL(SNDCTL_SEQ_GETINCOUNT) -COMPATIBLE_IOCTL(SNDCTL_SEQ_PERCMODE) -COMPATIBLE_IOCTL(SNDCTL_FM_LOAD_INSTR) -COMPATIBLE_IOCTL(SNDCTL_SEQ_TESTMIDI) -COMPATIBLE_IOCTL(SNDCTL_SEQ_RESETSAMPLES) -COMPATIBLE_IOCTL(SNDCTL_SEQ_NRSYNTHS) -COMPATIBLE_IOCTL(SNDCTL_SEQ_NRMIDIS) -COMPATIBLE_IOCTL(SNDCTL_MIDI_INFO) -COMPATIBLE_IOCTL(SNDCTL_SEQ_THRESHOLD) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_MEMAVL) -COMPATIBLE_IOCTL(SNDCTL_FM_4OP_ENABLE) -COMPATIBLE_IOCTL(SNDCTL_SEQ_PANIC) -COMPATIBLE_IOCTL(SNDCTL_SEQ_OUTOFBAND) -COMPATIBLE_IOCTL(SNDCTL_SEQ_GETTIME) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_ID) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_CONTROL) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_REMOVESAMPLE) -/* Big T for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_TMR_TIMEBASE) -COMPATIBLE_IOCTL(SNDCTL_TMR_START) -COMPATIBLE_IOCTL(SNDCTL_TMR_STOP) -COMPATIBLE_IOCTL(SNDCTL_TMR_CONTINUE) -COMPATIBLE_IOCTL(SNDCTL_TMR_TEMPO) -COMPATIBLE_IOCTL(SNDCTL_TMR_SOURCE) -COMPATIBLE_IOCTL(SNDCTL_TMR_METRONOME) -COMPATIBLE_IOCTL(SNDCTL_TMR_SELECT) -/* Little m for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_MIDI_PRETIME) -COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUMODE) -COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUCMD) -/* Big P for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_DSP_RESET) -COMPATIBLE_IOCTL(SNDCTL_DSP_SYNC) -COMPATIBLE_IOCTL(SNDCTL_DSP_SPEED) -COMPATIBLE_IOCTL(SNDCTL_DSP_STEREO) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETBLKSIZE) -COMPATIBLE_IOCTL(SNDCTL_DSP_CHANNELS) -COMPATIBLE_IOCTL(SOUND_PCM_WRITE_FILTER) -COMPATIBLE_IOCTL(SNDCTL_DSP_POST) -COMPATIBLE_IOCTL(SNDCTL_DSP_SUBDIVIDE) -COMPATIBLE_IOCTL(SNDCTL_DSP_SETFRAGMENT) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETFMTS) -COMPATIBLE_IOCTL(SNDCTL_DSP_SETFMT) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETOSPACE) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETISPACE) -COMPATIBLE_IOCTL(SNDCTL_DSP_NONBLOCK) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETCAPS) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETTRIGGER) -COMPATIBLE_IOCTL(SNDCTL_DSP_SETTRIGGER) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETIPTR) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETOPTR) -/* SNDCTL_DSP_MAPINBUF, XXX needs translation */ -/* SNDCTL_DSP_MAPOUTBUF, XXX needs translation */ -COMPATIBLE_IOCTL(SNDCTL_DSP_SETSYNCRO) -COMPATIBLE_IOCTL(SNDCTL_DSP_SETDUPLEX) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETODELAY) -COMPATIBLE_IOCTL(SNDCTL_DSP_PROFILE) -COMPATIBLE_IOCTL(SOUND_PCM_READ_RATE) -COMPATIBLE_IOCTL(SOUND_PCM_READ_CHANNELS) -COMPATIBLE_IOCTL(SOUND_PCM_READ_BITS) -COMPATIBLE_IOCTL(SOUND_PCM_READ_FILTER) -/* Big C for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_COPR_RESET) -COMPATIBLE_IOCTL(SNDCTL_COPR_LOAD) -COMPATIBLE_IOCTL(SNDCTL_COPR_RDATA) -COMPATIBLE_IOCTL(SNDCTL_COPR_RCODE) -COMPATIBLE_IOCTL(SNDCTL_COPR_WDATA) -COMPATIBLE_IOCTL(SNDCTL_COPR_WCODE) -COMPATIBLE_IOCTL(SNDCTL_COPR_RUN) -COMPATIBLE_IOCTL(SNDCTL_COPR_HALT) -COMPATIBLE_IOCTL(SNDCTL_COPR_SENDMSG) -COMPATIBLE_IOCTL(SNDCTL_COPR_RCVMSG) -/* Big M for sound/OSS */ -COMPATIBLE_IOCTL(SOUND_MIXER_READ_VOLUME) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_BASS) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_TREBLE) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_SYNTH) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_PCM) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_SPEAKER) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_MIC) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_CD) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_IMIX) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_ALTPCM) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECLEV) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_IGAIN) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_OGAIN) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE1) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE2) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE3) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL1)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL2)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL3)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEIN)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEOUT)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_VIDEO)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_RADIO)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_MONITOR)) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_MUTE) -/* SOUND_MIXER_READ_ENHANCE, same value as READ_MUTE */ -/* SOUND_MIXER_READ_LOUD, same value as READ_MUTE */ -COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECSRC) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_DEVMASK) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECMASK) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_STEREODEVS) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_CAPS) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_VOLUME) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_BASS) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_TREBLE) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_SYNTH) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_PCM) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_SPEAKER) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MIC) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_CD) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_IMIX) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_ALTPCM) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_RECLEV) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_IGAIN) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_OGAIN) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE1) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE2) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE3) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL1)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL2)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL3)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEIN)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEOUT)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_VIDEO)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_RADIO)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_MONITOR)) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MUTE) -/* SOUND_MIXER_WRITE_ENHANCE, same value as WRITE_MUTE */ -/* SOUND_MIXER_WRITE_LOUD, same value as WRITE_MUTE */ -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_RECSRC) -COMPATIBLE_IOCTL(SOUND_MIXER_INFO) -COMPATIBLE_IOCTL(SOUND_OLD_MIXER_INFO) -COMPATIBLE_IOCTL(SOUND_MIXER_ACCESS) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE1) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE2) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE3) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE4) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE5) -COMPATIBLE_IOCTL(SOUND_MIXER_GETLEVELS) -COMPATIBLE_IOCTL(SOUND_MIXER_SETLEVELS) -COMPATIBLE_IOCTL(OSS_GETVERSION) -/* AUTOFS */ -COMPATIBLE_IOCTL(AUTOFS_IOC_READY) -COMPATIBLE_IOCTL(AUTOFS_IOC_FAIL) -COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC) -COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER) -COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE) -/* DEVFS */ -COMPATIBLE_IOCTL(DEVFSDIOC_GET_PROTO_REV) -COMPATIBLE_IOCTL(DEVFSDIOC_SET_EVENT_MASK) -COMPATIBLE_IOCTL(DEVFSDIOC_RELEASE_EVENT_QUEUE) -COMPATIBLE_IOCTL(DEVFSDIOC_SET_DEBUG_MASK) -/* Raw devices */ -COMPATIBLE_IOCTL(RAW_SETBIND) -COMPATIBLE_IOCTL(RAW_GETBIND) -/* SMB ioctls which do not need any translations */ -COMPATIBLE_IOCTL(SMB_IOC_NEWCONN) -/* NCP ioctls which do not need any translations */ -COMPATIBLE_IOCTL(NCP_IOC_CONN_LOGGED_IN) -COMPATIBLE_IOCTL(NCP_IOC_SIGN_INIT) -COMPATIBLE_IOCTL(NCP_IOC_SIGN_WANTED) -COMPATIBLE_IOCTL(NCP_IOC_SET_SIGN_WANTED) -COMPATIBLE_IOCTL(NCP_IOC_LOCKUNLOCK) -COMPATIBLE_IOCTL(NCP_IOC_GETROOT) -COMPATIBLE_IOCTL(NCP_IOC_SETROOT) -COMPATIBLE_IOCTL(NCP_IOC_GETCHARSETS) -COMPATIBLE_IOCTL(NCP_IOC_SETCHARSETS) -COMPATIBLE_IOCTL(NCP_IOC_GETDENTRYTTL) -COMPATIBLE_IOCTL(NCP_IOC_SETDENTRYTTL) -/* Little a */ -COMPATIBLE_IOCTL(ATMSIGD_CTRL) -COMPATIBLE_IOCTL(ATMARPD_CTRL) -COMPATIBLE_IOCTL(ATMLEC_CTRL) -COMPATIBLE_IOCTL(ATMLEC_MCAST) -COMPATIBLE_IOCTL(ATMLEC_DATA) -COMPATIBLE_IOCTL(ATM_SETSC) -COMPATIBLE_IOCTL(SIOCSIFATMTCP) -COMPATIBLE_IOCTL(SIOCMKCLIP) -COMPATIBLE_IOCTL(ATMARP_MKIP) -COMPATIBLE_IOCTL(ATMARP_SETENTRY) -COMPATIBLE_IOCTL(ATMARP_ENCAP) -COMPATIBLE_IOCTL(ATMTCP_CREATE) -COMPATIBLE_IOCTL(ATMTCP_REMOVE) -COMPATIBLE_IOCTL(ATMMPC_CTRL) -COMPATIBLE_IOCTL(ATMMPC_DATA) -#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) -COMPATIBLE_IOCTL(DRM_IOCTL_GET_MAGIC) -COMPATIBLE_IOCTL(DRM_IOCTL_IRQ_BUSID) -COMPATIBLE_IOCTL(DRM_IOCTL_AUTH_MAGIC) -COMPATIBLE_IOCTL(DRM_IOCTL_BLOCK) -COMPATIBLE_IOCTL(DRM_IOCTL_UNBLOCK) -COMPATIBLE_IOCTL(DRM_IOCTL_CONTROL) -COMPATIBLE_IOCTL(DRM_IOCTL_ADD_BUFS) -COMPATIBLE_IOCTL(DRM_IOCTL_MARK_BUFS) -COMPATIBLE_IOCTL(DRM_IOCTL_ADD_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_RM_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_MOD_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_GET_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_SWITCH_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_NEW_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_ADD_DRAW) -COMPATIBLE_IOCTL(DRM_IOCTL_RM_DRAW) -COMPATIBLE_IOCTL(DRM_IOCTL_LOCK) -COMPATIBLE_IOCTL(DRM_IOCTL_UNLOCK) -COMPATIBLE_IOCTL(DRM_IOCTL_FINISH) -#endif /* DRM */ -/* Big W */ -/* WIOC_GETSUPPORT not yet implemented -E */ -COMPATIBLE_IOCTL(WDIOC_GETSTATUS) -COMPATIBLE_IOCTL(WDIOC_GETBOOTSTATUS) -COMPATIBLE_IOCTL(WDIOC_GETTEMP) -COMPATIBLE_IOCTL(WDIOC_SETOPTIONS) -COMPATIBLE_IOCTL(WDIOC_KEEPALIVE) -/* Big R */ -COMPATIBLE_IOCTL(RNDGETENTCNT) -COMPATIBLE_IOCTL(RNDADDTOENTCNT) -COMPATIBLE_IOCTL(RNDGETPOOL) -COMPATIBLE_IOCTL(RNDADDENTROPY) -COMPATIBLE_IOCTL(RNDZAPENTCNT) -COMPATIBLE_IOCTL(RNDCLEARPOOL) -/* Bluetooth ioctls */ -COMPATIBLE_IOCTL(HCIDEVUP) -COMPATIBLE_IOCTL(HCIDEVDOWN) -COMPATIBLE_IOCTL(HCIDEVRESET) -COMPATIBLE_IOCTL(HCIDEVRESTAT) -COMPATIBLE_IOCTL(HCIGETDEVLIST) -COMPATIBLE_IOCTL(HCIGETDEVINFO) -COMPATIBLE_IOCTL(HCIGETCONNLIST) -COMPATIBLE_IOCTL(HCIGETCONNINFO) -COMPATIBLE_IOCTL(HCISETRAW) -COMPATIBLE_IOCTL(HCISETSCAN) -COMPATIBLE_IOCTL(HCISETAUTH) -COMPATIBLE_IOCTL(HCISETENCRYPT) -COMPATIBLE_IOCTL(HCISETPTYPE) -COMPATIBLE_IOCTL(HCISETLINKPOL) -COMPATIBLE_IOCTL(HCISETLINKMODE) -COMPATIBLE_IOCTL(HCISETACLMTU) -COMPATIBLE_IOCTL(HCISETSCOMTU) -COMPATIBLE_IOCTL(HCIINQUIRY) -COMPATIBLE_IOCTL(HCIUARTSETPROTO) -COMPATIBLE_IOCTL(HCIUARTGETPROTO) -COMPATIBLE_IOCTL(RFCOMMCREATEDEV) -COMPATIBLE_IOCTL(RFCOMMRELEASEDEV) -COMPATIBLE_IOCTL(RFCOMMGETDEVLIST) -COMPATIBLE_IOCTL(RFCOMMGETDEVINFO) -COMPATIBLE_IOCTL(RFCOMMSTEALDLC) -COMPATIBLE_IOCTL(BNEPCONNADD) -COMPATIBLE_IOCTL(BNEPCONNDEL) -COMPATIBLE_IOCTL(BNEPGETCONNLIST) -COMPATIBLE_IOCTL(BNEPGETCONNINFO) -COMPATIBLE_IOCTL(PCIIOC_CONTROLLER) -COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO) -COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM) -COMPATIBLE_IOCTL(PCIIOC_WRITE_COMBINE) -/* USB */ -COMPATIBLE_IOCTL(USBDEVFS_RESETEP) -COMPATIBLE_IOCTL(USBDEVFS_SETINTERFACE) -COMPATIBLE_IOCTL(USBDEVFS_SETCONFIGURATION) -COMPATIBLE_IOCTL(USBDEVFS_GETDRIVER) -COMPATIBLE_IOCTL(USBDEVFS_DISCARDURB) -COMPATIBLE_IOCTL(USBDEVFS_CLAIMINTERFACE) -COMPATIBLE_IOCTL(USBDEVFS_RELEASEINTERFACE) -COMPATIBLE_IOCTL(USBDEVFS_CONNECTINFO) -COMPATIBLE_IOCTL(USBDEVFS_HUB_PORTINFO) -COMPATIBLE_IOCTL(USBDEVFS_RESET) -COMPATIBLE_IOCTL(USBDEVFS_CLEAR_HALT) -/* MTD */ -COMPATIBLE_IOCTL(MEMGETINFO) -COMPATIBLE_IOCTL(MEMERASE) -COMPATIBLE_IOCTL(MEMLOCK) -COMPATIBLE_IOCTL(MEMUNLOCK) -COMPATIBLE_IOCTL(MEMGETREGIONCOUNT) -COMPATIBLE_IOCTL(MEMGETREGIONINFO) -/* NBD */ -COMPATIBLE_IOCTL(NBD_SET_SOCK) -COMPATIBLE_IOCTL(NBD_SET_BLKSIZE) -COMPATIBLE_IOCTL(NBD_SET_SIZE) -COMPATIBLE_IOCTL(NBD_DO_IT) -COMPATIBLE_IOCTL(NBD_CLEAR_SOCK) -COMPATIBLE_IOCTL(NBD_CLEAR_QUE) -COMPATIBLE_IOCTL(NBD_PRINT_DEBUG) -COMPATIBLE_IOCTL(NBD_SET_SIZE_BLOCKS) -COMPATIBLE_IOCTL(NBD_DISCONNECT) -/* device-mapper */ -COMPATIBLE_IOCTL(DM_VERSION) -COMPATIBLE_IOCTL(DM_REMOVE_ALL) -COMPATIBLE_IOCTL(DM_DEV_CREATE) -COMPATIBLE_IOCTL(DM_DEV_REMOVE) -COMPATIBLE_IOCTL(DM_DEV_RELOAD) -COMPATIBLE_IOCTL(DM_DEV_SUSPEND) -COMPATIBLE_IOCTL(DM_DEV_RENAME) -COMPATIBLE_IOCTL(DM_DEV_DEPS) -COMPATIBLE_IOCTL(DM_DEV_STATUS) -COMPATIBLE_IOCTL(DM_TARGET_STATUS) -COMPATIBLE_IOCTL(DM_TARGET_WAIT) + /* And these ioctls need translation */ HANDLE_IOCTL(MEMREADOOB32, mtd_rw_oob) HANDLE_IOCTL(MEMWRITEOOB32, mtd_rw_oob) @@ -4473,4 +3874,4 @@ HANDLE_IOCTL(BLKBSZGET_32, do_blkbszget) HANDLE_IOCTL(BLKBSZSET_32, do_blkbszset) HANDLE_IOCTL(BLKGETSIZE64_32, do_blkgetsize64) -}; +IOCTL_TABLE_END diff -Nru a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c --- a/arch/ppc64/kernel/irq.c Sat May 24 12:48:24 2003 +++ b/arch/ppc64/kernel/irq.c Sat May 24 12:48:24 2003 @@ -212,7 +212,8 @@ return -ENOENT; } -int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), +int request_irq(unsigned int irq, + irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id) { struct irqaction *action; @@ -695,7 +696,7 @@ struct proc_dir_entry *entry; char name [MAX_NAMELEN]; - if (!root_irq_dir || (irq_desc[irq].handler == NULL)) + if (!root_irq_dir || (irq_desc[irq].handler == NULL) || irq_dir[irq]) return; memset(name, 0, MAX_NAMELEN); @@ -743,6 +744,7 @@ } } -void no_action(int irq, void *dev, struct pt_regs *regs) +irqreturn_t no_action(int irq, void *dev, struct pt_regs *regs) { + return IRQ_NONE; } diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S --- a/arch/ppc64/kernel/misc.S Sat May 24 12:48:31 2003 +++ b/arch/ppc64/kernel/misc.S Sat May 24 12:48:31 2003 @@ -170,12 +170,14 @@ */ LOADADDR(r10,naca) /* Get Naca address */ ld r10,0(r10) - lhz r7,DCACHEL1LINESIZE(r10) /* Get cache line size */ + LOADADDR(r11,systemcfg) /* Get systemcfg address */ + ld r11,0(r11) + lwz r7,DCACHEL1LINESIZE(r11)/* Get cache line size */ addi r5,r7,-1 andc r6,r3,r5 /* round low to line bdy */ subf r8,r6,r4 /* compute length */ add r8,r8,r5 /* ensure we get enough */ - lhz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of cache line size */ + lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of cache line size */ srw. r8,r8,r9 /* compute line count */ beqlr /* nothing to do? */ mtctr r8 @@ -186,12 +188,12 @@ /* Now invalidate the instruction cache */ - lhz r7,ICACHEL1LINESIZE(r10) /* Get Icache line size */ + lwz r7,ICACHEL1LINESIZE(r11) /* Get Icache line size */ addi r5,r7,-1 andc r6,r3,r5 /* round low to line bdy */ subf r8,r6,r4 /* compute length */ add r8,r8,r5 - lhz r9,ICACHEL1LOGLINESIZE(r10) /* Get log-2 of Icache line size */ + lwz r9,ICACHEL1LOGLINESIZE(r10) /* Get log-2 of Icache line size */ srw. r8,r8,r9 /* compute line count */ beqlr /* nothing to do? */ mtctr r8 @@ -217,12 +219,14 @@ */ LOADADDR(r10,naca) /* Get Naca address */ ld r10,0(r10) - lhz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */ + LOADADDR(r11,systemcfg) /* Get systemcfg address */ + ld r11,0(r11) + lwz r7,DCACHEL1LINESIZE(r11) /* Get dcache line size */ addi r5,r7,-1 andc r6,r3,r5 /* round low to line bdy */ subf r8,r6,r4 /* compute length */ add r8,r8,r5 /* ensure we get enough */ - lhz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */ + lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */ srw. r8,r8,r9 /* compute line count */ beqlr /* nothing to do? */ mtctr r8 @@ -249,9 +253,11 @@ /* Flush the dcache */ LOADADDR(r7,naca) ld r7,0(r7) + LOADADDR(r8,systemcfg) /* Get systemcfg address */ + ld r8,0(r8) clrrdi r3,r3,12 /* Page align */ - lhz r4,DCACHEL1LINESPERPAGE(r7) /* Get # dcache lines per page */ - lhz r5,DCACHEL1LINESIZE(r7) /* Get dcache line size */ + lwz r4,DCACHEL1LINESPERPAGE(r7) /* Get # dcache lines per page */ + lwz r5,DCACHEL1LINESIZE(r8) /* Get dcache line size */ mr r6,r3 mtctr r4 0: dcbst 0,r6 @@ -261,8 +267,8 @@ /* Now invalidate the icache */ - lhz r4,ICACHEL1LINESPERPAGE(r7) /* Get # icache lines per page */ - lhz r5,ICACHEL1LINESIZE(r7) /* Get icache line size */ + lwz r4,ICACHEL1LINESPERPAGE(r7) /* Get # icache lines per page */ + lwz r5,ICACHEL1LINESIZE(r8) /* Get icache line size */ mtctr r4 1: icbi 0,r3 add r3,r3,r5 @@ -574,7 +580,7 @@ .llong .sys32_ssetmask .llong .sys_setreuid /* 70 */ .llong .sys_setregid - .llong .sys_sigsuspend + .llong .sys32_sigsuspend .llong .compat_sys_sigpending .llong .sys32_sethostname .llong .compat_sys_setrlimit /* 75 */ @@ -737,7 +743,7 @@ .llong .sys_set_tid_address .llong .ppc32_fadvise64 .llong .sys_exit_group - .llong .ppc32_lookup_dcookie /* 245 */ + .llong .ppc32_lookup_dcookie /* 235 */ .llong .sys_epoll_create .llong .sys_epoll_ctl .llong .sys_epoll_wait @@ -812,13 +818,13 @@ .llong .sys_getppid .llong .sys_getpgrp /* 65 */ .llong .sys_setsid - .llong .sys_sigaction + .llong .sys_ni_syscall .llong .sys_sgetmask .llong .sys_ssetmask .llong .sys_setreuid /* 70 */ .llong .sys_setregid - .llong .sys_sigsuspend - .llong .sys_sigpending + .llong .sys_ni_syscall + .llong .sys_ni_syscall .llong .sys_sethostname .llong .sys_setrlimit /* 75 */ .llong .sys_ni_syscall /* old getrlimit syscall */ @@ -864,14 +870,14 @@ .llong .sys_sysinfo .llong .sys_ipc .llong .sys_fsync - .llong .ppc64_sigreturn + .llong .sys_ni_syscall .llong .sys_clone /* 120 */ .llong .sys_setdomainname .llong .ppc64_newuname .llong .sys_ni_syscall /* old modify_ldt syscall */ .llong .sys_adjtimex .llong .sys_mprotect /* 125 */ - .llong .sys_sigprocmask + .llong .sys_ni_syscall .llong .sys_ni_syscall /* old create_module syscall */ .llong .sys_init_module .llong .sys_delete_module diff -Nru a/arch/ppc64/kernel/module.c b/arch/ppc64/kernel/module.c --- a/arch/ppc64/kernel/module.c Sat May 24 12:48:32 2003 +++ b/arch/ppc64/kernel/module.c Sat May 24 12:48:32 2003 @@ -20,6 +20,8 @@ #include #include #include +#include +#include /* FIXME: We don't do .init separately. To do this, we'd need to have a separate r2 value in the init and core section, and stub between @@ -374,15 +376,15 @@ return 0; } -/* In arch/ppc64/mm/extable.c */ -extern void sort_ex_table(struct exception_table_entry *start, - struct exception_table_entry *finish); - int module_finalize(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, - struct module *me) + const Elf_Shdr *sechdrs, struct module *me) { - sort_ex_table(me->extable.entry, - me->extable.entry + me->extable.num_entries); + sort_ex_table((struct exception_table_entry *)me->extable, + (struct exception_table_entry *)me->extable + + me->num_exentries); return 0; +} + +void module_arch_cleanup(struct module *mod) +{ } diff -Nru a/arch/ppc64/kernel/open_pic.c b/arch/ppc64/kernel/open_pic.c --- a/arch/ppc64/kernel/open_pic.c Sat May 24 12:48:26 2003 +++ b/arch/ppc64/kernel/open_pic.c Sat May 24 12:48:26 2003 @@ -111,7 +111,6 @@ * data has probably been corrupted and we're going to panic or deadlock later * anyway --Troy */ -extern unsigned long* _get_SP(void); #define check_arg_irq(irq) \ if (irq < open_pic_irq_offset || irq >= (NumSources+open_pic_irq_offset)){ \ printk(KERN_ERR "open_pic.c:%d: illegal irq %d\n", __LINE__, irq); \ @@ -765,9 +764,11 @@ openpic_eoi(); } -static void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs) +static irqreturn_t openpic_ipi_action(int cpl, void *dev_id, + struct pt_regs *regs) { smp_message_recv(cpl-openpic_vec_ipi, regs); + return IRQ_HANDLED; } #endif /* CONFIG_SMP */ diff -Nru a/arch/ppc64/kernel/open_pic_defs.h b/arch/ppc64/kernel/open_pic_defs.h --- a/arch/ppc64/kernel/open_pic_defs.h Sat May 24 12:48:27 2003 +++ b/arch/ppc64/kernel/open_pic_defs.h Sat May 24 12:48:27 2003 @@ -298,7 +298,8 @@ #ifdef CONFIG_SMP /* Interprocessor Interrupts */ static void openpic_initipi(u_int ipi, u_int pri, u_int vector); -static void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs); +static irqreturn_t openpic_ipi_action(int cpl, void *dev_id, + struct pt_regs *regs); #endif /* Timer Interrupts */ diff -Nru a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c --- a/arch/ppc64/kernel/pSeries_lpar.c Sat May 24 12:48:33 2003 +++ b/arch/ppc64/kernel/pSeries_lpar.c Sat May 24 12:48:33 2003 @@ -110,29 +110,6 @@ lbuf[0], lbuf[1], &dummy, &dummy, &dummy); } -long plpar_eoi(unsigned long xirr) -{ - return plpar_hcall_norets(H_EOI, xirr); -} - -long plpar_cppr(unsigned long cppr) -{ - return plpar_hcall_norets(H_CPPR, cppr); -} - -long plpar_ipi(unsigned long servernum, - unsigned long mfrr) -{ - return plpar_hcall_norets(H_IPI, servernum, mfrr); -} - -long plpar_xirr(unsigned long *xirr_ret) -{ - unsigned long dummy; - return plpar_hcall(H_XIRR, 0, 0, 0, 0, - xirr_ret, &dummy, &dummy); -} - static void tce_build_pSeriesLP(struct TceTable *tbl, long tcenum, unsigned long uaddr, int direction ) { @@ -179,66 +156,6 @@ } } - -/* PowerPC Interrupts for lpar. */ -/* NOTE: this typedef is duplicated (for now) from xics.c! */ -typedef struct { - int (*xirr_info_get)(int cpu); - void (*xirr_info_set)(int cpu, int val); - void (*cppr_info)(int cpu, u8 val); - void (*qirr_info)(int cpu, u8 val); -} xics_ops; -static int pSeriesLP_xirr_info_get(int n_cpu) -{ - unsigned long lpar_rc; - unsigned long return_value; - - lpar_rc = plpar_xirr(&return_value); - if (lpar_rc != H_Success) { - panic(" bad return code xirr - rc = %lx \n", lpar_rc); - } - return ((int)(return_value)); -} - -static void pSeriesLP_xirr_info_set(int n_cpu, int value) -{ - unsigned long lpar_rc; - unsigned long val64 = value & 0xffffffff; - - lpar_rc = plpar_eoi(val64); - if (lpar_rc != H_Success) { - panic(" bad return code EOI - rc = %ld, value=%lx \n", lpar_rc, val64); - } -} - -static void pSeriesLP_cppr_info(int n_cpu, u8 value) -{ - unsigned long lpar_rc; - - lpar_rc = plpar_cppr(value); - if (lpar_rc != H_Success) { - panic(" bad return code cppr - rc = %lx \n", lpar_rc); - } -} - -static void pSeriesLP_qirr_info(int n_cpu , u8 value) -{ - unsigned long lpar_rc; - - lpar_rc = plpar_ipi(n_cpu, value); - if (lpar_rc != H_Success) { - panic(" bad return code qirr -ipi - rc = %lx \n", lpar_rc); - } -} - -xics_ops pSeriesLP_ops = { - pSeriesLP_xirr_info_get, - pSeriesLP_xirr_info_set, - pSeriesLP_cppr_info, - pSeriesLP_qirr_info -}; -/* end TAI-LPAR */ - int vtermno; /* virtual terminal# for udbg */ diff -Nru a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c --- a/arch/ppc64/kernel/pacaData.c Sat May 24 12:48:30 2003 +++ b/arch/ppc64/kernel/pacaData.c Sat May 24 12:48:30 2003 @@ -20,6 +20,7 @@ #include struct naca_struct *naca; +struct systemcfg *systemcfg; /* The Paca is an array with one entry per processor. Each contains an * ItLpPaca, which contains the information shared between the @@ -65,9 +66,9 @@ struct paca_struct paca[MAX_PACAS] __page_aligned = { #ifdef CONFIG_PPC_ISERIES - PACAINITDATA( 0, 1, &xItLpQueue, 0, 0xc000000000005000), + PACAINITDATA( 0, 1, &xItLpQueue, 0, STAB0_VIRT_ADDR), #else - PACAINITDATA( 0, 1, 0, 0x5000, 0xc000000000005000), + PACAINITDATA( 0, 1, 0, STAB0_PHYS_ADDR, STAB0_VIRT_ADDR), #endif PACAINITDATA( 1, 0, 0, 0, 0), PACAINITDATA( 2, 0, 0, 0, 0), diff -Nru a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c --- a/arch/ppc64/kernel/pci.c Sat May 24 12:48:31 2003 +++ b/arch/ppc64/kernel/pci.c Sat May 24 12:48:31 2003 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/ppc64/kernel/pci_dma.c b/arch/ppc64/kernel/pci_dma.c --- a/arch/ppc64/kernel/pci_dma.c Sat May 24 12:48:26 2003 +++ b/arch/ppc64/kernel/pci_dma.c Sat May 24 12:48:26 2003 @@ -134,7 +134,7 @@ dev = ppc64_isabridge_dev; if (!dev) return NULL; - if (naca->platform == PLATFORM_ISERIES_LPAR) { + if (systemcfg->platform == PLATFORM_ISERIES_LPAR) { return ISERIES_DEVNODE(dev)->DevTceTable; } else { return PCI_GET_DN(dev)->tce_table; @@ -723,8 +723,8 @@ */ busdn->bussubno = bus->number; create_pci_bus_tce_table((unsigned long)busdn); - } else - create_tce_tables_for_busesLP(&bus->children); + } + create_tce_tables_for_busesLP(&bus->children); } } @@ -732,7 +732,7 @@ struct pci_dev *dev; struct device_node *dn, *mydn; - if (naca->platform == PLATFORM_PSERIES_LPAR) { + if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { create_tce_tables_for_busesLP(&pci_root_buses); } else { @@ -773,7 +773,7 @@ /* - Tce Table Share between buses, */ /* - Tce Table per logical slot. */ /*****************************************************************/ - if(naca->platform == PLATFORM_ISERIES_LPAR) { + if(systemcfg->platform == PLATFORM_ISERIES_LPAR) { struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)token; getTceTableParmsiSeries(DevNode,newTceTable); @@ -797,7 +797,7 @@ dn = (struct device_node *)token; phb = dn->phb; - if (naca->platform == PLATFORM_PSERIES) + if (systemcfg->platform == PLATFORM_PSERIES) getTceTableParmsPSeries(phb, dn, newTceTable); else getTceTableParmsPSeriesLP(phb, dn, newTceTable); @@ -1135,7 +1135,8 @@ /* Client asked for way to much space. This is checked later anyway */ /* It is easier to debug here for the drivers than in the tce tables.*/ if(order >= NUM_TCE_LEVELS) { - printk("PCI_DMA: pci_unmap_single 0x%lx size to large: 0x%lx \n",dma_handle,size); + printk("PCI_DMA: pci_unmap_single 0x%lx size too" + " large: 0x%lx \n", (long)dma_handle, (long)size); return; } diff -Nru a/arch/ppc64/kernel/proc_ppc64.c b/arch/ppc64/kernel/proc_ppc64.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/proc_ppc64.c Sat May 24 12:48:34 2003 @@ -0,0 +1,177 @@ +/* + * arch/ppc64/kernel/proc_ppc64.c + * + * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* + * Change Activity: + * 2001 : mikec : Created + * 2001/06/05 : engebret : Software event count support. + * 2003/02/13 : bergner : Move PMC code to pmc.c + * End Change Activity + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +struct proc_ppc64_t proc_ppc64; + +void proc_ppc64_create_paca(int num); + +static loff_t page_map_seek( struct file *file, loff_t off, int whence); +static ssize_t page_map_read( struct file *file, char *buf, size_t nbytes, loff_t *ppos); +static int page_map_mmap( struct file *file, struct vm_area_struct *vma ); + +static struct file_operations page_map_fops = { + llseek: page_map_seek, + read: page_map_read, + mmap: page_map_mmap +}; + + +static int __init proc_ppc64_init(void) +{ + + printk(KERN_INFO "proc_ppc64: Creating /proc/ppc64/\n"); + + proc_ppc64.root = proc_mkdir("ppc64", 0); + if (!proc_ppc64.root) + return 0; + + proc_ppc64.naca = create_proc_entry("naca", S_IRUSR, proc_ppc64.root); + if ( proc_ppc64.naca ) { + proc_ppc64.naca->nlink = 1; + proc_ppc64.naca->data = naca; + proc_ppc64.naca->size = 4096; + proc_ppc64.naca->proc_fops = &page_map_fops; + } + + proc_ppc64.systemcfg = create_proc_entry("systemcfg", S_IFREG|S_IRUGO, proc_ppc64.root); + if ( proc_ppc64.systemcfg ) { + proc_ppc64.systemcfg->nlink = 1; + proc_ppc64.systemcfg->data = systemcfg; + proc_ppc64.systemcfg->size = 4096; + proc_ppc64.systemcfg->proc_fops = &page_map_fops; + } + + /* /proc/ppc64/paca/XX -- raw paca contents. Only readable to root */ + proc_ppc64.paca = proc_mkdir("paca", proc_ppc64.root); + if (proc_ppc64.paca) { + unsigned long i; + + for (i = 0; i < NR_CPUS; i++) { + if (!cpu_online(i)) + continue; + proc_ppc64_create_paca(i); + } + } + + /* Placeholder for rtas interfaces. */ + proc_ppc64.rtas = proc_mkdir("rtas", proc_ppc64.root); + + return 0; +} + + +/* + * NOTE: since paca data is always in flux the values will never be a consistant set. + * In theory it could be made consistent if we made the corresponding cpu + * copy the page for us (via an IPI). Probably not worth it. + * + */ +void proc_ppc64_create_paca(int num) +{ + struct proc_dir_entry *ent; + struct paca_struct *lpaca = paca + num; + char buf[16]; + + sprintf(buf, "%02x", num); + ent = create_proc_entry(buf, S_IRUSR, proc_ppc64.paca); + if ( ent ) { + ent->nlink = 1; + ent->data = lpaca; + ent->size = 4096; + ent->proc_fops = &page_map_fops; + } +} + + +static loff_t page_map_seek( struct file *file, loff_t off, int whence) +{ + loff_t new; + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + + switch(whence) { + case 0: + new = off; + break; + case 1: + new = file->f_pos + off; + break; + case 2: + new = dp->size + off; + break; + default: + return -EINVAL; + } + if ( new < 0 || new > dp->size ) + return -EINVAL; + return (file->f_pos = new); +} + +static ssize_t page_map_read( struct file *file, char *buf, size_t nbytes, loff_t *ppos) +{ + unsigned pos = *ppos; + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + + if ( pos >= dp->size ) + return 0; + if ( nbytes >= dp->size ) + nbytes = dp->size; + if ( pos + nbytes > dp->size ) + nbytes = dp->size - pos; + + copy_to_user( buf, (char *)dp->data + pos, nbytes ); + *ppos = pos + nbytes; + return nbytes; +} + +static int page_map_mmap( struct file *file, struct vm_area_struct *vma ) +{ + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + + vma->vm_flags |= VM_SHM | VM_LOCKED; + + if ((vma->vm_end - vma->vm_start) > dp->size) + return -EINVAL; + + remap_page_range( vma, vma->vm_start, __pa(dp->data), dp->size, vma->vm_page_prot ); + return 0; +} + +fs_initcall(proc_ppc64_init); + diff -Nru a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c --- a/arch/ppc64/kernel/process.c Sat May 24 12:48:26 2003 +++ b/arch/ppc64/kernel/process.c Sat May 24 12:48:26 2003 @@ -300,7 +300,6 @@ unsigned long p4, unsigned long p5, unsigned long p6, struct pt_regs *regs) { - struct task_struct *p; unsigned long parent_tidptr = 0; unsigned long child_tidptr = 0; @@ -320,36 +319,29 @@ if (regs->msr & MSR_FP) giveup_fpu(current); - p = do_fork(clone_flags & ~CLONE_IDLETASK, p2, regs, 0, + return do_fork(clone_flags & ~CLONE_IDLETASK, p2, regs, 0, (int *)parent_tidptr, (int *)child_tidptr); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; } int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3, unsigned long p4, unsigned long p5, unsigned long p6, struct pt_regs *regs) { - struct task_struct *p; - if (regs->msr & MSR_FP) giveup_fpu(current); - p = do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); } int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3, unsigned long p4, unsigned long p5, unsigned long p6, struct pt_regs *regs) { - struct task_struct *p; - if (regs->msr & MSR_FP) giveup_fpu(current); - p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0, + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; } int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, @@ -532,8 +524,6 @@ name_buf, 256)); } while (count++ < 32); } - -extern unsigned long *_get_SP(void); void dump_stack(void) { diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c --- a/arch/ppc64/kernel/prom.c Sat May 24 12:48:29 2003 +++ b/arch/ppc64/kernel/prom.c Sat May 24 12:48:29 2003 @@ -118,7 +118,6 @@ #define FB_MAX 8 #endif -static int ppc64_is_smp; struct prom_t prom = { 0, /* entry */ @@ -301,7 +300,9 @@ unsigned long offset = reloc_offset(); struct prom_t *_prom = PTRRELOC(&prom); struct naca_struct *_naca = RELOC(naca); + struct systemcfg *_systemcfg = RELOC(systemcfg); + /* NOTE: _naca->debug_switch is already initialized. */ #ifdef DEBUG_PROM prom_print(RELOC("prom_initialize_naca: start...\n")); #endif @@ -320,25 +321,35 @@ * d-cache and i-cache sizes... -Peter */ if ( num_cpus == 1 ) { - u32 size; + u32 size, lsize; call_prom(RELOC("getprop"), 4, 1, node, - RELOC("d-cache-line-size"), + RELOC("d-cache-size"), &size, sizeof(size)); - _naca->dCacheL1LineSize = size; - _naca->dCacheL1LogLineSize = __ilog2(size); - _naca->dCacheL1LinesPerPage = PAGE_SIZE / size; + call_prom(RELOC("getprop"), 4, 1, node, + RELOC("d-cache-line-size"), + &lsize, sizeof(lsize)); + + _systemcfg->dCacheL1Size = size; + _systemcfg->dCacheL1LineSize = lsize; + _naca->dCacheL1LogLineSize = __ilog2(lsize); + _naca->dCacheL1LinesPerPage = PAGE_SIZE/lsize; call_prom(RELOC("getprop"), 4, 1, node, - RELOC("i-cache-line-size"), + RELOC("i-cache-size"), &size, sizeof(size)); - _naca->iCacheL1LineSize = size; - _naca->iCacheL1LogLineSize = __ilog2(size); - _naca->iCacheL1LinesPerPage = PAGE_SIZE / size; + call_prom(RELOC("getprop"), 4, 1, node, + RELOC("i-cache-line-size"), + &lsize, sizeof(lsize)); - if (_naca->platform == PLATFORM_PSERIES_LPAR) { + _systemcfg->iCacheL1Size = size; + _systemcfg->iCacheL1LineSize = lsize; + _naca->iCacheL1LogLineSize = __ilog2(lsize); + _naca->iCacheL1LinesPerPage = PAGE_SIZE/lsize; + + if (_systemcfg->platform == PLATFORM_PSERIES_LPAR) { u32 pft_size[2]; call_prom(RELOC("getprop"), 4, 1, node, RELOC("ibm,pft-size"), @@ -408,20 +419,17 @@ } /* We gotta have at least 1 cpu... */ - if (num_cpus < 1) + if ( (_systemcfg->processorCount = num_cpus) < 1 ) PROM_BUG(); - if (num_cpus > 1) - RELOC(ppc64_is_smp) = 1; - - _naca->physicalMemorySize = lmb_phys_mem_size(); + _systemcfg->physicalMemorySize = lmb_phys_mem_size(); - if (_naca->platform == PLATFORM_PSERIES) { + if (_systemcfg->platform == PLATFORM_PSERIES) { unsigned long rnd_mem_size, pteg_count; /* round mem_size up to next power of 2 */ - rnd_mem_size = 1UL << __ilog2(_naca->physicalMemorySize); - if (rnd_mem_size < _naca->physicalMemorySize) + rnd_mem_size = 1UL << __ilog2(_systemcfg->physicalMemorySize); + if (rnd_mem_size < _systemcfg->physicalMemorySize) rnd_mem_size <<= 1; /* # pages / 2 */ @@ -442,49 +450,43 @@ */ _naca->slb_size = 64; -#ifdef DEBUG_PROM - prom_print(RELOC("naca->physicalMemorySize = 0x")); - prom_print_hex(_naca->physicalMemorySize); - prom_print_nl(); - - prom_print(RELOC("naca->pftSize = 0x")); - prom_print_hex(_naca->pftSize); - prom_print_nl(); - - prom_print(RELOC("naca->dCacheL1LineSize = 0x")); - prom_print_hex(_naca->dCacheL1LineSize); - prom_print_nl(); + /* Add an eye catcher and the systemcfg layout version number */ + strcpy(_systemcfg->eye_catcher, RELOC("SYSTEMCFG:PPC64")); + _systemcfg->version.major = SYSTEMCFG_MAJOR; + _systemcfg->version.minor = SYSTEMCFG_MINOR; + _systemcfg->processor = _get_PVR(); - prom_print(RELOC("naca->dCacheL1LogLineSize = 0x")); - prom_print_hex(_naca->dCacheL1LogLineSize); +#ifdef DEBUG_PROM + prom_print(RELOC("systemcfg->processorCount = 0x")); + prom_print_hex(_systemcfg->processorCount); prom_print_nl(); - prom_print(RELOC("naca->dCacheL1LinesPerPage = 0x")); - prom_print_hex(_naca->dCacheL1LinesPerPage); + prom_print(RELOC("systemcfg->physicalMemorySize = 0x")); + prom_print_hex(_systemcfg->physicalMemorySize); prom_print_nl(); - prom_print(RELOC("naca->iCacheL1LineSize = 0x")); - prom_print_hex(_naca->iCacheL1LineSize); + prom_print(RELOC("naca->pftSize = 0x")); + prom_print_hex(_naca->pftSize); prom_print_nl(); - prom_print(RELOC("naca->iCacheL1LogLineSize = 0x")); - prom_print_hex(_naca->iCacheL1LogLineSize); + prom_print(RELOC("systemcfg->dCacheL1LineSize = 0x")); + prom_print_hex(_systemcfg->dCacheL1LineSize); prom_print_nl(); - prom_print(RELOC("naca->iCacheL1LinesPerPage = 0x")); - prom_print_hex(_naca->iCacheL1LinesPerPage); + prom_print(RELOC("systemcfg->iCacheL1LineSize = 0x")); + prom_print_hex(_systemcfg->iCacheL1LineSize); prom_print_nl(); - prom_print(RELOC("naca->serialPortAddr = 0x")); + prom_print(RELOC("naca->serialPortAddr = 0x")); prom_print_hex(_naca->serialPortAddr); prom_print_nl(); - prom_print(RELOC("naca->interrupt_controller = 0x")); + prom_print(RELOC("naca->interrupt_controller = 0x")); prom_print_hex(_naca->interrupt_controller); prom_print_nl(); - prom_print(RELOC("naca->platform = 0x")); - prom_print_hex(_naca->platform); + prom_print(RELOC("systemcfg->platform = 0x")); + prom_print_hex(_systemcfg->platform); prom_print_nl(); prom_print(RELOC("prom_initialize_naca: end...\n")); @@ -549,7 +551,7 @@ unsigned long offset = reloc_offset(); struct prom_t *_prom = PTRRELOC(&prom); struct rtas_t *_rtas = PTRRELOC(&rtas); - struct naca_struct *_naca = RELOC(naca); + struct systemcfg *_systemcfg = RELOC(systemcfg); ihandle prom_rtas; u32 getprop_rval; @@ -565,7 +567,7 @@ RELOC("ibm,hypertas-functions"), hypertas_funcs, sizeof(hypertas_funcs))) > 0) { - _naca->platform = PLATFORM_PSERIES_LPAR; + _systemcfg->platform = PLATFORM_PSERIES_LPAR; } call_prom(RELOC("getprop"), @@ -582,7 +584,7 @@ * of physical memory (or within the RMO region) because RTAS * runs in 32-bit mode and relocate off. */ - if ( _naca->platform == PLATFORM_PSERIES_LPAR ) { + if ( _systemcfg->platform == PLATFORM_PSERIES_LPAR ) { struct lmb *_lmb = PTRRELOC(&lmb); rtas_region = min(_lmb->rmo_size, RTAS_INSTANTIATE_MAX); } @@ -767,13 +769,21 @@ * By doing this, we avoid the pitfalls of trying to DMA to * MMIO space and the DMA alias hole. */ - minsize = 4UL << 20; + /* + * On POWER4, firmware sets the TCE region by assuming + * each TCE table is 8MB. Using this memory for anything + * else will impact performance, so we always allocate 8MB. + * Anton + * + * XXX FIXME use a cpu feature here + */ + minsize = 8UL << 20; /* Align to the greater of the align or size */ - align = (minalign < minsize) ? minsize : minalign; + align = max(minalign, minsize); /* Carve out storage for the TCE table. */ - base = lmb_alloc(8UL << 20, 8UL << 20); + base = lmb_alloc(minsize, align); if ( !base ) { prom_print(RELOC("ERROR, cannot find space for TCE table.\n")); @@ -875,7 +885,7 @@ prom_hold_cpus(unsigned long mem) { unsigned long i; - unsigned int reg; + unsigned int cpuid; phandle node; unsigned long offset = reloc_offset(); char type[64], *path; @@ -885,9 +895,13 @@ unsigned long *spinloop = __v2a(&__secondary_hold_spinloop); unsigned long *acknowledge = __v2a(&__secondary_hold_acknowledge); unsigned long secondary_hold = (unsigned long)__v2a(*PTRRELOC((unsigned long *)__secondary_hold)); + struct systemcfg *_systemcfg = RELOC(systemcfg); struct paca_struct *_xPaca = PTRRELOC(&paca[0]); struct prom_t *_prom = PTRRELOC(&prom); + /* Initially, we must have one active CPU. */ + _systemcfg->processorCount = 1; + #ifdef DEBUG_PROM prom_print(RELOC("prom_hold_cpus: start...\n")); prom_print(RELOC(" 1) spinloop = 0x")); @@ -933,12 +947,12 @@ if (strcmp(type, RELOC("okay")) != 0) continue; - reg = -1; + cpuid = -1; call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"), - ®, sizeof(reg)); + &cpuid, sizeof(cpuid)); /* Only need to start secondary procs, not ourself. */ - if ( reg == _prom->cpu ) + if ( cpuid == _prom->cpu ) continue; path = (char *) mem; @@ -950,7 +964,7 @@ #ifdef DEBUG_PROM prom_print_nl(); prom_print(RELOC("cpu hw idx = 0x")); - prom_print_hex(reg); + prom_print_hex(cpuid); prom_print_nl(); #endif prom_print(RELOC("starting cpu ")); @@ -978,9 +992,8 @@ prom_print(RELOC(" 3) secondary_hold = 0x")); prom_print_hex(secondary_hold); prom_print_nl(); - prom_print_nl(); #endif - call_prom(RELOC("start-cpu"), 3, 0, node, secondary_hold, reg); + call_prom(RELOC("start-cpu"), 3, 0, node, secondary_hold, cpuid); prom_print(RELOC("...")); for ( i = 0 ; (i < 100000000) && (*acknowledge == ((unsigned long)-1)); i++ ) ; @@ -992,10 +1005,11 @@ prom_print_nl(); } #endif - if (*acknowledge == reg) { + if (*acknowledge == cpuid) { prom_print(RELOC("ok\n")); /* Set the number of active processors. */ - _xPaca[reg].active = 1; + _systemcfg->processorCount++; + _xPaca[cpuid].active = 1; } else { prom_print(RELOC("failed: ")); prom_print_hex(*acknowledge); @@ -1024,8 +1038,8 @@ } } _xPaca[i+1].active = 1; - RELOC(hmt_thread_data)[i].threadid = i+1; } + _systemcfg->processorCount *= 2; } else { prom_print(RELOC("Processor is not HMT capable\n")); } @@ -1046,20 +1060,21 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp, unsigned long r6, unsigned long r7) { + int chrp = 0; unsigned long mem; - ihandle prom_root, prom_cpu; + ihandle prom_mmu, prom_op, prom_root, prom_cpu; phandle cpu_pkg; unsigned long offset = reloc_offset(); - long l; + long l, sz; char *p, *d; unsigned long phys; u32 getprop_rval; - struct naca_struct *_naca = RELOC(naca); + struct systemcfg *_systemcfg = RELOC(systemcfg); struct paca_struct *_xPaca = PTRRELOC(&paca[0]); struct prom_t *_prom = PTRRELOC(&prom); /* Default machine type. */ - _naca->platform = PLATFORM_PSERIES; + _systemcfg->platform = PLATFORM_PSERIES; #if 0 /* Reset klimit to take into account the embedded system map */ @@ -1149,6 +1164,8 @@ mem = prom_bi_rec_reserve(mem); + mem = check_display(mem); + prom_instantiate_rtas(); /* Initialize some system info into the Naca early... */ @@ -1158,11 +1175,9 @@ * following, regardless of whether we have an SMP * kernel or not. */ - if (RELOC(ppc64_is_smp)) + if (_systemcfg->processorCount > 1) prom_hold_cpus(mem); - mem = check_display(mem); - #ifdef DEBUG_PROM prom_print(RELOC("copying OF device tree...\n")); #endif @@ -1172,7 +1187,7 @@ lmb_reserve(0, __pa(RELOC(klimit))); - if (_naca->platform == PLATFORM_PSERIES) + if (_systemcfg->platform == PLATFORM_PSERIES) prom_initialize_tce_table(); prom_print(RELOC("Calling quiesce ...\n")); diff -Nru a/arch/ppc64/kernel/ras.c b/arch/ppc64/kernel/ras.c --- a/arch/ppc64/kernel/ras.c Sat May 24 12:48:22 2003 +++ b/arch/ppc64/kernel/ras.c Sat May 24 12:48:22 2003 @@ -54,8 +54,10 @@ #include #include -static void ras_epow_interrupt(int irq, void *dev_id, struct pt_regs * regs); -static void ras_error_interrupt(int irq, void *dev_id, struct pt_regs * regs); +static irqreturn_t ras_epow_interrupt(int irq, void *dev_id, + struct pt_regs * regs); +static irqreturn_t ras_error_interrupt(int irq, void *dev_id, + struct pt_regs * regs); void init_ras_IRQ(void); /* #define DEBUG */ @@ -73,7 +75,7 @@ &len))) { for(i=0; i<(len / sizeof(*ireg)); i++) { request_irq(virt_irq_create_mapping(*(ireg)) + NUM_8259_INTERRUPTS, - &ras_error_interrupt, 0, + ras_error_interrupt, 0, "RAS_ERROR", NULL); ireg++; } @@ -84,7 +86,7 @@ &len))) { for(i=0; i<(len / sizeof(*ireg)); i++) { request_irq(virt_irq_create_mapping(*(ireg)) + NUM_8259_INTERRUPTS, - &ras_epow_interrupt, 0, + ras_epow_interrupt, 0, "RAS_EPOW", NULL); ireg++; } @@ -98,7 +100,7 @@ * to examine the type of power failure and take appropriate action where * the time horizon permits something useful to be done. */ -static void +static irqreturn_t ras_epow_interrupt(int irq, void *dev_id, struct pt_regs * regs) { struct rtas_error_log log_entry; @@ -114,7 +116,8 @@ udbg_printf("EPOW <0x%lx 0x%lx>\n", *((unsigned long *)&log_entry), status); printk(KERN_WARNING - "EPOW <0x%lx 0x%lx>\n",*((unsigned long *)&log_entry), status); + "EPOW <0x%lx 0x%lx>\n",*((unsigned long *)&log_entry), status); + return IRQ_HANDLED; } /* @@ -125,7 +128,7 @@ * For nonrecoverable errors, an error is logged and we stop all processing * as quickly as possible in order to prevent propagation of the failure. */ -static void +static irqreturn_t ras_error_interrupt(int irq, void *dev_id, struct pt_regs * regs) { struct rtas_error_log log_entry; @@ -158,7 +161,6 @@ printk(KERN_WARNING "Warning: Recoverable hardware error <0x%lx 0x%lx>\n", *((unsigned long *)&log_entry), status); - - return; } + return IRQ_HANDLED; } diff -Nru a/arch/ppc64/kernel/rtas-proc.c b/arch/ppc64/kernel/rtas-proc.c --- a/arch/ppc64/kernel/rtas-proc.c Sat May 24 12:48:24 2003 +++ b/arch/ppc64/kernel/rtas-proc.c Sat May 24 12:48:24 2003 @@ -201,7 +201,7 @@ struct proc_dir_entry *entry; rtas_node = find_devices("rtas"); - if ((rtas_node == NULL) || (naca->platform == PLATFORM_ISERIES_LPAR)) { + if ((rtas_node == NULL) || (systemcfg->platform == PLATFORM_ISERIES_LPAR)) { return; } @@ -506,21 +506,27 @@ int error, char * buf) { /* Defined return vales */ - const char * key_switch[] = { "Off\t", "Normal\t", "Secure\t", "Mainenance" }; + const char * key_switch[] = { "Off\t", "Normal\t", "Secure\t", + "Maintenance" }; const char * enclosure_switch[] = { "Closed", "Open" }; const char * lid_status[] = { " ", "Open", "Closed" }; - const char * power_source[] = { "AC\t", "Battery", "AC & Battery" }; + const char * power_source[] = { "AC\t", "Battery", + "AC & Battery" }; const char * battery_remaining[] = { "Very Low", "Low", "Mid", "High" }; const char * epow_sensor[] = { "EPOW Reset", "Cooling warning", "Power warning", "System shutdown", "System halt", "EPOW main enclosure", "EPOW power off" }; - const char * battery_cyclestate[] = { "None", "In progress", "Requested" }; - const char * battery_charging[] = { "Charging", "Discharching", "No current flow" }; - const char * ibm_drconnector[] = { "Empty", "Present" }; + const char * battery_cyclestate[] = { "None", "In progress", + "Requested" }; + const char * battery_charging[] = { "Charging", "Discharching", + "No current flow" }; + const char * ibm_drconnector[] = { "Empty", "Present", "Unusable", + "Exchange" }; const char * ibm_intqueue[] = { "Disabled", "Enabled" }; int have_strings = 0; + int num_states = 0; int temperature = 0; int unknown = 0; int n = 0; @@ -530,13 +536,20 @@ switch (s.token) { case KEY_SWITCH: n += sprintf(buf+n, "Key switch:\t"); - n += sprintf(buf+n, "%s\t", key_switch[state]); - have_strings = 1; + num_states = sizeof(key_switch) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", key_switch[state]); + have_strings = 1; + } break; case ENCLOSURE_SWITCH: n += sprintf(buf+n, "Enclosure switch:\t"); - n += sprintf(buf+n, "%s\t", enclosure_switch[state]); - have_strings = 1; + num_states = sizeof(enclosure_switch) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", + enclosure_switch[state]); + have_strings = 1; + } break; case THERMAL_SENSOR: n += sprintf(buf+n, "Temp. (°C/°F):\t"); @@ -544,39 +557,63 @@ break; case LID_STATUS: n += sprintf(buf+n, "Lid status:\t"); - n += sprintf(buf+n, "%s\t", lid_status[state]); - have_strings = 1; + num_states = sizeof(lid_status) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", lid_status[state]); + have_strings = 1; + } break; case POWER_SOURCE: n += sprintf(buf+n, "Power source:\t"); - n += sprintf(buf+n, "%s\t", power_source[state]); - have_strings = 1; + num_states = sizeof(power_source) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", + power_source[state]); + have_strings = 1; + } break; case BATTERY_VOLTAGE: n += sprintf(buf+n, "Battery voltage:\t"); break; case BATTERY_REMAINING: n += sprintf(buf+n, "Battery remaining:\t"); - n += sprintf(buf+n, "%s\t", battery_remaining[state]); - have_strings = 1; + num_states = sizeof(battery_remaining) / sizeof(char *); + if (state < num_states) + { + n += sprintf(buf+n, "%s\t", + battery_remaining[state]); + have_strings = 1; + } break; case BATTERY_PERCENTAGE: n += sprintf(buf+n, "Battery percentage:\t"); break; case EPOW_SENSOR: n += sprintf(buf+n, "EPOW Sensor:\t"); - n += sprintf(buf+n, "%s\t", epow_sensor[state]); - have_strings = 1; + num_states = sizeof(epow_sensor) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", epow_sensor[state]); + have_strings = 1; + } break; case BATTERY_CYCLESTATE: n += sprintf(buf+n, "Battery cyclestate:\t"); - n += sprintf(buf+n, "%s\t", battery_cyclestate[state]); - have_strings = 1; + num_states = sizeof(battery_cyclestate) / + sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", + battery_cyclestate[state]); + have_strings = 1; + } break; case BATTERY_CHARGING: n += sprintf(buf+n, "Battery Charging:\t"); - n += sprintf(buf+n, "%s\t", battery_charging[state]); - have_strings = 1; + num_states = sizeof(battery_charging) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", + battery_charging[state]); + have_strings = 1; + } break; case IBM_SURVEILLANCE: n += sprintf(buf+n, "Surveillance:\t"); @@ -589,16 +626,24 @@ break; case IBM_DRCONNECTOR: n += sprintf(buf+n, "DR connector:\t"); - n += sprintf(buf+n, "%s\t", ibm_drconnector[state]); - have_strings = 1; + num_states = sizeof(ibm_drconnector) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", + ibm_drconnector[state]); + have_strings = 1; + } break; case IBM_POWERSUPPLY: n += sprintf(buf+n, "Powersupply:\t"); break; case IBM_INTQUEUE: n += sprintf(buf+n, "Interrupt queue:\t"); - n += sprintf(buf+n, "%s\t", ibm_intqueue[state]); - have_strings = 1; + num_states = sizeof(ibm_intqueue) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", + ibm_intqueue[state]); + have_strings = 1; + } break; default: n += sprintf(buf+n, "Unkown sensor (type %d), ignoring it\n", diff -Nru a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c --- a/arch/ppc64/kernel/rtas.c Sat May 24 12:48:21 2003 +++ b/arch/ppc64/kernel/rtas.c Sat May 24 12:48:21 2003 @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -27,7 +28,6 @@ #include #include -struct proc_dir_entry *rtas_proc_dir; /* /proc/ppc64/rtas dir */ struct flash_block_list_header rtas_firmware_flash_list = {0, 0}; /* @@ -216,7 +216,11 @@ image_size += f->blocks[i].length; } next = f->next; - f->next = (struct flash_block_list *)virt_to_absolute((unsigned long)f->next); + /* Don't translate NULL pointer for last entry */ + if(f->next) + f->next = (struct flash_block_list *)virt_to_absolute((unsigned long)f->next); + else + f->next = 0LL; /* make num_blocks into the version/length field */ f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16); } @@ -283,7 +287,7 @@ rtas_power_off(); } -EXPORT_SYMBOL(rtas_proc_dir); +EXPORT_SYMBOL(proc_ppc64); EXPORT_SYMBOL(rtas_firmware_flash_list); EXPORT_SYMBOL(rtas_token); EXPORT_SYMBOL(rtas_call); diff -Nru a/arch/ppc64/kernel/rtas_flash.c b/arch/ppc64/kernel/rtas_flash.c --- a/arch/ppc64/kernel/rtas_flash.c Sat May 24 12:48:32 2003 +++ b/arch/ppc64/kernel/rtas_flash.c Sat May 24 12:48:32 2003 @@ -210,7 +210,7 @@ { struct proc_dir_entry *ent = NULL; - if (!rtas_proc_dir) { + if (!proc_ppc64.rtas) { printk(KERN_WARNING "rtas proc dir does not already exist"); return -ENOENT; } @@ -218,7 +218,7 @@ if (rtas_token("ibm,update-flash-64-and-reboot") != RTAS_UNKNOWN_SERVICE) flash_possible = 1; - if ((ent = create_proc_entry(FIRMWARE_FLASH_NAME, S_IRUSR | S_IWUSR, rtas_proc_dir)) != NULL) { + if ((ent = create_proc_entry(FIRMWARE_FLASH_NAME, S_IRUSR | S_IWUSR, proc_ppc64.rtas)) != NULL) { ent->nlink = 1; ent->proc_fops = &rtas_flash_operations; ent->owner = THIS_MODULE; @@ -228,9 +228,9 @@ void __exit rtas_flash_cleanup(void) { - if (!rtas_proc_dir) + if (!proc_ppc64.rtas) return; - remove_proc_entry(FIRMWARE_FLASH_NAME, rtas_proc_dir); + remove_proc_entry(FIRMWARE_FLASH_NAME, proc_ppc64.rtas); } module_init(rtas_flash_init); diff -Nru a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c --- a/arch/ppc64/kernel/setup.c Sat May 24 12:48:24 2003 +++ b/arch/ppc64/kernel/setup.c Sat May 24 12:48:24 2003 @@ -142,9 +142,6 @@ void setup_system(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { - /* This should be fixed properly in kernel/resource.c */ - iomem_resource.end = MEM_SPACE_LIMIT; - #ifdef CONFIG_XMON_DEFAULT debugger = xmon; debugger_bpt = xmon_bpt; @@ -156,10 +153,10 @@ #ifdef CONFIG_PPC_ISERIES /* pSeries systems are identified in prom.c via OF. */ if ( itLpNaca.xLparInstalled == 1 ) - naca->platform = PLATFORM_ISERIES_LPAR; + systemcfg->platform = PLATFORM_ISERIES_LPAR; #endif - switch (naca->platform) { + switch (systemcfg->platform) { #ifdef CONFIG_PPC_ISERIES case PLATFORM_ISERIES_LPAR: iSeries_init_early(); @@ -185,7 +182,7 @@ #endif } - if (naca->platform & PLATFORM_PSERIES) { + if (systemcfg->platform & PLATFORM_PSERIES) { early_console_initialized = 1; register_console(&udbg_console); } @@ -193,32 +190,27 @@ printk("Starting Linux PPC64 %s\n", UTS_RELEASE); printk("-----------------------------------------------------\n"); - printk("naca = 0x%p\n", naca); -#if 0 - printk("naca->processorCount = 0x%x\n", naca->processorCount); -#endif - printk("naca->physicalMemorySize = 0x%lx\n", naca->physicalMemorySize); - printk("naca->dCacheL1LineSize = 0x%x\n", naca->dCacheL1LineSize); - printk("naca->dCacheL1LogLineSize = 0x%x\n", naca->dCacheL1LogLineSize); - printk("naca->dCacheL1LinesPerPage = 0x%x\n", naca->dCacheL1LinesPerPage); - printk("naca->iCacheL1LineSize = 0x%x\n", naca->iCacheL1LineSize); - printk("naca->iCacheL1LogLineSize = 0x%x\n", naca->iCacheL1LogLineSize); - printk("naca->iCacheL1LinesPerPage = 0x%x\n", naca->iCacheL1LinesPerPage); - printk("naca->pftSize = 0x%lx\n", naca->pftSize); - printk("naca->debug_switch = 0x%lx\n", naca->debug_switch); - printk("naca->interrupt_controller = 0x%d\n", naca->interrupt_controller); - printk("htab_data.htab = 0x%p\n", htab_data.htab); - printk("htab_data.num_ptegs = 0x%lx\n", htab_data.htab_num_ptegs); + printk("naca = 0x%p\n", naca); + printk("naca->pftSize = 0x%lx\n", naca->pftSize); + printk("naca->debug_switch = 0x%lx\n", naca->debug_switch); + printk("naca->interrupt_controller = 0x%d\n", naca->interrupt_controller); + printk("systemcf = 0x%p\n", systemcfg); + printk("systemcfg->processorCount = 0x%x\n", systemcfg->processorCount); + printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize); + printk("systemcfg->dCacheL1LineSize = 0x%x\n", systemcfg->dCacheL1LineSize); + printk("systemcfg->iCacheL1LineSize = 0x%x\n", systemcfg->iCacheL1LineSize); + printk("htab_data.htab = 0x%p\n", htab_data.htab); + printk("htab_data.num_ptegs = 0x%lx\n", htab_data.htab_num_ptegs); printk("-----------------------------------------------------\n"); - if (naca->platform & PLATFORM_PSERIES) { + if (systemcfg->platform & PLATFORM_PSERIES) { finish_device_tree(); chrp_init(r3, r4, r5, r6, r7); } mm_init_ppc64(); - switch (naca->platform) { + switch (systemcfg->platform) { #ifdef CONFIG_PPC_ISERIES case PLATFORM_ISERIES_LPAR: iSeries_init(); @@ -312,7 +304,7 @@ * Assume here that all clock rates are the same in a * smp system. -- Cort */ - if (naca->platform != PLATFORM_ISERIES_LPAR) { + if (systemcfg->platform != PLATFORM_ISERIES_LPAR) { struct device_node *cpu_node; int *fp; @@ -516,8 +508,8 @@ * Systems with OF can look in the properties on the cpu node(s) * for a possibly more accurate value. */ - dcache_bsize = naca->dCacheL1LineSize; - icache_bsize = naca->iCacheL1LineSize; + dcache_bsize = systemcfg->dCacheL1LineSize; + icache_bsize = systemcfg->iCacheL1LineSize; /* reboot on panic */ panic_timeout = 180; diff -Nru a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c --- a/arch/ppc64/kernel/signal.c Sat May 24 12:48:19 2003 +++ b/arch/ppc64/kernel/signal.c Sat May 24 12:48:19 2003 @@ -43,57 +43,29 @@ #endif #define GP_REGS_SIZE MIN(sizeof(elf_gregset_t), sizeof(struct pt_regs)) +#define FP_REGS_SIZE sizeof(elf_fpregset_t) -/* - * These are the flags in the MSR that the user is allowed to change - * by modifying the saved value of the MSR on the stack. SE and BE - * should not be in this list since gdb may want to change these. I.e, - * you should be able to step out of a signal handler to see what - * instruction executes next after the signal handler completes. - * Alternately, if you stepped into a signal handler, you should be - * able to continue 'til the next breakpoint from within the signal - * handler, even if the handler returns. - */ -#if 0 -#define MSR_USERCHANGE (MSR_FE0 | MSR_FE1) -#else -/* - * glibc tries to set FE0/FE1 via a signal handler. Since it only ever - * sets both bits and this is the default setting we now disable this - * behaviour. This is done to insure the new prctl which alters FE0/FE1 does - * not get overriden by glibc. Setting and clearing FE0/FE1 via signal - * handler has always been bogus since load_up_fpu used to set FE0/FE1 - * unconditionally. - */ -#define MSR_USERCHANGE 0 -#endif +#define TRAMP_TRACEBACK 3 +#define TRAMP_SIZE 6 /* - * When we have signals to deliver, we set up on the - * user stack, going down from the original stack pointer: - * a sigregs struct - * one or more sigcontext structs with - * a gap of __SIGNAL_FRAMESIZE bytes - * - * Each of these things must be a multiple of 16 bytes in size. - * + * When we have signals to deliver, we set up on the user stack, + * going down from the original stack pointer: + * 1) a rt_sigframe struct which contains the ucontext + * 2) a gap of __SIGNAL_FRAMESIZE bytes which acts as a dummy caller + * frame for the signal handler. */ -struct sigregs { - elf_gregset_t gp_regs; - double fp_regs[ELF_NFPREG]; - unsigned int tramp[2]; - /* 64 bit API allows for 288 bytes below sp before - decrementing it. */ - int abigap[72]; -}; -struct rt_sigframe -{ - unsigned long _unused[2]; +struct rt_sigframe { + /* sys_rt_sigreturn requires the ucontext be the first field */ + struct ucontext uc; + unsigned long _unused[2]; + unsigned int tramp[TRAMP_SIZE]; struct siginfo *pinfo; void *puc; struct siginfo info; - struct ucontext uc; + /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */ + char abigap[288]; }; @@ -102,37 +74,6 @@ /* * Atomically swap in the new signal mask, and wait for a signal. */ -long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7, - struct pt_regs *regs) -{ - sigset_t saveset; - - mask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs->result = -EINTR; - regs->gpr[3] = EINTR; - regs->ccr |= 0x10000000; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(&saveset, regs)) - /* - * If a signal handler needs to be called, - * do_signal() has set R3 to the signal number (the - * first argument of the signal handler), so don't - * overwrite that with EINTR ! - * In the other cases, do_signal() doesn't touch - * R3, so it's still set to -EINTR (see above). - */ - return regs->gpr[3]; - } -} - long sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, int p3, int p4, int p6, int p7, struct pt_regs *regs) { @@ -170,339 +111,232 @@ return do_sigaltstack(uss, uoss, regs->gpr[1]); } -long sys_sigaction(int sig, const struct old_sigaction *act, - struct old_sigaction *oact) + +/* + * Set up the sigcontext for the signal frame. + */ + +static int +setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, + int signr, sigset_t *set, unsigned long handler) { - struct k_sigaction new_ka, old_ka; - int ret; + int err = 0; - if (act) { - old_sigset_t mask; + if (regs->msr & MSR_FP) + giveup_fpu(current); - if (verify_area(VERIFY_READ, act, sizeof(*act)) || - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) - return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); - siginitset(&new_ka.sa.sa_mask, mask); - } + current->thread.saved_msr = regs->msr & ~(MSR_FP | MSR_FE0 | MSR_FE1); + regs->msr = current->thread.saved_msr | current->thread.fpexc_mode; + current->thread.saved_softe = regs->softe; + + err |= __put_user(&sc->gp_regs, &sc->regs); + err |= __copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE); + err |= __copy_to_user(&sc->fp_regs, ¤t->thread.fpr, FP_REGS_SIZE); + err |= __put_user(signr, &sc->signal); + err |= __put_user(handler, &sc->handler); + if (set != NULL) + err |= __put_user(set->sig[0], &sc->oldmask); - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - if (!ret && oact) { - if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) - return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); - } + regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1); + current->thread.fpscr = 0; - return ret; + return err; } /* - * When we have rt signals to deliver, we set up on the - * user stack, going down from the original stack pointer: - * a sigregs struct - * one rt_sigframe struct (siginfo + ucontext) - * a gap of __SIGNAL_FRAMESIZE bytes - * - * Each of these things must be a multiple of 16 bytes in size. - * + * Restore the sigcontext from the signal frame. */ -int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, unsigned long r8, - struct pt_regs *regs) +static int +restore_sigcontext(struct pt_regs *regs, sigset_t *set, struct sigcontext *sc) { - struct rt_sigframe *rt_sf; - struct sigcontext sigctx; - struct sigregs *sr; - elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */ - sigset_t set; - stack_t st; + unsigned int err = 0; - rt_sf = (struct rt_sigframe *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); - if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx)) - || copy_from_user(&set, &rt_sf->uc.uc_sigmask, sizeof(set)) - || copy_from_user(&st, &rt_sf->uc.uc_stack, sizeof(st))) - goto badframe; - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); if (regs->msr & MSR_FP) giveup_fpu(current); - /* restore registers - - * sigctx is initialized to point to the - * preamble frame (where registers are stored) - * see handle_signal() - */ - sr = (struct sigregs *)sigctx.regs; - if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs))) - goto badframe; - saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) - | (saved_regs[PT_MSR] & MSR_USERCHANGE); - saved_regs[PT_SOFTE] = regs->softe; - memcpy(regs, saved_regs, GP_REGS_SIZE); - if (copy_from_user(current->thread.fpr, &sr->fp_regs, - sizeof(sr->fp_regs))) - goto badframe; - /* This function sets back the stack flags into - the current task structure. */ - sys_sigaltstack(&st, NULL, 0, 0, 0, 0, regs); + err |= __copy_from_user(regs, &sc->gp_regs, GP_REGS_SIZE); + err |= __copy_from_user(¤t->thread.fpr, &sc->fp_regs, FP_REGS_SIZE); + current->thread.fpexc_mode = regs->msr & (MSR_FE0 | MSR_FE1); + if (set != NULL) + err |= __get_user(set->sig[0], &sc->oldmask); + + /* Don't allow the signal handler to change these modulo FE{0,1} */ + regs->msr = current->thread.saved_msr & ~(MSR_FP | MSR_FE0 | MSR_FE1); + regs->softe = current->thread.saved_softe; - return regs->result; - -badframe: - do_exit(SIGSEGV); + return err; } -static void setup_rt_frame(struct pt_regs *regs, struct sigregs *frame, - signed long newsp) +/* + * Allocate space for the signal frame + */ +static inline void * +get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) { - struct rt_sigframe *rt_sf = (struct rt_sigframe *)newsp; - /* Handler is *really* a pointer to the function descriptor for - * the signal routine. The first entry in the function - * descriptor is the entry address of signal and the second - * entry is the TOC value we need to use. - */ - struct funct_descr_entry { - unsigned long entry; - unsigned long toc; - }; - - struct funct_descr_entry * funct_desc_ptr; - unsigned long temp_ptr; + unsigned long newsp; - /* Set up preamble frame */ - if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) - goto badframe; - if (regs->msr & MSR_FP) - giveup_fpu(current); - if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE) - || __copy_to_user(&frame->fp_regs, current->thread.fpr, - ELF_NFPREG * sizeof(double)) - /* li r0, __NR_rt_sigreturn */ - || __put_user(0x38000000UL + __NR_rt_sigreturn, &frame->tramp[0]) - /* sc */ - || __put_user(0x44000002UL, &frame->tramp[1])) - goto badframe; - flush_icache_range((unsigned long)&frame->tramp[0], - (unsigned long)&frame->tramp[2]); - current->thread.fpscr = 0; /* turn off all fp exceptions */ - - /* Retrieve rt_sigframe from stack and - set up registers for signal handler - */ - newsp -= __SIGNAL_FRAMESIZE; + /* Default to using normal stack */ + newsp = regs->gpr[1]; - if (get_user(temp_ptr, &rt_sf->uc.uc_mcontext.handler)) { - goto badframe; + if (ka->sa.sa_flags & SA_ONSTACK) { + if (! on_sig_stack(regs->gpr[1])) + newsp = (current->sas_ss_sp + current->sas_ss_size); } - funct_desc_ptr = (struct funct_descr_entry *)temp_ptr; - - if (put_user(regs->gpr[1], (unsigned long *)newsp) - || get_user(regs->nip, &funct_desc_ptr->entry) - || get_user(regs->gpr[2], &funct_desc_ptr->toc) - || get_user(regs->gpr[3], &rt_sf->uc.uc_mcontext.signal) - || get_user(regs->gpr[4], (unsigned long *)&rt_sf->pinfo) - || get_user(regs->gpr[5], (unsigned long *)&rt_sf->puc)) - goto badframe; + return (void *)((newsp - frame_size) & -8ul); +} - regs->gpr[1] = newsp; - regs->gpr[6] = (unsigned long)rt_sf; - regs->link = (unsigned long)frame->tramp; +static int +setup_trampoline(unsigned int syscall, unsigned int *tramp) +{ + int i, err = 0; - return; + /* addi r1, r1, __SIGNAL_FRAMESIZE # Pop the dummy stackframe */ + err |= __put_user(0x38210000UL | (__SIGNAL_FRAMESIZE & 0xffff), &tramp[0]); + /* li r0, __NR_[rt_]sigreturn| */ + err |= __put_user(0x38000000UL | (syscall & 0xffff), &tramp[1]); + /* sc */ + err |= __put_user(0x44000002UL, &tramp[2]); + + /* Minimal traceback info */ + for (i=TRAMP_TRACEBACK; i < TRAMP_SIZE ;i++) + err |= __put_user(0, &tramp[i]); + + if (!err) + flush_icache_range((unsigned long) &tramp[0], + (unsigned long) &tramp[TRAMP_SIZE]); -badframe: -#if DEBUG_SIG - printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", - regs, frame, newsp); -#endif - do_exit(SIGSEGV); + return err; } /* * Do a signal return; undo the signal stack. */ -long sys_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, unsigned long r8, - struct pt_regs *regs) -{ - struct sigcontext *sc, sigctx; - struct sigregs *sr; - elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */ + +int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, unsigned long r8, + struct pt_regs *regs) +{ + struct ucontext *uc = (struct ucontext *)regs->gpr[1]; sigset_t set; + stack_t st; - sc = (struct sigcontext *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); - if (copy_from_user(&sigctx, sc, sizeof(sigctx))) + if (verify_area(VERIFY_READ, uc, sizeof(*uc))) goto badframe; - set.sig[0] = sigctx.oldmask; -#if _NSIG_WORDS > 1 - set.sig[1] = sigctx._unused[3]; -#endif + if (__copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) + goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (regs->msr & MSR_FP) - giveup_fpu(current); - /* restore registers */ - sr = (struct sigregs *)sigctx.regs; - if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs))) + if (restore_sigcontext(regs, NULL, &uc->uc_mcontext)) goto badframe; - saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) - | (saved_regs[PT_MSR] & MSR_USERCHANGE); - saved_regs[PT_SOFTE] = regs->softe; - memcpy(regs, saved_regs, GP_REGS_SIZE); - if (copy_from_user(current->thread.fpr, &sr->fp_regs, - sizeof(sr->fp_regs))) + if (__copy_from_user(&st, &uc->uc_stack, sizeof(st))) goto badframe; + /* This function sets back the stack flags into + the current task structure. */ + sys_sigaltstack(&st, NULL, 0, 0, 0, 0, regs); return regs->result; badframe: +#if DEBUG_SIG + printk("badframe in sys_rt_sigreturn, regs=%p uc=%p &uc->uc_mcontext=%p\n", + regs, uc, &uc->uc_mcontext); +#endif do_exit(SIGSEGV); -} +} -/* - * Set up a signal frame. - */ -static void setup_frame(struct pt_regs *regs, struct sigregs *frame, - unsigned long newsp) +static void +setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs) { - /* Handler is *really* a pointer to the function descriptor for * the signal routine. The first entry in the function * descriptor is the entry address of signal and the second * entry is the TOC value we need to use. */ - struct funct_descr_entry { - unsigned long entry; - unsigned long toc; - }; - - struct funct_descr_entry * funct_desc_ptr; - unsigned long temp_ptr; + func_descr_t *funct_desc_ptr; + struct rt_sigframe *frame; + unsigned long newsp = 0; + int err = 0; - struct sigcontext *sc = (struct sigcontext *)newsp; - - if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) - goto badframe; - if (regs->msr & MSR_FP) - giveup_fpu(current); - if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE) - || __copy_to_user(&frame->fp_regs, current->thread.fpr, - ELF_NFPREG * sizeof(double)) - /* li r0, __NR_sigreturn */ - || __put_user(0x38000000UL + __NR_sigreturn, &frame->tramp[0]) - /* sc */ - || __put_user(0x44000002UL, &frame->tramp[1])) - goto badframe; - flush_icache_range((unsigned long)&frame->tramp[0], - (unsigned long)&frame->tramp[2]); - current->thread.fpscr = 0; /* turn off all fp exceptions */ + frame = get_sigframe(ka, regs, sizeof(*frame)); - newsp -= __SIGNAL_FRAMESIZE; - if (get_user(temp_ptr, &sc->handler)) + if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) goto badframe; - - funct_desc_ptr = (struct funct_descr_entry *)temp_ptr; - if (put_user(regs->gpr[1], (unsigned long *)newsp) - || get_user(regs->nip, &funct_desc_ptr ->entry) - || get_user(regs->gpr[2],&funct_desc_ptr->toc) - || get_user(regs->gpr[3], &sc->signal)) - goto badframe; + err |= __put_user(&frame->info, &frame->pinfo); + err |= __put_user(&frame->uc, &frame->puc); + err |= copy_siginfo_to_user(&frame->info, info); + if (err) + goto badframe; + + /* Create the ucontext. */ + err |= __put_user(0, &frame->uc.uc_flags); + err |= __put_user(0, &frame->uc.uc_link); + err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(regs->gpr[1]), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr, NULL, + (unsigned long)ka->sa.sa_handler); + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + if (err) + goto badframe; + + /* Set up to return from userspace. */ + err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); + if (err) + goto badframe; + + funct_desc_ptr = (func_descr_t *) ka->sa.sa_handler; + + /* Allocate a dummy caller frame for the signal handler. */ + newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE; + err |= put_user(0, (unsigned long *)newsp); + + /* Set up "regs" so we "return" to the signal handler. */ + err |= get_user(regs->nip, &funct_desc_ptr->entry); + regs->link = (unsigned long) &frame->tramp[0]; regs->gpr[1] = newsp; - regs->gpr[4] = (unsigned long)sc; - regs->link = (unsigned long)frame->tramp; + err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); + regs->gpr[3] = signr; + if (ka->sa.sa_flags & SA_SIGINFO) { + err |= get_user(regs->gpr[4], (unsigned long *)&frame->pinfo); + err |= get_user(regs->gpr[5], (unsigned long *)&frame->puc); + regs->gpr[6] = (unsigned long) frame; + } else { + regs->gpr[4] = (unsigned long)&frame->uc.uc_mcontext; + } + if (err) + goto badframe; return; badframe: #if DEBUG_SIG - printk("badframe in setup_frame, regs=%p frame=%p newsp=%lx\n", + printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif do_exit(SIGSEGV); } + /* * OK, we're invoking a handler */ -static void handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs, unsigned long *newspp, unsigned long frame) +static void +handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { - struct sigcontext *sc; - struct rt_sigframe *rt_sf; - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - - if (regs->trap == 0x0C00 /* System Call! */ - && ((int)regs->result == -ERESTARTNOHAND || - (int)regs->result == -ERESTART_RESTARTBLOCK || - ((int)regs->result == -ERESTARTSYS && - !(ka->sa.sa_flags & SA_RESTART)))) { - if ((int)regs->result == -ERESTART_RESTARTBLOCK) - current_thread_info()->restart_block.fn - = do_no_restart_syscall; - regs->result = -EINTR; - } - /* Set up Signal Frame */ - if (ka->sa.sa_flags & SA_SIGINFO) { - /* Put a Real Time Context onto stack */ - *newspp -= sizeof(*rt_sf); - rt_sf = (struct rt_sigframe *)*newspp; - if (verify_area(VERIFY_WRITE, rt_sf, sizeof(*rt_sf))) - goto badframe; - - if (__put_user((unsigned long)ka->sa.sa_handler, - &rt_sf->uc.uc_mcontext.handler) - || __put_user(&rt_sf->info, &rt_sf->pinfo) - || __put_user(&rt_sf->uc, &rt_sf->puc) - /* Put the siginfo */ - || copy_siginfo_to_user(&rt_sf->info, info) - /* Create the ucontext */ - || __put_user(0, &rt_sf->uc.uc_flags) - || __put_user(0, &rt_sf->uc.uc_link) - || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp) - || __put_user(sas_ss_flags(regs->gpr[1]), - &rt_sf->uc.uc_stack.ss_flags) - || __put_user(current->sas_ss_size, - &rt_sf->uc.uc_stack.ss_size) - || __copy_to_user(&rt_sf->uc.uc_sigmask, - oldset, sizeof(*oldset)) - /* mcontext.regs points to preamble register frame */ - || __put_user((struct pt_regs *)frame, &rt_sf->uc.uc_mcontext.regs) - || __put_user(sig, &rt_sf->uc.uc_mcontext.signal)) - goto badframe; - } else { - /* Put a sigcontext on the stack */ - *newspp -= sizeof(*sc); - sc = (struct sigcontext *)*newspp; - if (verify_area(VERIFY_WRITE, sc, sizeof(*sc))) - goto badframe; - - if (__put_user((unsigned long)ka->sa.sa_handler, &sc->handler) - || __put_user(oldset->sig[0], &sc->oldmask) -#if _NSIG_WORDS > 1 - || __put_user(oldset->sig[1], &sc->_unused[3]) -#endif - || __put_user((struct pt_regs *)frame, &sc->regs) - || __put_user(sig, &sc->signal)) - goto badframe; - } + setup_rt_frame(sig, ka, info, oldset, regs); if (ka->sa.sa_flags & SA_ONESHOT) ka->sa.sa_handler = SIG_DFL; @@ -515,14 +349,40 @@ spin_unlock_irq(¤t->sighand->siglock); } return; +} -badframe: -#if DEBUG_SIG - printk("badframe in handle_signal, regs=%p frame=%lx newsp=%lx\n", - regs, frame, *newspp); - printk("sc=%p sig=%d ka=%p info=%p oldset=%p\n", sc, sig, ka, info, oldset); -#endif - do_exit(SIGSEGV); +static inline void +syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) +{ + switch ((int)regs->result) { + case -ERESTART_RESTARTBLOCK: + current_thread_info()->restart_block.fn = do_no_restart_syscall; + /* fallthrough */ + case -ERESTARTNOHAND: + /* ERESTARTNOHAND means that the syscall should only be + * restarted if there was no handler for the signal, and since + * we only get here if there is a handler, we dont restart. + */ + regs->result = -EINTR; + break; + case -ERESTARTSYS: + /* ERESTARTSYS means to restart the syscall if there is no + * handler or the handler was registered with SA_RESTART + */ + if (!(ka->sa.sa_flags & SA_RESTART)) { + regs->result = -EINTR; + break; + } + /* fallthrough */ + case -ERESTARTNOINTR: + /* ERESTARTNOINTR means that the syscall should be + * called again after the signal handler returns. + */ + regs->gpr[3] = regs->orig_gpr3; + regs->nip -= 4; + regs->result = 0; + break; + } } /* @@ -535,8 +395,6 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) { siginfo_t info; - struct k_sigaction *ka; - unsigned long frame, newsp; int signr; /* @@ -549,20 +407,15 @@ if (!oldset) oldset = ¤t->blocked; - newsp = frame = 0; - signr = get_signal_to_deliver(&info, regs, NULL); if (signr > 0) { - ka = ¤t->sighand->action[signr-1]; - if ((ka->sa.sa_flags & SA_ONSTACK) - && (!on_sig_stack(regs->gpr[1]))) - newsp = (current->sas_ss_sp + current->sas_ss_size); - else - newsp = regs->gpr[1]; - newsp = frame = newsp - sizeof(struct sigregs); + struct k_sigaction *ka = ¤t->sighand->action[signr-1]; /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, oldset, regs, &newsp, frame); + if (regs->trap == 0x0C00) + syscall_restart(regs, ka); + handle_signal(signr, ka, &info, oldset, regs); + return 1; } if (regs->trap == 0x0C00) { /* System Call! */ @@ -579,13 +432,8 @@ } } - if (newsp == frame) - return 0; /* no signals delivered */ - - /* Invoke correct stack setup routine */ - if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame(regs, (struct sigregs *)frame, newsp); - else - setup_frame(regs, (struct sigregs *)frame, newsp); - return 1; + return 0; } + + + diff -Nru a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c --- a/arch/ppc64/kernel/signal32.c Sat May 24 12:48:31 2003 +++ b/arch/ppc64/kernel/signal32.c Sat May 24 12:48:31 2003 @@ -114,6 +114,40 @@ * setup_frame32 */ +/* + * Atomically swap in the new signal mask, and wait for a signal. + */ +long sys32_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7, + struct pt_regs *regs) +{ + sigset_t saveset; + + mask &= _BLOCKABLE; + spin_lock_irq(¤t->sighand->siglock); + saveset = current->blocked; + siginitset(¤t->blocked, mask); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + regs->result = -EINTR; + regs->gpr[3] = EINTR; + regs->ccr |= 0x10000000; + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (do_signal32(&saveset, regs)) + /* + * If a signal handler needs to be called, + * do_signal32() has set R3 to the signal number (the + * first argument of the signal handler), so don't + * overwrite that with EINTR ! + * In the other cases, do_signal32() doesn't touch + * R3, so it's still set to -EINTR (see above). + */ + return regs->gpr[3]; + } +} + long sys32_sigaction(int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact) { @@ -792,13 +826,13 @@ while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(&saveset, regs)) + if (do_signal32(&saveset, regs)) /* * If a signal handler needs to be called, - * do_signal() has set R3 to the signal number (the + * do_signal32() has set R3 to the signal number (the * first argument of the signal handler), so don't * overwrite that with EINTR ! - * In the other cases, do_signal() doesn't touch + * In the other cases, do_signal32() doesn't touch * R3, so it's still set to -EINTR (see above). */ return regs->gpr[3]; diff -Nru a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c --- a/arch/ppc64/kernel/smp.c Sat May 24 12:48:29 2003 +++ b/arch/ppc64/kernel/smp.c Sat May 24 12:48:29 2003 @@ -46,8 +46,9 @@ #include #include "open_pic.h" #include +#include -int smp_threads_ready = 0; +int smp_threads_ready; unsigned long cache_decay_ticks; /* initialised so it doesn't end up in bss */ @@ -63,18 +64,6 @@ void smp_call_function_interrupt(void); void smp_message_pass(int target, int msg, unsigned long data, int wait); -void xics_setup_cpu(void); -void xics_cause_IPI(int cpu); - -/* - * XICS only has a single IPI, so encode the messages per CPU - */ -struct xics_ipi_struct { - volatile unsigned long value; -} ____cacheline_aligned; - -struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; - #define smp_message_pass(t,m,d,w) smp_ops->message_pass((t),(m),(d),(w)) static inline void set_tb(unsigned int upper, unsigned int lower) @@ -189,7 +178,7 @@ smp_ops->kick_cpu = smp_iSeries_kick_cpu; smp_ops->setup_cpu = smp_iSeries_setup_cpu; #warning fix for iseries - naca->processorCount = smp_iSeries_numProcs(); + systemcfg->processorCount = smp_iSeries_numProcs(); } #endif @@ -353,7 +342,7 @@ smp_ops->probe = smp_xics_probe; } - if (naca->platform == PLATFORM_PSERIES) { + if (systemcfg->platform == PLATFORM_PSERIES) { smp_ops->give_timebase = pSeries_give_timebase; smp_ops->take_timebase = pSeries_take_timebase; } @@ -621,10 +610,11 @@ /* create a process for the processor */ /* only regs.msr is actually used, and 0 is OK for it */ memset(®s, 0, sizeof(struct pt_regs)); - p = do_fork(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); + p = copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); if (IS_ERR(p)) panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); + wake_up_forked_process(p); init_idle(p, cpu); unhash_process(p); diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c --- a/arch/ppc64/kernel/sys_ppc32.c Sat May 24 12:48:29 2003 +++ b/arch/ppc64/kernel/sys_ppc32.c Sat May 24 12:48:29 2003 @@ -1801,7 +1801,7 @@ err = do_sys32_shmctl(first, second, (void *)AA(ptr)); break; default: - err = -EINVAL; + err = -ENOSYS; break; } return err; diff -Nru a/arch/ppc64/kernel/syscalls.c b/arch/ppc64/kernel/syscalls.c --- a/arch/ppc64/kernel/syscalls.c Sat May 24 12:48:28 2003 +++ b/arch/ppc64/kernel/syscalls.c Sat May 24 12:48:28 2003 @@ -68,7 +68,7 @@ version = call >> 16; /* hack for backward compatibility */ call &= 0xffff; - ret = -EINVAL; + ret = -ENOSYS; switch (call) { case SEMOP: ret = sys_semop (first, (struct sembuf *)ptr, second); diff -Nru a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c --- a/arch/ppc64/kernel/traps.c Sat May 24 12:48:25 2003 +++ b/arch/ppc64/kernel/traps.c Sat May 24 12:48:25 2003 @@ -55,14 +55,12 @@ * Trap & Exception support */ -/* Should we panic on bad kernel exceptions or try to recover */ -#undef PANIC_ON_ERROR - static spinlock_t die_lock = SPIN_LOCK_UNLOCKED; void die(const char *str, struct pt_regs *regs, long err) { static int die_counter; + console_verbose(); spin_lock_irq(&die_lock); bust_spinlocks(1); @@ -71,11 +69,16 @@ bust_spinlocks(0); spin_unlock_irq(&die_lock); -#ifdef PANIC_ON_ERROR - panic(str); -#else + if (in_interrupt()) + panic("Fatal exception in interrupt"); + + if (panic_on_oops) { + printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n"); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(5 * HZ); + panic("Fatal exception"); + } do_exit(SIGSEGV); -#endif } static void @@ -139,15 +142,13 @@ #ifdef CONFIG_DEBUG_KERNEL if (debugger) debugger(regs); + else #endif + panic("System Reset"); -#ifdef PANIC_ON_ERROR - panic("System Reset"); -#else /* Must die if the interrupt is not recoverable */ if (!(regs->msr & MSR_RI)) panic("Unrecoverable System Reset"); -#endif /* What should we do here? We could issue a shutdown or hard reset. */ } @@ -343,6 +344,14 @@ info.si_addr = (void *)regs->nip; _exception(SIGILL, &info, regs); } +} + + void +KernelFPUnavailableException(struct pt_regs *regs) +{ + printk("Illegal floating point used in kernel (task=0x%016lx, pc=0x%016lx, trap=0x%08x)\n", + current, regs->nip, regs->trap); + panic("Unrecoverable FP Unavailable Exception in Kernel"); } void diff -Nru a/arch/ppc64/kernel/udbg.c b/arch/ppc64/kernel/udbg.c --- a/arch/ppc64/kernel/udbg.c Sat May 24 12:48:20 2003 +++ b/arch/ppc64/kernel/udbg.c Sat May 24 12:48:20 2003 @@ -176,7 +176,7 @@ void udbg_printSP(const char *s) { - if (naca->platform == PLATFORM_PSERIES) { + if (systemcfg->platform == PLATFORM_PSERIES) { unsigned long sp; asm("mr %0,1" : "=r" (sp) :); if (s) diff -Nru a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c --- a/arch/ppc64/kernel/xics.c Sat May 24 12:48:25 2003 +++ b/arch/ppc64/kernel/xics.c Sat May 24 12:48:25 2003 @@ -1,5 +1,5 @@ /* - * arch/ppc/kernel/xics.c + * arch/ppc64/kernel/xics.c * * Copyright 2000 IBM Corporation. * @@ -22,10 +22,11 @@ #include #include #include -#include "i8259.h" #include #include -#include +#include + +#include "i8259.h" void xics_enable_irq(u_int irq); void xics_disable_irq(u_int irq); @@ -61,33 +62,39 @@ /* Want a priority other than 0. Various HW issues require this. */ #define DEFAULT_PRIORITY 5 +/* + * Mark IPIs as higher priority so we can take them inside interrupts that + * arent marked SA_INTERRUPT + */ +#define IPI_PRIORITY 4 + struct xics_ipl { union { - u32 word; - u8 bytes[4]; + u32 word; + u8 bytes[4]; } xirr_poll; union { u32 word; - u8 bytes[4]; + u8 bytes[4]; } xirr; - u32 dummy; + u32 dummy; union { - u32 word; - u8 bytes[4]; + u32 word; + u8 bytes[4]; } qirr; }; -struct xics_info { - volatile struct xics_ipl * per_cpu[NR_CPUS]; -}; +static struct xics_ipl *xics_per_cpu[NR_CPUS]; -struct xics_info xics_info; +static int xics_irq_8259_cascade = 0; +static int xics_irq_8259_cascade_real = 0; +static unsigned int default_server = 0xFF; +static unsigned int default_distrib_server = 0; -unsigned long long intr_base = 0; -int xics_irq_8259_cascade = 0; -int xics_irq_8259_cascade_real = 0; -unsigned int default_server = 0xFF; -unsigned int default_distrib_server = 0; +/* + * XICS only has a single IPI, so encode the messages per CPU + */ +struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; /* RTAS service tokens */ int ibm_get_xive; @@ -95,11 +102,6 @@ int ibm_int_on; int ibm_int_off; -struct xics_interrupt_node { - unsigned long long addr; - unsigned long long size; -} inodes[NR_CPUS*2]; - typedef struct { int (*xirr_info_get)(int cpu); void (*xirr_info_set)(int cpu, int val); @@ -108,24 +110,26 @@ } xics_ops; +/* SMP */ + static int pSeries_xirr_info_get(int n_cpu) { - return (xics_info.per_cpu[n_cpu]->xirr.word); + return xics_per_cpu[n_cpu]->xirr.word; } static void pSeries_xirr_info_set(int n_cpu, int value) { - xics_info.per_cpu[n_cpu]->xirr.word = value; + xics_per_cpu[n_cpu]->xirr.word = value; } static void pSeries_cppr_info(int n_cpu, u8 value) { - xics_info.per_cpu[n_cpu]->xirr.bytes[0] = value; + xics_per_cpu[n_cpu]->xirr.bytes[0] = value; } -static void pSeries_qirr_info(int n_cpu , u8 value) +static void pSeries_qirr_info(int n_cpu, u8 value) { - xics_info.per_cpu[n_cpu]->qirr.bytes[0] = value; + xics_per_cpu[n_cpu]->qirr.bytes[0] = value; } static xics_ops pSeries_ops = { @@ -136,113 +140,174 @@ }; static xics_ops *ops = &pSeries_ops; -extern xics_ops pSeriesLP_ops; -void -xics_enable_irq( - u_int virq - ) +/* LPAR */ + +static inline long plpar_eoi(unsigned long xirr) { - u_int irq; - unsigned long status; - long call_status; + return plpar_hcall_norets(H_EOI, xirr); +} + +static inline long plpar_cppr(unsigned long cppr) +{ + return plpar_hcall_norets(H_CPPR, cppr); +} + +static inline long plpar_ipi(unsigned long servernum, unsigned long mfrr) +{ + return plpar_hcall_norets(H_IPI, servernum, mfrr); +} + +static inline long plpar_xirr(unsigned long *xirr_ret) +{ + unsigned long dummy; + return plpar_hcall(H_XIRR, 0, 0, 0, 0, xirr_ret, &dummy, &dummy); +} + +static int pSeriesLP_xirr_info_get(int n_cpu) +{ + unsigned long lpar_rc; + unsigned long return_value; + + lpar_rc = plpar_xirr(&return_value); + if (lpar_rc != H_Success) + panic(" bad return code xirr - rc = %lx \n", lpar_rc); + return (int)return_value; +} + +static void pSeriesLP_xirr_info_set(int n_cpu, int value) +{ + unsigned long lpar_rc; + unsigned long val64 = value & 0xffffffff; + + lpar_rc = plpar_eoi(val64); + if (lpar_rc != H_Success) + panic("bad return code EOI - rc = %ld, value=%lx\n", lpar_rc, + val64); +} + +static void pSeriesLP_cppr_info(int n_cpu, u8 value) +{ + unsigned long lpar_rc; + + lpar_rc = plpar_cppr(value); + if (lpar_rc != H_Success) + panic("bad return code cppr - rc = %lx\n", lpar_rc); +} + +static void pSeriesLP_qirr_info(int n_cpu , u8 value) +{ + unsigned long lpar_rc; + + lpar_rc = plpar_ipi(n_cpu, value); + if (lpar_rc != H_Success) + panic("bad return code qirr - rc = %lx\n", lpar_rc); +} + +xics_ops pSeriesLP_ops = { + pSeriesLP_xirr_info_get, + pSeriesLP_xirr_info_set, + pSeriesLP_cppr_info, + pSeriesLP_qirr_info +}; + +void xics_enable_irq(u_int virq) +{ + u_int irq; + long call_status; + unsigned int server; virq -= XICS_IRQ_OFFSET; irq = virt_irq_to_real(virq); if (irq == XICS_IPI) return; + #ifdef CONFIG_IRQ_ALL_CPUS - call_status = rtas_call(ibm_set_xive, 3, 1, (unsigned long*)&status, - irq, smp_threads_ready ? default_distrib_server : default_server, DEFAULT_PRIORITY); + if (smp_threads_ready) + server = default_distrib_server; + else + server = default_server; #else - call_status = rtas_call(ibm_set_xive, 3, 1, (unsigned long*)&status, - irq, default_server, DEFAULT_PRIORITY); + server = default_server; #endif - if( call_status != 0 ) { - printk("xics_enable_irq: irq=%x: rtas_call failed; retn=%lx, status=%lx\n", - irq, call_status, status); + + call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, + DEFAULT_PRIORITY); + if (call_status != 0) { + printk("xics_enable_irq: irq=%x: ibm_set_xive returned %lx\n", + irq, call_status); return; } + /* Now unmask the interrupt (often a no-op) */ - call_status = rtas_call(ibm_int_on, 1, 1, (unsigned long*)&status, - irq); - if( call_status != 0 ) { - printk("xics_disable_irq on: irq=%x: rtas_call failed, retn=%lx\n", + call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq); + if (call_status != 0) { + printk("xics_enable_irq: irq=%x: ibm_int_on returned %lx\n", irq, call_status); return; } } -void -xics_disable_irq( - u_int virq - ) -{ - u_int irq; - unsigned long status; - long call_status; +void xics_disable_irq(u_int virq) +{ + u_int irq; + long call_status; virq -= XICS_IRQ_OFFSET; irq = virt_irq_to_real(virq); - call_status = rtas_call(ibm_int_off, 1, 1, (unsigned long*)&status, - irq); - if( call_status != 0 ) { - printk("xics_disable_irq: irq=%x: rtas_call failed, retn=%lx\n", + if (irq == XICS_IPI) + return; + + call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq); + if (call_status != 0) { + printk("xics_disable_irq: irq=%x: ibm_int_off returned %lx\n", irq, call_status); return; } } -void -xics_end_irq( - u_int irq - ) +void xics_end_irq(u_int irq) { int cpu = smp_processor_id(); - ops->cppr_info(cpu, 0); /* actually the value overwritten by ack */ - iosync(); - ops->xirr_info_set(cpu, ((0xff<<24) | (virt_irq_to_real(irq-XICS_IRQ_OFFSET)))); iosync(); + ops->xirr_info_set(cpu, ((0xff<<24) | + (virt_irq_to_real(irq-XICS_IRQ_OFFSET)))); } -void -xics_mask_and_ack_irq(u_int irq) +void xics_mask_and_ack_irq(u_int irq) { int cpu = smp_processor_id(); - if( irq < XICS_IRQ_OFFSET ) { + if (irq < XICS_IRQ_OFFSET) { i8259_pic.ack(irq); iosync(); - ops->xirr_info_set(cpu, ((0xff<<24) | xics_irq_8259_cascade_real)); - iosync(); - } - else { - ops->cppr_info(cpu, 0xff); + ops->xirr_info_set(cpu, ((0xff<<24) | + xics_irq_8259_cascade_real)); iosync(); } } -int -xics_get_irq(struct pt_regs *regs) +int xics_get_irq(struct pt_regs *regs) { - u_int cpu = smp_processor_id(); - u_int vec; + u_int cpu = smp_processor_id(); + u_int vec; int irq; vec = ops->xirr_info_get(cpu); /* (vec >> 24) == old priority */ vec &= 0x00ffffff; + /* for sanity, this had better be < NR_IRQS - 16 */ - if( vec == xics_irq_8259_cascade_real ) { + if (vec == xics_irq_8259_cascade_real) { irq = i8259_irq(cpu); - if(irq == -1) { + if (irq == -1) { /* Spurious cascaded interrupt. Still must ack xics */ xics_end_irq(XICS_IRQ_OFFSET + xics_irq_8259_cascade); irq = -1; } - } else if( vec == XICS_IRQ_SPURIOUS ) { + } else if (vec == XICS_IRQ_SPURIOUS) { irq = -1; } else { irq = real_irq_to_virt(vec) + XICS_IRQ_OFFSET; @@ -250,45 +315,49 @@ return irq; } -struct xics_ipi_struct { - volatile unsigned long value; -} ____cacheline_aligned; +#ifdef CONFIG_SMP extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; -#ifdef CONFIG_SMP -void xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs) { int cpu = smp_processor_id(); + int handled = 0; ops->qirr_info(cpu, 0xff); while (xics_ipi_message[cpu].value) { - if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION, &xics_ipi_message[cpu].value)) { + handled = 1; + if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION, + &xics_ipi_message[cpu].value)) { mb(); smp_message_recv(PPC_MSG_CALL_FUNCTION, regs); } - if (test_and_clear_bit(PPC_MSG_RESCHEDULE, &xics_ipi_message[cpu].value)) { + if (test_and_clear_bit(PPC_MSG_RESCHEDULE, + &xics_ipi_message[cpu].value)) { mb(); smp_message_recv(PPC_MSG_RESCHEDULE, regs); } #if 0 - if (test_and_clear_bit(PPC_MSG_MIGRATE_TASK, &xics_ipi_message[cpu].value)) { + if (test_and_clear_bit(PPC_MSG_MIGRATE_TASK, + &xics_ipi_message[cpu].value)) { mb(); smp_message_recv(PPC_MSG_MIGRATE_TASK, regs); } #endif #ifdef CONFIG_XMON - if (test_and_clear_bit(PPC_MSG_XMON_BREAK, &xics_ipi_message[cpu].value)) { + if (test_and_clear_bit(PPC_MSG_XMON_BREAK, + &xics_ipi_message[cpu].value)) { mb(); smp_message_recv(PPC_MSG_XMON_BREAK, regs); } #endif } + return IRQ_RETVAL(handled); } void xics_cause_IPI(int cpu) { - ops->qirr_info(cpu,0) ; + ops->qirr_info(cpu, IPI_PRIORITY); } void xics_setup_cpu(void) @@ -298,15 +367,20 @@ ops->cppr_info(cpu, 0xff); iosync(); } + #endif /* CONFIG_SMP */ -void -xics_init_IRQ( void ) +void xics_init_IRQ(void) { int i; unsigned long intr_size = 0; struct device_node *np; uint *ireg, ilen, indx=0; + unsigned long intr_base = 0; + struct xics_interrupt_node { + unsigned long long addr; + unsigned long long size; + } inodes[NR_CPUS*2]; ppc64_boot_msg(0x20, "XICS Init"); @@ -386,23 +460,24 @@ xics_irq_8259_cascade = virt_irq_create_mapping(xics_irq_8259_cascade_real); } - if (naca->platform == PLATFORM_PSERIES) { + if (systemcfg->platform == PLATFORM_PSERIES) { #ifdef CONFIG_SMP for (i = 0; i < NR_CPUS; ++i) { if (!cpu_possible(i)) continue; - xics_info.per_cpu[i] = - __ioremap((ulong)inodes[i].addr, - (ulong)inodes[i].size, _PAGE_NO_CACHE); + xics_per_cpu[i] = __ioremap((ulong)inodes[i].addr, + (ulong)inodes[i].size, + _PAGE_NO_CACHE); } #else - xics_info.per_cpu[0] = __ioremap((ulong)intr_base, intr_size, _PAGE_NO_CACHE); + xics_per_cpu[0] = __ioremap((ulong)intr_base, intr_size, + _PAGE_NO_CACHE); #endif /* CONFIG_SMP */ #ifdef CONFIG_PPC_PSERIES /* actually iSeries does not use any of xics...but it has link dependencies * for now, except this new one... */ - } else if (naca->platform == PLATFORM_PSERIES_LPAR) { + } else if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { ops = &pSeriesLP_ops; #endif } @@ -417,8 +492,8 @@ ops->cppr_info(boot_cpuid, 0xff); iosync(); if (xics_irq_8259_cascade != -1) { - if (request_irq(xics_irq_8259_cascade + XICS_IRQ_OFFSET, no_action, - 0, "8259 cascade", 0)) + if (request_irq(xics_irq_8259_cascade + XICS_IRQ_OFFSET, + no_action, 0, "8259 cascade", 0)) printk(KERN_ERR "xics_init_IRQ: couldn't get 8259 cascade\n"); i8259_init(); } diff -Nru a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c --- a/arch/ppc64/mm/fault.c Sat May 24 12:48:30 2003 +++ b/arch/ppc64/mm/fault.c Sat May 24 12:48:30 2003 @@ -75,8 +75,8 @@ } #endif - /* On an SLB miss we can only check for a valid exception entry */ - if (regs->trap == 0x380) { + /* On a kernel SLB miss we can only check for a valid exception entry */ + if (!user_mode(regs) && (regs->trap == 0x380)) { bad_page_fault(regs, address, SIGSEGV); return; } diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c --- a/arch/ppc64/mm/init.c Sat May 24 12:48:26 2003 +++ b/arch/ppc64/mm/init.c Sat May 24 12:48:26 2003 @@ -69,8 +69,6 @@ int mem_init_done; unsigned long ioremap_bot = IMALLOC_BASE; -static int boot_mapsize; - extern pgd_t swapper_pg_dir[]; extern char __init_begin, __init_end; extern char _start[], _end[]; @@ -454,6 +452,7 @@ unsigned long i; unsigned long start, bootmap_pages; unsigned long total_pages = lmb_end_of_DRAM() >> PAGE_SHIFT; + int boot_mapsize; /* * Find an area to use for the bootmem bitmap. Calculate the size of @@ -532,7 +531,7 @@ int nid; for (nid = 0; nid < numnodes; nid++) { - if (numa_node_exists[nid]) { + if (node_data[nid].node_size != 0) { printk("freeing bootmem node %x\n", nid); totalram_pages += free_all_bootmem_node(NODE_DATA(nid)); diff -Nru a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c --- a/arch/ppc64/mm/numa.c Sat May 24 12:48:28 2003 +++ b/arch/ppc64/mm/numa.c Sat May 24 12:48:28 2003 @@ -24,11 +24,18 @@ int numa_cpu_lookup_table[NR_CPUS] = { [ 0 ... (NR_CPUS - 1)] = -1}; int numa_memory_lookup_table[MAX_MEMORY >> MEMORY_INCREMENT_SHIFT] = { [ 0 ... ((MAX_MEMORY >> MEMORY_INCREMENT_SHIFT) - 1)] = -1}; -int numa_node_exists[MAX_NUMNODES]; +unsigned long numa_cpumask_lookup_table[MAX_NUMNODES]; struct pglist_data node_data[MAX_NUMNODES]; bootmem_data_t plat_node_bdata[MAX_NUMNODES]; +static inline void map_cpu_to_node(int cpu, int node) +{ + dbg("cpu %d maps to domain %d\n", cpu, node); + numa_cpu_lookup_table[cpu] = node; + numa_cpumask_lookup_table[node] |= 1UL << cpu; +} + static int __init parse_numa_properties(void) { struct device_node *cpu; @@ -88,9 +95,7 @@ if (max_domain < numa_domain) max_domain = numa_domain; - numa_cpu_lookup_table[cpu_nr] = numa_domain; - - dbg("cpu %d maps to domain %d\n", cpu_nr, numa_domain); + map_cpu_to_node(cpu_nr, numa_domain); } for (memory = find_type_devices("memory"); memory; @@ -135,7 +140,7 @@ /* FIXME */ if (numa_domain == 0xffff) { - dbg("cpu has no numa doman\n"); + dbg("memory has no numa doman\n"); numa_domain = 0; } @@ -145,7 +150,8 @@ if (max_domain < numa_domain) max_domain = numa_domain; - numa_node_exists[numa_domain] = 1; + node_data[numa_domain].node_start_pfn = start / PAGE_SIZE; + node_data[numa_domain].node_size = size / PAGE_SIZE; for (i = start ; i < (start+size); i += MEMORY_INCREMENT) numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = @@ -176,27 +182,17 @@ BUG(); for (nid = 0; nid < numnodes; nid++) { - unsigned long start, end; unsigned long start_paddr, end_paddr; int i; unsigned long bootmem_paddr; unsigned long bootmap_pages; - if (!numa_node_exists[nid]) + if (node_data[nid].node_size == 0) continue; - /* Find start and end of this zone */ - start = 0; - while (numa_memory_lookup_table[start] != nid) - start++; - - end = (MAX_MEMORY >> MEMORY_INCREMENT_SHIFT) - 1; - while (numa_memory_lookup_table[end] != nid) - end--; - end++; - - start_paddr = start << MEMORY_INCREMENT_SHIFT; - end_paddr = end << MEMORY_INCREMENT_SHIFT; + start_paddr = node_data[nid].node_start_pfn * PAGE_SIZE; + end_paddr = start_paddr + + (node_data[nid].node_size * PAGE_SIZE); dbg("node %d\n", nid); dbg("start_paddr = %lx\n", start_paddr); @@ -278,7 +274,7 @@ unsigned long start_pfn; unsigned long end_pfn; - if (!numa_node_exists[nid]) + if (node_data[nid].node_size == 0) continue; start_pfn = plat_node_bdata[nid].node_boot_start >> PAGE_SHIFT; diff -Nru a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c --- a/arch/ppc64/xmon/xmon.c Sat May 24 12:48:31 2003 +++ b/arch/ppc64/xmon/xmon.c Sat May 24 12:48:31 2003 @@ -453,7 +453,7 @@ int i; struct bpt *bp; - if (naca->platform != PLATFORM_PSERIES) + if (systemcfg->platform != PLATFORM_PSERIES) return; bp = bpts; for (i = 0; i < NBPTS; ++i, ++bp) { @@ -469,12 +469,10 @@ } } - if (!__is_processor(PV_POWER4) && !__is_processor(PV_POWER4p)) { - if (dabr.enabled) - set_dabr(dabr.address); - if (iabr.enabled) - set_iabr(iabr.address); - } + if (cpu_has_dabr() && dabr.enabled) + set_dabr(dabr.address); + if (cpu_has_iabr() && iabr.enabled) + set_iabr(iabr.address); } static void @@ -484,12 +482,13 @@ struct bpt *bp; unsigned instr; - if (naca->platform != PLATFORM_PSERIES) + if (systemcfg->platform != PLATFORM_PSERIES) return; - if (!__is_processor(PV_POWER4) && !__is_processor(PV_POWER4p)) { + + if (cpu_has_dabr()) set_dabr(0); + if (cpu_has_iabr()) set_iabr(0); - } bp = bpts; for (i = 0; i < NBPTS; ++i, ++bp) { @@ -778,8 +777,8 @@ cmd = inchar(); switch (cmd) { case 'd': /* bd - hardware data breakpoint */ - if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) { - printf("Not implemented on POWER4\n"); + if (cpu_has_dabr()) { + printf("Not implemented on this cpu\n"); break; } mode = 7; @@ -798,7 +797,7 @@ dabr.address = (dabr.address & ~7) | mode; break; case 'i': /* bi - hardware instr breakpoint */ - if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) { + if (cpu_has_iabr()) { printf("Not implemented on POWER4\n"); break; } diff -Nru a/arch/s390/kernel/compat_exec.c b/arch/s390/kernel/compat_exec.c --- a/arch/s390/kernel/compat_exec.c Sat May 24 12:48:31 2003 +++ b/arch/s390/kernel/compat_exec.c Sat May 24 12:48:31 2003 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -32,8 +33,6 @@ #endif -extern void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long address); - #undef STACK_TOP #define STACK_TOP TASK31_SIZE @@ -81,7 +80,7 @@ struct page *page = bprm->page[i]; if (page) { bprm->page[i] = NULL; - put_dirty_page(current,page,stack_base); + put_dirty_page(current,page,stack_base,PAGE_COPY); } stack_base += PAGE_SIZE; } diff -Nru a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c --- a/arch/s390/kernel/module.c Sat May 24 12:48:31 2003 +++ b/arch/s390/kernel/module.c Sat May 24 12:48:31 2003 @@ -386,3 +386,7 @@ kfree(me->arch.syminfo); return 0; } + +void module_arch_cleanup(struct module *mod) +{ +} diff -Nru a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c --- a/arch/s390/kernel/s390_ksyms.c Sat May 24 12:48:26 2003 +++ b/arch/s390/kernel/s390_ksyms.c Sat May 24 12:48:26 2003 @@ -13,7 +13,7 @@ #include #include #include -#if CONFIG_IP_MULTICAST +#ifdef CONFIG_IP_MULTICAST #include #endif diff -Nru a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c --- a/arch/s390/kernel/traps.c Sat May 24 12:48:23 2003 +++ b/arch/s390/kernel/traps.c Sat May 24 12:48:23 2003 @@ -304,7 +304,7 @@ } else { -#if CONFIG_REMOTE_DEBUG +#ifdef CONFIG_REMOTE_DEBUG if(gdb_stub_initialised) { gdb_stub_handle_exception(regs, signal); diff -Nru a/arch/s390/math-emu/math.c b/arch/s390/math-emu/math.c --- a/arch/s390/math-emu/math.c Sat May 24 12:48:23 2003 +++ b/arch/s390/math-emu/math.c Sat May 24 12:48:23 2003 @@ -102,7 +102,7 @@ struct pt_regs *regs; __u16 *location; -#if CONFIG_SYSCTL +#ifdef CONFIG_SYSCTL if(sysctl_ieee_emulation_warnings) #endif { diff -Nru a/arch/sparc/Kconfig b/arch/sparc/Kconfig --- a/arch/sparc/Kconfig Sat May 24 12:48:19 2003 +++ b/arch/sparc/Kconfig Sat May 24 12:48:19 2003 @@ -1000,6 +1000,13 @@ If you say Y here, various routines which may sleep will become very noisy if they are called with a spinlock held. +config DEBUG_BUGVERBOSE + bool "Verbose BUG() reporting (adds 70K)" + help + Say Y here to make BUG() panics output the file name and line number + of the BUG call as well as the EIP and oops trace. This aids + debugging but costs about 70-100K of memory. + endmenu source "security/Kconfig" diff -Nru a/arch/sparc/defconfig b/arch/sparc/defconfig --- a/arch/sparc/defconfig Sat May 24 12:48:29 2003 +++ b/arch/sparc/defconfig Sat May 24 12:48:29 2003 @@ -2,7 +2,6 @@ # Automatically generated make config: don't edit # CONFIG_MMU=y -CONFIG_SWAP=y CONFIG_UID16=y CONFIG_HIGHMEM=y CONFIG_GENERIC_ISA_DMA=y @@ -15,10 +14,11 @@ # # General setup # -CONFIG_NET=y +CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 # # Loadable module support @@ -26,6 +26,8 @@ CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set CONFIG_KMOD=y # @@ -45,6 +47,7 @@ CONFIG_SUN_PM=y # CONFIG_SUN4 is not set CONFIG_PCI=y +# CONFIG_PCI_LEGACY_PROC is not set # CONFIG_PCI_NAMES is not set CONFIG_SUN_OPENPROMFS=m CONFIG_KCORE_ELF=y @@ -59,15 +62,17 @@ # CONFIG_PARPORT is not set # -# Console drivers +# Graphics support # -# CONFIG_PROM_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y +# CONFIG_FB is not set # -# Frame-buffer support +# Console display driver support # -# CONFIG_FB is not set +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +# CONFIG_PROM_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y # # Memory Technology Devices (MTD) @@ -130,7 +135,32 @@ # # SCSI support # -# CONFIG_SCSI is not set +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CDrom) +# +CONFIG_BLK_DEV_SD=y +CONFIG_SD_EXTRA_DEVS=40 +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=m +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_SR_EXTRA_DEVS=2 +CONFIG_CHR_DEV_SG=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +CONFIG_SCSI_SUNESP=y +CONFIG_SCSI_QLOGICPTI=m # # Fibre Channel support @@ -138,6 +168,11 @@ # CONFIG_FC4 is not set # +# Networking support +# +CONFIG_NET=y + +# # Networking options # CONFIG_PACKET=y @@ -389,6 +424,7 @@ # USB support # # CONFIG_USB is not set +# CONFIG_USB_GADGET is not set # # Bluetooth support @@ -407,6 +443,7 @@ CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_SPINLOCK=y # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +CONFIG_DEBUG_BUGVERBOSE=y # # Security options diff -Nru a/arch/sparc/kernel/asm-offsets.c b/arch/sparc/kernel/asm-offsets.c --- a/arch/sparc/kernel/asm-offsets.c Sat May 24 12:48:27 2003 +++ b/arch/sparc/kernel/asm-offsets.c Sat May 24 12:48:27 2003 @@ -22,8 +22,6 @@ int foo(void) { DEFINE(AOFF_task_thread, offsetof(struct task_struct, thread)); - DEFINE(AOFF_task_ptrace, offsetof(struct task_struct, ptrace)); - DEFINE(AOFF_task_blocked, offsetof(struct task_struct, blocked)); BLANK(); /* XXX This is the stuff for sclow.S, kill it. */ DEFINE(AOFF_task_pid, offsetof(struct task_struct, pid)); diff -Nru a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S --- a/arch/sparc/kernel/entry.S Sat May 24 12:48:24 2003 +++ b/arch/sparc/kernel/entry.S Sat May 24 12:48:24 2003 @@ -359,11 +359,11 @@ andcc %o1, %o4, %g0 be,a smp4m_ticker cmp %l7, 14 - cmp %l7, 13 + sethi %hi(0x40000000), %o2 add %o5, %o3, %o5 - bne,a 1f - sethi %hi(0x40000000), %o2 - sethi %hi(0x20000000), %o2 + andcc %o1, %o2, %g0 + be,a 1f + sethi %hi(0x20000000), %o2 1: st %o2, [%o5 + 0x4] WRITE_PAUSE @@ -374,7 +374,8 @@ WRITE_PAUSE wr %l4, PSR_ET, %psr WRITE_PAUSE - cmp %l7, 13 + srl %o2, (16+14), %o2 + tst %o2 bne 2f nop call C_LABEL(smp_reschedule_irq) @@ -1245,9 +1246,8 @@ call C_LABEL(do_ptrace) add %sp, STACKFRAME_SZ, %o0 - ld [%curptr + TI_TASK], %l5 - ld [%l5 + AOFF_task_ptrace], %l5 - andcc %l5, 0x02, %g0 + ld [%curptr + TI_FLAGS], %l5 + andcc %l5, _TIF_SYSCALL_TRACE, %g0 be 1f nop @@ -1296,9 +1296,8 @@ call C_LABEL(do_sigpause) add %sp, STACKFRAME_SZ, %o1 - ld [%curptr + TI_TASK], %l5 - ld [%l5 + AOFF_task_ptrace], %l5 - andcc %l5, 0x02, %g0 + ld [%curptr + TI_FLAGS], %l5 + andcc %l5, _TIF_SYSCALL_TRACE, %g0 be 1f nop @@ -1315,9 +1314,8 @@ call C_LABEL(do_sigsuspend) add %sp, STACKFRAME_SZ, %o0 - ld [%curptr + TI_TASK], %l5 - ld [%l5 + AOFF_task_ptrace], %l5 - andcc %l5, 0x02, %g0 + ld [%curptr + TI_FLAGS], %l5 + andcc %l5, _TIF_SYSCALL_TRACE, %g0 be 1f nop @@ -1335,9 +1333,8 @@ call C_LABEL(do_rt_sigsuspend) add %sp, STACKFRAME_SZ, %o2 - ld [%curptr + TI_TASK], %l5 - ld [%l5 + AOFF_task_ptrace], %l5 - andcc %l5, 0x02, %g0 + ld [%curptr + TI_FLAGS], %l5 + andcc %l5, _TIF_SYSCALL_TRACE, %g0 be 1f nop @@ -1354,9 +1351,8 @@ call C_LABEL(do_sigreturn) add %sp, STACKFRAME_SZ, %o0 - ld [%curptr + TI_TASK], %l5 - ld [%l5 + AOFF_task_ptrace], %l5 - andcc %l5, 0x02, %g0 + ld [%curptr + TI_FLAGS], %l5 + andcc %l5, _TIF_SYSCALL_TRACE, %g0 be 1f nop @@ -1375,9 +1371,8 @@ call C_LABEL(do_rt_sigreturn) add %sp, STACKFRAME_SZ, %o0 - ld [%curptr + TI_TASK], %l5 - ld [%l5 + AOFF_task_ptrace], %l5 - andcc %l5, 0x02, %g0 + ld [%curptr + TI_FLAGS], %l5 + andcc %l5, _TIF_SYSCALL_TRACE, %g0 be 1f nop @@ -1511,10 +1506,9 @@ mov %i1, %o1 mov %i2, %o2 - ld [%curptr + TI_TASK], %l5 - ld [%l5 + AOFF_task_ptrace], %l5 + ld [%curptr + TI_FLAGS], %l5 mov %i3, %o3 - andcc %l5, 0x02, %g0 + andcc %l5, _TIF_SYSCALL_TRACE, %g0 mov %i4, %o4 bne linux_syscall_trace mov %i0, %l5 @@ -1526,13 +1520,12 @@ .globl C_LABEL(ret_sys_call) C_LABEL(ret_sys_call): - ld [%curptr + TI_TASK], %l6 - ld [%l6 + AOFF_task_ptrace], %l6 + ld [%curptr + TI_FLAGS], %l6 cmp %o0, -ENOIOCTLCMD ld [%sp + STACKFRAME_SZ + PT_PSR], %g3 set PSR_C, %g2 bgeu 1f - andcc %l6, 0x02, %l6 + andcc %l6, _TIF_SYSCALL_TRACE, %g0 /* System call success, clear Carry condition code. */ andn %g3, %g2, %g3 diff -Nru a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c --- a/arch/sparc/kernel/module.c Sat May 24 12:48:19 2003 +++ b/arch/sparc/kernel/module.c Sat May 24 12:48:19 2003 @@ -145,3 +145,7 @@ { return 0; } + +void module_arch_cleanup(struct module *mod) +{ +} diff -Nru a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c --- a/arch/sparc/kernel/process.c Sat May 24 12:48:21 2003 +++ b/arch/sparc/kernel/process.c Sat May 24 12:48:21 2003 @@ -186,18 +186,6 @@ machine_halt(); } -void show_regwindow(struct reg_window *rw) -{ - printk("l0: %08lx l1: %08lx l2: %08lx l3: %08lx " - "l4: %08lx l5: %08lx l6: %08lx l7: %08lx\n", - rw->locals[0], rw->locals[1], rw->locals[2], rw->locals[3], - rw->locals[4], rw->locals[5], rw->locals[6], rw->locals[7]); - printk("i0: %08lx i1: %08lx i2: %08lx i3: %08lx " - "i4: %08lx i5: %08lx fp: %08lx i7: %08lx\n", - rw->ins[0], rw->ins[1], rw->ins[2], rw->ins[3], - rw->ins[4], rw->ins[5], rw->ins[6], rw->ins[7]); -} - static spinlock_t sparc_backtrace_lock = SPIN_LOCK_UNLOCKED; void __show_backtrace(unsigned long fp) @@ -248,6 +236,7 @@ } #endif +#if 0 void show_stackframe(struct sparc_stackf *sf) { unsigned long size; @@ -275,24 +264,27 @@ printk("s%d: %08lx\n", i++, *stk++); } while ((size -= sizeof(unsigned long))); } +#endif -void show_regs(struct pt_regs * regs) +void show_regs(struct pt_regs *r) { - printk("PSR: %08lx PC: %08lx NPC: %08lx Y: %08lx %s\n", regs->psr, - regs->pc, regs->npc, regs->y, print_tainted()); - printk("g0: %08lx g1: %08lx g2: %08lx g3: %08lx ", - regs->u_regs[0], regs->u_regs[1], regs->u_regs[2], - regs->u_regs[3]); - printk("g4: %08lx g5: %08lx g6: %08lx g7: %08lx\n", - regs->u_regs[4], regs->u_regs[5], regs->u_regs[6], - regs->u_regs[7]); - printk("o0: %08lx o1: %08lx o2: %08lx o3: %08lx ", - regs->u_regs[8], regs->u_regs[9], regs->u_regs[10], - regs->u_regs[11]); - printk("o4: %08lx o5: %08lx sp: %08lx o7: %08lx\n", - regs->u_regs[12], regs->u_regs[13], regs->u_regs[14], - regs->u_regs[15]); - show_regwindow((struct reg_window *)regs->u_regs[14]); + struct reg_window *rw = (struct reg_window *) r->u_regs[14]; + + printk("PSR: %08lx PC: %08lx NPC: %08lx Y: %08lx %s\n", + r->psr, r->pc, r->npc, r->y, print_tainted()); + printk("%%G: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + r->u_regs[0], r->u_regs[1], r->u_regs[2], r->u_regs[3], + r->u_regs[4], r->u_regs[5], r->u_regs[6], r->u_regs[7]); + printk("%%O: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + r->u_regs[8], r->u_regs[9], r->u_regs[10], r->u_regs[11], + r->u_regs[12], r->u_regs[13], r->u_regs[14], r->u_regs[15]); + + printk("%%L: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + rw->locals[0], rw->locals[1], rw->locals[2], rw->locals[3], + rw->locals[4], rw->locals[5], rw->locals[6], rw->locals[7]); + printk("%%I: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + rw->ins[0], rw->ins[1], rw->ins[2], rw->ins[3], + rw->ins[4], rw->ins[5], rw->ins[6], rw->ins[7]); } void show_trace_task(struct task_struct *tsk) @@ -411,7 +403,6 @@ { unsigned long parent_tid_ptr = 0; unsigned long child_tid_ptr = 0; - struct task_struct *p; clone_flags &= ~CLONE_IDLETASK; @@ -419,11 +410,10 @@ parent_tid_ptr = regs->u_regs[UREG_G2]; child_tid_ptr = regs->u_regs[UREG_G3]; } - p = do_fork(clone_flags, stack_start, - regs, stack_size, - (int *) parent_tid_ptr, - (int *) child_tid_ptr); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(clone_flags, stack_start, + regs, stack_size, + (int *) parent_tid_ptr, + (int *) child_tid_ptr); } /* Copy a Sparc thread. The fork() return value conventions diff -Nru a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c --- a/arch/sparc/kernel/ptrace.c Sat May 24 12:48:33 2003 +++ b/arch/sparc/kernel/ptrace.c Sat May 24 12:48:33 2003 @@ -521,7 +521,7 @@ addr = 1; case PTRACE_CONT: { /* restart after signal. */ - if ((unsigned long) data > _NSIG) { + if (data > _NSIG) { pt_error_return(regs, EIO); goto out_tsk; } @@ -545,11 +545,10 @@ child->exit_code = data; #ifdef DEBUG_PTRACE - printk("CONT: %s [%d]: set exit_code = %x %x %x\n", child->comm, - child->pid, child->exit_code, + printk("CONT: %s [%d]: set exit_code = %x %lx %lx\n", + child->comm, child->pid, child->exit_code, child->thread.kregs->pc, child->thread.kregs->npc); - #endif wake_up_process(child); pt_succ_return(regs, 0); diff -Nru a/arch/sparc/kernel/sclow.S b/arch/sparc/kernel/sclow.S --- a/arch/sparc/kernel/sclow.S Sat May 24 12:48:31 2003 +++ b/arch/sparc/kernel/sclow.S Sat May 24 12:48:31 2003 @@ -67,27 +67,6 @@ mov 256, %i0 CC_AND_RETT - .globl LABEL(sunossblock) -LABEL(sunossblock): - LOAD_CURRENT(l4, l5) - ld [%l4 + TI_TASK], %l4 - set -65793, %l5 - and %i0, %l5, %l5 - ld [%l4 + AOFF_task_blocked], %i0 - or %i0, %l5, %l5 - st %l5, [%l4 + AOFF_task_blocked] - CC_AND_RETT - - .globl LABEL(sunossmask) -LABEL(sunossmask): - LOAD_CURRENT(l4, l5) - ld [%l4 + TI_TASK], %l4 - set -65793, %l5 - and %i0, %l5, %l5 - ld [%l4 + AOFF_task_blocked], %i0 - st %l5, [%l4 + AOFF_task_blocked] - CC_AND_RETT - .globl LABEL(getpagesize) LABEL(getpagesize): set PAGE_SIZE, %i0 diff -Nru a/arch/sparc/kernel/smp.c b/arch/sparc/kernel/smp.c --- a/arch/sparc/kernel/smp.c Sat May 24 12:48:22 2003 +++ b/arch/sparc/kernel/smp.c Sat May 24 12:48:22 2003 @@ -133,6 +133,16 @@ smp4d_boot_cpus(); } +void smp_send_reschedule(int cpu) +{ + smp_message_pass (cpu, MSG_RESCHEDULE, 0, 0); +} + +void smp_send_stop(void) +{ + smp_message_pass (MSG_ALL_BUT_SELF, MSG_STOP_CPU, 0, 0); +} + void smp_flush_cache_all(void) { xc0((smpfunc_t) BTFIXUP_CALL(local_flush_cache_all)); diff -Nru a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c --- a/arch/sparc/kernel/sparc_ksyms.c Sat May 24 12:48:20 2003 +++ b/arch/sparc/kernel/sparc_ksyms.c Sat May 24 12:48:20 2003 @@ -53,6 +53,7 @@ #endif #include #include +#include extern spinlock_t rtc_lock; @@ -157,7 +158,7 @@ EXPORT_SYMBOL(rtc_lock); EXPORT_SYMBOL(mostek_lock); EXPORT_SYMBOL(mstk48t02_regs); -#if CONFIG_SUN_AUXIO +#ifdef CONFIG_SUN_AUXIO EXPORT_SYMBOL(set_auxio); EXPORT_SYMBOL(get_auxio); #endif @@ -183,7 +184,7 @@ EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(mmu_release_scsi_sgl)); EXPORT_SYMBOL_NOVERS(BTFIXUP_CALL(mmu_release_scsi_one)); -#if CONFIG_SBUS +#ifdef CONFIG_SBUS EXPORT_SYMBOL(sbus_root); EXPORT_SYMBOL(dma_chain); EXPORT_SYMBOL(sbus_set_sbus64); @@ -198,7 +199,7 @@ EXPORT_SYMBOL(sbus_iounmap); EXPORT_SYMBOL(sbus_ioremap); #endif -#if CONFIG_PCI +#ifdef CONFIG_PCI EXPORT_SYMBOL(ebus_chain); EXPORT_SYMBOL(insl); EXPORT_SYMBOL(outsl); @@ -311,6 +312,10 @@ EXPORT_SYMBOL_DOT(umul); EXPORT_SYMBOL_DOT(div); EXPORT_SYMBOL_DOT(udiv); + +#ifdef CONFIG_DEBUG_BUGVERBOSE +EXPORT_SYMBOL(do_BUG); +#endif /* Sun Power Management Idle Handler */ EXPORT_SYMBOL(pm_idle); diff -Nru a/arch/sparc/kernel/traps.c b/arch/sparc/kernel/traps.c --- a/arch/sparc/kernel/traps.c Sat May 24 12:48:25 2003 +++ b/arch/sparc/kernel/traps.c Sat May 24 12:48:25 2003 @@ -463,6 +463,14 @@ send_sig_info(SIGFPE, &info, current); } +#ifdef CONFIG_DEBUG_BUGVERBOSE +void do_BUG(const char *file, int line) +{ + // bust_spinlocks(1); XXX Not in our original BUG() + printk("kernel BUG at %s:%d!\n", file, line); +} +#endif + /* Since we have our mappings set up, on multiprocessors we can spin them * up here so that timer interrupts work during initialization. */ diff -Nru a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c --- a/arch/sparc/mm/init.c Sat May 24 12:48:24 2003 +++ b/arch/sparc/mm/init.c Sat May 24 12:48:24 2003 @@ -107,8 +107,6 @@ add_to_free_ctxlist(ctx_list_pool + ctx); } -#define DEBUG_BOOTMEM - extern unsigned long cmdline_memory_size; unsigned long last_valid_pfn; @@ -157,14 +155,11 @@ unsigned long __init bootmem_init(unsigned long *pages_avail) { - unsigned long bootmap_size, start_pfn, max_pfn; + unsigned long bootmap_size, start_pfn; unsigned long end_of_phys_memory = 0UL; unsigned long bootmap_pfn, bytes_avail, size; int i; -#ifdef DEBUG_BOOTMEM - prom_printf("bootmem_init: Scan sp_banks, "); -#endif bytes_avail = 0UL; for (i = 0; sp_banks[i].num_bytes != 0; i++) { end_of_phys_memory = sp_banks[i].base_addr + @@ -234,10 +229,6 @@ } #endif /* Initialize the boot-time allocator. */ -#ifdef DEBUG_BOOTMEM - prom_printf("init_bootmem(spfn[%lx],bpfn[%lx],mlpfn[%lx])\n", - start_pfn, bootmap_pfn, max_low_pfn); -#endif bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, phys_base>>PAGE_SHIFT, max_low_pfn); /* Now register the available physical memory with the @@ -264,23 +255,14 @@ size = (last_pfn - curr_pfn) << PAGE_SHIFT; *pages_avail += last_pfn - curr_pfn; -#ifdef DEBUG_BOOTMEM - prom_printf("free_bootmem: base[%lx] size[%lx]\n", - sp_banks[i].base_addr, - size); -#endif - free_bootmem(sp_banks[i].base_addr, - size); + + free_bootmem(sp_banks[i].base_addr, size); } #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start) { - size = initrd_end - initrd_start; -#ifdef DEBUG_BOOTMEM - prom_printf("reserve_bootmem: base[%lx] size[%lx]\n", - initrd_start, size); -#endif /* Reserve the initrd image area. */ + size = initrd_end - initrd_start; reserve_bootmem(initrd_start, size); *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; @@ -290,9 +272,6 @@ #endif /* Reserve the kernel text/data/bss. */ size = (start_pfn << PAGE_SHIFT) - phys_base; -#ifdef DEBUG_BOOTMEM - prom_printf("reserve_bootmem: base[%lx] size[%lx]\n", phys_base, size); -#endif reserve_bootmem(phys_base, size); *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; @@ -301,10 +280,6 @@ * in free_all_bootmem. */ size = bootmap_size; -#ifdef DEBUG_BOOTMEM - prom_printf("reserve_bootmem: base[%lx] size[%lx]\n", - (bootmap_pfn << PAGE_SHIFT), size); -#endif reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size); *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT; @@ -448,9 +423,6 @@ max_mapnr = last_valid_pfn - (phys_base >> PAGE_SHIFT); high_memory = __va(max_low_pfn << PAGE_SHIFT); -#ifdef DEBUG_BOOTMEM - prom_printf("mem_init: Calling free_all_bootmem().\n"); -#endif num_physpages = totalram_pages = free_all_bootmem(); for (i = 0; sp_banks[i].num_bytes != 0; i++) { diff -Nru a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c --- a/arch/sparc/mm/srmmu.c Sat May 24 12:48:25 2003 +++ b/arch/sparc/mm/srmmu.c Sat May 24 12:48:25 2003 @@ -1310,7 +1310,7 @@ flush_tlb_all(); poke_srmmu(); -#if CONFIG_SUN_IO +#ifdef CONFIG_SUN_IO srmmu_allocate_ptable_skeleton(sparc_iomap.start, IOBASE_END); srmmu_allocate_ptable_skeleton(DVMA_VADDR, DVMA_END); #endif diff -Nru a/arch/sparc64/defconfig b/arch/sparc64/defconfig --- a/arch/sparc64/defconfig Sat May 24 12:48:22 2003 +++ b/arch/sparc64/defconfig Sat May 24 12:48:22 2003 @@ -477,7 +477,16 @@ # CONFIG_SCTP_ADLER32 is not set # CONFIG_SCTP_DBG_MSG is not set # CONFIG_SCTP_DBG_OBJCNT is not set -# CONFIG_ATM is not set +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y +CONFIG_ATM=y +CONFIG_ATM_CLIP=y +# CONFIG_ATM_CLIP_NO_ICMP is not set +CONFIG_ATM_LANE=m +CONFIG_ATM_MPOA=m +CONFIG_ATM_BR2684=m +CONFIG_ATM_BR2684_IPFILTER=y CONFIG_VLAN_8021Q=m CONFIG_LLC=m CONFIG_LLC_UI=y @@ -487,17 +496,24 @@ # CONFIG_DEV_APPLETALK is not set CONFIG_DECNET=m CONFIG_DECNET_SIOCGIFCONF=y -# CONFIG_DECNET_ROUTER is not set +CONFIG_DECNET_ROUTER=y +CONFIG_DECNET_ROUTE_FWMARK=y + +# +# DECnet: Netfilter Configuration +# +CONFIG_DECNET_NF_GRABULATOR=m CONFIG_BRIDGE=m CONFIG_BRIDGE_NF_EBTABLES=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_IPF=m -CONFIG_BRIDGE_EBT_ARPF=m -CONFIG_BRIDGE_EBT_VLANF=m -CONFIG_BRIDGE_EBT_MARKF=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m CONFIG_BRIDGE_EBT_SNAT=m CONFIG_BRIDGE_EBT_DNAT=m CONFIG_BRIDGE_EBT_REDIRECT=m @@ -517,6 +533,7 @@ CONFIG_NET_SCH_CBQ=m CONFIG_NET_SCH_HTB=m CONFIG_NET_SCH_CSZ=m +CONFIG_NET_SCH_ATM=y CONFIG_NET_SCH_PRIO=m CONFIG_NET_SCH_RED=m CONFIG_NET_SCH_SFQ=m @@ -632,13 +649,14 @@ # CONFIG_ROADRUNNER is not set CONFIG_PLIP=m CONFIG_PPP=m -# CONFIG_PPP_MULTILINK is not set +CONFIG_PPP_MULTILINK=y CONFIG_PPP_FILTER=y -# CONFIG_PPP_ASYNC is not set -# CONFIG_PPP_SYNC_TTY is not set -# CONFIG_PPP_DEFLATE is not set -# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m CONFIG_PPPOE=m +CONFIG_PPPOATM=m CONFIG_SLIP=m CONFIG_SLIP_COMPRESSED=y CONFIG_SLIP_SMART=y @@ -647,7 +665,19 @@ # # Wireless LAN (non-hamradio) # -# CONFIG_NET_RADIO is not set +CONFIG_NET_RADIO=y + +# +# Obsolete Wireless cards support (pre-802.11) +# +# CONFIG_STRIP is not set + +# +# Wireless 802.11b ISA/PCI cards support +# +# CONFIG_AIRO is not set +# CONFIG_HERMES is not set +CONFIG_NET_WIRELESS=y # # Token Ring devices (depends on LLC=y) @@ -663,6 +693,30 @@ # CONFIG_WAN is not set # +# ATM drivers +# +CONFIG_ATM_TCP=m +# CONFIG_ATM_LANAI is not set +# CONFIG_ATM_ENI is not set +# CONFIG_ATM_FIRESTREAM is not set +# CONFIG_ATM_ZATM is not set +# CONFIG_ATM_NICSTAR is not set +# CONFIG_ATM_IDT77252 is not set +# CONFIG_ATM_AMBASSADOR is not set +# CONFIG_ATM_HORIZON is not set +# CONFIG_ATM_IA is not set +CONFIG_ATM_FORE200E_MAYBE=m +CONFIG_ATM_FORE200E_PCA=y +CONFIG_ATM_FORE200E_PCA_DEFAULT_FW=y +CONFIG_ATM_FORE200E_SBA=y +CONFIG_ATM_FORE200E_SBA_DEFAULT_FW=y +CONFIG_ATM_FORE200E_TX_RETRY=16 +CONFIG_ATM_FORE200E_DEBUG=0 +CONFIG_ATM_FORE200E=m +CONFIG_ATM_HE=m +CONFIG_ATM_HE_USE_SUNI=y + +# # Amateur Radio support # CONFIG_HAMRADIO=y @@ -759,9 +813,11 @@ CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y CONFIG_EXT3_FS=m CONFIG_EXT3_FS_XATTR=y CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y CONFIG_JBD=m # CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y @@ -1127,7 +1183,9 @@ CONFIG_USB_RIO500=m # CONFIG_USB_BRLVGER is not set CONFIG_USB_LCD=m +CONFIG_USB_SPEEDTOUCH=m CONFIG_USB_TEST=m +# CONFIG_USB_GADGET is not set # # Bluetooth support diff -Nru a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c --- a/arch/sparc64/kernel/ioctl32.c Sat May 24 12:48:31 2003 +++ b/arch/sparc64/kernel/ioctl32.c Sat May 24 12:48:31 2003 @@ -659,17 +659,6 @@ return err; } -static __inline__ void *alloc_user_space(long len) -{ - struct pt_regs *regs = current_thread_info()->kregs; - unsigned long usp = regs->u_regs[UREG_I6]; - - if (!(test_thread_flag(TIF_32BIT))) - usp += STACK_BIAS; - - return (void *) (usp - len); -} - int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { struct ifreq *u_ifreq64; @@ -685,7 +674,7 @@ return -EFAULT; data64 = A(data32); - u_ifreq64 = alloc_user_space(sizeof(*u_ifreq64)); + u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64)); /* Don't check these user accesses, just let that get trapped * in the ioctl handler instead. @@ -1701,7 +1690,7 @@ static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) { struct sock_fprog32 *u_fprog32 = (struct sock_fprog32 *) arg; - struct sock_fprog *u_fprog64 = alloc_user_space(sizeof(struct sock_fprog)); + struct sock_fprog *u_fprog64 = compat_alloc_user_space(sizeof(struct sock_fprog)); void __user *fptr64; u32 fptr32; u16 flen; diff -Nru a/arch/sparc64/kernel/module.c b/arch/sparc64/kernel/module.c --- a/arch/sparc64/kernel/module.c Sat May 24 12:48:27 2003 +++ b/arch/sparc64/kernel/module.c Sat May 24 12:48:27 2003 @@ -138,7 +138,9 @@ /* Free memory returned from module_core_alloc/module_init_alloc */ void module_free(struct module *mod, void *module_region) { + write_lock(&vmlist_lock); module_unmap(module_region); + write_unlock(&vmlist_lock); /* FIXME: If module_region == mod->init_region, trim exception table entries. */ } @@ -272,4 +274,8 @@ struct module *me) { return 0; +} + +void module_arch_cleanup(struct module *mod) +{ } diff -Nru a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c --- a/arch/sparc64/kernel/power.c Sat May 24 12:48:31 2003 +++ b/arch/sparc64/kernel/power.c Sat May 24 12:48:31 2003 @@ -84,6 +84,16 @@ return 0; } +static int __init has_button_interrupt(struct linux_ebus_device *edev) +{ + if (edev->irqs[0] == PCI_IRQ_NONE) + return 0; + if (!prom_node_has_property(edev->prom_node, "button")) + return 0; + + return 1; +} + void __init power_init(void) { struct linux_ebus *ebus; @@ -106,7 +116,7 @@ power_reg = (unsigned long)ioremap(edev->resource[0].start, 0x4); printk("power: Control reg at %016lx ... ", power_reg); poweroff_method = machine_halt; /* able to use the standard halt */ - if (edev->irqs[0] != PCI_IRQ_NONE) { + if (has_button_interrupt(edev)) { if (kernel_thread(powerd, 0, CLONE_FS) < 0) { printk("Failed to start power daemon.\n"); return; diff -Nru a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c --- a/arch/sparc64/kernel/process.c Sat May 24 12:48:24 2003 +++ b/arch/sparc64/kernel/process.c Sat May 24 12:48:24 2003 @@ -568,7 +568,6 @@ struct pt_regs *regs, unsigned long stack_size) { - struct task_struct *p; unsigned long parent_tid_ptr = 0; unsigned long child_tid_ptr = 0; @@ -583,12 +582,10 @@ } } - p = do_fork(clone_flags, stack_start, - regs, stack_size, - (int *) parent_tid_ptr, - (int *) child_tid_ptr); - - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(clone_flags, stack_start, + regs, stack_size, + (int *) parent_tid_ptr, + (int *) child_tid_ptr); } /* Copy a Sparc thread. The fork() return value conventions diff -Nru a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c --- a/arch/sparc64/kernel/sparc64_ksyms.c Sat May 24 12:48:31 2003 +++ b/arch/sparc64/kernel/sparc64_ksyms.c Sat May 24 12:48:31 2003 @@ -196,11 +196,11 @@ EXPORT_SYMBOL(mostek_lock); EXPORT_SYMBOL(mstk48t02_regs); EXPORT_SYMBOL(request_fast_irq); -#if CONFIG_SUN_AUXIO +#ifdef CONFIG_SUN_AUXIO EXPORT_SYMBOL(auxio_set_led); EXPORT_SYMBOL(auxio_set_lte); #endif -#if CONFIG_SBUS +#ifdef CONFIG_SBUS EXPORT_SYMBOL(sbus_root); EXPORT_SYMBOL(dma_chain); EXPORT_SYMBOL(sbus_set_sbus64); diff -Nru a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c --- a/arch/sparc64/solaris/socksys.c Sat May 24 12:48:23 2003 +++ b/arch/sparc64/solaris/socksys.c Sat May 24 12:48:23 2003 @@ -191,10 +191,9 @@ printk ("Couldn't create socket\n"); return ret; } - devfs_register (NULL, "socksys", DEVFS_FL_DEFAULT, - 30, 0, - S_IFCHR | S_IRUSR | S_IWUSR, - &socksys_fops, NULL); + + devfs_mk_cdev(MKDEV(30, 0), S_IFCHR|S_IRUSR|S_IWUSR, "socksys"); + file = fcheck(ret); /* N.B. Is this valid? Suppose the f_ops are in a module ... */ socksys_file_ops = *file->f_op; diff -Nru a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c --- a/arch/um/drivers/mmapper_kern.c Sat May 24 12:48:20 2003 +++ b/arch/um/drivers/mmapper_kern.c Sat May 24 12:48:20 2003 @@ -124,9 +124,7 @@ p_buf = __pa(v_buf); - devfs_register (NULL, "mmapper", DEVFS_FL_DEFAULT, - 30, 0, S_IFCHR | S_IRUGO | S_IWUGO, - &mmapper_fops, NULL); + devfs_mk_cdev(MKDEV(30, 0), S_IFCHR|S_IRUGO|S_IWUGO, "mmapper"); devfs_mk_symlink("mmapper0", "mmapper"); return(0); } diff -Nru a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c --- a/arch/um/kernel/irq.c Sat May 24 12:48:30 2003 +++ b/arch/um/kernel/irq.c Sat May 24 12:48:30 2003 @@ -48,7 +48,7 @@ * each architecture has to answer this themselves, it doesn't deserve * a generic callback i think. */ -#if CONFIG_X86 +#ifdef CONFIG_X86 printk(KERN_ERR "unexpected IRQ trap at vector %02x\n", irq); #ifdef CONFIG_X86_LOCAL_APIC /* @@ -121,7 +121,7 @@ } p += sprintf(p, "\n"); #ifdef notdef -#if CONFIG_SMP +#ifdef CONFIG_SMP p += sprintf(p, "LOC: "); for (j = 0; j < num_online_cpus(); j++) p += sprintf(p, "%10u ", @@ -198,7 +198,7 @@ spin_unlock_irqrestore(&desc->lock, flags); } -#if CONFIG_SMP +#ifdef CONFIG_SMP inline void synchronize_irq(unsigned int irq) { /* is there anything to synchronize with? */ @@ -621,7 +621,7 @@ err = parse_hex_value(buffer, count, &new_value); -#if CONFIG_SMP +#ifdef CONFIG_SMP /* * Do not allow disabling IRQs completely - it's a too easy * way to make the system unusable accidentally :-) At least diff -Nru a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c --- a/arch/um/kernel/mem.c Sat May 24 12:48:23 2003 +++ b/arch/um/kernel/mem.c Sat May 24 12:48:23 2003 @@ -124,7 +124,7 @@ kmem_top = new; } -#if CONFIG_HIGHMEM +#ifdef CONFIG_HIGHMEM /* Changed during early boot */ pte_t *kmap_pte; pgprot_t kmap_prot; @@ -329,7 +329,7 @@ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; fixrange_init(vaddr, FIXADDR_TOP, swapper_pg_dir); -#if CONFIG_HIGHMEM +#ifdef CONFIG_HIGHMEM init_highmem(); setup_highmem(highmem); #endif diff -Nru a/arch/um/kernel/sys_call_table.c b/arch/um/kernel/sys_call_table.c --- a/arch/um/kernel/sys_call_table.c Sat May 24 12:48:31 2003 +++ b/arch/um/kernel/sys_call_table.c Sat May 24 12:48:31 2003 @@ -236,7 +236,7 @@ extern syscall_handler_t sys_remap_file_pages; extern syscall_handler_t sys_set_tid_address; -#if CONFIG_NFSD +#ifdef CONFIG_NFSD #define NFSSERVCTL sys_nfsservctl #else #define NFSSERVCTL sys_ni_syscall diff -Nru a/arch/v850/kernel/module.c b/arch/v850/kernel/module.c --- a/arch/v850/kernel/module.c Sat May 24 12:48:25 2003 +++ b/arch/v850/kernel/module.c Sat May 24 12:48:25 2003 @@ -230,3 +230,8 @@ return 0; } + +void +module_arch_cleanup(struct module *mod) +{ +} diff -Nru a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig --- a/arch/x86_64/Kconfig Sat May 24 12:48:30 2003 +++ b/arch/x86_64/Kconfig Sat May 24 12:48:30 2003 @@ -652,6 +652,7 @@ config IOMMU_LEAK bool "IOMMU leak tracing" depends on DEBUG_KERNEL + depends on IOMMU_DEBUG help Add a simple leak tracer to the IOMMU code. This is useful when you are debugging a buggy device driver that leaks IOMMU mappings. diff -Nru a/arch/x86_64/Makefile b/arch/x86_64/Makefile --- a/arch/x86_64/Makefile Sat May 24 12:48:31 2003 +++ b/arch/x86_64/Makefile Sat May 24 12:48:31 2003 @@ -46,6 +46,7 @@ CFLAGS += -fno-reorder-blocks # should lower this a lot and see how much .text is saves CFLAGS += -finline-limit=2000 +CFLAGS += -Wno-sign-compare #CFLAGS += -g # don't enable this when you use kgdb: ifneq ($(CONFIG_X86_REMOTE_DEBUG),y) diff -Nru a/arch/x86_64/defconfig b/arch/x86_64/defconfig --- a/arch/x86_64/defconfig Sat May 24 12:48:28 2003 +++ b/arch/x86_64/defconfig Sat May 24 12:48:28 2003 @@ -4,7 +4,6 @@ CONFIG_X86_64=y CONFIG_X86=y CONFIG_MMU=y -CONFIG_SWAP=y CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_X86_CMPXCHG=y CONFIG_EARLY_PRINTK=y @@ -18,6 +17,7 @@ # # General setup # +CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y @@ -47,8 +47,12 @@ CONFIG_X86_IO_APIC=y CONFIG_X86_LOCAL_APIC=y CONFIG_MTRR=y -CONFIG_HUGETLB_PAGE=y +# CONFIG_HUGETLB_PAGE is not set CONFIG_SMP=y +# CONFIG_PREEMPT is not set +CONFIG_K8_NUMA=y +CONFIG_DISCONTIGMEM=y +CONFIG_NUMA=y CONFIG_HAVE_DEC_LOCK=y CONFIG_NR_CPUS=8 CONFIG_GART_IOMMU=y @@ -222,9 +226,8 @@ # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set -CONFIG_NETLINK_DEV=y +# CONFIG_NETLINK_DEV is not set # CONFIG_NETFILTER is not set -CONFIG_FILTER=y CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y @@ -239,8 +242,9 @@ # CONFIG_SYN_COOKIES is not set # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set -# CONFIG_XFRM_USER is not set +# CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set # # SCTP Configuration (EXPERIMENTAL) @@ -331,6 +335,11 @@ # CONFIG_R8169 is not set # CONFIG_SK98LIN is not set CONFIG_TIGON3=y + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set # CONFIG_PPP is not set @@ -405,15 +414,7 @@ CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y # CONFIG_MOUSE_SERIAL is not set -CONFIG_INPUT_JOYSTICK=y -# CONFIG_JOYSTICK_IFORCE is not set -# CONFIG_JOYSTICK_WARRIOR is not set -# CONFIG_JOYSTICK_MAGELLAN is not set -# CONFIG_JOYSTICK_SPACEORB is not set -# CONFIG_JOYSTICK_SPACEBALL is not set -# CONFIG_JOYSTICK_STINGER is not set -# CONFIG_JOYSTICK_TWIDDLER is not set -# CONFIG_INPUT_JOYDUMP is not set +# CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set @@ -452,6 +453,7 @@ # # I2C Hardware Sensors Chip support # +# CONFIG_I2C_SENSOR is not set # # Mice @@ -468,8 +470,7 @@ # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set -# CONFIG_AMD_RNG is not set +CONFIG_HW_RANDOM=y # CONFIG_NVRAM is not set CONFIG_RTC=y # CONFIG_DTLK is not set @@ -481,8 +482,8 @@ # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_AGP_GART is not set +CONFIG_AGP=y +CONFIG_AGP_AMD_8151=y # CONFIG_DRM is not set # CONFIG_MWAVE is not set CONFIG_RAW_DRIVER=y @@ -498,57 +499,75 @@ # CONFIG_VIDEO_DEV is not set # +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# # File systems # -# CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y -# CONFIG_AUTOFS4_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_FS_XATTR is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set CONFIG_REISERFS_FS=y # CONFIG_REISERFS_CHECK is not set # CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_JFS_FS is not set +CONFIG_XFS_FS=m +# CONFIG_XFS_RT is not set +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_POSIX_ACL is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_TMPFS=y +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=y -# CONFIG_EXT3_FS_XATTR is not set -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -# CONFIG_FAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_HUGETLBFS=y -CONFIG_ISO9660_FS=y -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_JFS_FS is not set -# CONFIG_MINIX_FS is not set # CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set # CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set # CONFIG_UFS_FS is not set -CONFIG_XFS_FS=m -# CONFIG_XFS_RT is not set -# CONFIG_XFS_QUOTA is not set -# CONFIG_XFS_POSIX_ACL is not set # # Network File Systems # -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V4 is not set @@ -556,14 +575,16 @@ CONFIG_NFSD_V3=y # CONFIG_NFSD_V4 is not set CONFIG_NFSD_TCP=y -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_GSS is not set CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y -# CONFIG_CIFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set # CONFIG_AFS_FS is not set # @@ -594,6 +615,7 @@ # USB support # # CONFIG_USB is not set +# CONFIG_USB_GADGET is not set # # Bluetooth support @@ -615,6 +637,9 @@ # CONFIG_INIT_DEBUG is not set CONFIG_KALLSYMS=y # CONFIG_FRAME_POINTER is not set +CONFIG_IOMMU_DEBUG=y +CONFIG_IOMMU_LEAK=y +CONFIG_MCE_DEBUG=y # # Security options diff -Nru a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile --- a/arch/x86_64/ia32/Makefile Sat May 24 12:48:22 2003 +++ b/arch/x86_64/ia32/Makefile Sat May 24 12:48:22 2003 @@ -5,3 +5,12 @@ obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_ioctl.o \ ia32_signal.o tls32.o \ ia32_binfmt.o fpu32.o ptrace32.o ipc32.o syscall32.o + +$(obj)/syscall32.o: $(src)/syscall32.c $(obj)/vsyscall.so + +# The DSO images are built using a special linker script. +$(obj)/vsyscall.so: $(src)/vsyscall.lds $(obj)/vsyscall.o + $(CC) -m32 -nostdlib -shared -s -Wl,-soname=linux-vsyscall.so.1 \ + -o $@ -Wl,-T,$^ + +AFLAGS_vsyscall.o = -m32 diff -Nru a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c --- a/arch/x86_64/ia32/ia32_binfmt.c Sat May 24 12:48:19 2003 +++ b/arch/x86_64/ia32/ia32_binfmt.c Sat May 24 12:48:19 2003 @@ -6,13 +6,14 @@ * of ugly preprocessor tricks. Talk about very very poor man's inheritance. */ #include -#include #include #include #include #include +#include #include #include +#include #include #include #include @@ -22,12 +23,17 @@ #include #include #include +#include #define ELF_NAME "elf/i386" #define AT_SYSINFO 32 +#define AT_SYSINFO_EHDR 33 -#define ARCH_DLINFO NEW_AUX_ENT(AT_SYSINFO, 0xffffe000) +#define ARCH_DLINFO do { \ + NEW_AUX_ENT(AT_SYSINFO, (u32)(u64)VSYSCALL32_VSYSCALL); \ + NEW_AUX_ENT(AT_SYSINFO_EHDR, VSYSCALL32_BASE); \ +} while(0) struct file; struct elf_phdr; @@ -53,6 +59,47 @@ #define ELF_NGREG (sizeof (struct user_regs_struct32) / sizeof(elf_greg_t)) typedef elf_greg_t elf_gregset_t[ELF_NGREG]; +/* + * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out + * extra segments containing the vsyscall DSO contents. Dumping its + * contents makes post-mortem fully interpretable later without matching up + * the same kernel and hardware config to see what PC values meant. + * Dumping its extra ELF program headers includes all the other information + * a debugger needs to easily find how the vsyscall DSO was being used. + */ +#define ELF_CORE_EXTRA_PHDRS (VSYSCALL32_EHDR->e_phnum) +#define ELF_CORE_WRITE_EXTRA_PHDRS \ +do { \ + const struct elf32_phdr *const vsyscall_phdrs = \ + (const struct elf32_phdr *) (VSYSCALL32_BASE \ + + VSYSCALL32_EHDR->e_phoff); \ + int i; \ + Elf32_Off ofs = 0; \ + for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \ + struct elf_phdr phdr = vsyscall_phdrs[i]; \ + if (phdr.p_type == PT_LOAD) { \ + ofs = phdr.p_offset = offset; \ + offset += phdr.p_filesz; \ + } \ + else \ + phdr.p_offset += ofs; \ + phdr.p_paddr = 0; /* match other core phdrs */ \ + DUMP_WRITE(&phdr, sizeof(phdr)); \ + } \ +} while (0) +#define ELF_CORE_WRITE_EXTRA_DATA \ +do { \ + const struct elf32_phdr *const vsyscall_phdrs = \ + (const struct elf32_phdr *) (VSYSCALL32_BASE \ + + VSYSCALL32_EHDR->e_phoff); \ + int i; \ + for (i = 0; i < VSYSCALL32_EHDR->e_phnum; ++i) { \ + if (vsyscall_phdrs[i].p_type == PT_LOAD) \ + DUMP_WRITE((void *) (u64) vsyscall_phdrs[i].p_vaddr, \ + vsyscall_phdrs[i].p_filesz); \ + } \ +} while (0) + struct elf_siginfo { int si_signo; /* signal number */ @@ -156,7 +203,6 @@ struct _fpstate_ia32 *fpstate = (void*)fpu; struct pt_regs *regs = (struct pt_regs *)(tsk->thread.rsp0); mm_segment_t oldfs = get_fs(); - int ret; if (!tsk->used_math) return 0; @@ -164,12 +210,12 @@ if (tsk == current) unlazy_fpu(tsk); set_fs(KERNEL_DS); - ret = save_i387_ia32(tsk, fpstate, regs, 1); + save_i387_ia32(tsk, fpstate, regs, 1); /* Correct for i386 bug. It puts the fop into the upper 16bits of the tag word (like FXSAVE), not into the fcs*/ fpstate->cssel |= fpstate->tag & 0xffff0000; set_fs(oldfs); - return ret; + return 1; } #define ELF_CORE_COPY_XFPREGS 1 @@ -272,9 +318,6 @@ set_thread_flag(TIF_IA32); } -extern void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long address); - - int setup_arg_pages(struct linux_binprm *bprm) { unsigned long stack_base; @@ -304,8 +347,9 @@ mpnt->vm_mm = mm; mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p; mpnt->vm_end = IA32_STACK_TOP; - mpnt->vm_page_prot = PAGE_COPY_EXEC; - mpnt->vm_flags = VM_STACK_FLAGS; + mpnt->vm_flags = vm_stack_flags32; + mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC) ? + PAGE_COPY_EXEC : PAGE_COPY; mpnt->vm_ops = NULL; mpnt->vm_pgoff = 0; mpnt->vm_file = NULL; @@ -319,7 +363,7 @@ struct page *page = bprm->page[i]; if (page) { bprm->page[i] = NULL; - put_dirty_page(current,page,stack_base); + put_dirty_page(current,page,stack_base,PAGE_COPY_EXEC); } stack_base += PAGE_SIZE; } @@ -335,7 +379,7 @@ struct task_struct *me = current; if (prot & PROT_READ) - prot |= PROT_EXEC; + prot |= vm_force_exec32; down_write(&me->mm->mmap_sem); map_addr = do_mmap(filep, ELF_PAGESTART(addr), diff -Nru a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c --- a/arch/x86_64/ia32/ia32_ioctl.c Sat May 24 12:48:25 2003 +++ b/arch/x86_64/ia32/ia32_ioctl.c Sat May 24 12:48:25 2003 @@ -10,10 +10,10 @@ */ #include +#include #include #include #include -#include #include #include #include @@ -108,10 +108,6 @@ #include - -#define A(__x) ((void *)(unsigned long)(__x)) -#define AA(__x) A(__x) - /* Aiee. Someone does not find a difference between int and long */ #define EXT2_IOC32_GETFLAGS _IOR('f', 1, int) #define EXT2_IOC32_SETFLAGS _IOW('f', 2, int) @@ -163,10 +159,10 @@ } struct video_tuner32 { - s32 tuner; - u8 name[32]; - u32 rangelow, rangehigh; - u32 flags; + compat_int_t tuner; + char name[32]; + compat_ulong_t rangelow, rangehigh; + u32 flags; /* It is really u32 in videodev.h */ u16 mode, signal; }; @@ -203,8 +199,8 @@ } struct video_buffer32 { - /* void * */ u32 base; - s32 height, width, depth, bytesperline; + compat_caddr_t base; + compat_int_t height, width, depth, bytesperline; }; static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 *up) @@ -235,14 +231,14 @@ } struct video_clip32 { - s32 x, y, width, height; - /* struct video_clip32 * */ u32 next; + s32 x, y, width, height; /* Its really s32 in videodev.h */ + compat_caddr_t next; }; struct video_window32 { u32 x, y, width, height, chromakey, flags; - /* struct video_clip32 * */ u32 clips; - s32 clipcount; + compat_caddr_t clips; + compat_int_t clipcount; }; static void free_kvideo_clips(struct video_window *kp) @@ -270,7 +266,7 @@ __get_user(kp->flags, &up->flags); __get_user(kp->clipcount, &up->clipcount); __get_user(tmp, &up->clips); - ucp = (struct video_clip32 *)A(tmp); + ucp = compat_ptr(tmp); kp->clips = NULL; nclips = kp->clipcount; @@ -421,8 +417,8 @@ } struct ifmap32 { - u32 mem_start; - u32 mem_end; + compat_ulong_t mem_start; + compat_ulong_t mem_end; unsigned short base_addr; unsigned char irq; unsigned char dma; @@ -442,17 +438,18 @@ struct sockaddr ifru_netmask; struct sockaddr ifru_hwaddr; short ifru_flags; - int ifru_ivalue; - int ifru_mtu; + compat_int_t ifru_ivalue; + compat_int_t ifru_mtu; struct ifmap32 ifru_map; char ifru_slave[IFNAMSIZ]; /* Just fits the size */ char ifru_newname[IFNAMSIZ]; compat_caddr_t ifru_data; + /* XXXX? ifru_settings should be here */ } ifr_ifru; }; struct ifconf32 { - int ifc_len; /* size of buffer */ + compat_int_t ifc_len; /* size of buffer */ compat_caddr_t ifcbuf; }; @@ -504,7 +501,7 @@ return -ENOMEM; } ifr = ifc.ifc_req; - ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf); + ifr32 = compat_ptr(ifc32.ifcbuf); for (i = 0; i < ifc32.ifc_len; i += sizeof (struct ifreq32)) { if (copy_from_user(ifr, ifr32, sizeof (struct ifreq32))) { kfree (ifc.ifc_buf); @@ -518,7 +515,7 @@ set_fs (old_fs); if (!err) { ifr = ifc.ifc_req; - ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf); + ifr32 = compat_ptr(ifc32.ifcbuf); for (i = 0, j = 0; i < ifc32.ifc_len && j < ifc.ifc_len; i += sizeof (struct ifreq32), j += sizeof (struct ifreq)) { int k = copy_to_user(ifr32, ifr, sizeof (struct ifreq32)); @@ -568,7 +565,7 @@ __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data)); - if (get_user(ethcmd, (u32 *)A(data))) { + if (get_user(ethcmd, (u32 *)compat_ptr(data))) { err = -EFAULT; goto out; } @@ -579,12 +576,16 @@ case ETHTOOL_GLINK: case ETHTOOL_NWAY_RST: len = sizeof(struct ethtool_value); break; case ETHTOOL_GREGS: { - struct ethtool_regs *regaddr = (struct ethtool_regs *)A(data); + struct ethtool_regs *regaddr = compat_ptr(data); /* darned variable size arguments */ if (get_user(len, (u32 *)®addr->len)) { err = -EFAULT; goto out; } + if (len > PAGE_SIZE - sizeof(struct ethtool_regs)) { + err = -EINVAL; + goto out; + } len += sizeof(struct ethtool_regs); break; } @@ -595,7 +596,7 @@ goto out; } - if (copy_from_user(ifr.ifr_data, (char *)A(data), len)) { + if (copy_from_user(ifr.ifr_data, compat_ptr(data), len)) { err = -EFAULT; goto out; } @@ -608,7 +609,7 @@ u32 data; __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data)); - len = copy_to_user((char *)A(data), ifr.ifr_data, len); + len = copy_to_user(compat_ptr(data), ifr.ifr_data, len); if (len) err = -EFAULT; } @@ -651,7 +652,7 @@ }; __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data)); - if (copy_from_user(ifr.ifr_data, (char *)A(data), len)) { + if (copy_from_user(ifr.ifr_data, compat_ptr(data), len)) { err = -EFAULT; goto out; } @@ -661,7 +662,7 @@ err = sys_ioctl (fd, cmd, (unsigned long)&ifr); set_fs (old_fs); if (!err) { - len = copy_to_user((char *)A(data), ifr.ifr_data, len); + len = copy_to_user(compat_ptr(data), ifr.ifr_data, len); if (len) err = -EFAULT; } @@ -671,12 +672,6 @@ return err; } -static __inline__ void *alloc_user_space(long len) -{ - struct pt_regs *regs = (void *)current->thread.rsp0 - sizeof(struct pt_regs); - return (void *)regs->rsp - len; -} - int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { struct ifreq *u_ifreq64; @@ -690,9 +685,9 @@ return -EFAULT; if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data)) return -EFAULT; - data64 = (void *) A(data32); + data64 = compat_ptr(data32); - u_ifreq64 = alloc_user_space(sizeof(*u_ifreq64)); + u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64)); /* Don't check these user accesses, just let that get trapped * in the ioctl handler instead. @@ -827,7 +822,7 @@ ret |= __get_user (r4.rt_irtt, &(((struct rtentry32 *)arg)->rt_irtt)); ret |= __get_user (rtdev, &(((struct rtentry32 *)arg)->rt_dev)); if (rtdev) { - ret |= copy_from_user (devname, (char *)A(rtdev), 15); + ret |= copy_from_user (devname, compat_ptr(rtdev), 15); r4.rt_dev = devname; devname[15] = 0; } else r4.rt_dev = 0; @@ -874,23 +869,23 @@ struct fb_fix_screeninfo32 { char id[16]; compat_caddr_t smem_start; - __u32 smem_len; - __u32 type; - __u32 type_aux; - __u32 visual; - __u16 xpanstep; - __u16 ypanstep; - __u16 ywrapstep; - __u32 line_length; + u32 smem_len; + u32 type; + u32 type_aux; + u32 visual; + u16 xpanstep; + u16 ypanstep; + u16 ywrapstep; + u32 line_length; compat_caddr_t mmio_start; - __u32 mmio_len; - __u32 accel; - __u16 reserved[3]; + u32 mmio_len; + u32 accel; + u16 reserved[3]; }; struct fb_cmap32 { - __u32 start; - __u32 len; + u32 start; + u32 len; compat_caddr_t red; compat_caddr_t green; compat_caddr_t blue; @@ -924,6 +919,10 @@ err = -EFAULT; goto out; } + if (cmap.len > PAGE_SIZE/sizeof(u16)) { + err = -EINVAL; + goto out; + } err = -ENOMEM; cmap.red = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL); if (!cmap.red) @@ -943,10 +942,10 @@ if (cmd == FBIOGETCMAP) break; - err = __copy_from_user(cmap.red, (char *)A(red), cmap.len * sizeof(__u16)); - err |= __copy_from_user(cmap.green, (char *)A(green), cmap.len * sizeof(__u16)); - err |= __copy_from_user(cmap.blue, (char *)A(blue), cmap.len * sizeof(__u16)); - if (cmap.transp) err |= __copy_from_user(cmap.transp, (char *)A(transp), cmap.len * sizeof(__u16)); + err = __copy_from_user(cmap.red, compat_ptr(red), cmap.len * sizeof(__u16)); + err |= __copy_from_user(cmap.green, compat_ptr(green), cmap.len * sizeof(__u16)); + err |= __copy_from_user(cmap.blue, compat_ptr(blue), cmap.len * sizeof(__u16)); + if (cmap.transp) err |= __copy_from_user(cmap.transp, compat_ptr(transp), cmap.len * sizeof(__u16)); if (err) { err = -EFAULT; goto out; @@ -985,11 +984,11 @@ err |= __copy_to_user((char *)((struct fb_fix_screeninfo32 *)arg)->reserved, (char *)fix.reserved, sizeof(fix.reserved)); break; case FBIOGETCMAP: - err = __copy_to_user((char *)A(red), cmap.red, cmap.len * sizeof(__u16)); - err |= __copy_to_user((char *)A(green), cmap.blue, cmap.len * sizeof(__u16)); - err |= __copy_to_user((char *)A(blue), cmap.blue, cmap.len * sizeof(__u16)); + err = __copy_to_user(compat_ptr(red), cmap.red, cmap.len * sizeof(__u16)); + err |= __copy_to_user(compat_ptr(green), cmap.blue, cmap.len * sizeof(__u16)); + err |= __copy_to_user(compat_ptr(blue), cmap.blue, cmap.len * sizeof(__u16)); if (cmap.transp) - err |= __copy_to_user((char *)A(transp), cmap.transp, cmap.len * sizeof(__u16)); + err |= __copy_to_user(compat_ptr(transp), cmap.transp, cmap.len * sizeof(__u16)); break; case FBIOPUTCMAP: break; @@ -1024,11 +1023,11 @@ } struct floppy_struct32 { - unsigned int size; - unsigned int sect; - unsigned int head; - unsigned int track; - unsigned int stretch; + compat_uint_t size; + compat_uint_t sect; + compat_uint_t head; + compat_uint_t track; + compat_uint_t stretch; unsigned char gap; unsigned char rate; unsigned char spec1; @@ -1038,51 +1037,51 @@ struct floppy_drive_params32 { char cmos; - u32 max_dtr; - u32 hlt; - u32 hut; - u32 srt; - u32 spinup; - u32 spindown; + compat_ulong_t max_dtr; + compat_ulong_t hlt; + compat_ulong_t hut; + compat_ulong_t srt; + compat_ulong_t spinup; + compat_ulong_t spindown; unsigned char spindown_offset; unsigned char select_delay; unsigned char rps; unsigned char tracks; - u32 timeout; + compat_ulong_t timeout; unsigned char interleave_sect; struct floppy_max_errors max_errors; char flags; char read_track; short autodetect[8]; - int checkfreq; - int native_format; + compat_int_t checkfreq; + compat_int_t native_format; }; struct floppy_drive_struct32 { signed char flags; - u32 spinup_date; - u32 select_date; - u32 first_read_date; + compat_ulong_t spinup_date; + compat_ulong_t select_date; + compat_ulong_t first_read_date; short probed_format; short track; short maxblock; short maxtrack; - int generation; - int keep_data; - int fd_ref; - int fd_device; - int last_checked; + compat_int_t generation; + compat_int_t keep_data; + compat_int_t fd_ref; + compat_int_t fd_device; + compat_int_t last_checked; compat_caddr_t dmabuf; - int bufblocks; + compat_int_t bufblocks; }; struct floppy_fdc_state32 { - int spec1; - int spec2; - int dtr; + compat_int_t spec1; + compat_int_t spec2; + compat_int_t dtr; unsigned char version; unsigned char dor; - u32 address; + compat_ulong_t address; unsigned int rawcmd:2; unsigned int reset:1; unsigned int need_configure:1; @@ -1094,11 +1093,11 @@ struct floppy_write_errors32 { unsigned int write_errors; - u32 first_error_sector; - int first_error_generation; - u32 last_error_sector; - int last_error_generation; - unsigned int badness; + compat_ulong_t first_error_sector; + compat_int_t first_error_generation; + compat_ulong_t last_error_sector; + compat_int_t last_error_generation; + compat_uint_t badness; }; #define FDSETPRM32 _IOW(2, 0x42, struct floppy_struct32) @@ -1335,42 +1334,46 @@ typedef struct sg_io_hdr32 { - s32 interface_id; /* [i] 'S' for SCSI generic (required) */ - s32 dxfer_direction; /* [i] data transfer direction */ - u8 cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ - u8 mx_sb_len; /* [i] max length to write to sbp */ - u16 iovec_count; /* [i] 0 implies no scatter gather */ - u32 dxfer_len; /* [i] byte count of data transfer */ - u32 dxferp; /* [i], [*io] points to data transfer memory + compat_int_t interface_id; /* [i] 'S' for SCSI generic (required) */ + compat_int_t dxfer_direction; /* [i] data transfer direction */ + unsigned char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ + unsigned char mx_sb_len; /* [i] max length to write to sbp */ + unsigned short iovec_count; /* [i] 0 implies no scatter gather */ + compat_uint_t dxfer_len; /* [i] byte count of data transfer */ + compat_uint_t dxferp; /* [i], [*io] points to data transfer memory or scatter gather list */ - u32 cmdp; /* [i], [*i] points to command to perform */ - u32 sbp; /* [i], [*o] points to sense_buffer memory */ - u32 timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */ - u32 flags; /* [i] 0 -> default, see SG_FLAG... */ - s32 pack_id; /* [i->o] unused internally (normally) */ - u32 usr_ptr; /* [i->o] unused internally */ - u8 status; /* [o] scsi status */ - u8 masked_status; /* [o] shifted, masked scsi status */ - u8 msg_status; /* [o] messaging level data (optional) */ - u8 sb_len_wr; /* [o] byte count actually written to sbp */ - u16 host_status; /* [o] errors from host adapter */ - u16 driver_status; /* [o] errors from software driver */ - s32 resid; /* [o] dxfer_len - actual_transferred */ - u32 duration; /* [o] time taken by cmd (unit: millisec) */ - u32 info; /* [o] auxiliary information */ + compat_uptr_t cmdp; /* [i], [*i] points to command to perform */ + compat_uptr_t sbp; /* [i], [*o] points to sense_buffer memory */ + compat_uint_t timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */ + compat_uint_t flags; /* [i] 0 -> default, see SG_FLAG... */ + compat_int_t pack_id; /* [i->o] unused internally (normally) */ + compat_uptr_t usr_ptr; /* [i->o] unused internally */ + unsigned char status; /* [o] scsi status */ + unsigned char masked_status; /* [o] shifted, masked scsi status */ + unsigned char msg_status; /* [o] messaging level data (optional) */ + unsigned char sb_len_wr; /* [o] byte count actually written to sbp */ + unsigned short host_status; /* [o] errors from host adapter */ + unsigned short driver_status; /* [o] errors from software driver */ + compat_int_t resid; /* [o] dxfer_len - actual_transferred */ + compat_uint_t duration; /* [o] time taken by cmd (unit: millisec) */ + compat_uint_t info; /* [o] auxiliary information */ } sg_io_hdr32_t; /* 64 bytes long (on sparc32) */ typedef struct sg_iovec32 { - u32 iov_base; - u32 iov_len; + compat_uint_t iov_base; + compat_uint_t iov_len; } sg_iovec32_t; +#define EMU_SG_MAX 128 + static int alloc_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32) { - sg_iovec32_t *uiov = (sg_iovec32_t *) A(uptr32); + sg_iovec32_t *uiov = compat_ptr(uptr32); sg_iovec_t *kiov; int i; + if (sgp->iovec_count > EMU_SG_MAX) + return -EINVAL; sgp->dxferp = kmalloc(sgp->iovec_count * sizeof(sg_iovec_t), GFP_KERNEL); if (!sgp->dxferp) @@ -1384,39 +1387,9 @@ if (__get_user(iov_base32, &uiov->iov_base) || __get_user(kiov->iov_len, &uiov->iov_len)) return -EFAULT; - - kiov->iov_base = kmalloc(kiov->iov_len, GFP_KERNEL); - if (!kiov->iov_base) - return -ENOMEM; - if (copy_from_user(kiov->iov_base, - (void *) A(iov_base32), - kiov->iov_len)) + if (verify_area(VERIFY_WRITE, compat_ptr(iov_base32), kiov->iov_len)) return -EFAULT; - - uiov++; - kiov++; - } - - return 0; -} - -static int copy_back_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32) -{ - sg_iovec32_t *uiov = (sg_iovec32_t *) A(uptr32); - sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp; - int i; - - for (i = 0; i < sgp->iovec_count; i++) { - u32 iov_base32; - - if (__get_user(iov_base32, &uiov->iov_base)) - return -EFAULT; - - if (copy_to_user((void *) A(iov_base32), - kiov->iov_base, - kiov->iov_len)) - return -EFAULT; - + kiov->iov_base = compat_ptr(iov_base32); uiov++; kiov++; } @@ -1426,16 +1399,6 @@ static void free_sg_iovec(sg_io_hdr_t *sgp) { - sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp; - int i; - - for (i = 0; i < sgp->iovec_count; i++) { - if (kiov->iov_base) { - kfree(kiov->iov_base); - kiov->iov_base = NULL; - } - kiov++; - } kfree(sgp->dxferp); sgp->dxferp = NULL; } @@ -1465,12 +1428,8 @@ err |= __get_user(cmdp32, &sg_io32->cmdp); sg_io64.cmdp = kmalloc(sg_io64.cmd_len, GFP_KERNEL); - if (!sg_io64.cmdp) { - err = -ENOMEM; - goto out; - } if (copy_from_user(sg_io64.cmdp, - (void *) A(cmdp32), + compat_ptr(cmdp32), sg_io64.cmd_len)) { err = -EFAULT; goto out; @@ -1483,7 +1442,7 @@ goto out; } if (copy_from_user(sg_io64.sbp, - (void *) A(sbp32), + compat_ptr(sbp32), sg_io64.mx_sb_len)) { err = -EFAULT; goto out; @@ -1498,17 +1457,11 @@ goto out; } } else { - sg_io64.dxferp = kmalloc(sg_io64.dxfer_len, GFP_KERNEL); - if (!sg_io64.dxferp) { - err = -ENOMEM; - goto out; - } - if (copy_from_user(sg_io64.dxferp, - (void *) A(dxferp32), - sg_io64.dxfer_len)) { - err = -EFAULT; + err = verify_area(VERIFY_WRITE, compat_ptr(dxferp32), sg_io64.dxfer_len); + if (err) goto out; - } + + sg_io64.dxferp = compat_ptr(dxferp32); } /* Unused internally, do not even bother to copy it over. */ @@ -1535,15 +1488,7 @@ err |= __put_user(sg_io64.resid, &sg_io32->resid); err |= __put_user(sg_io64.duration, &sg_io32->duration); err |= __put_user(sg_io64.info, &sg_io32->info); - err |= copy_to_user((void *)A(sbp32), sg_io64.sbp, sg_io64.mx_sb_len); - if (sg_io64.dxferp) { - if (sg_io64.iovec_count) - err |= copy_back_sg_iovec(&sg_io64, dxferp32); - else - err |= copy_to_user((void *)A(dxferp32), - sg_io64.dxferp, - sg_io64.dxfer_len); - } + err |= copy_to_user(compat_ptr(sbp32), sg_io64.sbp, sg_io64.mx_sb_len); if (err) err = -EFAULT; @@ -1552,19 +1497,14 @@ kfree(sg_io64.cmdp); if (sg_io64.sbp) kfree(sg_io64.sbp); - if (sg_io64.dxferp) { - if (sg_io64.iovec_count) { + if (sg_io64.dxferp && sg_io64.iovec_count) free_sg_iovec(&sg_io64); - } else { - kfree(sg_io64.dxferp); - } - } return err; } struct sock_fprog32 { - __u16 len; - __u32 filter; + unsigned short len; + compat_caddr_t filter; }; #define PPPIOCSPASS32 _IOW('t', 71, struct sock_fprog32) @@ -1573,7 +1513,7 @@ static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) { struct sock_fprog32 *u_fprog32 = (struct sock_fprog32 *) arg; - struct sock_fprog *u_fprog64 = alloc_user_space(sizeof(struct sock_fprog)); + struct sock_fprog *u_fprog64 = compat_alloc_user_space(sizeof(struct sock_fprog)); void *fptr64; u32 fptr32; u16 flen; @@ -1582,7 +1522,7 @@ get_user(fptr32, &u_fprog32->filter)) return -EFAULT; - fptr64 = (void *) A(fptr32); + fptr64 = compat_ptr(fptr32); if (put_user(flen, &u_fprog64->len) || put_user(fptr64, &u_fprog64->filter)) @@ -1598,8 +1538,8 @@ struct ppp_option_data32 { compat_caddr_t ptr; - __u32 length; - int transmit; + u32 length; + compat_int_t transmit; }; #define PPPIOCSCOMPRESS32 _IOW('t', 77, struct ppp_option_data32) @@ -1628,10 +1568,12 @@ case PPPIOCSCOMPRESS32: if (copy_from_user(&data32, (struct ppp_option_data32 *)arg, sizeof(struct ppp_option_data32))) return -EFAULT; + if (data32.length > PAGE_SIZE) + return -EINVAL; data.ptr = kmalloc (data32.length, GFP_KERNEL); if (!data.ptr) return -ENOMEM; - if (copy_from_user(data.ptr, (__u8 *)A(data32.ptr), data32.length)) { + if (copy_from_user(data.ptr, compat_ptr(data32.ptr), data32.length)) { kfree(data.ptr); return -EFAULT; } @@ -1673,40 +1615,40 @@ struct mtget32 { - __u32 mt_type; - __u32 mt_resid; - __u32 mt_dsreg; - __u32 mt_gstat; - __u32 mt_erreg; + compat_long_t mt_type; + compat_long_t mt_resid; + compat_long_t mt_dsreg; + compat_long_t mt_gstat; + compat_long_t mt_erreg; compat_daddr_t mt_fileno; compat_daddr_t mt_blkno; }; #define MTIOCGET32 _IOR('m', 2, struct mtget32) struct mtpos32 { - __u32 mt_blkno; + compat_long_t mt_blkno; }; #define MTIOCPOS32 _IOR('m', 3, struct mtpos32) struct mtconfiginfo32 { - __u32 mt_type; - __u32 ifc_type; - __u16 irqnr; - __u16 dmanr; - __u16 port; - __u32 debug; - __u32 have_dens:1; - __u32 have_bsf:1; - __u32 have_fsr:1; - __u32 have_bsr:1; - __u32 have_eod:1; - __u32 have_seek:1; - __u32 have_tell:1; - __u32 have_ras1:1; - __u32 have_ras2:1; - __u32 have_ras3:1; - __u32 have_qfa:1; - __u32 pad1:5; + compat_long_t mt_type; + compat_long_t ifc_type; + unsigned short irqnr; + unsigned short dmanr; + unsigned short port; + compat_ulong_t debug; + compat_uint_t have_dens:1; + compat_uint_t have_bsf:1; + compat_uint_t have_fsr:1; + compat_uint_t have_bsr:1; + compat_uint_t have_eod:1; + compat_uint_t have_seek:1; + compat_uint_t have_tell:1; + compat_uint_t have_ras1:1; + compat_uint_t have_ras2:1; + compat_uint_t have_ras3:1; + compat_uint_t have_qfa:1; + compat_uint_t pad1:5; char reserved[10]; }; #define MTIOCGETCONFIG32 _IOR('m', 4, struct mtconfiginfo32) @@ -1796,25 +1738,25 @@ } struct cdrom_read32 { - int cdread_lba; + compat_int_t cdread_lba; compat_caddr_t cdread_bufaddr; - int cdread_buflen; + compat_int_t cdread_buflen; }; struct cdrom_read_audio32 { union cdrom_addr addr; - u_char addr_format; - int nframes; + u8 addr_format; + compat_int_t nframes; compat_caddr_t buf; }; struct cdrom_generic_command32 { unsigned char cmd[CDROM_PACKET_SIZE]; compat_caddr_t buffer; - unsigned int buflen; - int stat; + compat_uint_t buflen; + compat_int_t stat; compat_caddr_t sense; - compat_caddr_t reserved[3]; + compat_caddr_t reserved[3]; /* Oops? it has data_direction, quiet and timeout fields? */ }; static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) @@ -1839,10 +1781,9 @@ err |= __get_user(cdread.cdread_buflen, &((struct cdrom_read32 *)arg)->cdread_buflen); if (err) return -EFAULT; - data = kmalloc(cdread.cdread_buflen, GFP_KERNEL); - if (!data) - return -ENOMEM; - cdread.cdread_bufaddr = data; + if (verify_area(VERIFY_WRITE, compat_ptr(addr), cdread.cdread_buflen)) + return -EFAULT; + cdread.cdread_bufaddr = compat_ptr(addr); break; case CDROMREADAUDIO: karg = &cdreadaudio; @@ -1852,10 +1793,11 @@ err |= __get_user(addr, &((struct cdrom_read_audio32 *)arg)->buf); if (err) return -EFAULT; - data = kmalloc(cdreadaudio.nframes * 2352, GFP_KERNEL); - if (!data) - return -ENOMEM; - cdreadaudio.buf = data; + + + if (verify_area(VERIFY_WRITE, compat_ptr(addr), cdreadaudio.nframes*2352)) + return -EFAULT; + cdreadaudio.buf = compat_ptr(addr); break; case CDROM_SEND_PACKET: karg = &cgc; @@ -1864,9 +1806,9 @@ err |= __get_user(cgc.buflen, &((struct cdrom_generic_command32 *)arg)->buflen); if (err) return -EFAULT; - if ((data = kmalloc(cgc.buflen, GFP_KERNEL)) == NULL) - return -ENOMEM; - cgc.buffer = data; + if (verify_area(VERIFY_WRITE, compat_ptr(addr), cgc.buflen)) + return -EFAULT; + cgc.buffer = compat_ptr(addr); break; default: do { @@ -1881,41 +1823,23 @@ set_fs (KERNEL_DS); err = sys_ioctl (fd, cmd, (unsigned long)karg); set_fs (old_fs); - if (err) - goto out; - switch (cmd) { - case CDROMREADMODE2: - case CDROMREADMODE1: - case CDROMREADRAW: - case CDROMREADCOOKED: - err = copy_to_user((char *)A(addr), data, cdread.cdread_buflen); - break; - case CDROMREADAUDIO: - err = copy_to_user((char *)A(addr), data, cdreadaudio.nframes * 2352); - break; - case CDROM_SEND_PACKET: - err = copy_to_user((char *)A(addr), data, cgc.buflen); - break; - default: - break; - } -out: if (data) + if (data) kfree(data); return err ? -EFAULT : 0; } struct loop_info32 { - int lo_number; /* ioctl r/o */ + compat_int_t lo_number; /* ioctl r/o */ compat_dev_t lo_device; /* ioctl r/o */ - unsigned int lo_inode; /* ioctl r/o */ + compat_ulong_t lo_inode; /* ioctl r/o */ compat_dev_t lo_rdevice; /* ioctl r/o */ - int lo_offset; - int lo_encrypt_type; - int lo_encrypt_key_size; /* ioctl w/o */ - int lo_flags; /* ioctl r/o */ + compat_int_t lo_offset; + compat_int_t lo_encrypt_type; + compat_int_t lo_encrypt_key_size; /* ioctl w/o */ + compat_int_t lo_flags; /* ioctl r/o */ char lo_name[LO_NAME_SIZE]; unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ - unsigned int lo_init[2]; + compat_ulong_t lo_init[2]; char reserved[4]; }; @@ -1931,6 +1855,7 @@ err |= __get_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device); err |= __get_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode); err |= __get_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice); + err |= __copy_from_user((char *)&l.lo_offset, (char *)&((struct loop_info32 *)arg)->lo_offset, 8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset); if (err) { @@ -1996,7 +1921,7 @@ struct consolefontdesc32 { unsigned short charcount; /* characters in font (256 or 512) */ unsigned short charheight; /* scan lines per character (1-32) */ - u32 chardata; /* font data in expanded form */ + compat_caddr_t chardata; /* font data in expanded form */ }; static int do_fontx_ioctl(unsigned int fd, int cmd, struct consolefontdesc32 *user_cfd, struct file *file) @@ -2011,7 +1936,7 @@ if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc32))) return -EFAULT; - cfdarg.chardata = (unsigned char *)A(((struct consolefontdesc32 *)&cfdarg)->chardata); + cfdarg.chardata = compat_ptr(((struct consolefontdesc32 *)&cfdarg)->chardata); switch (cmd) { case PIO_FONTX: @@ -2047,11 +1972,11 @@ } struct console_font_op32 { - unsigned int op; /* operation code KD_FONT_OP_* */ - unsigned int flags; /* KD_FONT_FLAG_* */ - unsigned int width, height; /* font size */ - unsigned int charcount; - u32 data; /* font data with height fixed to 32 */ + compat_uint_t op; /* operation code KD_FONT_OP_* */ + compat_uint_t flags; /* KD_FONT_FLAG_* */ + compat_uint_t width, height; /* font size */ + compat_uint_t charcount; + compat_caddr_t data; /* font data with height fixed to 32 */ }; static int do_kdfontop_ioctl(unsigned int fd, unsigned int cmd, struct console_font_op32 *fontop, struct file *file) @@ -2066,7 +1991,7 @@ return -EFAULT; if (!perm && op.op != KD_FONT_OP_GET) return -EPERM; - op.data = (unsigned char *)A(((struct console_font_op32 *)&op)->data); + op.data = compat_ptr(((struct console_font_op32 *)&op)->data); op.flags |= KD_FONT_FLAG_OLD; vt = (struct vt_struct *)((struct tty_struct *)file->private_data)->driver_data; i = con_font_op(vt->vc_num, &op); @@ -2079,7 +2004,7 @@ struct unimapdesc32 { unsigned short entry_ct; - u32 entries; + compat_caddr_t entries; }; static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, struct unimapdesc32 *user_ud, struct file *file) @@ -2093,9 +2018,9 @@ switch (cmd) { case PIO_UNIMAP: if (!perm) return -EPERM; - return con_set_unimap(fg_console, tmp.entry_ct, (struct unipair *)A(tmp.entries)); + return con_set_unimap(fg_console, tmp.entry_ct, compat_ptr(tmp.entries)); case GIO_UNIMAP: - return con_get_unimap(fg_console, tmp.entry_ct, &(user_ud->entry_ct), (struct unipair *)A(tmp.entries)); + return con_get_unimap(fg_console, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries)); } return 0; } @@ -2119,13 +2044,13 @@ } struct atmif_sioc32 { - int number; - int length; + compat_int_t number; + compat_int_t length; compat_caddr_t arg; }; struct atm_iobuf32 { - int length; + compat_int_t length; compat_caddr_t buffer; }; @@ -2190,38 +2115,17 @@ if (iobuf32.buffer == (compat_caddr_t) NULL || iobuf32.length == 0) { iobuf.buffer = (void*)(unsigned long)iobuf32.buffer; } else { - iobuf.buffer = kmalloc(iobuf.length, GFP_KERNEL); - if (iobuf.buffer == NULL) { - err = -ENOMEM; - goto out; - } - - err = copy_from_user(iobuf.buffer, A(iobuf32.buffer), iobuf.length); - if (err) { - err = -EFAULT; - goto out; - } + iobuf.buffer = compat_ptr(iobuf32.buffer); + if (verify_area(VERIFY_WRITE, iobuf.buffer, iobuf.length)) + return -EINVAL; } old_fs = get_fs(); set_fs (KERNEL_DS); err = sys_ioctl (fd, cmd, (unsigned long)&iobuf); set_fs (old_fs); - if(err) - goto out; - - if(iobuf.buffer && iobuf.length > 0) { - err = copy_to_user(A(iobuf32.buffer), iobuf.buffer, iobuf.length); - if (err) { - err = -EFAULT; - goto out; - } - } + if(!err) err = __put_user(iobuf.length, &(((struct atm_iobuf32*)arg)->length)); - out: - if(iobuf32.buffer && iobuf32.length > 0) - kfree(iobuf.buffer); - return err; } @@ -2244,39 +2148,16 @@ if (sioc32.arg == (compat_caddr_t) NULL || sioc32.length == 0) { sioc.arg = (void*)(unsigned long)sioc32.arg; } else { - sioc.arg = kmalloc(sioc.length, GFP_KERNEL); - if (sioc.arg == NULL) { - err = -ENOMEM; - goto out; - } - - err = copy_from_user(sioc.arg, A(sioc32.arg), sioc32.length); - if (err) { - err = -EFAULT; - goto out; - } + sioc.arg = compat_ptr(sioc32.arg); + if (verify_area(VERIFY_WRITE, sioc.arg, sioc32.length)) + return -EFAULT; } old_fs = get_fs(); set_fs (KERNEL_DS); err = sys_ioctl (fd, cmd, (unsigned long)&sioc); set_fs (old_fs); - if(err) { - goto out; - } - - if(sioc.arg && sioc.length > 0) { - err = copy_to_user(A(sioc32.arg), sioc.arg, sioc.length); - if (err) { - err = -EFAULT; - goto out; - } - } + if (!err) err = __put_user(sioc.length, &(((struct atmif_sioc32*)arg)->length)); - - out: - if(sioc32.arg && sioc32.length > 0) - kfree(sioc.arg); - return err; } @@ -2346,10 +2227,10 @@ } struct blkpg_ioctl_arg32 { - int op; - int flags; - int datalen; - u32 data; + compat_int_t op; + compat_int_t flags; + compat_int_t datalen; + compat_caddr_t data; }; static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, struct blkpg_ioctl_arg32 *arg) @@ -2408,7 +2289,7 @@ struct raw32_config_request { - int raw_minor; + compat_int_t raw_minor; __u64 block_major; __u64 block_minor; } __attribute__((packed)); @@ -2440,24 +2321,24 @@ } struct serial_struct32 { - int type; - int line; - unsigned int port; - int irq; - int flags; - int xmit_fifo_size; - int custom_divisor; - int baud_base; + compat_int_t type; + compat_int_t line; + compat_uint_t port; + compat_int_t irq; + compat_int_t flags; + compat_int_t xmit_fifo_size; + compat_int_t custom_divisor; + compat_int_t baud_base; unsigned short close_delay; char io_type; char reserved_char[1]; - int hub6; + compat_int_t hub6; unsigned short closing_wait; /* time to wait before closing */ unsigned short closing_wait2; /* no longer used... */ - __u32 iomem_base; + compat_uint_t iomem_base; unsigned short iomem_reg_shift; unsigned int port_high; - int reserved[1]; + compat_int_t reserved[1]; }; static int serial_struct_ioctl(unsigned fd, unsigned cmd, void *ptr) @@ -2500,7 +2381,7 @@ } struct dirent32 { - unsigned int d_ino; + compat_int_t d_ino; compat_off_t d_off; unsigned short d_reclen; char d_name[256]; /* We must not include limits.h! */ @@ -2606,13 +2487,13 @@ #define BNEPGETCONNINFO _IOR('B', 211, int) struct usbdevfs_ctrltransfer32 { - __u8 bRequestType; - __u8 bRequest; - __u16 wValue; - __u16 wIndex; - __u16 wLength; - __u32 timeout; /* in milliseconds */ - __u32 data; + u8 bRequestType; + u8 bRequest; + u16 wValue; + u16 wIndex; + u16 wLength; + u32 timeout; /* in milliseconds */ + compat_caddr_t data; }; #define USBDEVFS_CONTROL32 _IOWR('U', 0, struct usbdevfs_ctrltransfer32) @@ -2635,7 +2516,7 @@ if (get_user(udata, &uctrl->data)) return -EFAULT; - uptr = (void *) A(udata); + uptr = compat_ptr(udata); /* In usbdevice_fs, it limits the control buffer to a page, * for simplicity so do we. @@ -2670,10 +2551,10 @@ } struct usbdevfs_bulktransfer32 { - unsigned int ep; - unsigned int len; - unsigned int timeout; /* in milliseconds */ - __u32 data; + compat_uint_t ep; + compat_uint_t len; + compat_uint_t timeout; /* in milliseconds */ + compat_caddr_t data; }; #define USBDEVFS_BULK32 _IOWR('U', 2, struct usbdevfs_bulktransfer32) @@ -2695,7 +2576,7 @@ get_user(udata, &ubulk->data)) return -EFAULT; - uptr = (void *) A(udata); + uptr = compat_ptr(udata); /* In usbdevice_fs, it limits the control buffer to a page, * for simplicity so do we. @@ -2771,18 +2652,18 @@ */ #if 0 struct usbdevfs_urb32 { - __u8 type; - __u8 endpoint; - __s32 status; - __u32 flags; - __u32 buffer; - __s32 buffer_length; - __s32 actual_length; - __s32 start_frame; - __s32 number_of_packets; - __s32 error_count; - __u32 signr; - __u32 usercontext; /* unused */ + unsigned char type; + unsigned char endpoint; + compat_int_t status; + compat_uint_t flags; + compat_caddr_t buffer; + compat_int_t buffer_length; + compat_int_t actual_length; + compat_int_t start_frame; + compat_int_t number_of_packets; + compat_int_t error_count; + compat_uint_t signr; + compat_caddr_t usercontext; /* unused */ struct usbdevfs_iso_packet_desc iso_frame_desc[0]; }; @@ -2902,19 +2783,13 @@ err = -EFAULT; if (__get_user(udata, &uurb->buffer)) goto out; - uptr = (void *) A(udata); + uptr = compat_ptr(udata); - err = -ENOMEM; buflen = kurb->buffer_length; - kptr = kmalloc(buflen, GFP_KERNEL); - if (!kptr) + err = verify_area(VERIFY_WRITE, uptr, buflen); + if (err) goto out; - kurb->buffer = kptr; - - err = -EFAULT; - if (copy_from_user(kptr, uptr, buflen)) - goto out_kptr; old_fs = get_fs(); set_fs(KERNEL_DS); @@ -2925,15 +2800,9 @@ /* RED-PEN Shit, this doesn't work for async URBs :-( XXX */ if (put_urb32(kurb, uurb)) { err = -EFAULT; - } else if ((kurb->endpoint & USB_DIR_IN) != 0) { - if (copy_to_user(uptr, kptr, buflen)) - err = -EFAULT; } } -out_kptr: - kfree(kptr); - out: kfree(kurb); return err; @@ -2959,15 +2828,15 @@ set_fs(old_fs); if (err >= 0 && - put_user(((u32)(long)kptr), (u32 *) A(arg))) + put_user(((u32)(long)kptr), compat_ptr(arg))) err = -EFAULT; return err; } struct usbdevfs_disconnectsignal32 { - unsigned int signr; - u32 context; + compat_int_t signr; + compat_caddr_t context; }; #define USBDEVFS_DISCSIGNAL32 _IOR('U', 14, struct usbdevfs_disconnectsignal32) @@ -2997,9 +2866,9 @@ } struct mtd_oob_buf32 { - u32 start; - u32 length; - u32 ptr; /* unsigned char* */ + u_int32_t start; + u_int32_t length; + compat_caddr_t ptr; /* unsigned char* */ }; #define MEMWRITEOOB32 _IOWR('M',3,struct mtd_oob_buf32) @@ -3011,7 +2880,6 @@ struct mtd_oob_buf32 *uarg = (struct mtd_oob_buf32 *)arg; struct mtd_oob_buf karg; u32 tmp; - char *ptr; int ret; if (get_user(karg.start, &uarg->start) || @@ -3019,18 +2887,9 @@ get_user(tmp, &uarg->ptr)) return -EFAULT; - ptr = (char *)A(tmp); - if (0 >= karg.length) - return -EINVAL; - - karg.ptr = kmalloc(karg.length, GFP_KERNEL); - if (NULL == karg.ptr) - return -ENOMEM; - - if (copy_from_user(karg.ptr, ptr, karg.length)) { - kfree(karg.ptr); + karg.ptr = compat_ptr(tmp); + if (verify_area(VERIFY_WRITE, karg.ptr, karg.length)) return -EFAULT; - } set_fs(KERNEL_DS); if (MEMREADOOB32 == cmd) @@ -3042,13 +2901,11 @@ set_fs(old_fs); if (0 == ret && cmd == MEMREADOOB32) { - ret = copy_to_user(ptr, karg.ptr, karg.length); - ret |= put_user(karg.start, &uarg->start); + ret = put_user(karg.start, &uarg->start); ret |= put_user(karg.length, &uarg->length); } - kfree(karg.ptr); - return ((0 == ret) ? 0 : -EFAULT); + return ret; } /* /proc/mtrr ioctls */ @@ -3056,17 +2913,17 @@ struct mtrr_sentry32 { - unsigned int base; /* Base address */ - unsigned int size; /* Size of region */ - unsigned int type; /* Type of region */ + compat_ulong_t base; /* Base address */ + compat_uint_t size; /* Size of region */ + compat_uint_t type; /* Type of region */ }; struct mtrr_gentry32 { - unsigned int regnum; /* Register number */ - unsigned int base; /* Base address */ - unsigned int size; /* Size of region */ - unsigned int type; /* Type of region */ + compat_ulong_t regnum; /* Register number */ + compat_uint_t base; /* Base address */ + compat_uint_t size; /* Size of region */ + compat_uint_t type; /* Type of region */ }; #define MTRR_IOCTL_BASE 'M' @@ -3137,7 +2994,7 @@ } #define REF_SYMBOL(handler) if (0) (void)handler; -#define HANDLE_IOCTL2(cmd,handler) REF_SYMBOL(handler); asm volatile(".quad %c0, " #handler ",0"::"i" (cmd)); +#define HANDLE_IOCTL2(cmd,handler) REF_SYMBOL(handler); asm volatile(".quad %P0, " #handler ",0"::"i" (cmd)); #define HANDLE_IOCTL(cmd,handler) HANDLE_IOCTL2(cmd,handler) #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd,sys_ioctl) #define IOCTL_TABLE_START void ioctl_dummy(void) { asm volatile("\n.global ioctl_start\nioctl_start:\n\t" ); diff -Nru a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c --- a/arch/x86_64/ia32/ia32_signal.c Sat May 24 12:48:32 2003 +++ b/arch/x86_64/ia32/ia32_signal.c Sat May 24 12:48:32 2003 @@ -33,6 +33,7 @@ #include #include #include +#include #define ptr_to_u32(x) ((u32)(u64)(x)) /* avoid gcc warning */ @@ -428,7 +429,7 @@ /* Return stub is in 32bit vsyscall page */ { - void *restorer = syscall32_page + 32; + void *restorer = VSYSCALL32_SIGRETURN; if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; err |= __put_user(ptr_to_u32(restorer), &frame->pretcode); @@ -521,7 +522,7 @@ { - void *restorer = syscall32_page + 32; + void *restorer = VSYSCALL32_RTSIGRETURN; if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; err |= __put_user(ptr_to_u32(restorer), &frame->pretcode); diff -Nru a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S --- a/arch/x86_64/ia32/ia32entry.S Sat May 24 12:48:24 2003 +++ b/arch/x86_64/ia32/ia32entry.S Sat May 24 12:48:24 2003 @@ -182,9 +182,9 @@ PTREGSCALL stub32_sigaltstack, sys32_sigaltstack PTREGSCALL stub32_sigsuspend, sys32_sigsuspend PTREGSCALL stub32_execve, sys32_execve - PTREGSCALL stub32_fork, sys32_fork + PTREGSCALL stub32_fork, sys_fork PTREGSCALL stub32_clone, sys32_clone - PTREGSCALL stub32_vfork, sys32_vfork + PTREGSCALL stub32_vfork, sys_vfork PTREGSCALL stub32_iopl, sys_iopl PTREGSCALL stub32_rt_sigsuspend, sys_rt_sigsuspend diff -Nru a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c --- a/arch/x86_64/ia32/ptrace32.c Sat May 24 12:48:22 2003 +++ b/arch/x86_64/ia32/ptrace32.c Sat May 24 12:48:22 2003 @@ -78,12 +78,24 @@ case offsetof(struct user32, u_debugreg[5]): return -EIO; - case offsetof(struct user32, u_debugreg[0]) ... - offsetof(struct user32, u_debugreg[3]): + case offsetof(struct user32, u_debugreg[0]): + child->thread.debugreg0 = val; + break; + + case offsetof(struct user32, u_debugreg[1]): + child->thread.debugreg1 = val; + break; + + case offsetof(struct user32, u_debugreg[2]): + child->thread.debugreg2 = val; + break; + + case offsetof(struct user32, u_debugreg[3]): + child->thread.debugreg3 = val; + break; + case offsetof(struct user32, u_debugreg[6]): - child->thread.debugreg - [(regno-offsetof(struct user32, u_debugreg[0]))/4] - = val; + child->thread.debugreg6 = val; break; case offsetof(struct user32, u_debugreg[7]): @@ -92,7 +104,7 @@ for(i=0; i<4; i++) if ((0x5454 >> ((val >> (16 + 4*i)) & 0xf)) & 1) return -EIO; - child->thread.debugreg[7] = val; + child->thread.debugreg7 = val; break; default: @@ -142,8 +154,23 @@ R32(eflags, eflags); R32(esp, rsp); - case offsetof(struct user32, u_debugreg[0]) ... offsetof(struct user32, u_debugreg[7]): - *val = child->thread.debugreg[(regno-offsetof(struct user32, u_debugreg[0]))/4]; + case offsetof(struct user32, u_debugreg[0]): + *val = child->thread.debugreg0; + break; + case offsetof(struct user32, u_debugreg[1]): + *val = child->thread.debugreg1; + break; + case offsetof(struct user32, u_debugreg[2]): + *val = child->thread.debugreg2; + break; + case offsetof(struct user32, u_debugreg[3]): + *val = child->thread.debugreg3; + break; + case offsetof(struct user32, u_debugreg[6]): + *val = child->thread.debugreg6; + break; + case offsetof(struct user32, u_debugreg[7]): + *val = child->thread.debugreg7; break; default: diff -Nru a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c --- a/arch/x86_64/ia32/sys_ia32.c Sat May 24 12:48:24 2003 +++ b/arch/x86_64/ia32/sys_ia32.c Sat May 24 12:48:24 2003 @@ -234,7 +234,7 @@ } if (a.prot & PROT_READ) - a.prot |= PROT_EXEC; + a.prot |= vm_force_exec32; mm = current->mm; down_write(&mm->mmap_sem); @@ -253,7 +253,7 @@ sys32_mprotect(unsigned long start, size_t len, unsigned long prot) { if (prot & PROT_READ) - prot |= PROT_EXEC; + prot |= vm_force_exec32; return sys_mprotect(start,len,prot); } @@ -929,7 +929,11 @@ u32 totalswap; u32 freeswap; unsigned short procs; - char _f[22]; + unsigned short pad; + u32 totalhigh; + u32 freehigh; + u32 mem_unit; + char _f[20-2*sizeof(u32)-sizeof(int)]; }; extern asmlinkage long sys_sysinfo(struct sysinfo *info); @@ -955,7 +959,10 @@ __put_user (s.bufferram, &info->bufferram) || __put_user (s.totalswap, &info->totalswap) || __put_user (s.freeswap, &info->freeswap) || - __put_user (s.procs, &info->procs)) + __put_user (s.procs, &info->procs) || + __put_user (s.totalhigh, &info->totalhigh) || + __put_user (s.freehigh, &info->freehigh) || + __put_user (s.mem_unit, &info->mem_unit)) return -EFAULT; return 0; } @@ -1419,7 +1426,7 @@ } if (prot & PROT_READ) - prot |= PROT_EXEC; + prot |= vm_force_exec32; down_write(&mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); @@ -1587,40 +1594,14 @@ return ret; } -asmlinkage long sys32_fork(struct pt_regs regs) -{ - struct task_struct *p; - p = do_fork(SIGCHLD, regs.rsp, ®s, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; -} - asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, struct pt_regs regs) { - struct task_struct *p; void *parent_tid = (void *)regs.rdx; void *child_tid = (void *)regs.rdi; if (!newsp) newsp = regs.rsp; - p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, + return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, parent_tid, child_tid); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; -} - -/* - * This is trivial, and on the face of it looks like it - * could equally well be done in user mode. - * - * Not so, for quite unobvious reasons - register pressure. - * In user mode vfork() cannot have a stack frame, and if - * done by calling the "clone()" system call directly, you - * do not have enough call-clobbered registers to hold all - * the information you need. - */ -asmlinkage long sys32_vfork(struct pt_regs regs) -{ - struct task_struct *p; - p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.rsp, ®s, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; } /* diff -Nru a/arch/x86_64/ia32/syscall32.c b/arch/x86_64/ia32/syscall32.c --- a/arch/x86_64/ia32/syscall32.c Sat May 24 12:48:27 2003 +++ b/arch/x86_64/ia32/syscall32.c Sat May 24 12:48:27 2003 @@ -13,33 +13,14 @@ #include #include -/* 32bit SYSCALL stub mapped into user space. */ -asm(" .code32\n" - "\nsyscall32:\n" - " pushl %ebp\n" - " movl %ecx,%ebp\n" - " syscall\n" - " popl %ebp\n" - " ret\n" +/* 32bit VDSO mapped into user space. */ +asm(".section \".init.data\",\"aw\"\n" + "syscall32:\n" + ".incbin \"arch/x86_64/ia32/vsyscall.so\"\n" "syscall32_end:\n" - - /* signal trampolines */ - - "sig32_rt_tramp:\n" - " movl $" __stringify(__NR_ia32_rt_sigreturn) ",%eax\n" - " syscall\n" - "sig32_rt_tramp_end:\n" - - "sig32_tramp:\n" - " popl %eax\n" - " movl $" __stringify(__NR_ia32_sigreturn) ",%eax\n" - " syscall\n" - "sig32_tramp_end:\n" - " .code64\n"); + ".previous"); extern unsigned char syscall32[], syscall32_end[]; -extern unsigned char sig32_rt_tramp[], sig32_rt_tramp_end[]; -extern unsigned char sig32_tramp[], sig32_tramp_end[]; char *syscall32_page; @@ -76,10 +57,6 @@ panic("Cannot allocate syscall32 page"); SetPageReserved(virt_to_page(syscall32_page)); memcpy(syscall32_page, syscall32, syscall32_end - syscall32); - memcpy(syscall32_page + 32, sig32_rt_tramp, - sig32_rt_tramp_end - sig32_rt_tramp); - memcpy(syscall32_page + 64, sig32_tramp, - sig32_tramp_end - sig32_tramp); return 0; } diff -Nru a/arch/x86_64/ia32/vsyscall.S b/arch/x86_64/ia32/vsyscall.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/x86_64/ia32/vsyscall.S Sat May 24 12:48:34 2003 @@ -0,0 +1,172 @@ +/* + * Code for the vsyscall page. This version uses the syscall instruction. + */ + +#include +#include + + .text + .section .text.vsyscall,"ax" + .globl __kernel_vsyscall + .type __kernel_vsyscall,@function +__kernel_vsyscall: +.LSTART_vsyscall: + push %ebp +.Lpush_ebp: + movl %ecx, %ebp + syscall + popl %ebp +.Lpop_ebp: + ret +.LEND_vsyscall: + .size __kernel_vsyscall,.-.LSTART_vsyscall + + .section .text.sigreturn,"ax" + .balign 32 + .globl __kernel_sigreturn + .type __kernel_sigreturn,@function +__kernel_sigreturn: +.LSTART_sigreturn: + popl %eax + movl $__NR_ia32_sigreturn, %eax + syscall +.LEND_sigreturn: + .size __kernel_sigreturn,.-.LSTART_sigreturn + + .section .text.rtsigreturn,"ax" + .balign 32 + .globl __kernel_rt_sigreturn,"ax" + .type __kernel_rt_sigreturn,@function +__kernel_rt_sigreturn: +.LSTART_rt_sigreturn: + movl $__NR_ia32_rt_sigreturn, %eax + syscall +.LEND_rt_sigreturn: + .size __kernel_rt_sigreturn,.-.LSTART_rt_sigreturn + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .long .LENDCIE-.LSTARTCIE +.LSTARTCIE: + .long 0 /* CIE ID */ + .byte 1 /* Version number */ + .string "zR" /* NUL-terminated augmentation string */ + .uleb128 1 /* Code alignment factor */ + .sleb128 -4 /* Data alignment factor */ + .byte 8 /* Return address register column */ + .uleb128 1 /* Augmentation value length */ + .byte 0x1b /* DW_EH_PE_pcrel|DW_EH_PE_sdata4. */ + .byte 0x0c /* DW_CFA_def_cfa */ + .uleb128 4 + .uleb128 4 + .byte 0x88 /* DW_CFA_offset, column 0x8 */ + .uleb128 1 + .align 4 +.LENDCIE: + + .long .LENDFDE1-.LSTARTFDE1 /* Length FDE */ +.LSTARTFDE1: + .long .LSTARTFDE1-.LSTARTFRAME /* CIE pointer */ + .long .LSTART_vsyscall-. /* PC-relative start address */ + .long .LEND_vsyscall-.LSTART_vsyscall + .uleb128 0 /* Augmentation length */ + /* What follows are the instructions for the table generation. + We have to record all changes of the stack pointer. */ + .byte 0x40 + .Lpush_ebp-.LSTART_vsyscall /* DW_CFA_advance_loc */ + .byte 0x0e /* DW_CFA_def_cfa_offset */ + .uleb128 8 + .byte 0x85, 0x02 /* DW_CFA_offset %ebp -8 */ + .byte 0x40 + .Lpop_ebp-.Lpush_ebp /* DW_CFA_advance_loc */ + .byte 0xc5 /* DW_CFA_restore %ebp */ + .byte 0x0e /* DW_CFA_def_cfa_offset */ + .uleb128 4 + .align 4 +.LENDFDE1: + + .long .LENDFDE2-.LSTARTFDE2 /* Length FDE */ +.LSTARTFDE2: + .long .LSTARTFDE2-.LSTARTFRAME /* CIE pointer */ + /* HACK: The dwarf2 unwind routines will subtract 1 from the + return address to get an address in the middle of the + presumed call instruction. Since we didn't get here via + a call, we need to include the nop before the real start + to make up for it. */ + .long .LSTART_sigreturn-1-. /* PC-relative start address */ + .long .LEND_sigreturn-.LSTART_sigreturn+1 + .uleb128 0 /* Augmentation length */ + /* What follows are the instructions for the table generation. + We record the locations of each register saved. This is + complicated by the fact that the "CFA" is always assumed to + be the value of the stack pointer in the caller. This means + that we must define the CFA of this body of code to be the + saved value of the stack pointer in the sigcontext. Which + also means that there is no fixed relation to the other + saved registers, which means that we must use DW_CFA_expression + to compute their addresses. It also means that when we + adjust the stack with the popl, we have to do it all over again. */ + +#define do_cfa_expr(offset) \ + .byte 0x0f; /* DW_CFA_def_cfa_expression */ \ + .uleb128 1f-0f; /* length */ \ +0: .byte 0x74; /* DW_OP_breg4 */ \ + .sleb128 offset; /* offset */ \ + .byte 0x06; /* DW_OP_deref */ \ +1: + +#define do_expr(regno, offset) \ + .byte 0x10; /* DW_CFA_expression */ \ + .uleb128 regno; /* regno */ \ + .uleb128 1f-0f; /* length */ \ +0: .byte 0x74; /* DW_OP_breg4 */ \ + .sleb128 offset; /* offset */ \ +1: + + do_cfa_expr(IA32_SIGCONTEXT_esp+4) + do_expr(0, IA32_SIGCONTEXT_eax+4) + do_expr(1, IA32_SIGCONTEXT_ecx+4) + do_expr(2, IA32_SIGCONTEXT_edx+4) + do_expr(3, IA32_SIGCONTEXT_ebx+4) + do_expr(5, IA32_SIGCONTEXT_ebp+4) + do_expr(6, IA32_SIGCONTEXT_esi+4) + do_expr(7, IA32_SIGCONTEXT_edi+4) + do_expr(8, IA32_SIGCONTEXT_eip+4) + + .byte 0x42 /* DW_CFA_advance_loc 2 -- nop; popl eax. */ + + do_cfa_expr(IA32_SIGCONTEXT_esp) + do_expr(0, IA32_SIGCONTEXT_eax) + do_expr(1, IA32_SIGCONTEXT_ecx) + do_expr(2, IA32_SIGCONTEXT_edx) + do_expr(3, IA32_SIGCONTEXT_ebx) + do_expr(5, IA32_SIGCONTEXT_ebp) + do_expr(6, IA32_SIGCONTEXT_esi) + do_expr(7, IA32_SIGCONTEXT_edi) + do_expr(8, IA32_SIGCONTEXT_eip) + + .align 4 +.LENDFDE2: + + .long .LENDFDE3-.LSTARTFDE3 /* Length FDE */ +.LSTARTFDE3: + .long .LSTARTFDE3-.LSTARTFRAME /* CIE pointer */ + /* HACK: See above wrt unwind library assumptions. */ + .long .LSTART_rt_sigreturn-1-. /* PC-relative start address */ + .long .LEND_rt_sigreturn-.LSTART_rt_sigreturn+1 + .uleb128 0 /* Augmentation */ + /* What follows are the instructions for the table generation. + We record the locations of each register saved. This is + slightly less complicated than the above, since we don't + modify the stack pointer in the process. */ + + do_cfa_expr(IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_esp) + do_expr(0, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_eax) + do_expr(1, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_ecx) + do_expr(2, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_edx) + do_expr(3, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_ebx) + do_expr(5, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_ebp) + do_expr(6, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_esi) + do_expr(7, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_edi) + do_expr(8, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_eip) + + .align 4 +.LENDFDE3: diff -Nru a/arch/x86_64/ia32/vsyscall.lds b/arch/x86_64/ia32/vsyscall.lds --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/x86_64/ia32/vsyscall.lds Sat May 24 12:48:34 2003 @@ -0,0 +1,77 @@ +/* + * Linker script for vsyscall DSO. The vsyscall page is an ELF shared + * object prelinked to its virtual address. This script controls its layout. + */ + +/* This must match . */ +VSYSCALL_BASE = 0xffffe000; + +SECTIONS +{ + . = VSYSCALL_BASE + SIZEOF_HEADERS; + + .hash : { *(.hash) } :text + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + + /* This linker script is used both with -r and with -shared. + For the layouts to match, we need to skip more than enough + space for the dynamic symbol table et al. If this amount + is insufficient, ld -shared will barf. Just increase it here. */ + . = VSYSCALL_BASE + 0x400; + + .text.vsyscall : { *(.text.vsyscall) } :text =0x90909090 + + /* This is an 32bit object and we cannot easily get the offsets + into the 64bit kernel. Just hardcode them here. This assumes + that all the stubs don't need more than 0x100 bytes. */ + . = VSYSCALL_BASE + 0x500; + + .text.sigreturn : { *(.text.sigreturn) } :text =0x90909090 + + . = VSYSCALL_BASE + 0x600; + + .text.rtsigreturn : { *(.text.rtsigreturn) } :text =0x90909090 + + .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr + .eh_frame : { KEEP (*(.eh_frame)) } :text + .dynamic : { *(.dynamic) } :text :dynamic + .useless : { + *(.got.plt) *(.got) + *(.data .data.* .gnu.linkonce.d.*) + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + } :text +} + +/* + * We must supply the ELF program headers explicitly to get just one + * PT_LOAD segment, and set the flags explicitly to make segments read-only. + */ +PHDRS +{ + text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */ + dynamic PT_DYNAMIC FLAGS(4); /* PF_R */ + eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */ +} + +/* + * This controls what symbols we export from the DSO. + */ +VERSION +{ + LINUX_2.5 { + global: + __kernel_vsyscall; + __kernel_sigreturn; + __kernel_rt_sigreturn; + + local: *; + }; +} + +/* The ELF entry point can be used to set the AT_SYSINFO value. */ +ENTRY(__kernel_vsyscall); diff -Nru a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile --- a/arch/x86_64/kernel/Makefile Sat May 24 12:48:29 2003 +++ b/arch/x86_64/kernel/Makefile Sat May 24 12:48:29 2003 @@ -7,7 +7,7 @@ obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \ ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_x86_64.o \ pci-dma.o x8664_ksyms.o i387.o syscall.o vsyscall.o \ - setup64.o bluesmoke.o bootflag.o e820.o reboot.o + setup64.o bluesmoke.o bootflag.o e820.o reboot.o warmreboot.o obj-$(CONFIG_MTRR) += mtrr/ obj-$(CONFIG_ACPI) += acpi/ diff -Nru a/arch/x86_64/kernel/acpi/wakeup.S b/arch/x86_64/kernel/acpi/wakeup.S --- a/arch/x86_64/kernel/acpi/wakeup.S Sat May 24 12:48:28 2003 +++ b/arch/x86_64/kernel/acpi/wakeup.S Sat May 24 12:48:28 2003 @@ -94,12 +94,6 @@ movw %ax, %ss mov $(wakeup_stack - __START_KERNEL_map), %esp - - call 1f -1: popl %eax - movl $0xb8040, %ebx - call early_print - movl saved_magic - __START_KERNEL_map, %eax cmpl $0x9abcdef0, %eax jne bogus_32_magic @@ -115,11 +109,7 @@ movl %eax, %cr4 /* Setup early boot stage 4 level pagetables */ -#if 1 movl $(wakeup_level4_pgt - __START_KERNEL_map), %eax -#else - movl saved_cr3 - __START_KERNEL_map, %eax -#endif movl %eax, %cr3 /* Setup EFER (Extended Feature Enable Register) */ @@ -222,19 +212,6 @@ jmp %rax .code32 - -early_print: - movl $16, %edx -1: - movl %eax, %ecx - andl $0xf, %ecx - shrl $4, %eax - addw $0x0e00 + '0', %ecx - movw %ecx, %ds:(%edx, %ebx) - decl %edx - decl %edx - jnz 1b - ret .align 64 gdta: diff -Nru a/arch/x86_64/kernel/acpi.c b/arch/x86_64/kernel/acpi.c --- a/arch/x86_64/kernel/acpi.c Sat May 24 12:48:20 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,512 +0,0 @@ -/* - * acpi.c - Architecture-Specific Low-Level ACPI Support - * - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * Copyright (C) 2001 Jun Nakajima - * Copyright (C) 2001 Patrick Mochel - * Copyright (C) 2002 Andi Kleen, SuSE Labs (x86-64 port) - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern int acpi_disabled; - -#define PREFIX "ACPI: " - - -/* -------------------------------------------------------------------------- - Boot-time Configuration - -------------------------------------------------------------------------- */ - -#ifdef CONFIG_ACPI_BOOT - -enum acpi_irq_model_id acpi_irq_model; - -/* rely on all ACPI tables being in the direct mapping */ -char * -__acpi_map_table ( - unsigned long phys_addr, - unsigned long size) -{ - if (!phys_addr || !size) - return NULL; - - if (phys_addr < (end_pfn_map << PAGE_SHIFT)) - return __va(phys_addr); - - return NULL; -} - -#ifdef CONFIG_X86_LOCAL_APIC - -int acpi_lapic; - -static u64 acpi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; - - -static int __init -acpi_parse_madt ( - unsigned long phys_addr, - unsigned long size) -{ - struct acpi_table_madt *madt = NULL; - - if (!phys_addr || !size) - return -EINVAL; - - madt = (struct acpi_table_madt *) __acpi_map_table(phys_addr, size); - if (!madt) { - printk(KERN_WARNING PREFIX "Unable to map MADT\n"); - return -ENODEV; - } - - if (madt->lapic_address) - acpi_lapic_addr = (u64) madt->lapic_address; - - printk(KERN_INFO PREFIX "Local APIC address 0x%08x\n", - madt->lapic_address); - - return 0; -} - - -static int __init -acpi_parse_lapic ( - acpi_table_entry_header *header) -{ - struct acpi_table_lapic *processor = NULL; - - processor = (struct acpi_table_lapic*) header; - if (!processor) - return -EINVAL; - - acpi_table_print_madt_entry(header); - - mp_register_lapic ( - processor->id, /* APIC ID */ - processor->flags.enabled); /* Enabled? */ - - return 0; -} - - -static int __init -acpi_parse_lapic_addr_ovr ( - acpi_table_entry_header *header) -{ - struct acpi_table_lapic_addr_ovr *lapic_addr_ovr = NULL; - - lapic_addr_ovr = (struct acpi_table_lapic_addr_ovr*) header; - if (!lapic_addr_ovr) - return -EINVAL; - - acpi_lapic_addr = lapic_addr_ovr->address; - - return 0; -} - - -static int __init -acpi_parse_lapic_nmi ( - acpi_table_entry_header *header) -{ - struct acpi_table_lapic_nmi *lapic_nmi = NULL; - - lapic_nmi = (struct acpi_table_lapic_nmi*) header; - if (!lapic_nmi) - return -EINVAL; - - acpi_table_print_madt_entry(header); - - if (lapic_nmi->lint != 1) - printk(KERN_WARNING PREFIX "NMI not connected to LINT 1!\n"); - - return 0; -} - -#endif /*CONFIG_X86_LOCAL_APIC*/ - -#ifdef CONFIG_X86_IO_APIC - -int acpi_ioapic; - -static int __init -acpi_parse_ioapic ( - acpi_table_entry_header *header) -{ - struct acpi_table_ioapic *ioapic = NULL; - - ioapic = (struct acpi_table_ioapic*) header; - if (!ioapic) - return -EINVAL; - - acpi_table_print_madt_entry(header); - - mp_register_ioapic ( - ioapic->id, - ioapic->address, - ioapic->global_irq_base); - - return 0; -} - - -static int __init -acpi_parse_int_src_ovr ( - acpi_table_entry_header *header) -{ - struct acpi_table_int_src_ovr *intsrc = NULL; - - intsrc = (struct acpi_table_int_src_ovr*) header; - if (!intsrc) - return -EINVAL; - - acpi_table_print_madt_entry(header); - - mp_override_legacy_irq ( - intsrc->bus_irq, - intsrc->flags.polarity, - intsrc->flags.trigger, - intsrc->global_irq); - - return 0; -} - - -static int __init -acpi_parse_nmi_src ( - acpi_table_entry_header *header) -{ - struct acpi_table_nmi_src *nmi_src = NULL; - - nmi_src = (struct acpi_table_nmi_src*) header; - if (!nmi_src) - return -EINVAL; - - acpi_table_print_madt_entry(header); - - /* TBD: Support nimsrc entries? */ - - return 0; -} - -#endif /*CONFIG_X86_IO_APIC*/ - -#ifdef CONFIG_HPET_TIMER -static int __init -acpi_parse_hpet ( - unsigned long phys_addr, - unsigned long size) -{ - struct acpi_table_hpet *hpet_tbl; - - hpet_tbl = __va(phys_addr); - - if (hpet_tbl->addr.space_id != ACPI_SPACE_MEM) { - printk(KERN_WARNING "acpi: HPET timers must be located in memory.\n"); - return -1; - } - - hpet.address = hpet_tbl->addr.addrl | ((long) hpet_tbl->addr.addrh << 32); - - printk(KERN_INFO "acpi: HPET id: %#x base: %#lx\n", hpet_tbl->id, hpet.address); - - return 0; -} -#endif - -static unsigned long __init -acpi_scan_rsdp ( - unsigned long start, - unsigned long length) -{ - unsigned long offset = 0; - unsigned long sig_len = sizeof("RSD PTR ") - 1; - - /* - * Scan all 16-byte boundaries of the physical memory region for the - * RSDP signature. - */ - for (offset = 0; offset < length; offset += 16) { - if (strncmp((char *) (start + offset), "RSD PTR ", sig_len)) - continue; - return (start + offset); - } - - return 0; -} - - -unsigned long __init -acpi_find_rsdp (void) -{ - unsigned long rsdp_phys = 0; - - /* - * Scan memory looking for the RSDP signature. First search EBDA (low - * memory) paragraphs and then search upper memory (E0000-FFFFF). - */ - rsdp_phys = acpi_scan_rsdp (0, 0x400); - if (!rsdp_phys) - rsdp_phys = acpi_scan_rsdp (0xE0000, 0xFFFFF); - - return rsdp_phys; -} - - -int __init -acpi_boot_init (void) -{ - int result = 0; - - /* - * The default interrupt routing model is PIC (8259). This gets - * overridden if IOAPICs are enumerated (below). - */ - acpi_irq_model = ACPI_IRQ_MODEL_PIC; - - /* - * Initialize the ACPI boot-time table parser. - */ - result = acpi_table_init(); - if (result) - return result; - - result = acpi_blacklisted(); - if (result) { - acpi_disabled = 1; - return result; - } else - printk(KERN_NOTICE PREFIX "BIOS passes blacklist\n"); - - extern int disable_apic; - if (disable_apic) - return 0; - -#ifdef CONFIG_X86_LOCAL_APIC - - /* - * MADT - * ---- - * Parse the Multiple APIC Description Table (MADT), if exists. - * Note that this table provides platform SMP configuration - * information -- the successor to MPS tables. - */ - - result = acpi_table_parse(ACPI_APIC, acpi_parse_madt); - if (!result) { - printk(KERN_WARNING PREFIX "MADT not present\n"); - return 0; - } - else if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing MADT\n"); - return result; - } - else if (result > 1) - printk(KERN_WARNING PREFIX "Multiple MADT tables exist\n"); - - /* - * Local APIC - * ---------- - * Note that the LAPIC address is obtained from the MADT (32-bit value) - * and (optionally) overridden by a LAPIC_ADDR_OVR entry (64-bit value). - */ - - result = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr); - if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n"); - return result; - } - - mp_register_lapic_address(acpi_lapic_addr); - - result = acpi_table_parse_madt(ACPI_MADT_LAPIC, acpi_parse_lapic); - if (!result) { - printk(KERN_ERR PREFIX "No LAPIC entries present\n"); - /* TBD: Cleanup to allow fallback to MPS */ - return -ENODEV; - } - else if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing LAPIC entry\n"); - /* TBD: Cleanup to allow fallback to MPS */ - return result; - } - - result = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi); - if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n"); - /* TBD: Cleanup to allow fallback to MPS */ - return result; - } - - acpi_lapic = 1; - -#endif /*CONFIG_X86_LOCAL_APIC*/ - -#ifdef CONFIG_X86_IO_APIC - - /* - * I/O APIC - * -------- - */ - - result = acpi_table_parse_madt(ACPI_MADT_IOAPIC, acpi_parse_ioapic); - if (!result) { - printk(KERN_ERR PREFIX "No IOAPIC entries present\n"); - return -ENODEV; - } - else if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing IOAPIC entry\n"); - return result; - } - - /* Build a default routing table for legacy (ISA) interrupts. */ - mp_config_acpi_legacy_irqs(); - - result = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr); - if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n"); - /* TBD: Cleanup to allow fallback to MPS */ - return result; - } - - result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src); - if (result < 0) { - printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n"); - /* TBD: Cleanup to allow fallback to MPS */ - return result; - } - - acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC; - - acpi_ioapic = 1; - -#endif /*CONFIG_X86_IO_APIC*/ - -#ifdef CONFIG_X86_LOCAL_APIC - if (acpi_lapic && acpi_ioapic) - smp_found_config = 1; -#endif - -#ifdef CONFIG_HPET_TIMER - result = acpi_table_parse(ACPI_HPET, acpi_parse_hpet); - if (result < 0) - printk("ACPI: no HPET table found (%d).\n", result); -#endif - - return 0; -} - -#endif /*CONFIG_ACPI_BOOT*/ - - -/* -------------------------------------------------------------------------- - Low-Level Sleep Support - -------------------------------------------------------------------------- */ - -#ifdef CONFIG_ACPI_SLEEP - -extern void acpi_prepare_wakeup(void); -extern unsigned char acpi_wakeup[], acpi_wakeup_end[], s3_prot16[]; - -/* address in low memory of the wakeup routine. */ -unsigned long acpi_wakeup_address; - -/** - * acpi_save_state_mem - save kernel state - */ -int acpi_save_state_mem (void) -{ - if (!acpi_wakeup_address) - return -1; - - memcpy((void*)acpi_wakeup_address, acpi_wakeup, acpi_wakeup_end - acpi_wakeup); - return 0; -} - -/** - * acpi_save_state_disk - save kernel state to disk - * - * Assume preemption/interrupts are already turned off and that we're running - * on the BP (note this doesn't imply SMP is handled correctly) - */ -int acpi_save_state_disk (void) -{ - unsigned long pbase = read_cr3() & PAGE_MASK; - if (pbase >= 0xffffffffUL) { - printk(KERN_ERR "ACPI: High page table. Suspend disabled.\n"); - return 1; - } - set_seg_base(smp_processor_id(), GDT_ENTRY_KERNELCS16, s3_prot16); - swap_low_mappings(); - acpi_prepare_wakeup(); - return 0; -} - -/* - * acpi_restore_state - */ -void acpi_restore_state_mem (void) -{ - swap_low_mappings(); -} - -/** - * acpi_reserve_bootmem - do _very_ early ACPI initialisation - * - * We allocate a page in 1MB low memory for the real-mode wakeup - * routine for when we come back from a sleep state. The - * runtime allocator allows specification of <16M pages, but not - * <1M pages. - */ -void __init acpi_reserve_bootmem(void) -{ - acpi_wakeup_address = (unsigned long)alloc_bootmem_low(PAGE_SIZE); - if (!acpi_wakeup_address) { - printk(KERN_ERR "ACPI: Cannot allocate lowmem. S3 disabled.\n"); - return; - } -} - -#endif /*CONFIG_ACPI_SLEEP*/ - -void acpi_pci_link_exit(void) {} diff -Nru a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c --- a/arch/x86_64/kernel/apic.c Sat May 24 12:48:21 2003 +++ b/arch/x86_64/kernel/apic.c Sat May 24 12:48:21 2003 @@ -385,10 +385,10 @@ value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; if (!smp_processor_id() && (pic_mode || !value)) { value = APIC_DM_EXTINT; - printk("enabled ExtINT on CPU#%d\n", smp_processor_id()); + Dprintk(KERN_INFO "enabled ExtINT on CPU#%d\n", smp_processor_id()); } else { value = APIC_DM_EXTINT | APIC_LVT_MASKED; - printk("masked ExtINT on CPU#%d\n", smp_processor_id()); + Dprintk(KERN_INFO "masked ExtINT on CPU#%d\n", smp_processor_id()); } apic_write_around(APIC_LVT0, value); diff -Nru a/arch/x86_64/kernel/asm-offsets.c b/arch/x86_64/kernel/asm-offsets.c --- a/arch/x86_64/kernel/asm-offsets.c Sat May 24 12:48:25 2003 +++ b/arch/x86_64/kernel/asm-offsets.c Sat May 24 12:48:25 2003 @@ -12,6 +12,7 @@ #include #include #include +#include #define DEFINE(sym, val) \ asm volatile("\n->" #sym " %0 " #val : : "i" (val)) @@ -43,5 +44,21 @@ ENTRY(irqstackptr); BLANK(); #undef ENTRY +#define ENTRY(entry) DEFINE(IA32_SIGCONTEXT_ ## entry, offsetof(struct sigcontext_ia32, entry)) + ENTRY(eax); + ENTRY(ebx); + ENTRY(ecx); + ENTRY(edx); + ENTRY(esi); + ENTRY(edi); + ENTRY(ebp); + ENTRY(esp); + ENTRY(eip); + BLANK(); +#undef ENTRY + DEFINE(IA32_RT_SIGFRAME_sigcontext, + offsetof (struct rt_sigframe32, uc.uc_mcontext)); + BLANK(); + return 0; } diff -Nru a/arch/x86_64/kernel/bluesmoke.c b/arch/x86_64/kernel/bluesmoke.c --- a/arch/x86_64/kernel/bluesmoke.c Sat May 24 12:48:31 2003 +++ b/arch/x86_64/kernel/bluesmoke.c Sat May 24 12:48:31 2003 @@ -129,12 +129,75 @@ int cpu = smp_processor_id(); pci_for_each_dev(dev) { if (dev->bus->number==0 && PCI_FUNC(dev->devfn)==3 && - PCI_SLOT(dev->devfn) == (24+cpu)) + PCI_SLOT(dev->devfn) == (24U+cpu)) return dev; } return NULL; } +/* When we have kallsyms we can afford kmcedecode too. */ + +static char *transaction[] = { + "instruction", "data", "generic", "reserved" +}; +static char *cachelevel[] = { + "level 0", "level 1", "level 2", "level generic" +}; +static char *memtrans[] = { + "generic error", "generic read", "generic write", "data read", + "data write", "instruction fetch", "prefetch", "snoop", + "?", "?", "?", "?", "?", "?", "?" +}; +static char *partproc[] = { + "local node origin", "local node response", + "local node observed", "generic" +}; +static char *timeout[] = { + "request didn't time out", + "request timed out" +}; +static char *memoryio[] = { + "memory access", "res.", "i/o access", "generic" +}; +static char *extendederr[] = { + "ecc error", + "crc error", + "sync error", + "mst abort", + "tgt abort", + "gart error", + "rmw error", + "wdog error", + "chipkill ecc error", + "<9>","<10>","<11>","<12>", + "<13>","<14>","<15>" +}; +static char *highbits[32] = { + [31] = "previous error lost", + [30] = "error overflow", + [29] = "error uncorrected", + [28] = "error enable", + [27] = "misc error valid", + [26] = "error address valid", + [25] = "processor context corrupt", + [24] = "res24", + [23] = "res23", + /* 22-15 ecc syndrome bits */ + [14] = "corrected ecc error", + [13] = "uncorrected ecc error", + [12] = "res12", + [11] = "res11", + [10] = "res10", + [9] = "res9", + [8] = "dram scrub error", + [7] = "res7", + /* 6-4 ht link number of error */ + [3] = "res3", + [2] = "res2", + [1] = "err cpu0", + [0] = "err cpu1", +}; + static void check_k8_nb(void) { struct pci_dev *nb; @@ -149,20 +212,52 @@ return; printk(KERN_ERR "Northbridge status %08x%08x\n", statushigh,statuslow); - if (statuslow & 0x10) - printk(KERN_ERR "GART error %d\n", statuslow & 0xf); - if (statushigh & (1<<31)) - printk(KERN_ERR "Lost an northbridge error\n"); - if (statushigh & (1<<25)) - printk(KERN_EMERG "NB status: unrecoverable\n"); + + unsigned short errcode = statuslow & 0xffff; + switch (errcode >> 8) { + case 0: + printk(KERN_ERR " GART TLB error %s %s\n", + transaction[(errcode >> 2) & 3], + cachelevel[errcode & 3]); + break; + case 1: + if (errcode & (1<<11)) { + printk(KERN_ERR " bus error %s %s %s %s %s\n", + partproc[(errcode >> 10) & 0x3], + timeout[(errcode >> 9) & 1], + memtrans[(errcode >> 4) & 0xf], + memoryio[(errcode >> 2) & 0x3], + cachelevel[(errcode & 0x3)]); + } else if (errcode & (1<<8)) { + printk(KERN_ERR " memory error %s %s %s\n", + memtrans[(errcode >> 4) & 0xf], + transaction[(errcode >> 2) & 0x3], + cachelevel[(errcode & 0x3)]); + } else { + printk(KERN_ERR " unknown error code %x\n", errcode); + } + break; + } + if (statushigh & ((1<<14)|(1<<13))) + printk(KERN_ERR " ECC syndrome bits %x\n", + (((statuslow >> 24) & 0xff) << 8) | ((statushigh >> 15) & 0x7f)); + errcode = (statuslow >> 16) & 0xf; + printk(KERN_ERR " extended error %s\n", extendederr[(statuslow >> 16) & 0xf]); + + /* should only print when it was a HyperTransport related error. */ + printk(KERN_ERR " link number %x\n", (statushigh >> 4) & 3); + + int i; + for (i = 0; i < 32; i++) + if (highbits[i] && (statushigh & (1< arg1 */ call schedule_tail GET_THREAD_INFO(%rcx) bt $TIF_SYSCALL_TRACE,threadinfo_flags(%rcx) @@ -414,6 +414,7 @@ .previous .section .fixup,"ax" /* force a signal here? this matches i386 behaviour */ + /* running with kernel gs */ bad_iret: movq $-9999,%rdi /* better code? */ jmp do_exit @@ -519,21 +520,27 @@ */ ENTRY(error_entry) /* rdi slot contains rax, oldrax contains error code */ - pushq %rsi - movq 8(%rsp),%rsi /* load rax */ - pushq %rdx - pushq %rcx - pushq %rsi /* store rax */ - pushq %r8 - pushq %r9 - pushq %r10 - pushq %r11 cld - SAVE_REST + subq $14*8,%rsp + movq %rsi,13*8(%rsp) + movq 14*8(%rsp),%rsi /* load rax from rdi slot */ + movq %rdx,12*8(%rsp) + movq %rcx,11*8(%rsp) + movq %rsi,10*8(%rsp) /* store rax */ + movq %r8, 9*8(%rsp) + movq %r9, 8*8(%rsp) + movq %r10,7*8(%rsp) + movq %r11,6*8(%rsp) + movq %rbx,5*8(%rsp) + movq %rbp,4*8(%rsp) + movq %r12,3*8(%rsp) + movq %r13,2*8(%rsp) + movq %r14,1*8(%rsp) + movq %r15,(%rsp) + xorl %ebx,%ebx testl $3,CS(%rsp) je error_kernelspace error_swapgs: - xorl %ebx,%ebx swapgs error_sti: movq %rdi,RDI(%rsp) @@ -557,13 +564,14 @@ iretq error_kernelspace: + incl %ebx /* There are two places in the kernel that can potentially fault with - usergs. Handle them here. */ + usergs. Handle them here. The exception handlers after + iret run with kernel gs again, so don't set the user space flag. */ cmpq $iret_label,RIP(%rsp) je error_swapgs cmpq $gs_change,RIP(%rsp) je error_swapgs - movl $1,%ebx jmp error_sti /* Reload gs selector with exception handling */ @@ -584,7 +592,9 @@ .quad gs_change,bad_gs .previous .section .fixup,"ax" + /* running with kernelgs */ bad_gs: + swapgs /* switch back to user gs */ xorl %eax,%eax movl %eax,%gs jmp 2b @@ -614,12 +624,8 @@ # clone now call do_fork - + movq %rax,RAX(%rsp) xorl %edi,%edi - cmpq $-1000,%rax - jnb 1f - movl tsk_pid(%rax),%eax -1: movq %rax,RAX(%rsp) /* * It isn't worth to check for reschedule here, diff -Nru a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S --- a/arch/x86_64/kernel/head.S Sat May 24 12:48:27 2003 +++ b/arch/x86_64/kernel/head.S Sat May 24 12:48:27 2003 @@ -351,7 +351,7 @@ ENTRY(cpu_gdt_table) .quad 0x0000000000000000 /* NULL descriptor */ - .quad 0x0000000000000000 /* unused */ + .quad 0x00af9a000000ffff ^ (1<<21) /* __KERNEL_COMPAT32_CS */ .quad 0x00af9a000000ffff /* __KERNEL_CS */ .quad 0x00cf92000000ffff /* __KERNEL_DS */ .quad 0x00cffe000000ffff /* __USER32_CS */ diff -Nru a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c --- a/arch/x86_64/kernel/io_apic.c Sat May 24 12:48:25 2003 +++ b/arch/x86_64/kernel/io_apic.c Sat May 24 12:48:25 2003 @@ -1060,7 +1060,8 @@ phys_id_present_map |= 1 << i; mp_ioapics[apic].mpc_apicid = i; } else { - printk("Setting %d in the phys_id_present_map\n", mp_ioapics[apic].mpc_apicid); + printk(KERN_INFO + "Using IO-APIC %d\n", mp_ioapics[apic].mpc_apicid); phys_id_present_map |= 1 << mp_ioapics[apic].mpc_apicid; } diff -Nru a/arch/x86_64/kernel/ioport.c b/arch/x86_64/kernel/ioport.c --- a/arch/x86_64/kernel/ioport.c Sat May 24 12:48:21 2003 +++ b/arch/x86_64/kernel/ioport.c Sat May 24 12:48:21 2003 @@ -1,5 +1,5 @@ /* - * linux/arch/i386/kernel/ioport.c + * linux/arch/x86_64/kernel/ioport.c * * This contains the io-permission bitmap code - written by obz, with changes * by Linus. @@ -15,34 +15,35 @@ #include #include #include +#include /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */ static void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value) { - int mask; - unsigned long *bitmap_base = bitmap + (base >> 6); + unsigned long mask; + unsigned long *bitmap_base = bitmap + (base / sizeof(unsigned long)); unsigned short low_index = base & 0x3f; int length = low_index + extent; if (low_index != 0) { - mask = (~0 << low_index); + mask = (~0UL << low_index); if (length < 64) - mask &= ~(~0 << length); + mask &= ~(~0UL << length); if (new_value) *bitmap_base++ |= mask; else *bitmap_base++ &= ~mask; - length -= 32; + length -= 64; } - mask = (new_value ? ~0 : 0); + mask = (new_value ? ~0UL : 0UL); while (length >= 64) { *bitmap_base++ = mask; length -= 64; } if (length > 0) { - mask = ~(~0 << length); + mask = ~(~0UL << length); if (new_value) *bitmap_base++ |= mask; else @@ -113,3 +114,10 @@ regs.eflags = (regs.eflags & 0xffffffffffffcfff) | (level << 12); return 0; } + +void eat_key(void) +{ + if (inb(0x60) & 1) + inb(0x64); +} + diff -Nru a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c --- a/arch/x86_64/kernel/irq.c Sat May 24 12:48:24 2003 +++ b/arch/x86_64/kernel/irq.c Sat May 24 12:48:24 2003 @@ -90,7 +90,7 @@ * each architecture has to answer this themselves, it doesn't deserve * a generic callback i think. */ -#if CONFIG_X86 +#ifdef CONFIG_X86 printk("unexpected IRQ trap at vector %02x\n", irq); #ifdef CONFIG_X86_LOCAL_APIC /* @@ -171,7 +171,7 @@ if (cpu_online(j)) seq_printf(p, "%10u ", cpu_pda[j].__nmi_count); seq_putc(p, '\n'); -#if CONFIG_X86_LOCAL_APIC +#ifdef CONFIG_X86_LOCAL_APIC seq_printf(p, "LOC: "); for (j = 0; j < NR_CPUS; j++) if (cpu_online(j)) @@ -795,7 +795,7 @@ { unsigned char hexnum [HEX_DIGITS]; unsigned long value; - int i; + unsigned i; if (!count) return -EINVAL; @@ -827,7 +827,7 @@ return 0; } -#if CONFIG_SMP +#ifdef CONFIG_SMP static struct proc_dir_entry * smp_affinity_entry [NR_IRQS]; @@ -906,7 +906,7 @@ /* create /proc/irq/1234 */ irq_dir[irq] = proc_mkdir(name, root_irq_dir); -#if CONFIG_SMP +#ifdef CONFIG_SMP { struct proc_dir_entry *entry; diff -Nru a/arch/x86_64/kernel/ldt.c b/arch/x86_64/kernel/ldt.c --- a/arch/x86_64/kernel/ldt.c Sat May 24 12:48:32 2003 +++ b/arch/x86_64/kernel/ldt.c Sat May 24 12:48:32 2003 @@ -32,13 +32,13 @@ } #endif -static int alloc_ldt(mm_context_t *pc, int mincount, int reload) +static int alloc_ldt(mm_context_t *pc, unsigned mincount, int reload) { void *oldldt; void *newldt; - int oldsize; + unsigned oldsize; - if (mincount <= pc->size) + if (mincount <= (unsigned)pc->size) return 0; oldsize = pc->size; mincount = (mincount+511)&(~511); @@ -63,7 +63,7 @@ #ifdef CONFIG_SMP preempt_disable(); load_LDT(pc); - if (current->mm->cpu_vm_mask != (1<mm->cpu_vm_mask != (1UL<context.size) { - if (mm->context.size*LDT_ENTRY_SIZE > PAGE_SIZE) + if ((unsigned)mm->context.size*LDT_ENTRY_SIZE > PAGE_SIZE) vfree(mm->context.ldt); else kfree(mm->context.ldt); @@ -190,7 +190,7 @@ } down(&mm->context.sem); - if (ldt_info.entry_number >= mm->context.size) { + if (ldt_info.entry_number >= (unsigned)mm->context.size) { error = alloc_ldt(¤t->mm->context, ldt_info.entry_number+1, 1); if (error < 0) goto out_unlock; diff -Nru a/arch/x86_64/kernel/module.c b/arch/x86_64/kernel/module.c --- a/arch/x86_64/kernel/module.c Sat May 24 12:48:31 2003 +++ b/arch/x86_64/kernel/module.c Sat May 24 12:48:31 2003 @@ -48,7 +48,6 @@ for (prevp = &mod_vmlist ; (map = *prevp) ; prevp = &map->next) { if ((unsigned long)map->addr == addr) { *prevp = map->next; - write_unlock(&vmlist_lock); goto found; } } @@ -57,6 +56,7 @@ return; found: unmap_vm_area(map); + write_unlock(&vmlist_lock); if (map->pages) { for (i = 0; i < map->nr_pages; i++) if (map->pages[i]) @@ -230,4 +230,8 @@ struct module *me) { return 0; +} + +void module_arch_cleanup(struct module *mod) +{ } diff -Nru a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c --- a/arch/x86_64/kernel/mpparse.c Sat May 24 12:48:22 2003 +++ b/arch/x86_64/kernel/mpparse.c Sat May 24 12:48:22 2003 @@ -892,11 +892,15 @@ list_for_each(node, &acpi_prt.entries) { entry = list_entry(node, struct acpi_prt_entry, node); - /* We're only interested in static (non-link) entries. */ - if (entry->link.handle) + /* Need to get irq for dynamic entry */ + if (entry->link.handle) { + irq = acpi_pci_link_get_irq(entry->link.handle, entry->link.index); + if (!irq) continue; - + } + else irq = entry->link.index; + ioapic = mp_find_ioapic(irq); if (ioapic < 0) continue; diff -Nru a/arch/x86_64/kernel/pci-dma.c b/arch/x86_64/kernel/pci-dma.c --- a/arch/x86_64/kernel/pci-dma.c Sat May 24 12:48:32 2003 +++ b/arch/x86_64/kernel/pci-dma.c Sat May 24 12:48:32 2003 @@ -32,7 +32,6 @@ int i; BUG_ON(direction == PCI_DMA_NONE); - for (i = 0; i < nents; i++ ) { struct scatterlist *s = &sg[i]; diff -Nru a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c --- a/arch/x86_64/kernel/pci-gart.c Sat May 24 12:48:24 2003 +++ b/arch/x86_64/kernel/pci-gart.c Sat May 24 12:48:24 2003 @@ -14,15 +14,10 @@ /* * Notebook: -agpgart_be - check if the simple reservation scheme is enough. - possible future tuning: - fast path for sg streaming mappings - more intelligent flush strategy - flush only a single NB? flush only when - gart area fills up and alloc_iommu wraps. - don't flush on allocation - need to unmap the gart area first to avoid prefetches - by the CPU + fast path for sg streaming mappings - only take the locks once. + more intelligent flush strategy - flush only the NB of the CPU directly + connected to the device? move boundary between IOMMU and AGP in GART dynamically */ @@ -67,7 +62,8 @@ #define GPTE_VALID 1 #define GPTE_COHERENT 2 -#define GPTE_ENCODE(x) (((x) & 0xfffff000) | (((x) >> 32) << 4) | GPTE_VALID | GPTE_COHERENT) +#define GPTE_ENCODE(x) \ + (((x) & 0xfffff000) | (((x) >> 32) << 4) | GPTE_VALID | GPTE_COHERENT) #define GPTE_DECODE(x) (((x) & 0xfffff000) | (((u64)(x) & 0xff0) << 28)) #define for_all_nb(dev) \ @@ -90,20 +86,23 @@ static unsigned long next_bit; /* protected by iommu_bitmap_lock */ -static unsigned long alloc_iommu(int size) +static unsigned long alloc_iommu(int size, int *flush) { unsigned long offset, flags; spin_lock_irqsave(&iommu_bitmap_lock, flags); - offset = find_next_zero_string(iommu_gart_bitmap,next_bit,iommu_pages,size); - if (offset == -1) + if (offset == -1) { + *flush = 1; offset = find_next_zero_string(iommu_gart_bitmap,0,next_bit,size); + } if (offset != -1) { set_bit_string(iommu_gart_bitmap, offset, size); next_bit = offset+size; - if (next_bit >= iommu_pages) + if (next_bit >= iommu_pages) { next_bit = 0; + *flush = 1; + } } spin_unlock_irqrestore(&iommu_bitmap_lock, flags); return offset; @@ -114,7 +113,6 @@ unsigned long flags; spin_lock_irqsave(&iommu_bitmap_lock, flags); clear_bit_string(iommu_gart_bitmap, offset, size); - next_bit = offset; spin_unlock_irqrestore(&iommu_bitmap_lock, flags); } @@ -137,6 +135,7 @@ int gfp = GFP_ATOMIC; int i; unsigned long iommu_page; + int flush = 0; if (hwdev == NULL || hwdev->dma_mask < 0xffffffff || no_iommu) gfp |= GFP_DMA; @@ -150,9 +149,10 @@ if (memory == NULL) { return NULL; } else { - int high = (unsigned long)virt_to_bus(memory) + size - >= 0xffffffff; - int mmu = high; + int high = 0, mmu; + if (((unsigned long)virt_to_bus(memory) + size) > 0xffffffffUL) + high = 1; + mmu = 1; if (force_mmu && !(gfp & GFP_DMA)) mmu = 1; if (no_iommu) { @@ -168,7 +168,7 @@ size >>= PAGE_SHIFT; - iommu_page = alloc_iommu(size); + iommu_page = alloc_iommu(size, &flush); if (iommu_page == -1) goto error; @@ -183,6 +183,7 @@ iommu_gatt_base[iommu_page + i] = GPTE_ENCODE(phys_mem); } + if (flush) flush_gart(); *dma_handle = iommu_bus_base + (iommu_page << PAGE_SHIFT); return memory; @@ -199,25 +200,24 @@ void pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t bus) { - u64 pte; unsigned long iommu_page; - int i; size = round_up(size, PAGE_SIZE); - if (bus < iommu_bus_base || bus > iommu_bus_base + iommu_size) { - free_pages((unsigned long)vaddr, get_order(size)); - return; - } - size >>= PAGE_SHIFT; - iommu_page = (bus - iommu_bus_base) / PAGE_SIZE; - for (i = 0; i < size; i++) { - pte = iommu_gatt_base[iommu_page + i]; + if (bus >= iommu_bus_base && bus <= iommu_bus_base + iommu_size) { + unsigned pages = size >> PAGE_SHIFT; + iommu_page = (bus - iommu_bus_base) >> PAGE_SHIFT; + vaddr = __va(GPTE_DECODE(iommu_gatt_base[iommu_page])); +#ifdef CONFIG_IOMMU_DEBUG + int i; + for (i = 0; i < pages; i++) { + u64 pte = iommu_gatt_base[iommu_page + i]; BUG_ON((pte & GPTE_VALID) == 0); iommu_gatt_base[iommu_page + i] = 0; - free_page((unsigned long) __va(GPTE_DECODE(pte))); } - flush_gart(); - free_iommu(iommu_page, size); +#endif + free_iommu(iommu_page, pages); + } + free_pages((unsigned long)vaddr, get_order(size)); } #ifdef CONFIG_IOMMU_LEAK @@ -257,7 +257,7 @@ */ printk(KERN_ERR - "PCI-DMA: Error: ran out out IOMMU space for %p size %lu at device %s[%s]\n", + "PCI-DMA: Out of IOMMU space for %p size %lu at device %s[%s]\n", addr,size, dev ? dev->dev.name : "?", dev ? dev->slot_name : "?"); if (size > PAGE_SIZE*EMERGENCY_PAGES) { @@ -287,12 +287,12 @@ return mmu; } -dma_addr_t __pci_map_single(struct pci_dev *dev, void *addr, size_t size, - int dir, int flush) +dma_addr_t pci_map_single(struct pci_dev *dev, void *addr, size_t size, int dir) { unsigned long iommu_page; unsigned long phys_mem, bus; int i, npages; + int flush = 0; BUG_ON(dir == PCI_DMA_NONE); @@ -302,7 +302,7 @@ npages = round_up(size + ((u64)addr & ~PAGE_MASK), PAGE_SIZE) >> PAGE_SHIFT; - iommu_page = alloc_iommu(npages); + iommu_page = alloc_iommu(npages, &flush); if (iommu_page == -1) { iommu_full(dev, addr, size, dir); return iommu_bus_base; @@ -343,12 +343,14 @@ size_t size, int direction) { unsigned long iommu_page; - int i, npages; + int npages; if (dma_addr < iommu_bus_base + EMERGENCY_PAGES*PAGE_SIZE || dma_addr > iommu_bus_base + iommu_size) return; iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT; npages = round_up(size + (dma_addr & ~PAGE_MASK), PAGE_SIZE) >> PAGE_SHIFT; +#ifdef CONFIG_IOMMU_DEBUG + int i; for (i = 0; i < npages; i++) { iommu_gatt_base[iommu_page + i] = 0; #ifdef CONFIG_IOMMU_LEAK @@ -356,11 +358,11 @@ iommu_leak_tab[iommu_page + i] = 0; #endif } - flush_gart(); +#endif free_iommu(iommu_page, npages); } -EXPORT_SYMBOL(__pci_map_single); +EXPORT_SYMBOL(pci_map_single); EXPORT_SYMBOL(pci_unmap_single); static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size) @@ -407,7 +409,7 @@ * Private Northbridge GATT initialization in case we cannot use the * AGP driver for some reason. */ -static __init int init_k8_gatt(agp_kern_info *info) +static __init int init_k8_gatt(struct agp_kern_info *info) { struct pci_dev *dev; void *gatt; @@ -443,7 +445,7 @@ u32 ctl; u32 gatt_reg; - gatt_reg = ((u64)gatt) >> 12; + gatt_reg = __pa(gatt) >> 12; gatt_reg <<= 4; pci_write_config_dword(dev, 0x98, gatt_reg); pci_read_config_dword(dev, 0x90, &ctl); @@ -465,9 +467,11 @@ return -1; } +extern int agp_amdk8_init(void); + void __init pci_iommu_init(void) { - agp_kern_info info; + struct agp_kern_info info; unsigned long aper_size; unsigned long iommu_start; @@ -476,7 +480,6 @@ #else /* Add other K8 AGP bridge drivers here */ no_agp = no_agp || - (agp_init() < 0) || (agp_amdk8_init() < 0) || (agp_copy_info(&info) < 0); #endif @@ -536,8 +539,17 @@ iommu_gatt_base = agp_gatt_table + (iommu_start>>PAGE_SHIFT); bad_dma_address = iommu_bus_base; - change_page_attr(virt_to_page(__va(iommu_start)), iommu_pages, PAGE_KERNEL); - global_flush_tlb(); + /* + * Unmap the IOMMU part of the GART. The alias of the page is always mapped + * with cache enabled and there is no full cache coherency across the GART + * remapping. The unmapping avoids automatic prefetches from the CPU + * allocating cache lines in there. All CPU accesses are done via the + * direct mapping to the backing memory. The GART address is only used by PCI + * devices. + */ + clear_kernel_mapping((unsigned long)__va(iommu_bus_base), iommu_size); + + flush_gart(); } /* iommu=[size][,noagp][,off][,force][,noforce][,leak][,memaper[=order]] diff -Nru a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c --- a/arch/x86_64/kernel/process.c Sat May 24 12:48:25 2003 +++ b/arch/x86_64/kernel/process.c Sat May 24 12:48:25 2003 @@ -216,7 +216,12 @@ { struct task_struct *tsk = current; - memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8); + tsk->thread.debugreg0 = 0; + tsk->thread.debugreg1 = 0; + tsk->thread.debugreg2 = 0; + tsk->thread.debugreg3 = 0; + tsk->thread.debugreg6 = 0; + tsk->thread.debugreg7 = 0; memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); /* * Forget coprocessor state.. @@ -285,7 +290,7 @@ childregs->rax = 0; childregs->rsp = rsp; - if (rsp == ~0) { + if (rsp == ~0UL) { childregs->rsp = (unsigned long)childregs; } p->set_child_tid = p->clear_child_tid = NULL; @@ -294,7 +299,7 @@ p->thread.rsp0 = (unsigned long) (childregs+1); p->thread.userrsp = me->thread.userrsp; - p->thread.rip = (unsigned long) ret_from_fork; + set_ti_thread_flag(p->thread_info, TIF_FORK); p->thread.fs = me->thread.fs; p->thread.gs = me->thread.gs; @@ -335,8 +340,7 @@ /* * This special macro can be used to load a debugging register */ -#define loaddebug(thread,register) \ - set_debug(thread->debugreg[register], register) +#define loaddebug(thread,r) set_debug(thread->debugreg ## r, r) /* * switch_to(x,y) should switch tasks from x to y. @@ -422,7 +426,7 @@ /* * Now maybe reload the debug registers */ - if (unlikely(next->debugreg[7])) { + if (unlikely(next->debugreg7)) { loaddebug(next, 0); loaddebug(next, 1); loaddebug(next, 2); @@ -490,19 +494,15 @@ asmlinkage long sys_fork(struct pt_regs regs) { - struct task_struct *p; - p = do_fork(SIGCHLD, regs.rsp, ®s, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(SIGCHLD, regs.rsp, ®s, 0, NULL, NULL); } asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, void *parent_tid, void *child_tid, struct pt_regs regs) { - struct task_struct *p; if (!newsp) newsp = regs.rsp; - p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, + return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, parent_tid, child_tid); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; } /* @@ -517,10 +517,8 @@ */ asmlinkage long sys_vfork(struct pt_regs regs) { - struct task_struct *p; - p = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.rsp, ®s, 0, + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.rsp, ®s, 0, NULL, NULL); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; } /* diff -Nru a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c --- a/arch/x86_64/kernel/ptrace.c Sat May 24 12:48:22 2003 +++ b/arch/x86_64/kernel/ptrace.c Sat May 24 12:48:22 2003 @@ -178,11 +178,11 @@ } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data) { struct task_struct *child; - struct user * dummy = NULL; long i, ret; + unsigned ui; /* This lock_kernel fixes a subtle race with suid exec */ lock_kernel(); @@ -240,18 +240,35 @@ unsigned long tmp; ret = -EIO; - if ((addr & 7) || addr < 0 || + if ((addr & 7) || addr > sizeof(struct user) - 7) break; - tmp = 0; /* Default return condition */ - if(addr < sizeof(struct user_regs_struct)) + switch (addr) { + case 0 ... sizeof(struct user_regs_struct): tmp = getreg(child, addr); - if(addr >= (long) &dummy->u_debugreg[0] && - addr <= (long) &dummy->u_debugreg[7]){ - addr -= (long) &dummy->u_debugreg[0]; - addr = addr >> 3; - tmp = child->thread.debugreg[addr]; + break; + case offsetof(struct user, u_debugreg[0]): + tmp = child->thread.debugreg0; + break; + case offsetof(struct user, u_debugreg[1]): + tmp = child->thread.debugreg1; + break; + case offsetof(struct user, u_debugreg[2]): + tmp = child->thread.debugreg2; + break; + case offsetof(struct user, u_debugreg[3]): + tmp = child->thread.debugreg3; + break; + case offsetof(struct user, u_debugreg[6]): + tmp = child->thread.debugreg6; + break; + case offsetof(struct user, u_debugreg[7]): + tmp = child->thread.debugreg7; + break; + default: + tmp = 0; + break; } ret = put_user(tmp,(unsigned long *) data); break; @@ -268,47 +285,53 @@ case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ ret = -EIO; - if ((addr & 7) || addr < 0 || + if ((addr & 7) || addr > sizeof(struct user) - 7) break; - if (addr < sizeof(struct user_regs_struct)) { + switch (addr) { + case 0 ... sizeof(struct user_regs_struct): ret = putreg(child, addr, data); break; - } - /* We need to be very careful here. We implicitly - want to modify a portion of the task_struct, and we - have to be selective about what portions we allow someone - to modify. */ - - ret = -EIO; - if(addr >= (long) &dummy->u_debugreg[0] && - addr <= (long) &dummy->u_debugreg[7]){ - - if(addr == (long) &dummy->u_debugreg[4]) break; - if(addr == (long) &dummy->u_debugreg[5]) break; - if(addr < (long) &dummy->u_debugreg[4] && - ((unsigned long) data) >= TASK_SIZE-3) break; - - if (addr == (long) &dummy->u_debugreg[6]) { + /* Disallows to set a breakpoint into the vsyscall */ + case offsetof(struct user, u_debugreg[0]): + if (data >= TASK_SIZE-7) break; + child->thread.debugreg0 = data; + ret = 0; + break; + case offsetof(struct user, u_debugreg[1]): + if (data >= TASK_SIZE-7) break; + child->thread.debugreg1 = data; + ret = 0; + break; + case offsetof(struct user, u_debugreg[2]): + if (data >= TASK_SIZE-7) break; + child->thread.debugreg2 = data; + ret = 0; + break; + case offsetof(struct user, u_debugreg[3]): + if (data >= TASK_SIZE-7) break; + child->thread.debugreg3 = data; + ret = 0; + break; + case offsetof(struct user, u_debugreg[6]): if (data >> 32) - goto out_tsk; - } - - if(addr == (long) &dummy->u_debugreg[7]) { + break; + child->thread.debugreg6 = data; + ret = 0; + break; + case offsetof(struct user, u_debugreg[7]): data &= ~DR_CONTROL_RESERVED; for(i=0; i<4; i++) if ((0x5454 >> ((data >> (16 + 4*i)) & 0xf)) & 1) - goto out_tsk; - } - - addr -= (long) &dummy->u_debugreg; - addr = addr >> 3; - child->thread.debugreg[addr] = data; + break; + if (i == 4) { + child->thread.debugreg7 = data; ret = 0; } break; - + } + break; case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ long tmp; @@ -408,8 +431,8 @@ ret = -EIO; break; } - for ( i = 0; i < sizeof(struct user_regs_struct); i += sizeof(long) ) { - __put_user(getreg(child, i),(unsigned long *) data); + for (ui = 0; ui < sizeof(struct user_regs_struct); ui += sizeof(long)) { + __put_user(getreg(child, ui),(unsigned long *) data); data += sizeof(long); } ret = 0; @@ -422,9 +445,9 @@ ret = -EIO; break; } - for ( i = 0; i < sizeof(struct user_regs_struct); i += sizeof(long) ) { + for (ui = 0; ui < sizeof(struct user_regs_struct); ui += sizeof(long)) { __get_user(tmp, (unsigned long *) data); - putreg(child, i, tmp); + putreg(child, ui, tmp); data += sizeof(long); } ret = 0; diff -Nru a/arch/x86_64/kernel/reboot.c b/arch/x86_64/kernel/reboot.c --- a/arch/x86_64/kernel/reboot.c Sat May 24 12:48:31 2003 +++ b/arch/x86_64/kernel/reboot.c Sat May 24 12:48:31 2003 @@ -9,7 +9,9 @@ #include #include #include - +#include +#include +#include /* * Power off function, if any @@ -17,35 +19,37 @@ void (*pm_power_off)(void); static long no_idt[3]; -static int reboot_mode; - -#ifdef CONFIG_SMP -int reboot_smp = 0; -static int reboot_cpu = -1; -#endif - +static enum { + BOOT_BIOS = 'b', + BOOT_TRIPLE = 't', + BOOT_KBD = 'k' +} reboot_type = BOOT_KBD; +static int reboot_mode = 0; + +/* reboot=b[ios] | t[riple] | k[bd] [, [w]arm | [c]old] + bios Use the CPU reboto vector for warm reset + warm Don't set the cold reboot flag + cold Set the cold reboto flag + triple Force a triple fault (init) + kbd Use the keyboard controller. cold reset (default) + */ static int __init reboot_setup(char *str) { - while(1) { + for (;;) { switch (*str) { - case 'w': /* "warm" reboot (no memory testing etc) */ + case 'w': reboot_mode = 0x1234; break; - case 'c': /* "cold" reboot (with memory testing etc) */ - reboot_mode = 0x0; + + case 'c': + reboot_mode = 0; break; -#ifdef CONFIG_SMP - case 's': /* "smp" reboot by executing reset on BSP or other CPU*/ - reboot_smp = 1; - if (isdigit(str[1])) - sscanf(str+1, "%d", &reboot_cpu); - else if (!strncmp(str,"smp",3)) - sscanf(str+3, "%d", &reboot_cpu); - /* we will leave sorting out the final value - when we are ready to reboot, since we might not - have set up boot_cpu_id or smp_num_cpu */ + + case 't': + case 'b': + case 'k': + reboot_type = *str; break; -#endif } if((str = strchr(str,',')) != NULL) str++; @@ -57,6 +61,56 @@ __setup("reboot=", reboot_setup); +/* overwrites random kernel memory. Should not be kernel .text */ +#define WARMBOOT_TRAMP 0x1000UL + +static void reboot_warm(void) +{ + extern unsigned char warm_reboot[], warm_reboot_end[]; + printk("warm reboot\n"); + + local_irq_disable(); + + /* restore identity mapping */ + init_level4_pgt[0] = __pml4(__pa(level3_ident_pgt) | 7); + __flush_tlb_all(); + + /* Move the trampoline to low memory */ + memcpy(__va(WARMBOOT_TRAMP), warm_reboot, warm_reboot_end - warm_reboot); + + /* Start it in compatibility mode. */ + asm volatile( " pushq $0\n" /* ss */ + " pushq $0x2000\n" /* rsp */ + " pushfq\n" /* eflags */ + " pushq %[cs]\n" + " pushq %[target]\n" + " iretq" :: + [cs] "i" (__KERNEL_COMPAT32_CS), + [target] "b" (WARMBOOT_TRAMP)); +} + +#ifdef CONFIG_SMP +static void smp_halt(void) +{ + int cpuid = safe_smp_processor_id(); + + /* Only run this on the boot processor */ + if (cpuid != boot_cpu_id) { + static int first_entry = 1; + if (first_entry) { + first_entry = 0; + smp_call_function((void *)machine_restart, NULL, 1, 0); + } else { + /* AP reentering. just halt */ + for(;;) + asm volatile("hlt"); + } + + } + smp_send_stop(); +} +#endif + static inline void kb_wait(void) { int i; @@ -68,48 +122,24 @@ void machine_restart(char * __unused) { -#if CONFIG_SMP - int cpuid; - - cpuid = GET_APIC_ID(apic_read(APIC_ID)); - - if (reboot_smp) { + int i; - /* check to see if reboot_cpu is valid - if its not, default to the BSP */ - if ((reboot_cpu == -1) || - (reboot_cpu > (NR_CPUS -1)) || - !(phys_cpu_present_map & (1<x86_power & (1 << i)) { if (i < ARRAY_SIZE(x86_power_flags)) diff -Nru a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c --- a/arch/x86_64/kernel/setup64.c Sat May 24 12:48:22 2003 +++ b/arch/x86_64/kernel/setup64.c Sat May 24 12:48:22 2003 @@ -23,6 +23,7 @@ #include #include #include +#include char x86_boot_params[2048] __initdata = {0,}; @@ -40,21 +41,78 @@ char boot_cpu_stack[IRQSTACKSIZE] __cacheline_aligned; unsigned long __supported_pte_mask = ~0UL; -static int do_not_nx = 1; +static int do_not_nx __initdata = 0; +unsigned long vm_stack_flags = __VM_STACK_FLAGS; +unsigned long vm_stack_flags32 = __VM_STACK_FLAGS; +unsigned long vm_data_default_flags = __VM_DATA_DEFAULT_FLAGS; +unsigned long vm_data_default_flags32 = __VM_DATA_DEFAULT_FLAGS; +unsigned long vm_force_exec32 = PROT_EXEC; + +/* noexec=on|off +Control non executable mappings for 64bit processes. + +on Enable +off Disable +noforce (default) Don't enable by default for heap/stack/data, + but allow PROT_EXEC to be effective +*/ static int __init nonx_setup(char *str) { - if (!strncmp(str,"off",3)) { - __supported_pte_mask &= ~_PAGE_NX; - do_not_nx = 1; - } else if (!strncmp(str, "on",3)) { - do_not_nx = 0; + if (!strncmp(str, "on",3)) { __supported_pte_mask |= _PAGE_NX; + do_not_nx = 0; + vm_data_default_flags &= ~VM_EXEC; + vm_stack_flags &= ~VM_EXEC; + } else if (!strncmp(str, "noforce",7) || !strncmp(str,"off",3)) { + do_not_nx = (str[0] == 'o'); + if (do_not_nx) + __supported_pte_mask &= ~_PAGE_NX; + vm_data_default_flags |= VM_EXEC; + vm_stack_flags |= VM_EXEC; } return 1; } __setup("noexec=", nonx_setup); + +/* noexec32=opt{,opt} + +Control the no exec default for 32bit processes. Can be also overwritten +per executable using ELF header flags (e.g. needed for the X server) +Requires noexec=on or noexec=noforce to be effective. + +Valid options: + all,on Heap,stack,data is non executable. + off (default) Heap,stack,data is executable + stack Stack is non executable, heap/data is. + force Don't imply PROT_EXEC for PROT_READ + compat (default) Imply PROT_EXEC for PROT_READ + +*/ + static int __init nonx32_setup(char *str) + { + char *s; + while ((s = strsep(&str, ",")) != NULL) { + if (!strcmp(s, "all") || !strcmp(s,"on")) { + vm_data_default_flags32 &= ~VM_EXEC; + vm_stack_flags32 &= ~VM_EXEC; + } else if (!strcmp(s, "off")) { + vm_data_default_flags32 |= VM_EXEC; + vm_stack_flags32 |= VM_EXEC; + } else if (!strcmp(s, "stack")) { + vm_data_default_flags32 |= VM_EXEC; + vm_stack_flags32 &= ~VM_EXEC; + } else if (!strcmp(s, "force")) { + vm_force_exec32 = 0; + } else if (!strcmp(s, "compat")) { + vm_force_exec32 = PROT_EXEC; + } + } + return 1; +} + +__setup("noexec32=", nonx32_setup); #ifndef __GENERIC_PER_CPU diff -Nru a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c --- a/arch/x86_64/kernel/signal.c Sat May 24 12:48:28 2003 +++ b/arch/x86_64/kernel/signal.c Sat May 24 12:48:28 2003 @@ -371,7 +371,7 @@ regs->rax = regs->orig_rax; regs->rip -= 2; } - if (regs->rax == -ERESTART_RESTARTBLOCK){ + if (regs->rax == (unsigned long)-ERESTART_RESTARTBLOCK){ regs->rax = __NR_restart_syscall; regs->rip -= 2; } @@ -434,8 +434,8 @@ * have been cleared if the watchpoint triggered * inside the kernel. */ - if (current->thread.debugreg[7]) - asm volatile("movq %0,%%db7" : : "r" (current->thread.debugreg[7])); + if (current->thread.debugreg7) + asm volatile("movq %0,%%db7" : : "r" (current->thread.debugreg7)); /* Whee! Actually deliver the signal. */ handle_signal(signr, &info, oldset, regs); @@ -446,9 +446,10 @@ /* Did we come from a system call? */ if (regs->orig_rax >= 0) { /* Restart the system call - no handlers present */ - if (regs->rax == -ERESTARTNOHAND || - regs->rax == -ERESTARTSYS || - regs->rax == -ERESTARTNOINTR) { + long res = regs->rax; + if (res == -ERESTARTNOHAND || + res == -ERESTARTSYS || + res == -ERESTARTNOINTR) { regs->rax = regs->orig_rax; regs->rip -= 2; } diff -Nru a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c --- a/arch/x86_64/kernel/smpboot.c Sat May 24 12:48:33 2003 +++ b/arch/x86_64/kernel/smpboot.c Sat May 24 12:48:33 2003 @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -123,7 +124,7 @@ unsigned long long t0; unsigned long long sum, avg; long long delta; - unsigned long one_usec; + long one_usec; int buggy = 0; extern unsigned cpu_khz; @@ -339,7 +340,7 @@ /* * Activate a secondary processor. */ -int __init start_secondary(void *unused) +void __init start_secondary(void) { /* * Dont put anything before smp_callin(), SMP @@ -380,29 +381,7 @@ set_bit(smp_processor_id(), &cpu_online_map); wmb(); - return cpu_idle(); -} - -/* - * Everything has been set up for the secondary - * CPUs - they just need to reload everything - * from the task structure - * This function must not return. - */ -void __init initialize_secondary(void) -{ - struct task_struct *me = stack_current(); - - /* - * We don't actually need to load the full TSS, - * basically just the stack pointer and the eip. - */ - - asm volatile( - "movq %0,%%rsp\n\t" - "jmp *%1" - : - :"r" (me->thread.rsp),"r" (me->thread.rip)); + cpu_idle(); } extern volatile unsigned long init_rsp; @@ -412,16 +391,16 @@ { struct pt_regs regs; /* - * don't care about the rip and regs settings since + * don't care about the eip and regs settings since * we'll never reschedule the forked task. */ - return do_fork(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); + return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); } #if APIC_DEBUG static inline void inquire_remote_apic(int apicid) { - int i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 }; + unsigned i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 }; char *names[] = { "ID", "VERSION", "SPIV" }; int timeout, status; @@ -596,6 +575,7 @@ idle = fork_by_hand(); if (IS_ERR(idle)) panic("failed fork for CPU %d", cpu); + wake_up_forked_process(idle); /* * We remove it from the pidhash and the runqueue @@ -603,22 +583,19 @@ */ init_idle(idle,cpu); - idle->thread.rip = (unsigned long)start_secondary; -// idle->thread.rsp = (unsigned long)idle->thread_info + THREAD_SIZE - 512; - unhash_process(idle); cpu_pda[cpu].pcurrent = idle; - /* start_eip had better be page-aligned! */ start_rip = setup_trampoline(); - init_rsp = (unsigned long)idle->thread_info + PAGE_SIZE + 1024; + init_rsp = idle->thread.rsp; init_tss[cpu].rsp0 = init_rsp; - initial_code = initialize_secondary; + initial_code = start_secondary; + clear_ti_thread_flag(idle->thread_info, TIF_FORK); - printk(KERN_INFO "Booting processor %d/%d rip %lx rsp %lx rsp2 %lx\n", cpu, apicid, - start_rip, idle->thread.rsp, init_rsp); + printk(KERN_INFO "Booting processor %d/%d rip %lx rsp %lx\n", cpu, apicid, + start_rip, init_rsp); /* * This grunge runs the startup process for @@ -676,7 +653,7 @@ if (test_bit(cpu, &cpu_callin_map)) { /* number CPUs logically, starting from 1 (BSP is 0) */ Dprintk("OK.\n"); - printk("KERN_INFO CPU%d: ", cpu); + printk(KERN_INFO "CPU%d: ", cpu); print_cpu_info(&cpu_data[cpu]); Dprintk("CPU has booted.\n"); } else { @@ -708,7 +685,7 @@ static void smp_tune_scheduling (void) { - unsigned long cachesize; /* kB */ + int cachesize; /* kB */ unsigned long bandwidth = 1000; /* MB/s */ /* * Rough estimation for SMP scheduling, this is the number of @@ -753,7 +730,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus) { - int apicid, cpu; + unsigned apicid, cpu; /* * Setup boot CPU information diff -Nru a/arch/x86_64/kernel/sys_x86_64.c b/arch/x86_64/kernel/sys_x86_64.c --- a/arch/x86_64/kernel/sys_x86_64.c Sat May 24 12:48:27 2003 +++ b/arch/x86_64/kernel/sys_x86_64.c Sat May 24 12:48:27 2003 @@ -117,5 +117,5 @@ asmlinkage long wrap_sys_shmat(int shmid, char *shmaddr, int shmflg) { unsigned long raddr; - return sys_shmat(shmid,shmaddr,shmflg,&raddr) ?: raddr; + return sys_shmat(shmid,shmaddr,shmflg,&raddr) ?: (long)raddr; } diff -Nru a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c --- a/arch/x86_64/kernel/traps.c Sat May 24 12:48:19 2003 +++ b/arch/x86_64/kernel/traps.c Sat May 24 12:48:19 2003 @@ -529,7 +529,7 @@ unsigned char reason = inb(0x61); if (!(reason & 0xc0)) { -#if CONFIG_X86_LOCAL_APIC +#ifdef CONFIG_X86_LOCAL_APIC /* * Ok, so this is none of the documented NMI sources, * so it must be the NMI watchdog. @@ -584,12 +584,12 @@ /* Mask out spurious debug traps due to lazy DR7 setting */ if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) { - if (!tsk->thread.debugreg[7]) { + if (!tsk->thread.debugreg7) { goto clear_dr7; } } - tsk->thread.debugreg[6] = condition; + tsk->thread.debugreg6 = condition; /* Mask out spurious TF errors due to lazy TF clearing */ if (condition & DR_STEP) { diff -Nru a/arch/x86_64/kernel/vsyscall.S b/arch/x86_64/kernel/vsyscall.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/x86_64/kernel/vsyscall.S Sat May 24 12:48:34 2003 @@ -0,0 +1,169 @@ +/* + * Code for the vsyscall page. This version uses the syscall instruction. + */ + +#include +#include + + .text + .globl __kernel_vsyscall + .type __kernel_vsyscall,@function +__kernel_vsyscall: +.LSTART_vsyscall: + push %ebp +.Lpush_ebp: + movl %ecx, %ebp + syscall + popl %ebp +.Lpop_ebp: + ret +.LEND_vsyscall: + .size __kernel_vsyscall,.-.LSTART_vsyscall + + .balign 32 + .globl __kernel_sigreturn + .type __kernel_sigreturn,@function +__kernel_sigreturn: +.LSTART_sigreturn: + popl %eax + movl $__NR_ia32_sigreturn, %eax + syscall +.LEND_sigreturn: + .size __kernel_sigreturn,.-.LSTART_sigreturn + + .balign 32 + .globl __kernel_rt_sigreturn + .type __kernel_rt_sigreturn,@function +__kernel_rt_sigreturn: +.LSTART_rt_sigreturn: + movl $__NR_ia32_rt_sigreturn, %eax + syscall +.LEND_rt_sigreturn: + .size __kernel_rt_sigreturn,.-.LSTART_rt_sigreturn + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .long .LENDCIE-.LSTARTCIE +.LSTARTCIE: + .long 0 /* CIE ID */ + .byte 1 /* Version number */ + .string "zR" /* NUL-terminated augmentation string */ + .uleb128 1 /* Code alignment factor */ + .sleb128 -4 /* Data alignment factor */ + .byte 8 /* Return address register column */ + .uleb128 1 /* Augmentation value length */ + .byte 0x1b /* DW_EH_PE_pcrel|DW_EH_PE_sdata4. */ + .byte 0x0c /* DW_CFA_def_cfa */ + .uleb128 4 + .uleb128 4 + .byte 0x88 /* DW_CFA_offset, column 0x8 */ + .uleb128 1 + .align 4 +.LENDCIE: + + .long .LENDFDE1-.LSTARTFDE1 /* Length FDE */ +.LSTARTFDE1: + .long .LSTARTFDE1-.LSTARTFRAME /* CIE pointer */ + .long .LSTART_vsyscall-. /* PC-relative start address */ + .long .LEND_vsyscall-.LSTART_vsyscall + .uleb128 0 /* Augmentation length */ + /* What follows are the instructions for the table generation. + We have to record all changes of the stack pointer. */ + .byte 0x40 + .Lpush_ebp-.LSTART_vsyscall /* DW_CFA_advance_loc */ + .byte 0x0e /* DW_CFA_def_cfa_offset */ + .uleb128 8 + .byte 0x85, 0x02 /* DW_CFA_offset %ebp -8 */ + .byte 0x40 + .Lpop_ebp-.Lpush_ebp /* DW_CFA_advance_loc */ + .byte 0xc5 /* DW_CFA_restore %ebp */ + .byte 0x0e /* DW_CFA_def_cfa_offset */ + .uleb128 4 + .align 4 +.LENDFDE1: + + .long .LENDFDE2-.LSTARTFDE2 /* Length FDE */ +.LSTARTFDE2: + .long .LSTARTFDE2-.LSTARTFRAME /* CIE pointer */ + /* HACK: The dwarf2 unwind routines will subtract 1 from the + return address to get an address in the middle of the + presumed call instruction. Since we didn't get here via + a call, we need to include the nop before the real start + to make up for it. */ + .long .LSTART_sigreturn-1-. /* PC-relative start address */ + .long .LEND_sigreturn-.LSTART_sigreturn+1 + .uleb128 0 /* Augmentation length */ + /* What follows are the instructions for the table generation. + We record the locations of each register saved. This is + complicated by the fact that the "CFA" is always assumed to + be the value of the stack pointer in the caller. This means + that we must define the CFA of this body of code to be the + saved value of the stack pointer in the sigcontext. Which + also means that there is no fixed relation to the other + saved registers, which means that we must use DW_CFA_expression + to compute their addresses. It also means that when we + adjust the stack with the popl, we have to do it all over again. */ + +#define do_cfa_expr(offset) \ + .byte 0x0f; /* DW_CFA_def_cfa_expression */ \ + .uleb128 1f-0f; /* length */ \ +0: .byte 0x74; /* DW_OP_breg4 */ \ + .sleb128 offset; /* offset */ \ + .byte 0x06; /* DW_OP_deref */ \ +1: + +#define do_expr(regno, offset) \ + .byte 0x10; /* DW_CFA_expression */ \ + .uleb128 regno; /* regno */ \ + .uleb128 1f-0f; /* length */ \ +0: .byte 0x74; /* DW_OP_breg4 */ \ + .sleb128 offset; /* offset */ \ +1: + + do_cfa_expr(IA32_SIGCONTEXT_esp+4) + do_expr(0, IA32_SIGCONTEXT_eax+4) + do_expr(1, IA32_SIGCONTEXT_ecx+4) + do_expr(2, IA32_SIGCONTEXT_edx+4) + do_expr(3, IA32_SIGCONTEXT_ebx+4) + do_expr(5, IA32_SIGCONTEXT_ebp+4) + do_expr(6, IA32_SIGCONTEXT_esi+4) + do_expr(7, IA32_SIGCONTEXT_edi+4) + do_expr(8, IA32_SIGCONTEXT_eip+4) + + .byte 0x42 /* DW_CFA_advance_loc 2 -- nop; popl eax. */ + + do_cfa_expr(IA32_SIGCONTEXT_esp) + do_expr(0, IA32_SIGCONTEXT_eax) + do_expr(1, IA32_SIGCONTEXT_ecx) + do_expr(2, IA32_SIGCONTEXT_edx) + do_expr(3, IA32_SIGCONTEXT_ebx) + do_expr(5, IA32_SIGCONTEXT_ebp) + do_expr(6, IA32_SIGCONTEXT_esi) + do_expr(7, IA32_SIGCONTEXT_edi) + do_expr(8, IA32_SIGCONTEXT_eip) + + .align 4 +.LENDFDE2: + + .long .LENDFDE3-.LSTARTFDE3 /* Length FDE */ +.LSTARTFDE3: + .long .LSTARTFDE3-.LSTARTFRAME /* CIE pointer */ + /* HACK: See above wrt unwind library assumptions. */ + .long .LSTART_rt_sigreturn-1-. /* PC-relative start address */ + .long .LEND_rt_sigreturn-.LSTART_rt_sigreturn+1 + .uleb128 0 /* Augmentation */ + /* What follows are the instructions for the table generation. + We record the locations of each register saved. This is + slightly less complicated than the above, since we don't + modify the stack pointer in the process. */ + + do_cfa_expr(IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_esp) + do_expr(0, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_eax) + do_expr(1, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_ecx) + do_expr(2, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_edx) + do_expr(3, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_ebx) + do_expr(5, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_ebp) + do_expr(6, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_esi) + do_expr(7, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_edi) + do_expr(8, IA32_RT_SIGFRAME_sigcontext-4 + IA32_SIGCONTEXT_eip) + + .align 4 +.LENDFDE3: diff -Nru a/arch/x86_64/kernel/warmreboot.S b/arch/x86_64/kernel/warmreboot.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/x86_64/kernel/warmreboot.S Sat May 24 12:48:34 2003 @@ -0,0 +1,83 @@ +/* + * Switch back to real mode and call the BIOS reboot vector. + * This is a trampoline copied around in process.c + * Written 2003 by Andi Kleen, SuSE Labs. + */ + +#include + +#define R(x) x-warm_reboot(%ebx) +#define R64(x) x-warm_reboot(%rbx) + + /* running in identity mapping and in the first 64k of memory + and in compatibility mode. This must be position independent */ + + /* Follows 14.7 "Leaving Long Mode" in the AMD x86-64 manual, volume 2 + and 8.9.2 "Switching Back to Real-Address Mode" in the Intel IA32 + manual, volume 2 */ + + /* ebx: self pointer to warm_reboot */ + + .globl warm_reboot +warm_reboot: + addl %ebx, R64(real_mode_desc) /* relocate tables */ + addl %ebx,2+R64(warm_gdt_desc) + + movq %cr0,%rax + btr $31,%rax + movq %rax,%cr0 /* disable paging */ + jmp 1f /* flush prefetch queue */ + + .code32 +1: movl $MSR_EFER,%ecx + rdmsr + andl $~((1<<_EFER_LME)|(1<<_EFER_SCE)|(1<<_EFER_NX)),%eax + wrmsr /* disable long mode in EFER */ + + xorl %eax,%eax + movl %eax,%cr3 /* flush tlb */ + + /* Running protected mode without paging now */ + + wbinvd /* flush caches. Needed? */ + + lidt R(warm_idt_desc) + lgdt R(warm_gdt_desc) + + movl $0x10,%ecx /* load segment registers with real mode settings */ + movl %ecx,%ds + movl %ecx,%es + movl %ecx,%fs + movl %ecx,%gs + movl %ecx,%ss + + lea R(real_mode_desc),%eax + ljmp *(%eax) + + .code16: +real_mode: + xorl %eax,%eax + movl %eax,%cr0 + + /* some people claim $0xf000,0xfff0 is better. Use what 32bit linux uses. */ + /* code as bytes because gas has problems with it */ + .byte 0xea,0xf0,0xff,0x00,0xf0 /* ljmp 0xf000:0xfff0 */ + +real_mode_desc: + .long real_mode - warm_reboot + .short 8 +warm_gdt_desc: + .short 8*3 + .long warm_gdt - warm_reboot +warm_gdt: + .quad 0 + .quad 0x00009a000000ffff /* 16-bit real-mode 64k code at 0x00000000 */ + .quad 0x000092000100ffff /* 16-bit real-mode 64k data at 0x00000100 */ + +warm_idt_desc: + .short 0x3ff + .long 0 + + .globl warm_reboot_end +warm_reboot_end: + diff -Nru a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c --- a/arch/x86_64/kernel/x8664_ksyms.c Sat May 24 12:48:21 2003 +++ b/arch/x86_64/kernel/x8664_ksyms.c Sat May 24 12:48:21 2003 @@ -207,3 +207,12 @@ extern unsigned long __supported_pte_mask; EXPORT_SYMBOL(__supported_pte_mask); + +#ifdef CONFIG_DISCONTIGMEM +EXPORT_SYMBOL(memnode_shift); +EXPORT_SYMBOL(memnodemap); +EXPORT_SYMBOL(node_data); +EXPORT_SYMBOL(fake_node); +#endif + +EXPORT_SYMBOL(clear_page); diff -Nru a/arch/x86_64/lib/copy_user.S b/arch/x86_64/lib/copy_user.S --- a/arch/x86_64/lib/copy_user.S Sat May 24 12:48:26 2003 +++ b/arch/x86_64/lib/copy_user.S Sat May 24 12:48:26 2003 @@ -6,16 +6,13 @@ #define FIX_ALIGNMENT 1 -#define movnti movq /* write to cache for now */ -#define prefetch prefetcht2 - #include #include #include /* Standard copy_to_user with segment limit checking */ .globl copy_to_user - .p2align + .p2align 4 copy_to_user: GET_THREAD_INFO(%rax) movq %rdi,%rcx @@ -27,7 +24,7 @@ /* Standard copy_from_user with segment limit checking */ .globl copy_from_user - .p2align + .p2align 4 copy_from_user: GET_THREAD_INFO(%rax) movq %rsi,%rcx @@ -58,23 +55,23 @@ * rdx count * * Output: - * eax uncopied bytes or 0 if successful. + * eax uncopied bytes or 0 if successfull. */ .globl copy_user_generic + .p2align 4 copy_user_generic: /* Put the first cacheline into cache. This should handle the small movements in ioctls etc., but not penalize the bigger filesystem data copies too much. */ pushq %rbx - prefetch (%rsi) xorl %eax,%eax /*zero for the exception handler */ #ifdef FIX_ALIGNMENT /* check for bad alignment of destination */ movl %edi,%ecx andl $7,%ecx - jnz bad_alignment -after_bad_alignment: + jnz .Lbad_alignment +.Lafter_bad_alignment: #endif movq %rdx,%rcx @@ -82,133 +79,133 @@ movl $64,%ebx shrq $6,%rdx decq %rdx - js handle_tail - jz loop_no_prefetch - -loop: - prefetch 64(%rsi) + js .Lhandle_tail -loop_no_prefetch: -s1: movq (%rsi),%r11 -s2: movq 1*8(%rsi),%r8 -s3: movq 2*8(%rsi),%r9 -s4: movq 3*8(%rsi),%r10 -d1: movnti %r11,(%rdi) -d2: movnti %r8,1*8(%rdi) -d3: movnti %r9,2*8(%rdi) -d4: movnti %r10,3*8(%rdi) + .p2align 4 +.Lloop: +.Ls1: movq (%rsi),%r11 +.Ls2: movq 1*8(%rsi),%r8 +.Ls3: movq 2*8(%rsi),%r9 +.Ls4: movq 3*8(%rsi),%r10 +.Ld1: movq %r11,(%rdi) +.Ld2: movq %r8,1*8(%rdi) +.Ld3: movq %r9,2*8(%rdi) +.Ld4: movq %r10,3*8(%rdi) -s5: movq 4*8(%rsi),%r11 -s6: movq 5*8(%rsi),%r8 -s7: movq 6*8(%rsi),%r9 -s8: movq 7*8(%rsi),%r10 -d5: movnti %r11,4*8(%rdi) -d6: movnti %r8,5*8(%rdi) -d7: movnti %r9,6*8(%rdi) -d8: movnti %r10,7*8(%rdi) - - addq %rbx,%rsi - addq %rbx,%rdi +.Ls5: movq 4*8(%rsi),%r11 +.Ls6: movq 5*8(%rsi),%r8 +.Ls7: movq 6*8(%rsi),%r9 +.Ls8: movq 7*8(%rsi),%r10 +.Ld5: movq %r11,4*8(%rdi) +.Ld6: movq %r8,5*8(%rdi) +.Ld7: movq %r9,6*8(%rdi) +.Ld8: movq %r10,7*8(%rdi) decq %rdx - jz loop_no_prefetch - jns loop -handle_tail: + leaq 64(%rsi),%rsi + leaq 64(%rdi),%rdi + + jns .Lloop + + .p2align 4 +.Lhandle_tail: movl %ecx,%edx andl $63,%ecx shrl $3,%ecx - jz handle_7 + jz .Lhandle_7 movl $8,%ebx -loop_8: -s9: movq (%rsi),%r8 -d9: movq %r8,(%rdi) - addq %rbx,%rdi - addq %rbx,%rsi + .p2align 4 +.Lloop_8: +.Ls9: movq (%rsi),%r8 +.Ld9: movq %r8,(%rdi) decl %ecx - jnz loop_8 + leaq 8(%rdi),%rdi + leaq 8(%rsi),%rsi + jnz .Lloop_8 -handle_7: +.Lhandle_7: movl %edx,%ecx andl $7,%ecx - jz ende -loop_1: -s10: movb (%rsi),%bl -d10: movb %bl,(%rdi) + jz .Lende + .p2align 4 +.Lloop_1: +.Ls10: movb (%rsi),%bl +.Ld10: movb %bl,(%rdi) incq %rdi incq %rsi decl %ecx - jnz loop_1 + jnz .Lloop_1 -ende: - sfence +.Lende: popq %rbx ret #ifdef FIX_ALIGNMENT /* align destination */ -bad_alignment: + .p2align 4 +.Lbad_alignment: movl $8,%r9d subl %ecx,%r9d movl %r9d,%ecx subq %r9,%rdx - jz small_align - js small_align -align_1: -s11: movb (%rsi),%bl -d11: movb %bl,(%rdi) + jz .Lsmall_align + js .Lsmall_align +.Lalign_1: +.Ls11: movb (%rsi),%bl +.Ld11: movb %bl,(%rdi) incq %rsi incq %rdi decl %ecx - jnz align_1 - jmp after_bad_alignment -small_align: + jnz .Lalign_1 + jmp .Lafter_bad_alignment +.Lsmall_align: addq %r9,%rdx - jmp handle_7 + jmp .Lhandle_7 #endif /* table sorted by exception address */ .section __ex_table,"a" .align 8 - .quad s1,s1e - .quad s2,s2e - .quad s3,s3e - .quad s4,s4e - .quad d1,s1e - .quad d2,s2e - .quad d3,s3e - .quad d4,s4e - .quad s5,s5e - .quad s6,s6e - .quad s7,s7e - .quad s8,s8e - .quad d5,s5e - .quad d6,s6e - .quad d7,s7e - .quad d8,s8e - .quad s9,e_quad - .quad d9,e_quad - .quad s10,e_byte - .quad d10,e_byte + .quad .Ls1,.Ls1e + .quad .Ls2,.Ls2e + .quad .Ls3,.Ls3e + .quad .Ls4,.Ls4e + .quad .Ld1,.Ls1e + .quad .Ld2,.Ls2e + .quad .Ld3,.Ls3e + .quad .Ld4,.Ls4e + .quad .Ls5,.Ls5e + .quad .Ls6,.Ls6e + .quad .Ls7,.Ls7e + .quad .Ls8,.Ls8e + .quad .Ld5,.Ls5e + .quad .Ld6,.Ls6e + .quad .Ld7,.Ls7e + .quad .Ld8,.Ls8e + .quad .Ls9,.Le_quad + .quad .Ld9,.Le_quad + .quad .Ls10,.Le_byte + .quad .Ld10,.Le_byte #ifdef FIX_ALIGNMENT - .quad s11,e_byte - .quad d11,e_byte + .quad .Ls11,.Le_byte + .quad .Ld11,.Le_byte #endif - .quad e5,e_zero + .quad .Le5,.Le_zero .previous /* compute 64-offset for main loop. 8 bytes accuracy with error on the pessimistic side. this is gross. it would be better to fix the interface. */ /* eax: zero, ebx: 64 */ -s1e: addl $8,%eax -s2e: addl $8,%eax -s3e: addl $8,%eax -s4e: addl $8,%eax -s5e: addl $8,%eax -s6e: addl $8,%eax -s7e: addl $8,%eax -s8e: addl $8,%eax +.Ls1e: addl $8,%eax +.Ls2e: addl $8,%eax +.Ls3e: addl $8,%eax +.Ls4e: addl $8,%eax +.Ls5e: addl $8,%eax +.Ls6e: addl $8,%eax +.Ls7e: addl $8,%eax +.Ls8e: addl $8,%eax addq %rbx,%rdi /* +64 */ subq %rax,%rdi /* correct destination with computed offset */ @@ -216,22 +213,22 @@ addq %rax,%rdx /* add offset to loopcnt */ andl $63,%ecx /* remaining bytes */ addq %rcx,%rdx /* add them */ - jmp zero_rest + jmp .Lzero_rest /* exception on quad word loop in tail handling */ /* ecx: loopcnt/8, %edx: length, rdi: correct */ -e_quad: +.Le_quad: shll $3,%ecx andl $7,%edx addl %ecx,%edx /* edx: bytes to zero, rdi: dest, eax:zero */ -zero_rest: +.Lzero_rest: movq %rdx,%rcx -e_byte: +.Le_byte: xorl %eax,%eax -e5: rep +.Le5: rep stosb /* when there is another exception while zeroing the rest just return */ -e_zero: +.Le_zero: movq %rdx,%rax - jmp ende + jmp .Lende diff -Nru a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c --- a/arch/x86_64/mm/fault.c Sat May 24 12:48:19 2003 +++ b/arch/x86_64/mm/fault.c Sat May 24 12:48:19 2003 @@ -226,17 +226,18 @@ bad_area_nosemaphore: - /* User mode accesses just cause a SIGSEGV */ - if (error_code & 4) { #ifdef CONFIG_IA32_EMULATION /* 32bit vsyscall. map on demand. */ if (test_thread_flag(TIF_IA32) && - address >= 0xffffe000 && address < 0xffffefff-7) { + address >= 0xffffe000 && address < 0xffffe000 + PAGE_SIZE) { if (map_syscall32(mm, address) < 0) goto out_of_memory2; return; } #endif + + /* User mode accesses just cause a SIGSEGV */ + if (error_code & 4) { printk(KERN_INFO "%s[%d] segfault at rip:%lx rsp:%lx adr:%lx err:%lx\n", tsk->comm, tsk->pid, regs->rip, regs->rsp, address, diff -Nru a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c --- a/arch/x86_64/mm/init.c Sat May 24 12:48:21 2003 +++ b/arch/x86_64/mm/init.c Sat May 24 12:48:21 2003 @@ -39,7 +39,7 @@ #include #include -#define Dprintk(x...) printk(x) +#define Dprintk(x...) struct mmu_gather mmu_gathers[NR_CPUS]; @@ -105,7 +105,7 @@ pml4_t *level4; pgd_t *pgd; pmd_t *pmd; - pte_t *pte; + pte_t *pte, new_pte; Dprintk("set_pte_phys %lx to %lx\n", vaddr, phys); @@ -132,11 +132,13 @@ return; } } + new_pte = pfn_pte(phys >> PAGE_SHIFT, prot); + pte = pte_offset_kernel(pmd, vaddr); - /* CHECKME: */ - if (pte_val(*pte)) + if (!pte_none(*pte) && + pte_val(*pte) != (pte_val(new_pte) & __supported_pte_mask)) pte_ERROR(*pte); - set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot)); + set_pte(pte, new_pte); /* * It's enough to flush this one mapping. @@ -339,6 +341,35 @@ return; } #endif + +/* Unmap a kernel mapping if it exists. This is useful to avoid prefetches + from the CPU leading to inconsistent cache lines. address and size + must be aligned to 2MB boundaries. + Does nothing when the mapping doesn't exist. */ +void __init clear_kernel_mapping(unsigned long address, unsigned long size) +{ + unsigned long end = address + size; + + BUG_ON(address & ~LARGE_PAGE_MASK); + BUG_ON(size & ~LARGE_PAGE_MASK); + + for (; address < end; address += LARGE_PAGE_SIZE) { + pgd_t *pgd = pgd_offset_k(address); + if (!pgd || pgd_none(*pgd)) + continue; + pmd_t *pmd = pmd_offset(pgd, address); + if (!pmd || pmd_none(*pmd)) + continue; + if (0 == (pmd_val(*pmd) & _PAGE_PSE)) { + /* Could handle this, but it should not happen currently. */ + printk(KERN_ERR + "clear_kernel_mapping: mapping has been split. will leak memory\n"); + pmd_ERROR(*pmd); + } + set_pmd(pmd, __pmd(0)); + } + __flush_tlb_all(); +} static inline int page_is_ram (unsigned long pagenr) { diff -Nru a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c --- a/arch/x86_64/mm/ioremap.c Sat May 24 12:48:32 2003 +++ b/arch/x86_64/mm/ioremap.c Sat May 24 12:48:32 2003 @@ -222,7 +222,6 @@ return; } - unmap_vm_area(p); if (p->flags && p->phys_addr < virt_to_phys(high_memory)) { change_page_attr(virt_to_page(__va(p->phys_addr)), p->size >> PAGE_SHIFT, diff -Nru a/arch/x86_64/mm/k8topology.c b/arch/x86_64/mm/k8topology.c --- a/arch/x86_64/mm/k8topology.c Sat May 24 12:48:32 2003 +++ b/arch/x86_64/mm/k8topology.c Sat May 24 12:48:32 2003 @@ -87,10 +87,8 @@ if (limit > end_pfn_map << PAGE_SHIFT) limit = end_pfn_map << PAGE_SHIFT; - if (limit <= base) { - printk(KERN_INFO "Node %d beyond memory map\n", nodeid); + if (limit <= base) continue; - } base >>= 16; base <<= 24; diff -Nru a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c --- a/arch/x86_64/mm/numa.c Sat May 24 12:48:31 2003 +++ b/arch/x86_64/mm/numa.c Sat May 24 12:48:31 2003 @@ -15,7 +15,7 @@ #include #include -#define Dprintk(x...) printk(x) +#define Dprintk(x...) struct pglist_data *node_data[MAXNODE]; bootmem_data_t plat_node_bdata[MAX_NUMNODES]; @@ -104,8 +104,11 @@ reserve_bootmem_node(NODE_DATA(nodeid), nodedata_phys, pgdat_size); reserve_bootmem_node(NODE_DATA(nodeid), bootmap_start, bootmap_pages< numnodes) + if (nodeid + 1 > numnodes) { numnodes = nodeid + 1; + printk(KERN_INFO + "setup_node_bootmem: enlarging numnodes to %d\n", numnodes); + } nodes_present |= (1UL << nodeid); } @@ -121,7 +124,7 @@ start_pfn = node_start_pfn(nodeid); end_pfn = node_end_pfn(nodeid); - printk("setting up node %d %lx-%lx\n", nodeid, start_pfn, end_pfn); + printk(KERN_INFO "setting up node %d %lx-%lx\n", nodeid, start_pfn, end_pfn); /* All nodes > 0 have a zero length zone DMA */ dma_end_pfn = __pa(MAX_DMA_ADDRESS) >> PAGE_SHIFT; diff -Nru a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c --- a/arch/x86_64/mm/pageattr.c Sat May 24 12:48:24 2003 +++ b/arch/x86_64/mm/pageattr.c Sat May 24 12:48:24 2003 @@ -63,29 +63,53 @@ __flush_tlb_one(address); } + +static inline void flush_map(unsigned long address) +{ + on_each_cpu(flush_kernel_map, (void *)address, 1, 1); +} + +struct deferred_page { + struct deferred_page *next; + struct page *fpage; + unsigned long address; +}; +static struct deferred_page *df_list; /* protected by init_mm.mmap_sem */ + +static inline void save_page(unsigned long address, struct page *fpage) +{ + struct deferred_page *df; + df = kmalloc(sizeof(struct deferred_page), GFP_KERNEL); + if (!df) { + flush_map(address); + __free_page(fpage); + } else { + df->next = df_list; + df->fpage = fpage; + df->address = address; + df_list = df; + } +} + /* * No more special protections in this 2/4MB area - revert to a * large page again. */ -static inline void revert_page(struct page *kpte_page, unsigned long address) +static void revert_page(struct page *kpte_page, unsigned long address) { pgd_t *pgd; pmd_t *pmd; pte_t large_pte; pgd = pgd_offset_k(address); - if (!pgd) BUG(); pmd = pmd_offset(pgd, address); - if (!pmd) BUG(); - if ((pmd_val(*pmd) & _PAGE_GLOBAL) == 0) BUG(); - + BUG_ON(pmd_val(*pmd) & _PAGE_PSE); large_pte = mk_pte_phys(__pa(address) & LARGE_PAGE_MASK, PAGE_KERNEL_LARGE); set_pte((pte_t *)pmd, large_pte); } static int -__change_page_attr(unsigned long address, struct page *page, pgprot_t prot, - struct page **oldpage) +__change_page_attr(unsigned long address, struct page *page, pgprot_t prot) { pte_t *kpte; struct page *kpte_page; @@ -107,6 +131,7 @@ struct page *split = split_large_page(address, prot); if (!split) return -ENOMEM; + atomic_inc(&kpte_page->count); set_pte(kpte,mk_pte(split, PAGE_KERNEL)); } } else if ((kpte_flags & _PAGE_PSE) == 0) { @@ -115,39 +140,12 @@ } if (atomic_read(&kpte_page->count) == 1) { - *oldpage = kpte_page; + save_page(address, kpte_page); revert_page(kpte_page, address); } return 0; } -static inline void flush_map(unsigned long address) -{ - on_each_cpu(flush_kernel_map, (void *)address, 1, 1); -} - -struct deferred_page { - struct deferred_page *next; - struct page *fpage; - unsigned long address; -}; -static struct deferred_page *df_list; /* protected by init_mm.mmap_sem */ - -static inline void save_page(unsigned long address, struct page *fpage) -{ - struct deferred_page *df; - df = kmalloc(sizeof(struct deferred_page), GFP_KERNEL); - if (!df) { - flush_map(address); - __free_page(fpage); - } else { - df->next = df_list; - df->fpage = fpage; - df->address = address; - df_list = df; - } -} - /* * Change the page attributes of an page in the linear mapping. * @@ -164,24 +162,19 @@ int change_page_attr(struct page *page, int numpages, pgprot_t prot) { int err = 0; - struct page *fpage, *fpage2; int i; down_write(&init_mm.mmap_sem); - for (i = 0; i < numpages; i++, page++) { + for (i = 0; i < numpages; !err && i++, page++) { unsigned long address = (unsigned long)page_address(page); - fpage = NULL; - err = __change_page_attr(address, page, prot, &fpage); + err = __change_page_attr(address, page, prot); + if (err) + break; /* Handle kernel mapping too which aliases part of the lowmem */ - if (!err && page_to_phys(page) < KERNEL_TEXT_SIZE) { + if (page_to_phys(page) < KERNEL_TEXT_SIZE) { unsigned long addr2 = __START_KERNEL_map + page_to_phys(page); - fpage2 = NULL; - err = __change_page_attr(addr2, page, prot, &fpage2); - if (fpage2) - save_page(addr2, fpage2); + err = __change_page_attr(addr2, page, prot); } - if (fpage) - save_page(address, fpage); } up_write(&init_mm.mmap_sem); return err; diff -Nru a/arch/x86_64/pci/irq.c b/arch/x86_64/pci/irq.c --- a/arch/x86_64/pci/irq.c Sat May 24 12:48:26 2003 +++ b/arch/x86_64/pci/irq.c Sat May 24 12:48:26 2003 @@ -378,8 +378,9 @@ return NULL; } -static void pcibios_test_irq_handler(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t pcibios_test_irq_handler(int irq, void *dev_id, struct pt_regs *regs) { + return IRQ_NONE; } static int pcibios_lookup_irq(struct pci_dev *dev, int assign) diff -Nru a/arch/x86_64/vmlinux.lds.S b/arch/x86_64/vmlinux.lds.S --- a/arch/x86_64/vmlinux.lds.S Sat May 24 12:48:20 2003 +++ b/arch/x86_64/vmlinux.lds.S Sat May 24 12:48:20 2003 @@ -127,7 +127,7 @@ /* Sections to be discarded */ /DISCARD/ : { *(.exit.data) - *(.exit.text) + /* *(.exit.text) */ *(.exitcall.exit) *(.eh_frame) } diff -Nru a/crypto/Kconfig b/crypto/Kconfig --- a/crypto/Kconfig Sat May 24 12:48:32 2003 +++ b/crypto/Kconfig Sat May 24 12:48:32 2003 @@ -6,14 +6,16 @@ config CRYPTO bool "Cryptographic API" - default y if INET_AH=y || INET_AH=m || INET_ESP=y || INET_ESP=m + default y if INET_AH=y || INET_AH=m || INET_ESP=y || INET_ESP=m || INET6_AH=y || INET6_AH=m || \ + INET6_ESP=y || INET6_ESP=m help This option provides the core Cryptographic API. config CRYPTO_HMAC bool "HMAC support" depends on CRYPTO - default y if INET_AH=y || INET_AH=m || INET_ESP=y || INET_ESP=m + default y if INET_AH=y || INET_AH=m || INET_ESP=y || INET_ESP=m || INET6_AH=y || INET6_AH=m || \ + INET6_ESP=y || INET6_ESP=m help HMAC: Keyed-Hashing for Message Authentication (RFC2104). This is required for IPSec. @@ -33,14 +35,16 @@ config CRYPTO_MD5 tristate "MD5 digest algorithm" depends on CRYPTO - default y if INET_AH=y || INET_AH=m || INET_ESP=y || INET_ESP=m + default y if INET_AH=y || INET_AH=m || INET_ESP=y || INET_ESP=m || INET6_AH=y || INET6_AH=m || \ + INET6_ESP=y || INET6_ESP=m help MD5 message digest algorithm (RFC1321). config CRYPTO_SHA1 tristate "SHA1 digest algorithm" depends on CRYPTO - default y if INET_AH=y || INET_AH=m || INET_ESP=y || INET_ESP=m + default y if INET_AH=y || INET_AH=m || INET_ESP=y || INET_ESP=m || INET6_AH=y || INET6_AH=m || \ + INET6_ESP=y || INET6_ESP=m help SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2). @@ -68,7 +72,7 @@ config CRYPTO_DES tristate "DES and Triple DES EDE cipher algorithms" depends on CRYPTO - default y if INET_AH=y || INET_AH=m || INET_ESP=y || INET_ESP=m + default y if INET_ESP=y || INET_ESP=m || INET6_ESP=y || INET6_ESP=m help DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3). @@ -134,7 +138,7 @@ config CRYPTO_DEFLATE tristate "Deflate compression algorithm" depends on CRYPTO - default y if INET_IPCOMP=y || INET_IPCOMP=m + default y if INET_IPCOMP=y || INET_IPCOMP=m || INET6_IPCOMP=y || INET6_IPCOMP=m help This is the Deflate algorithm (RFC1951), specified for use in IPSec with the IPCOMP protocol (RFC3173, RFC2394). diff -Nru a/crypto/autoload.c b/crypto/autoload.c --- a/crypto/autoload.c Sat May 24 12:48:23 2003 +++ b/crypto/autoload.c Sat May 24 12:48:23 2003 @@ -23,7 +23,7 @@ */ void crypto_alg_autoload(const char *name) { - request_module(name); + request_module("%s", name); } struct crypto_alg *crypto_alg_mod_lookup(const char *name) diff -Nru a/crypto/deflate.c b/crypto/deflate.c --- a/crypto/deflate.c Sat May 24 12:48:32 2003 +++ b/crypto/deflate.c Sat May 24 12:48:32 2003 @@ -81,7 +81,7 @@ ret = -ENOMEM; goto out; } - memset(stream->workspace, 0, sizeof(stream->workspace)); + memset(stream->workspace, 0, zlib_deflate_workspacesize()); ret = zlib_deflateInit2(stream, DEFLATE_DEF_LEVEL, Z_DEFLATED, -DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL, Z_DEFAULT_STRATEGY); @@ -108,7 +108,7 @@ ret = -ENOMEM; goto out; } - memset(stream->workspace, 0, sizeof(stream->workspace)); + memset(stream->workspace, 0, zlib_inflate_workspacesize()); ret = zlib_inflateInit2(stream, -DEFLATE_DEF_WINBITS); if (ret != Z_OK) { ret = -EINVAL; diff -Nru a/crypto/md4.c b/crypto/md4.c --- a/crypto/md4.c Sat May 24 12:48:25 2003 +++ b/crypto/md4.c Sat May 24 12:48:25 2003 @@ -215,7 +215,7 @@ md4_transform(mctx->hash, mctx->block); cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(u32)); memcpy(out, mctx->hash, sizeof(mctx->hash)); - memset(mctx, 0, sizeof(mctx)); + memset(mctx, 0, sizeof(*mctx)); } static struct crypto_alg alg = { diff -Nru a/crypto/md5.c b/crypto/md5.c --- a/crypto/md5.c Sat May 24 12:48:24 2003 +++ b/crypto/md5.c Sat May 24 12:48:24 2003 @@ -210,7 +210,7 @@ md5_transform(mctx->hash, mctx->block); cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(u32)); memcpy(out, mctx->hash, sizeof(mctx->hash)); - memset(mctx, 0, sizeof(mctx)); + memset(mctx, 0, sizeof(*mctx)); } static struct crypto_alg alg = { diff -Nru a/crypto/tcrypt.c b/crypto/tcrypt.c --- a/crypto/tcrypt.c Sat May 24 12:48:30 2003 +++ b/crypto/tcrypt.c Sat May 24 12:48:30 2003 @@ -113,7 +113,7 @@ printk("\ntesting md5 across pages\n"); /* setup the dummy buffer first */ - memset(xbuf, 0, sizeof (xbuf)); + memset(xbuf, 0, XBUFSIZE); memcpy(&xbuf[IDX1], "abcdefghijklm", 13); memcpy(&xbuf[IDX2], "nopqrstuvwxyz", 13); @@ -188,7 +188,7 @@ printk("\ntesting hmac_md5 across pages\n"); - memset(xbuf, 0, sizeof (xbuf)); + memset(xbuf, 0, XBUFSIZE); memcpy(&xbuf[IDX1], "what do ya want ", 16); memcpy(&xbuf[IDX2], "for nothing?", 12); @@ -267,7 +267,7 @@ printk("\ntesting hmac_sha1 across pages\n"); /* setup the dummy buffer first */ - memset(xbuf, 0, sizeof (xbuf)); + memset(xbuf, 0, XBUFSIZE); memcpy(&xbuf[IDX1], "what do ya want ", 16); memcpy(&xbuf[IDX2], "for nothing?", 12); @@ -450,7 +450,7 @@ printk("\ntesting sha1 across pages\n"); /* setup the dummy buffer first */ - memset(xbuf, 0, sizeof (xbuf)); + memset(xbuf, 0, XBUFSIZE); memcpy(&xbuf[IDX1], "abcdbcdecdefdefgefghfghighij", 28); memcpy(&xbuf[IDX2], "hijkijkljklmklmnlmnomnopnopq", 28); @@ -525,7 +525,7 @@ printk("\ntesting sha256 across pages\n"); /* setup the dummy buffer first */ - memset(xbuf, 0, sizeof (xbuf)); + memset(xbuf, 0, XBUFSIZE); memcpy(&xbuf[IDX1], "abcdbcdecdefdefgefghfghighij", 28); memcpy(&xbuf[IDX2], "hijkijkljklmklmnlmnomnopnopq", 28); @@ -1027,7 +1027,7 @@ } /* setup the dummy buffer first */ - memset(xbuf, 0, sizeof (xbuf)); + memset(xbuf, 0, XBUFSIZE); xbuf[IDX1] = des_tv[i].plaintext[0]; xbuf[IDX2] = des_tv[i].plaintext[1]; diff -Nru a/drivers/Makefile b/drivers/Makefile --- a/drivers/Makefile Sat May 24 12:48:30 2003 +++ b/drivers/Makefile Sat May 24 12:48:30 2003 @@ -37,6 +37,7 @@ obj-$(CONFIG_PARIDE) += block/paride/ obj-$(CONFIG_TC) += tc/ obj-$(CONFIG_USB) += usb/ +obj-$(CONFIG_USB_GADGET) += usb/gadget/ obj-$(CONFIG_INPUT) += input/ obj-$(CONFIG_GAMEPORT) += input/gameport/ obj-$(CONFIG_SERIO) += input/serio/ diff -Nru a/drivers/acorn/char/i2c.c b/drivers/acorn/char/i2c.c --- a/drivers/acorn/char/i2c.c Sat May 24 12:48:33 2003 +++ b/drivers/acorn/char/i2c.c Sat May 24 12:48:33 2003 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -306,7 +307,7 @@ .id = I2C_HW_B_IOC, .algo_data = &ioc_data, .client_register = ioc_client_reg, - .client_unregister = ioc_client_unreg + .client_unregister = ioc_client_unreg, .dev = { .name = "IOC/IOMD", }, diff -Nru a/drivers/acorn/char/pcf8583.c b/drivers/acorn/char/pcf8583.c --- a/drivers/acorn/char/pcf8583.c Sat May 24 12:48:32 2003 +++ b/drivers/acorn/char/pcf8583.c Sat May 24 12:48:32 2003 @@ -34,7 +34,7 @@ .force = ignore, }; -#define DAT(x) ((unsigned int)(x->data)) +#define DAT(x) ((unsigned int)(x->dev.driver_data)) static int pcf8583_attach(struct i2c_adapter *adap, int addr, unsigned short flags, @@ -51,13 +51,13 @@ if (!c) return -ENOMEM; - strcpy(c->name, "PCF8583"); + strcpy(c->dev.name, "PCF8583"); c->id = pcf8583_driver.id; c->flags = 0; c->addr = addr; c->adapter = adap; c->driver = &pcf8583_driver; - c->data = NULL; + c->dev.driver_data = NULL; if (i2c_transfer(c->adapter, msgs, 2) == 2) DAT(c) = buf[0]; diff -Nru a/drivers/acorn/net/Kconfig b/drivers/acorn/net/Kconfig --- a/drivers/acorn/net/Kconfig Sat May 24 12:48:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,25 +0,0 @@ -# -# Acorn Network device configuration -# These are for Acorn's Expansion card network interfaces -# -config ARM_ETHER1 - tristate "Acorn Ether1 support" - depends on NET_ETHERNET && ARM && ARCH_ACORN - help - If you have an Acorn system with one of these (AKA25) network cards, - you should say Y to this option if you wish to use it with Linux. - -config ARM_ETHER3 - tristate "Acorn/ANT Ether3 support" - depends on NET_ETHERNET && ARM && ARCH_ACORN - help - If you have an Acorn system with one of these network cards, you - should say Y to this option if you wish to use it with Linux. - -config ARM_ETHERH - tristate "I-cubed EtherH/ANT EtherM support" - depends on NET_ETHERNET && ARM && ARCH_ACORN - help - If you have an Acorn system with one of these network cards, you - should say Y to this option if you wish to use it with Linux. - diff -Nru a/drivers/acorn/net/Makefile b/drivers/acorn/net/Makefile --- a/drivers/acorn/net/Makefile Sat May 24 12:48:27 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,8 +0,0 @@ -# File: drivers/acorn/net/Makefile -# -# Makefile for the Acorn ethercard network device drivers -# - -obj-$(CONFIG_ARM_ETHERH) += etherh.o -obj-$(CONFIG_ARM_ETHER3) += ether3.o -obj-$(CONFIG_ARM_ETHER1) += ether1.o diff -Nru a/drivers/acorn/net/ether1.c b/drivers/acorn/net/ether1.c --- a/drivers/acorn/net/ether1.c Sat May 24 12:48:26 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1103 +0,0 @@ -/* - * linux/drivers/acorn/net/ether1.c - * - * Copyright (C) 1996-2000 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Acorn ether1 driver (82586 chip) for Acorn machines - * - * We basically keep two queues in the cards memory - one for transmit - * and one for receive. Each has a head and a tail. The head is where - * we/the chip adds packets to be transmitted/received, and the tail - * is where the transmitter has got to/where the receiver will stop. - * Both of these queues are circular, and since the chip is running - * all the time, we have to be careful when we modify the pointers etc - * so that the buffer memory contents is valid all the time. - * - * Change log: - * 1.00 RMK Released - * 1.01 RMK 19/03/1996 Transfers the last odd byte onto/off of the card now. - * 1.02 RMK 25/05/1997 Added code to restart RU if it goes not ready - * 1.03 RMK 14/09/1997 Cleaned up the handling of a reset during the TX interrupt. - * Should prevent lockup. - * 1.04 RMK 17/09/1997 Added more info when initialsation of chip goes wrong. - * TDR now only reports failure when chip reports non-zero - * TDR time-distance. - * 1.05 RMK 31/12/1997 Removed calls to dev_tint for 2.1 - * 1.06 RMK 10/02/2000 Updated for 2.3.43 - * 1.07 RMK 13/05/2000 Updated for 2.3.99-pre8 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#define __ETHER1_C -#include "ether1.h" - -static unsigned int net_debug = NET_DEBUG; - -#define BUFFER_SIZE 0x10000 -#define TX_AREA_START 0x00100 -#define TX_AREA_END 0x05000 -#define RX_AREA_START 0x05000 -#define RX_AREA_END 0x0fc00 - -static int ether1_open(struct net_device *dev); -static int ether1_sendpacket(struct sk_buff *skb, struct net_device *dev); -static void ether1_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static int ether1_close(struct net_device *dev); -static struct net_device_stats *ether1_getstats(struct net_device *dev); -static void ether1_setmulticastlist(struct net_device *dev); -static void ether1_timeout(struct net_device *dev); - -/* ------------------------------------------------------------------------- */ - -static char version[] __initdata = "ether1 ethernet driver (c) 2000 Russell King v1.07\n"; - -#define BUS_16 16 -#define BUS_8 8 - -/* ------------------------------------------------------------------------- */ - -#define DISABLEIRQS 1 -#define NORMALIRQS 0 - -#define ether1_inw(dev, addr, type, offset, svflgs) ether1_inw_p (dev, addr + (int)(&((type *)0)->offset), svflgs) -#define ether1_outw(dev, val, addr, type, offset, svflgs) ether1_outw_p (dev, val, addr + (int)(&((type *)0)->offset), svflgs) - -static inline unsigned short -ether1_inw_p (struct net_device *dev, int addr, int svflgs) -{ - unsigned long flags; - unsigned short ret; - - if (svflgs) - local_irq_save (flags); - - outb (addr >> 12, REG_PAGE); - ret = inw (ETHER1_RAM + ((addr & 4095) >> 1)); - if (svflgs) - local_irq_restore (flags); - return ret; -} - -static inline void -ether1_outw_p (struct net_device *dev, unsigned short val, int addr, int svflgs) -{ - unsigned long flags; - - if (svflgs) - local_irq_save (flags); - - outb (addr >> 12, REG_PAGE); - outw (val, ETHER1_RAM + ((addr & 4095) >> 1)); - if (svflgs) - local_irq_restore (flags); -} - -/* - * Some inline assembler to allow fast transfers on to/off of the card. - * Since this driver depends on some features presented by the ARM - * specific architecture, and that you can't configure this driver - * without specifiing ARM mode, this is not a problem. - * - * This routine is essentially an optimised memcpy from the card's - * onboard RAM to kernel memory. - */ -static void -ether1_writebuffer (struct net_device *dev, void *data, unsigned int start, unsigned int length) -{ - unsigned int page, thislen, offset, addr; - - offset = start & 4095; - page = start >> 12; - addr = ioaddr(ETHER1_RAM + (offset >> 1)); - - if (offset + length > 4096) - thislen = 4096 - offset; - else - thislen = length; - - do { - int used; - - outb(page, REG_PAGE); - length -= thislen; - - __asm__ __volatile__( - "subs %3, %3, #2 - bmi 2f -1: ldr %0, [%1], #2 - mov %0, %0, lsl #16 - orr %0, %0, %0, lsr #16 - str %0, [%2], #4 - subs %3, %3, #2 - bmi 2f - ldr %0, [%1], #2 - mov %0, %0, lsl #16 - orr %0, %0, %0, lsr #16 - str %0, [%2], #4 - subs %3, %3, #2 - bmi 2f - ldr %0, [%1], #2 - mov %0, %0, lsl #16 - orr %0, %0, %0, lsr #16 - str %0, [%2], #4 - subs %3, %3, #2 - bmi 2f - ldr %0, [%1], #2 - mov %0, %0, lsl #16 - orr %0, %0, %0, lsr #16 - str %0, [%2], #4 - subs %3, %3, #2 - bpl 1b -2: adds %3, %3, #1 - ldreqb %0, [%1] - streqb %0, [%2]" - : "=&r" (used), "=&r" (data) - : "r" (addr), "r" (thislen), "1" (data)); - - addr = ioaddr(ETHER1_RAM); - - thislen = length; - if (thislen > 4096) - thislen = 4096; - page++; - } while (thislen); -} - -static void -ether1_readbuffer (struct net_device *dev, void *data, unsigned int start, unsigned int length) -{ - unsigned int page, thislen, offset, addr; - - offset = start & 4095; - page = start >> 12; - addr = ioaddr(ETHER1_RAM + (offset >> 1)); - - if (offset + length > 4096) - thislen = 4096 - offset; - else - thislen = length; - - do { - int used; - - outb(page, REG_PAGE); - length -= thislen; - - __asm__ __volatile__( - "subs %3, %3, #2 - bmi 2f -1: ldr %0, [%2], #4 - strb %0, [%1], #1 - mov %0, %0, lsr #8 - strb %0, [%1], #1 - subs %3, %3, #2 - bmi 2f - ldr %0, [%2], #4 - strb %0, [%1], #1 - mov %0, %0, lsr #8 - strb %0, [%1], #1 - subs %3, %3, #2 - bmi 2f - ldr %0, [%2], #4 - strb %0, [%1], #1 - mov %0, %0, lsr #8 - strb %0, [%1], #1 - subs %3, %3, #2 - bmi 2f - ldr %0, [%2], #4 - strb %0, [%1], #1 - mov %0, %0, lsr #8 - strb %0, [%1], #1 - subs %3, %3, #2 - bpl 1b -2: adds %3, %3, #1 - ldreqb %0, [%2] - streqb %0, [%1]" - : "=&r" (used), "=&r" (data) - : "r" (addr), "r" (thislen), "1" (data)); - - addr = ioaddr(ETHER1_RAM); - - thislen = length; - if (thislen > 4096) - thislen = 4096; - page++; - } while (thislen); -} - -static int __init -ether1_ramtest(struct net_device *dev, unsigned char byte) -{ - unsigned char *buffer = kmalloc (BUFFER_SIZE, GFP_KERNEL); - int i, ret = BUFFER_SIZE; - int max_errors = 15; - int bad = -1; - int bad_start = 0; - - if (!buffer) - return 1; - - memset (buffer, byte, BUFFER_SIZE); - ether1_writebuffer (dev, buffer, 0, BUFFER_SIZE); - memset (buffer, byte ^ 0xff, BUFFER_SIZE); - ether1_readbuffer (dev, buffer, 0, BUFFER_SIZE); - - for (i = 0; i < BUFFER_SIZE; i++) { - if (buffer[i] != byte) { - if (max_errors >= 0 && bad != buffer[i]) { - if (bad != -1) - printk ("\n"); - printk (KERN_CRIT "%s: RAM failed with (%02X instead of %02X) at 0x%04X", - dev->name, buffer[i], byte, i); - ret = -ENODEV; - max_errors --; - bad = buffer[i]; - bad_start = i; - } - } else { - if (bad != -1) { - if (bad_start == i - 1) - printk ("\n"); - else - printk (" - 0x%04X\n", i - 1); - bad = -1; - } - } - } - - if (bad != -1) - printk (" - 0x%04X\n", BUFFER_SIZE); - kfree (buffer); - - return ret; -} - -static int -ether1_reset (struct net_device *dev) -{ - outb (CTRL_RST|CTRL_ACK, REG_CONTROL); - return BUS_16; -} - -static int __init -ether1_init_2(struct net_device *dev) -{ - int i; - dev->mem_start = 0; - - i = ether1_ramtest (dev, 0x5a); - - if (i > 0) - i = ether1_ramtest (dev, 0x1e); - - if (i <= 0) - return -ENODEV; - - dev->mem_end = i; - return 0; -} - -/* - * These are the structures that are loaded into the ether RAM card to - * initialise the 82586 - */ - -/* at 0x0100 */ -#define NOP_ADDR (TX_AREA_START) -#define NOP_SIZE (0x06) -static nop_t init_nop = { - 0, - CMD_NOP, - NOP_ADDR -}; - -/* at 0x003a */ -#define TDR_ADDR (0x003a) -#define TDR_SIZE (0x08) -static tdr_t init_tdr = { - 0, - CMD_TDR | CMD_INTR, - NOP_ADDR, - 0 -}; - -/* at 0x002e */ -#define MC_ADDR (0x002e) -#define MC_SIZE (0x0c) -static mc_t init_mc = { - 0, - CMD_SETMULTICAST, - TDR_ADDR, - 0, - { { 0, } } -}; - -/* at 0x0022 */ -#define SA_ADDR (0x0022) -#define SA_SIZE (0x0c) -static sa_t init_sa = { - 0, - CMD_SETADDRESS, - MC_ADDR, - { 0, } -}; - -/* at 0x0010 */ -#define CFG_ADDR (0x0010) -#define CFG_SIZE (0x12) -static cfg_t init_cfg = { - 0, - CMD_CONFIG, - SA_ADDR, - 8, - 8, - CFG8_SRDY, - CFG9_PREAMB8 | CFG9_ADDRLENBUF | CFG9_ADDRLEN(6), - 0, - 0x60, - 0, - CFG13_RETRY(15) | CFG13_SLOTH(2), - 0, -}; - -/* at 0x0000 */ -#define SCB_ADDR (0x0000) -#define SCB_SIZE (0x10) -static scb_t init_scb = { - 0, - SCB_CMDACKRNR | SCB_CMDACKCNA | SCB_CMDACKFR | SCB_CMDACKCX, - CFG_ADDR, - RX_AREA_START, - 0, - 0, - 0, - 0 -}; - -/* at 0xffee */ -#define ISCP_ADDR (0xffee) -#define ISCP_SIZE (0x08) -static iscp_t init_iscp = { - 1, - SCB_ADDR, - 0x0000, - 0x0000 -}; - -/* at 0xfff6 */ -#define SCP_ADDR (0xfff6) -#define SCP_SIZE (0x0a) -static scp_t init_scp = { - SCP_SY_16BBUS, - { 0, 0 }, - ISCP_ADDR, - 0 -}; - -#define RFD_SIZE (0x16) -static rfd_t init_rfd = { - 0, - 0, - 0, - 0, - { 0, }, - { 0, }, - 0 -}; - -#define RBD_SIZE (0x0a) -static rbd_t init_rbd = { - 0, - 0, - 0, - 0, - ETH_FRAME_LEN + 8 -}; - -#define TX_SIZE (0x08) -#define TBD_SIZE (0x08) - -static int -ether1_init_for_open (struct net_device *dev) -{ - struct ether1_priv *priv = (struct ether1_priv *)dev->priv; - int i, status, addr, next, next2; - int failures = 0; - - outb (CTRL_RST|CTRL_ACK, REG_CONTROL); - - for (i = 0; i < 6; i++) - init_sa.sa_addr[i] = dev->dev_addr[i]; - - /* load data structures into ether1 RAM */ - ether1_writebuffer (dev, &init_scp, SCP_ADDR, SCP_SIZE); - ether1_writebuffer (dev, &init_iscp, ISCP_ADDR, ISCP_SIZE); - ether1_writebuffer (dev, &init_scb, SCB_ADDR, SCB_SIZE); - ether1_writebuffer (dev, &init_cfg, CFG_ADDR, CFG_SIZE); - ether1_writebuffer (dev, &init_sa, SA_ADDR, SA_SIZE); - ether1_writebuffer (dev, &init_mc, MC_ADDR, MC_SIZE); - ether1_writebuffer (dev, &init_tdr, TDR_ADDR, TDR_SIZE); - ether1_writebuffer (dev, &init_nop, NOP_ADDR, NOP_SIZE); - - if (ether1_inw (dev, CFG_ADDR, cfg_t, cfg_command, NORMALIRQS) != CMD_CONFIG) { - printk (KERN_ERR "%s: detected either RAM fault or compiler bug\n", - dev->name); - return 1; - } - - /* - * setup circularly linked list of { rfd, rbd, buffer }, with - * all rfds circularly linked, rbds circularly linked. - * First rfd is linked to scp, first rbd is linked to first - * rfd. Last rbd has a suspend command. - */ - addr = RX_AREA_START; - do { - next = addr + RFD_SIZE + RBD_SIZE + ETH_FRAME_LEN + 10; - next2 = next + RFD_SIZE + RBD_SIZE + ETH_FRAME_LEN + 10; - - if (next2 >= RX_AREA_END) { - next = RX_AREA_START; - init_rfd.rfd_command = RFD_CMDEL | RFD_CMDSUSPEND; - priv->rx_tail = addr; - } else - init_rfd.rfd_command = 0; - if (addr == RX_AREA_START) - init_rfd.rfd_rbdoffset = addr + RFD_SIZE; - else - init_rfd.rfd_rbdoffset = 0; - init_rfd.rfd_link = next; - init_rbd.rbd_link = next + RFD_SIZE; - init_rbd.rbd_bufl = addr + RFD_SIZE + RBD_SIZE; - - ether1_writebuffer (dev, &init_rfd, addr, RFD_SIZE); - ether1_writebuffer (dev, &init_rbd, addr + RFD_SIZE, RBD_SIZE); - addr = next; - } while (next2 < RX_AREA_END); - - priv->tx_link = NOP_ADDR; - priv->tx_head = NOP_ADDR + NOP_SIZE; - priv->tx_tail = TDR_ADDR; - priv->rx_head = RX_AREA_START; - - /* release reset & give 586 a prod */ - priv->resetting = 1; - priv->initialising = 1; - outb (CTRL_RST, REG_CONTROL); - outb (0, REG_CONTROL); - outb (CTRL_CA, REG_CONTROL); - - /* 586 should now unset iscp.busy */ - i = jiffies + HZ/2; - while (ether1_inw (dev, ISCP_ADDR, iscp_t, iscp_busy, DISABLEIRQS) == 1) { - if (time_after(jiffies, i)) { - printk (KERN_WARNING "%s: can't initialise 82586: iscp is busy\n", dev->name); - return 1; - } - } - - /* check status of commands that we issued */ - i += HZ/10; - while (((status = ether1_inw (dev, CFG_ADDR, cfg_t, cfg_status, DISABLEIRQS)) - & STAT_COMPLETE) == 0) { - if (time_after(jiffies, i)) - break; - } - - if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) { - printk (KERN_WARNING "%s: can't initialise 82586: config status %04X\n", dev->name, status); - printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name, - ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS), - ether1_inw (dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS), - ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS), - ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS)); - failures += 1; - } - - i += HZ/10; - while (((status = ether1_inw (dev, SA_ADDR, sa_t, sa_status, DISABLEIRQS)) - & STAT_COMPLETE) == 0) { - if (time_after(jiffies, i)) - break; - } - - if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) { - printk (KERN_WARNING "%s: can't initialise 82586: set address status %04X\n", dev->name, status); - printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name, - ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS), - ether1_inw (dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS), - ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS), - ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS)); - failures += 1; - } - - i += HZ/10; - while (((status = ether1_inw (dev, MC_ADDR, mc_t, mc_status, DISABLEIRQS)) - & STAT_COMPLETE) == 0) { - if (time_after(jiffies, i)) - break; - } - - if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) { - printk (KERN_WARNING "%s: can't initialise 82586: set multicast status %04X\n", dev->name, status); - printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name, - ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS), - ether1_inw (dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS), - ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS), - ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS)); - failures += 1; - } - - i += HZ; - while (((status = ether1_inw (dev, TDR_ADDR, tdr_t, tdr_status, DISABLEIRQS)) - & STAT_COMPLETE) == 0) { - if (time_after(jiffies, i)) - break; - } - - if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) { - printk (KERN_WARNING "%s: can't tdr (ignored)\n", dev->name); - printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name, - ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS), - ether1_inw (dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS), - ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS), - ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS)); - } else { - status = ether1_inw (dev, TDR_ADDR, tdr_t, tdr_result, DISABLEIRQS); - if (status & TDR_XCVRPROB) - printk (KERN_WARNING "%s: i/f failed tdr: transceiver problem\n", dev->name); - else if ((status & (TDR_SHORT|TDR_OPEN)) && (status & TDR_TIME)) { -#ifdef FANCY - printk (KERN_WARNING "%s: i/f failed tdr: cable %s %d.%d us away\n", dev->name, - status & TDR_SHORT ? "short" : "open", (status & TDR_TIME) / 10, - (status & TDR_TIME) % 10); -#else - printk (KERN_WARNING "%s: i/f failed tdr: cable %s %d clks away\n", dev->name, - status & TDR_SHORT ? "short" : "open", (status & TDR_TIME)); -#endif - } - } - - if (failures) - ether1_reset (dev); - return failures ? 1 : 0; -} - -/* ------------------------------------------------------------------------- */ - -static int -ether1_txalloc (struct net_device *dev, int size) -{ - struct ether1_priv *priv = (struct ether1_priv *)dev->priv; - int start, tail; - - size = (size + 1) & ~1; - tail = priv->tx_tail; - - if (priv->tx_head + size > TX_AREA_END) { - if (tail > priv->tx_head) - return -1; - start = TX_AREA_START; - if (start + size > tail) - return -1; - priv->tx_head = start + size; - } else { - if (priv->tx_head < tail && (priv->tx_head + size) > tail) - return -1; - start = priv->tx_head; - priv->tx_head += size; - } - - return start; -} - -static int -ether1_open (struct net_device *dev) -{ - struct ether1_priv *priv = (struct ether1_priv *)dev->priv; - - if (!is_valid_ether_addr(dev->dev_addr)) { - printk(KERN_WARNING "%s: invalid ethernet MAC address\n", - dev->name); - return -EINVAL; - } - - if (request_irq(dev->irq, ether1_interrupt, 0, "ether1", dev)) - return -EAGAIN; - - memset (&priv->stats, 0, sizeof (struct net_device_stats)); - - if (ether1_init_for_open (dev)) { - free_irq (dev->irq, dev); - return -EAGAIN; - } - - netif_start_queue(dev); - - return 0; -} - -static void -ether1_timeout(struct net_device *dev) -{ - struct ether1_priv *priv = (struct ether1_priv *)dev->priv; - - printk(KERN_WARNING "%s: transmit timeout, network cable problem?\n", - dev->name); - printk(KERN_WARNING "%s: resetting device\n", dev->name); - - ether1_reset (dev); - - if (ether1_init_for_open (dev)) - printk (KERN_ERR "%s: unable to restart interface\n", dev->name); - - priv->stats.tx_errors++; - netif_wake_queue(dev); -} - -static int -ether1_sendpacket (struct sk_buff *skb, struct net_device *dev) -{ - struct ether1_priv *priv = (struct ether1_priv *)dev->priv; - int len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; - int tmp, tst, nopaddr, txaddr, tbdaddr, dataddr; - unsigned long flags; - tx_t tx; - tbd_t tbd; - nop_t nop; - - if (priv->restart) { - printk(KERN_WARNING "%s: resetting device\n", dev->name); - - ether1_reset(dev); - - if (ether1_init_for_open(dev)) - printk(KERN_ERR "%s: unable to restart interface\n", dev->name); - else - priv->restart = 0; - } - - /* - * insert packet followed by a nop - */ - txaddr = ether1_txalloc (dev, TX_SIZE); - tbdaddr = ether1_txalloc (dev, TBD_SIZE); - dataddr = ether1_txalloc (dev, len); - nopaddr = ether1_txalloc (dev, NOP_SIZE); - - tx.tx_status = 0; - tx.tx_command = CMD_TX | CMD_INTR; - tx.tx_link = nopaddr; - tx.tx_tbdoffset = tbdaddr; - tbd.tbd_opts = TBD_EOL | len; - tbd.tbd_link = I82586_NULL; - tbd.tbd_bufl = dataddr; - tbd.tbd_bufh = 0; - nop.nop_status = 0; - nop.nop_command = CMD_NOP; - nop.nop_link = nopaddr; - - local_irq_save(flags); - ether1_writebuffer (dev, &tx, txaddr, TX_SIZE); - ether1_writebuffer (dev, &tbd, tbdaddr, TBD_SIZE); - ether1_writebuffer (dev, skb->data, dataddr, len); - ether1_writebuffer (dev, &nop, nopaddr, NOP_SIZE); - tmp = priv->tx_link; - priv->tx_link = nopaddr; - - /* now reset the previous nop pointer */ - ether1_outw (dev, txaddr, tmp, nop_t, nop_link, NORMALIRQS); - - local_irq_restore(flags); - - /* handle transmit */ - dev->trans_start = jiffies; - - /* check to see if we have room for a full sized ether frame */ - tmp = priv->tx_head; - tst = ether1_txalloc (dev, TX_SIZE + TBD_SIZE + NOP_SIZE + ETH_FRAME_LEN); - priv->tx_head = tmp; - dev_kfree_skb (skb); - - if (tst == -1) - netif_stop_queue(dev); - - return 0; -} - -static void -ether1_xmit_done (struct net_device *dev) -{ - struct ether1_priv *priv = (struct ether1_priv *)dev->priv; - nop_t nop; - int caddr, tst; - - caddr = priv->tx_tail; - -again: - ether1_readbuffer (dev, &nop, caddr, NOP_SIZE); - - switch (nop.nop_command & CMD_MASK) { - case CMD_TDR: - /* special case */ - if (ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS) - != (unsigned short)I82586_NULL) { - ether1_outw(dev, SCB_CMDCUCSTART | SCB_CMDRXSTART, SCB_ADDR, scb_t, - scb_command, NORMALIRQS); - outb (CTRL_CA, REG_CONTROL); - } - priv->tx_tail = NOP_ADDR; - return; - - case CMD_NOP: - if (nop.nop_link == caddr) { - if (priv->initialising == 0) - printk (KERN_WARNING "%s: strange command complete with no tx command!\n", dev->name); - else - priv->initialising = 0; - return; - } - if (caddr == nop.nop_link) - return; - caddr = nop.nop_link; - goto again; - - case CMD_TX: - if (nop.nop_status & STAT_COMPLETE) - break; - printk (KERN_ERR "%s: strange command complete without completed command\n", dev->name); - priv->restart = 1; - return; - - default: - printk (KERN_WARNING "%s: strange command %d complete! (offset %04X)", dev->name, - nop.nop_command & CMD_MASK, caddr); - priv->restart = 1; - return; - } - - while (nop.nop_status & STAT_COMPLETE) { - if (nop.nop_status & STAT_OK) { - priv->stats.tx_packets ++; - priv->stats.collisions += (nop.nop_status & STAT_COLLISIONS); - } else { - priv->stats.tx_errors ++; - - if (nop.nop_status & STAT_COLLAFTERTX) - priv->stats.collisions ++; - if (nop.nop_status & STAT_NOCARRIER) - priv->stats.tx_carrier_errors ++; - if (nop.nop_status & STAT_TXLOSTCTS) - printk (KERN_WARNING "%s: cts lost\n", dev->name); - if (nop.nop_status & STAT_TXSLOWDMA) - priv->stats.tx_fifo_errors ++; - if (nop.nop_status & STAT_COLLEXCESSIVE) - priv->stats.collisions += 16; - } - - if (nop.nop_link == caddr) { - printk (KERN_ERR "%s: tx buffer chaining error: tx command points to itself\n", dev->name); - break; - } - - caddr = nop.nop_link; - ether1_readbuffer (dev, &nop, caddr, NOP_SIZE); - if ((nop.nop_command & CMD_MASK) != CMD_NOP) { - printk (KERN_ERR "%s: tx buffer chaining error: no nop after tx command\n", dev->name); - break; - } - - if (caddr == nop.nop_link) - break; - - caddr = nop.nop_link; - ether1_readbuffer (dev, &nop, caddr, NOP_SIZE); - if ((nop.nop_command & CMD_MASK) != CMD_TX) { - printk (KERN_ERR "%s: tx buffer chaining error: no tx command after nop\n", dev->name); - break; - } - } - priv->tx_tail = caddr; - - caddr = priv->tx_head; - tst = ether1_txalloc (dev, TX_SIZE + TBD_SIZE + NOP_SIZE + ETH_FRAME_LEN); - priv->tx_head = caddr; - if (tst != -1) - netif_wake_queue(dev); -} - -static void -ether1_recv_done (struct net_device *dev) -{ - struct ether1_priv *priv = (struct ether1_priv *)dev->priv; - int status; - int nexttail, rbdaddr; - rbd_t rbd; - - do { - status = ether1_inw (dev, priv->rx_head, rfd_t, rfd_status, NORMALIRQS); - if ((status & RFD_COMPLETE) == 0) - break; - - rbdaddr = ether1_inw (dev, priv->rx_head, rfd_t, rfd_rbdoffset, NORMALIRQS); - ether1_readbuffer (dev, &rbd, rbdaddr, RBD_SIZE); - - if ((rbd.rbd_status & (RBD_EOF | RBD_ACNTVALID)) == (RBD_EOF | RBD_ACNTVALID)) { - int length = rbd.rbd_status & RBD_ACNT; - struct sk_buff *skb; - - length = (length + 1) & ~1; - skb = dev_alloc_skb (length + 2); - - if (skb) { - skb->dev = dev; - skb_reserve (skb, 2); - - ether1_readbuffer (dev, skb_put (skb, length), rbd.rbd_bufl, length); - - skb->protocol = eth_type_trans (skb, dev); - netif_rx (skb); - priv->stats.rx_packets ++; - } else - priv->stats.rx_dropped ++; - } else { - printk(KERN_WARNING "%s: %s\n", dev->name, - (rbd.rbd_status & RBD_EOF) ? "oversized packet" : "acnt not valid"); - priv->stats.rx_dropped ++; - } - - nexttail = ether1_inw (dev, priv->rx_tail, rfd_t, rfd_link, NORMALIRQS); - /* nexttail should be rx_head */ - if (nexttail != priv->rx_head) - printk(KERN_ERR "%s: receiver buffer chaining error (%04X != %04X)\n", - dev->name, nexttail, priv->rx_head); - ether1_outw (dev, RFD_CMDEL | RFD_CMDSUSPEND, nexttail, rfd_t, rfd_command, NORMALIRQS); - ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_command, NORMALIRQS); - ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_status, NORMALIRQS); - ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_rbdoffset, NORMALIRQS); - - priv->rx_tail = nexttail; - priv->rx_head = ether1_inw (dev, priv->rx_head, rfd_t, rfd_link, NORMALIRQS); - } while (1); -} - -static void -ether1_interrupt (int irq, void *dev_id, struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *)dev_id; - struct ether1_priv *priv = (struct ether1_priv *)dev->priv; - int status; - - status = ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS); - - if (status) { - ether1_outw(dev, status & (SCB_STRNR | SCB_STCNA | SCB_STFR | SCB_STCX), - SCB_ADDR, scb_t, scb_command, NORMALIRQS); - outb (CTRL_CA | CTRL_ACK, REG_CONTROL); - if (status & SCB_STCX) { - ether1_xmit_done (dev); - } - if (status & SCB_STCNA) { - if (priv->resetting == 0) - printk (KERN_WARNING "%s: CU went not ready ???\n", dev->name); - else - priv->resetting += 1; - if (ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS) - != (unsigned short)I82586_NULL) { - ether1_outw (dev, SCB_CMDCUCSTART, SCB_ADDR, scb_t, scb_command, NORMALIRQS); - outb (CTRL_CA, REG_CONTROL); - } - if (priv->resetting == 2) - priv->resetting = 0; - } - if (status & SCB_STFR) { - ether1_recv_done (dev); - } - if (status & SCB_STRNR) { - if (ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS) & SCB_STRXSUSP) { - printk (KERN_WARNING "%s: RU went not ready: RU suspended\n", dev->name); - ether1_outw (dev, SCB_CMDRXRESUME, SCB_ADDR, scb_t, scb_command, NORMALIRQS); - outb (CTRL_CA, REG_CONTROL); - priv->stats.rx_dropped ++; /* we suspended due to lack of buffer space */ - } else - printk(KERN_WARNING "%s: RU went not ready: %04X\n", dev->name, - ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS)); - printk (KERN_WARNING "RU ptr = %04X\n", ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset, - NORMALIRQS)); - } - } else - outb (CTRL_ACK, REG_CONTROL); -} - -static int -ether1_close (struct net_device *dev) -{ - ether1_reset (dev); - - free_irq(dev->irq, dev); - - return 0; -} - -static struct net_device_stats * -ether1_getstats (struct net_device *dev) -{ - struct ether1_priv *priv = (struct ether1_priv *)dev->priv; - return &priv->stats; -} - -/* - * Set or clear the multicast filter for this adaptor. - * num_addrs == -1 Promiscuous mode, receive all packets. - * num_addrs == 0 Normal mode, clear multicast list. - * num_addrs > 0 Multicast mode, receive normal and MC packets, and do - * best-effort filtering. - */ -static void -ether1_setmulticastlist (struct net_device *dev) -{ -} - -/* ------------------------------------------------------------------------- */ - -static void __init ether1_banner(void) -{ - static unsigned int version_printed = 0; - - if (net_debug && version_printed++ == 0) - printk(KERN_INFO "%s", version); -} - -static int __devinit -ether1_probe(struct expansion_card *ec, const struct ecard_id *id) -{ - struct net_device *dev; - struct ether1_priv *priv; - int i, ret = 0; - - ether1_banner(); - - dev = init_etherdev(NULL, sizeof(struct ether1_priv)); - if (!dev) { - ret = -ENOMEM; - goto out; - } - - SET_MODULE_OWNER(dev); - - dev->base_addr = ecard_address(ec, ECARD_IOC, ECARD_FAST); - dev->irq = ec->irq; - - /* - * these will not fail - the nature of the bus ensures this - */ - request_region(dev->base_addr, 16, dev->name); - request_region(dev->base_addr + 0x800, 4096, dev->name); - - priv = (struct ether1_priv *)dev->priv; - if ((priv->bus_type = ether1_reset(dev)) == 0) { - ret = -ENODEV; - goto release; - } - - printk(KERN_INFO "%s: ether1 in slot %d, ", - dev->name, ec->slot_no); - - for (i = 0; i < 6; i++) { - dev->dev_addr[i] = inb(IDPROM_ADDRESS + i); - printk ("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':'); - } - - if (ether1_init_2(dev)) { - ret = -ENODEV; - goto release; - } - - dev->open = ether1_open; - dev->stop = ether1_close; - dev->hard_start_xmit = ether1_sendpacket; - dev->get_stats = ether1_getstats; - dev->set_multicast_list = ether1_setmulticastlist; - dev->tx_timeout = ether1_timeout; - dev->watchdog_timeo = 5 * HZ / 100; - - ecard_set_drvdata(ec, dev); - return 0; - -release: - release_region(dev->base_addr, 16); - release_region(dev->base_addr + 0x800, 4096); - unregister_netdev(dev); - kfree(dev); -out: - return ret; -} - -static void __devexit ether1_remove(struct expansion_card *ec) -{ - struct net_device *dev = ecard_get_drvdata(ec); - - ecard_set_drvdata(ec, NULL); - - unregister_netdev(dev); - - release_region(dev->base_addr, 16); - release_region(dev->base_addr + 0x800, 4096); - kfree(dev); -} - -static const struct ecard_id ether1_ids[] = { - { MANU_ACORN, PROD_ACORN_ETHER1 }, - { 0xffff, 0xffff } -}; - -static struct ecard_driver ether1_driver = { - .probe = ether1_probe, - .remove = __devexit_p(ether1_remove), - .id_table = ether1_ids, - .drv = { - .name = "ether1", - }, -}; - -static int __init ether1_init(void) -{ - return ecard_register_driver(ðer1_driver); -} - -static void __exit ether1_exit(void) -{ - ecard_remove_driver(ðer1_driver); -} - -module_init(ether1_init); -module_exit(ether1_exit); - -MODULE_LICENSE("GPL"); diff -Nru a/drivers/acorn/net/ether1.h b/drivers/acorn/net/ether1.h --- a/drivers/acorn/net/ether1.h Sat May 24 12:48:33 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,278 +0,0 @@ -/* - * linux/drivers/acorn/net/ether1.h - * - * Copyright (C) 1996 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Network driver for Acorn Ether1 cards. - */ - -#ifndef _LINUX_ether1_H -#define _LINUX_ether1_H - -#ifdef __ETHER1_C -/* use 0 for production, 1 for verification, >2 for debug */ -#ifndef NET_DEBUG -#define NET_DEBUG 0 -#endif - -/* Page register */ -#define REG_PAGE (dev->base_addr + 0x00) - -/* Control register */ -#define REG_CONTROL (dev->base_addr + 0x01) -#define CTRL_RST 0x01 -#define CTRL_LOOPBACK 0x02 -#define CTRL_CA 0x04 -#define CTRL_ACK 0x08 - -#define ETHER1_RAM (dev->base_addr + 0x800) - -/* HW address */ -#define IDPROM_ADDRESS (dev->base_addr + 0x09) - -struct ether1_priv { - struct net_device_stats stats; - unsigned int tx_link; - unsigned int tx_head; - volatile unsigned int tx_tail; - volatile unsigned int rx_head; - volatile unsigned int rx_tail; - unsigned char bus_type; - unsigned char resetting; - unsigned char initialising : 1; - unsigned char restart : 1; -}; - -#define I82586_NULL (-1) - -typedef struct { /* tdr */ - unsigned short tdr_status; - unsigned short tdr_command; - unsigned short tdr_link; - unsigned short tdr_result; -#define TDR_TIME (0x7ff) -#define TDR_SHORT (1 << 12) -#define TDR_OPEN (1 << 13) -#define TDR_XCVRPROB (1 << 14) -#define TDR_LNKOK (1 << 15) -} tdr_t; - -typedef struct { /* transmit */ - unsigned short tx_status; - unsigned short tx_command; - unsigned short tx_link; - unsigned short tx_tbdoffset; -} tx_t; - -typedef struct { /* tbd */ - unsigned short tbd_opts; -#define TBD_CNT (0x3fff) -#define TBD_EOL (1 << 15) - unsigned short tbd_link; - unsigned short tbd_bufl; - unsigned short tbd_bufh; -} tbd_t; - -typedef struct { /* rfd */ - unsigned short rfd_status; -#define RFD_NOEOF (1 << 6) -#define RFD_FRAMESHORT (1 << 7) -#define RFD_DMAOVRN (1 << 8) -#define RFD_NORESOURCES (1 << 9) -#define RFD_ALIGNERROR (1 << 10) -#define RFD_CRCERROR (1 << 11) -#define RFD_OK (1 << 13) -#define RFD_FDCONSUMED (1 << 14) -#define RFD_COMPLETE (1 << 15) - unsigned short rfd_command; -#define RFD_CMDSUSPEND (1 << 14) -#define RFD_CMDEL (1 << 15) - unsigned short rfd_link; - unsigned short rfd_rbdoffset; - unsigned char rfd_dest[6]; - unsigned char rfd_src[6]; - unsigned short rfd_len; -} rfd_t; - -typedef struct { /* rbd */ - unsigned short rbd_status; -#define RBD_ACNT (0x3fff) -#define RBD_ACNTVALID (1 << 14) -#define RBD_EOF (1 << 15) - unsigned short rbd_link; - unsigned short rbd_bufl; - unsigned short rbd_bufh; - unsigned short rbd_len; -} rbd_t; - -typedef struct { /* nop */ - unsigned short nop_status; - unsigned short nop_command; - unsigned short nop_link; -} nop_t; - -typedef struct { /* set multicast */ - unsigned short mc_status; - unsigned short mc_command; - unsigned short mc_link; - unsigned short mc_cnt; - unsigned char mc_addrs[1][6]; -} mc_t; - -typedef struct { /* set address */ - unsigned short sa_status; - unsigned short sa_command; - unsigned short sa_link; - unsigned char sa_addr[6]; -} sa_t; - -typedef struct { /* config command */ - unsigned short cfg_status; - unsigned short cfg_command; - unsigned short cfg_link; - unsigned char cfg_bytecnt; /* size foll data: 4 - 12 */ - unsigned char cfg_fifolim; /* FIFO threshold */ - unsigned char cfg_byte8; -#define CFG8_SRDY (1 << 6) -#define CFG8_SAVEBADF (1 << 7) - unsigned char cfg_byte9; -#define CFG9_ADDRLEN(x) (x) -#define CFG9_ADDRLENBUF (1 << 3) -#define CFG9_PREAMB2 (0 << 4) -#define CFG9_PREAMB4 (1 << 4) -#define CFG9_PREAMB8 (2 << 4) -#define CFG9_PREAMB16 (3 << 4) -#define CFG9_ILOOPBACK (1 << 6) -#define CFG9_ELOOPBACK (1 << 7) - unsigned char cfg_byte10; -#define CFG10_LINPRI(x) (x) -#define CFG10_ACR(x) (x << 4) -#define CFG10_BOFMET (1 << 7) - unsigned char cfg_ifs; - unsigned char cfg_slotl; - unsigned char cfg_byte13; -#define CFG13_SLOTH(x) (x) -#define CFG13_RETRY(x) (x << 4) - unsigned char cfg_byte14; -#define CFG14_PROMISC (1 << 0) -#define CFG14_DISBRD (1 << 1) -#define CFG14_MANCH (1 << 2) -#define CFG14_TNCRS (1 << 3) -#define CFG14_NOCRC (1 << 4) -#define CFG14_CRC16 (1 << 5) -#define CFG14_BTSTF (1 << 6) -#define CFG14_FLGPAD (1 << 7) - unsigned char cfg_byte15; -#define CFG15_CSTF(x) (x) -#define CFG15_ICSS (1 << 3) -#define CFG15_CDTF(x) (x << 4) -#define CFG15_ICDS (1 << 7) - unsigned short cfg_minfrmlen; -} cfg_t; - -typedef struct { /* scb */ - unsigned short scb_status; /* status of 82586 */ -#define SCB_STRXMASK (7 << 4) /* Receive unit status */ -#define SCB_STRXIDLE (0 << 4) /* Idle */ -#define SCB_STRXSUSP (1 << 4) /* Suspended */ -#define SCB_STRXNRES (2 << 4) /* No resources */ -#define SCB_STRXRDY (4 << 4) /* Ready */ -#define SCB_STCUMASK (7 << 8) /* Command unit status */ -#define SCB_STCUIDLE (0 << 8) /* Idle */ -#define SCB_STCUSUSP (1 << 8) /* Suspended */ -#define SCB_STCUACTV (2 << 8) /* Active */ -#define SCB_STRNR (1 << 12) /* Receive unit not ready */ -#define SCB_STCNA (1 << 13) /* Command unit not ready */ -#define SCB_STFR (1 << 14) /* Frame received */ -#define SCB_STCX (1 << 15) /* Command completed */ - unsigned short scb_command; /* Next command */ -#define SCB_CMDRXSTART (1 << 4) /* Start (at rfa_offset) */ -#define SCB_CMDRXRESUME (2 << 4) /* Resume reception */ -#define SCB_CMDRXSUSPEND (3 << 4) /* Suspend reception */ -#define SCB_CMDRXABORT (4 << 4) /* Abort reception */ -#define SCB_CMDCUCSTART (1 << 8) /* Start (at cbl_offset) */ -#define SCB_CMDCUCRESUME (2 << 8) /* Resume execution */ -#define SCB_CMDCUCSUSPEND (3 << 8) /* Suspend execution */ -#define SCB_CMDCUCABORT (4 << 8) /* Abort execution */ -#define SCB_CMDACKRNR (1 << 12) /* Ack RU not ready */ -#define SCB_CMDACKCNA (1 << 13) /* Ack CU not ready */ -#define SCB_CMDACKFR (1 << 14) /* Ack Frame received */ -#define SCB_CMDACKCX (1 << 15) /* Ack Command complete */ - unsigned short scb_cbl_offset; /* Offset of first command unit */ - unsigned short scb_rfa_offset; /* Offset of first receive frame area */ - unsigned short scb_crc_errors; /* Properly aligned frame with CRC error*/ - unsigned short scb_aln_errors; /* Misaligned frames */ - unsigned short scb_rsc_errors; /* Frames lost due to no space */ - unsigned short scb_ovn_errors; /* Frames lost due to slow bus */ -} scb_t; - -typedef struct { /* iscp */ - unsigned short iscp_busy; /* set by CPU before CA */ - unsigned short iscp_offset; /* offset of SCB */ - unsigned short iscp_basel; /* base of SCB */ - unsigned short iscp_baseh; -} iscp_t; - - /* this address must be 0xfff6 */ -typedef struct { /* scp */ - unsigned short scp_sysbus; /* bus size */ -#define SCP_SY_16BBUS 0x00 -#define SCP_SY_8BBUS 0x01 - unsigned short scp_junk[2]; /* junk */ - unsigned short scp_iscpl; /* lower 16 bits of iscp */ - unsigned short scp_iscph; /* upper 16 bits of iscp */ -} scp_t; - -/* commands */ -#define CMD_NOP 0 -#define CMD_SETADDRESS 1 -#define CMD_CONFIG 2 -#define CMD_SETMULTICAST 3 -#define CMD_TX 4 -#define CMD_TDR 5 -#define CMD_DUMP 6 -#define CMD_DIAGNOSE 7 - -#define CMD_MASK 7 - -#define CMD_INTR (1 << 13) -#define CMD_SUSP (1 << 14) -#define CMD_EOL (1 << 15) - -#define STAT_COLLISIONS (15) -#define STAT_COLLEXCESSIVE (1 << 5) -#define STAT_COLLAFTERTX (1 << 6) -#define STAT_TXDEFERRED (1 << 7) -#define STAT_TXSLOWDMA (1 << 8) -#define STAT_TXLOSTCTS (1 << 9) -#define STAT_NOCARRIER (1 << 10) -#define STAT_FAIL (1 << 11) -#define STAT_ABORTED (1 << 12) -#define STAT_OK (1 << 13) -#define STAT_BUSY (1 << 14) -#define STAT_COMPLETE (1 << 15) -#endif -#endif - -/* - * Ether1 card definitions: - * - * FAST accesses: - * +0 Page register - * 16 pages - * +4 Control - * '1' = reset - * '2' = loopback - * '4' = CA - * '8' = int ack - * - * RAM at address + 0x2000 - * Pod. Prod id = 3 - * Words after ID block [base + 8 words] - * +0 pcb issue (0x0c and 0xf3 invalid) - * +1 - +6 eth hw address - */ diff -Nru a/drivers/acorn/net/ether3.c b/drivers/acorn/net/ether3.c --- a/drivers/acorn/net/ether3.c Sat May 24 12:48:32 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,944 +0,0 @@ -/* - * linux/drivers/acorn/net/ether3.c - * - * Copyright (C) 1995-2000 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * SEEQ nq8005 ethernet driver for Acorn/ANT Ether3 card - * for Acorn machines - * - * By Russell King, with some suggestions from borris@ant.co.uk - * - * Changelog: - * 1.04 RMK 29/02/1996 Won't pass packets that are from our ethernet - * address up to the higher levels - they're - * silently ignored. I/F can now be put into - * multicast mode. Receiver routine optimised. - * 1.05 RMK 30/02/1996 Now claims interrupt at open when part of - * the kernel rather than when a module. - * 1.06 RMK 02/03/1996 Various code cleanups - * 1.07 RMK 13/10/1996 Optimised interrupt routine and transmit - * routines. - * 1.08 RMK 14/10/1996 Fixed problem with too many packets, - * prevented the kernel message about dropped - * packets appearing too many times a second. - * Now does not disable all IRQs, only the IRQ - * used by this card. - * 1.09 RMK 10/11/1996 Only enables TX irq when buffer space is low, - * but we still service the TX queue if we get a - * RX interrupt. - * 1.10 RMK 15/07/1997 Fixed autoprobing of NQ8004. - * 1.11 RMK 16/11/1997 Fixed autoprobing of NQ8005A. - * 1.12 RMK 31/12/1997 Removed reference to dev_tint for Linux 2.1. - * RMK 27/06/1998 Changed asm/delay.h to linux/delay.h. - * 1.13 RMK 29/06/1998 Fixed problem with transmission of packets. - * Chip seems to have a bug in, whereby if the - * packet starts two bytes from the end of the - * buffer, it corrupts the receiver chain, and - * never updates the transmit status correctly. - * 1.14 RMK 07/01/1998 Added initial code for ETHERB addressing. - * 1.15 RMK 30/04/1999 More fixes to the transmit routine for buggy - * hardware. - * 1.16 RMK 10/02/2000 Updated for 2.3.43 - * 1.17 RMK 13/05/2000 Updated for 2.3.99-pre8 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -static char version[] __initdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n"; - -#include "ether3.h" - -static unsigned int net_debug = NET_DEBUG; - -static void ether3_setmulticastlist(struct net_device *dev); -static int ether3_rx(struct net_device *dev, struct dev_priv *priv, unsigned int maxcnt); -static void ether3_tx(struct net_device *dev, struct dev_priv *priv); -static int ether3_open (struct net_device *dev); -static int ether3_sendpacket (struct sk_buff *skb, struct net_device *dev); -static void ether3_interrupt (int irq, void *dev_id, struct pt_regs *regs); -static int ether3_close (struct net_device *dev); -static struct net_device_stats *ether3_getstats (struct net_device *dev); -static void ether3_setmulticastlist (struct net_device *dev); -static void ether3_timeout(struct net_device *dev); - -#define BUS_16 2 -#define BUS_8 1 -#define BUS_UNKNOWN 0 - -/* --------------------------------------------------------------------------- */ - -typedef enum { - buffer_write, - buffer_read -} buffer_rw_t; - -/* - * ether3 read/write. Slow things down a bit... - * The SEEQ8005 doesn't like us writing to its registers - * too quickly. - */ -static inline void ether3_outb(int v, const int r) -{ - outb(v, r); - udelay(1); -} - -static inline void ether3_outw(int v, const int r) -{ - outw(v, r); - udelay(1); -} -#define ether3_inb(r) ({ unsigned int __v = inb((r)); udelay(1); __v; }) -#define ether3_inw(r) ({ unsigned int __v = inw((r)); udelay(1); __v; }) - -static int -ether3_setbuffer(struct net_device *dev, buffer_rw_t read, int start) -{ - struct dev_priv *priv = (struct dev_priv *)dev->priv; - int timeout = 1000; - - ether3_outw(priv->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1); - ether3_outw(priv->regs.command | CMD_FIFOWRITE, REG_COMMAND); - - while ((ether3_inw(REG_STATUS) & STAT_FIFOEMPTY) == 0) { - if (!timeout--) { - printk("%s: setbuffer broken\n", dev->name); - priv->broken = 1; - return 1; - } - udelay(1); - } - - if (read == buffer_read) { - ether3_outw(start, REG_DMAADDR); - ether3_outw(priv->regs.command | CMD_FIFOREAD, REG_COMMAND); - } else { - ether3_outw(priv->regs.command | CMD_FIFOWRITE, REG_COMMAND); - ether3_outw(start, REG_DMAADDR); - } - return 0; -} - -/* - * write data to the buffer memory - */ -#define ether3_writebuffer(dev,data,length) \ - outsw(REG_BUFWIN, (data), (length) >> 1) - -#define ether3_writeword(dev,data) \ - outw((data), REG_BUFWIN) - -#define ether3_writelong(dev,data) { \ - unsigned long reg_bufwin = REG_BUFWIN; \ - outw((data), reg_bufwin); \ - outw((data) >> 16, reg_bufwin); \ -} - -/* - * read data from the buffer memory - */ -#define ether3_readbuffer(dev,data,length) \ - insw(REG_BUFWIN, (data), (length) >> 1) - -#define ether3_readword(dev) \ - inw(REG_BUFWIN) - -#define ether3_readlong(dev) \ - inw(REG_BUFWIN) | (inw(REG_BUFWIN) << 16) - -/* - * Switch LED off... - */ -static void -ether3_ledoff(unsigned long data) -{ - struct net_device *dev = (struct net_device *)data; - struct dev_priv *priv = (struct dev_priv *)dev->priv; - ether3_outw(priv->regs.config2 |= CFG2_CTRLO, REG_CONFIG2); -} - -/* - * switch LED on... - */ -static inline void -ether3_ledon(struct net_device *dev, struct dev_priv *priv) -{ - del_timer(&priv->timer); - priv->timer.expires = jiffies + HZ / 50; /* leave on for 1/50th second */ - priv->timer.data = (unsigned long)dev; - priv->timer.function = ether3_ledoff; - add_timer(&priv->timer); - if (priv->regs.config2 & CFG2_CTRLO) - ether3_outw(priv->regs.config2 &= ~CFG2_CTRLO, REG_CONFIG2); -} - -/* - * Read the ethernet address string from the on board rom. - * This is an ascii string!!! - */ -static int __init -ether3_addr(char *addr, struct expansion_card *ec) -{ - struct in_chunk_dir cd; - char *s; - - if (ecard_readchunk(&cd, ec, 0xf5, 0) && (s = strchr(cd.d.string, '('))) { - int i; - for (i = 0; i<6; i++) { - addr[i] = simple_strtoul(s + 1, &s, 0x10); - if (*s != (i==5?')' : ':' )) - break; - } - if (i == 6) - return 0; - } - /* I wonder if we should even let the user continue in this case - * - no, it would be better to disable the device - */ - printk(KERN_ERR "ether3: Couldn't read a valid MAC address from card.\n"); - return -ENODEV; -} - -/* --------------------------------------------------------------------------- */ - -static int __init -ether3_ramtest(struct net_device *dev, unsigned char byte) -{ - unsigned char *buffer = kmalloc(RX_END, GFP_KERNEL); - int i,ret = 0; - int max_errors = 4; - int bad = -1; - - if (!buffer) - return 1; - - memset(buffer, byte, RX_END); - ether3_setbuffer(dev, buffer_write, 0); - ether3_writebuffer(dev, buffer, TX_END); - ether3_setbuffer(dev, buffer_write, RX_START); - ether3_writebuffer(dev, buffer + RX_START, RX_LEN); - memset(buffer, byte ^ 0xff, RX_END); - ether3_setbuffer(dev, buffer_read, 0); - ether3_readbuffer(dev, buffer, TX_END); - ether3_setbuffer(dev, buffer_read, RX_START); - ether3_readbuffer(dev, buffer + RX_START, RX_LEN); - - for (i = 0; i < RX_END; i++) { - if (buffer[i] != byte) { - if (max_errors > 0 && bad != buffer[i]) { - printk("%s: RAM failed with (%02X instead of %02X) at 0x%04X", - dev->name, buffer[i], byte, i); - ret = 2; - max_errors--; - bad = i; - } - } else { - if (bad != -1) { - if (bad != i - 1) - printk(" - 0x%04X\n", i - 1); - printk("\n"); - bad = -1; - } - } - } - if (bad != -1) - printk(" - 0xffff\n"); - kfree(buffer); - - return ret; -} - -/* ------------------------------------------------------------------------------- */ - -static int __init -ether3_init_2(struct net_device *dev) -{ - struct dev_priv *priv = (struct dev_priv *)dev->priv; - int i; - - priv->regs.config1 = CFG1_RECVCOMPSTAT0|CFG1_DMABURST8; - priv->regs.config2 = CFG2_CTRLO|CFG2_RECVCRC|CFG2_ERRENCRC; - priv->regs.command = 0; - - /* - * Set up our hardware address - */ - ether3_outw(priv->regs.config1 | CFG1_BUFSELSTAT0, REG_CONFIG1); - for (i = 0; i < 6; i++) - ether3_outb(dev->dev_addr[i], REG_BUFWIN); - - if (dev->flags & IFF_PROMISC) - priv->regs.config1 |= CFG1_RECVPROMISC; - else if (dev->flags & IFF_MULTICAST) - priv->regs.config1 |= CFG1_RECVSPECBRMULTI; - else - priv->regs.config1 |= CFG1_RECVSPECBROAD; - - /* - * There is a problem with the NQ8005 in that it occasionally loses the - * last two bytes. To get round this problem, we receive the CRC as - * well. That way, if we do lose the last two, then it doesn't matter. - */ - ether3_outw(priv->regs.config1 | CFG1_TRANSEND, REG_CONFIG1); - ether3_outw((TX_END>>8) - 1, REG_BUFWIN); - ether3_outw(priv->rx_head, REG_RECVPTR); - ether3_outw(0, REG_TRANSMITPTR); - ether3_outw(priv->rx_head >> 8, REG_RECVEND); - ether3_outw(priv->regs.config2, REG_CONFIG2); - ether3_outw(priv->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1); - ether3_outw(priv->regs.command, REG_COMMAND); - - i = ether3_ramtest(dev, 0x5A); - if(i) - return i; - i = ether3_ramtest(dev, 0x1E); - if(i) - return i; - - ether3_setbuffer(dev, buffer_write, 0); - ether3_writelong(dev, 0); - return 0; -} - -static void -ether3_init_for_open(struct net_device *dev) -{ - struct dev_priv *priv = (struct dev_priv *)dev->priv; - int i; - - memset(&priv->stats, 0, sizeof(struct net_device_stats)); - - /* Reset the chip */ - ether3_outw(CFG2_RESET, REG_CONFIG2); - udelay(4); - - priv->regs.command = 0; - ether3_outw(CMD_RXOFF|CMD_TXOFF, REG_COMMAND); - while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON)); - - ether3_outw(priv->regs.config1 | CFG1_BUFSELSTAT0, REG_CONFIG1); - for (i = 0; i < 6; i++) - ether3_outb(dev->dev_addr[i], REG_BUFWIN); - - priv->tx_head = 0; - priv->tx_tail = 0; - priv->regs.config2 |= CFG2_CTRLO; - priv->rx_head = RX_START; - - ether3_outw(priv->regs.config1 | CFG1_TRANSEND, REG_CONFIG1); - ether3_outw((TX_END>>8) - 1, REG_BUFWIN); - ether3_outw(priv->rx_head, REG_RECVPTR); - ether3_outw(priv->rx_head >> 8, REG_RECVEND); - ether3_outw(0, REG_TRANSMITPTR); - ether3_outw(priv->regs.config2, REG_CONFIG2); - ether3_outw(priv->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1); - - ether3_setbuffer(dev, buffer_write, 0); - ether3_writelong(dev, 0); - - priv->regs.command = CMD_ENINTRX | CMD_ENINTTX; - ether3_outw(priv->regs.command | CMD_RXON, REG_COMMAND); -} - -static inline int -ether3_probe_bus_8(struct net_device *dev, int val) -{ - int write_low, write_high, read_low, read_high; - - write_low = val & 255; - write_high = val >> 8; - - printk(KERN_DEBUG "ether3_probe: write8 [%02X:%02X]", write_high, write_low); - - ether3_outb(write_low, REG_RECVPTR); - ether3_outb(write_high, REG_RECVPTR + 1); - - read_low = ether3_inb(REG_RECVPTR); - read_high = ether3_inb(REG_RECVPTR + 1); - - printk(", read8 [%02X:%02X]\n", read_high, read_low); - - return read_low == write_low && read_high == write_high; -} - -static inline int -ether3_probe_bus_16(struct net_device *dev, int val) -{ - int read_val; - - ether3_outw(val, REG_RECVPTR); - read_val = ether3_inw(REG_RECVPTR); - - printk(KERN_DEBUG "ether3_probe: write16 [%04X], read16 [%04X]\n", val, read_val); - - return read_val == val; -} - -/* - * Open/initialize the board. This is called (in the current kernel) - * sometime after booting when the 'ifconfig' program is run. - * - * This routine should set everything up anew at each open, even - * registers that "should" only need to be set once at boot, so that - * there is non-reboot way to recover if something goes wrong. - */ -static int -ether3_open(struct net_device *dev) -{ - if (!is_valid_ether_addr(dev->dev_addr)) { - printk(KERN_WARNING "%s: invalid ethernet MAC address\n", - dev->name); - return -EINVAL; - } - - if (request_irq(dev->irq, ether3_interrupt, 0, "ether3", dev)) - return -EAGAIN; - - ether3_init_for_open(dev); - - netif_start_queue(dev); - - return 0; -} - -/* - * The inverse routine to ether3_open(). - */ -static int -ether3_close(struct net_device *dev) -{ - struct dev_priv *priv = (struct dev_priv *)dev->priv; - - netif_stop_queue(dev); - - disable_irq(dev->irq); - - ether3_outw(CMD_RXOFF|CMD_TXOFF, REG_COMMAND); - priv->regs.command = 0; - while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON)); - ether3_outb(0x80, REG_CONFIG2 + 1); - ether3_outw(0, REG_COMMAND); - - free_irq(dev->irq, dev); - - return 0; -} - -/* - * Get the current statistics. This may be called with the card open or - * closed. - */ -static struct net_device_stats *ether3_getstats(struct net_device *dev) -{ - struct dev_priv *priv = (struct dev_priv *)dev->priv; - return &priv->stats; -} - -/* - * Set or clear promiscuous/multicast mode filter for this adaptor. - * - * We don't attempt any packet filtering. The card may have a SEEQ 8004 - * in which does not have the other ethernet address registers present... - */ -static void ether3_setmulticastlist(struct net_device *dev) -{ - struct dev_priv *priv = (struct dev_priv *)dev->priv; - - priv->regs.config1 &= ~CFG1_RECVPROMISC; - - if (dev->flags & IFF_PROMISC) { - /* promiscuous mode */ - priv->regs.config1 |= CFG1_RECVPROMISC; - } else if (dev->flags & IFF_ALLMULTI) { - priv->regs.config1 |= CFG1_RECVSPECBRMULTI; - } else - priv->regs.config1 |= CFG1_RECVSPECBROAD; - - ether3_outw(priv->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1); -} - -static void -ether3_timeout(struct net_device *dev) -{ - struct dev_priv *priv = (struct dev_priv *)dev->priv; - unsigned long flags; - - del_timer(&priv->timer); - - local_irq_save(flags); - printk(KERN_ERR "%s: transmit timed out, network cable problem?\n", dev->name); - printk(KERN_ERR "%s: state: { status=%04X cfg1=%04X cfg2=%04X }\n", dev->name, - ether3_inw(REG_STATUS), ether3_inw(REG_CONFIG1), ether3_inw(REG_CONFIG2)); - printk(KERN_ERR "%s: { rpr=%04X rea=%04X tpr=%04X }\n", dev->name, - ether3_inw(REG_RECVPTR), ether3_inw(REG_RECVEND), ether3_inw(REG_TRANSMITPTR)); - printk(KERN_ERR "%s: tx head=%X tx tail=%X\n", dev->name, - priv->tx_head, priv->tx_tail); - ether3_setbuffer(dev, buffer_read, priv->tx_tail); - printk(KERN_ERR "%s: packet status = %08X\n", dev->name, ether3_readlong(dev)); - local_irq_restore(flags); - - priv->regs.config2 |= CFG2_CTRLO; - priv->stats.tx_errors += 1; - ether3_outw(priv->regs.config2, REG_CONFIG2); - priv->tx_head = priv->tx_tail = 0; - - netif_wake_queue(dev); -} - -/* - * Transmit a packet - */ -static int -ether3_sendpacket(struct sk_buff *skb, struct net_device *dev) -{ - struct dev_priv *priv = (struct dev_priv *)dev->priv; - unsigned long flags; - unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned int ptr, next_ptr; - - length = (length + 1) & ~1; - - if (priv->broken) { - dev_kfree_skb(skb); - priv->stats.tx_dropped ++; - netif_start_queue(dev); - return 0; - } - - next_ptr = (priv->tx_head + 1) & 15; - - local_irq_save(flags); - - if (priv->tx_tail == next_ptr) { - local_irq_restore(flags); - return 1; /* unable to queue */ - } - - dev->trans_start = jiffies; - ptr = 0x600 * priv->tx_head; - priv->tx_head = next_ptr; - next_ptr *= 0x600; - -#define TXHDR_FLAGS (TXHDR_TRANSMIT|TXHDR_CHAINCONTINUE|TXHDR_DATAFOLLOWS|TXHDR_ENSUCCESS) - - ether3_setbuffer(dev, buffer_write, next_ptr); - ether3_writelong(dev, 0); - ether3_setbuffer(dev, buffer_write, ptr); - ether3_writelong(dev, 0); - ether3_writebuffer(dev, skb->data, length); - ether3_writeword(dev, htons(next_ptr)); - ether3_writeword(dev, TXHDR_CHAINCONTINUE >> 16); - ether3_setbuffer(dev, buffer_write, ptr); - ether3_writeword(dev, htons((ptr + length + 4))); - ether3_writeword(dev, TXHDR_FLAGS >> 16); - ether3_ledon(dev, priv); - - if (!(ether3_inw(REG_STATUS) & STAT_TXON)) { - ether3_outw(ptr, REG_TRANSMITPTR); - ether3_outw(priv->regs.command | CMD_TXON, REG_COMMAND); - } - - next_ptr = (priv->tx_head + 1) & 15; - local_irq_restore(flags); - - dev_kfree_skb(skb); - - if (priv->tx_tail == next_ptr) - netif_stop_queue(dev); - - return 0; -} - -static void -ether3_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct net_device *dev = (struct net_device *)dev_id; - struct dev_priv *priv; - unsigned int status; - -#if NET_DEBUG > 1 - if(net_debug & DEBUG_INT) - printk("eth3irq: %d ", irq); -#endif - - priv = (struct dev_priv *)dev->priv; - - status = ether3_inw(REG_STATUS); - - if (status & STAT_INTRX) { - ether3_outw(CMD_ACKINTRX | priv->regs.command, REG_COMMAND); - ether3_rx(dev, priv, 12); - } - - if (status & STAT_INTTX) { - ether3_outw(CMD_ACKINTTX | priv->regs.command, REG_COMMAND); - ether3_tx(dev, priv); - } - -#if NET_DEBUG > 1 - if(net_debug & DEBUG_INT) - printk("done\n"); -#endif -} - -/* - * If we have a good packet(s), get it/them out of the buffers. - */ -static int -ether3_rx(struct net_device *dev, struct dev_priv *priv, unsigned int maxcnt) -{ - unsigned int next_ptr = priv->rx_head, received = 0; - ether3_ledon(dev, priv); - - do { - unsigned int this_ptr, status; - unsigned char addrs[16]; - - /* - * read the first 16 bytes from the buffer. - * This contains the status bytes etc and ethernet addresses, - * and we also check the source ethernet address to see if - * it originated from us. - */ - { - unsigned int temp_ptr; - ether3_setbuffer(dev, buffer_read, next_ptr); - temp_ptr = ether3_readword(dev); - status = ether3_readword(dev); - if ((status & (RXSTAT_DONE | RXHDR_CHAINCONTINUE | RXHDR_RECEIVE)) != - (RXSTAT_DONE | RXHDR_CHAINCONTINUE) || !temp_ptr) - break; - - this_ptr = next_ptr + 4; - next_ptr = ntohs(temp_ptr); - } - ether3_setbuffer(dev, buffer_read, this_ptr); - ether3_readbuffer(dev, addrs+2, 12); - -if (next_ptr < RX_START || next_ptr >= RX_END) { - int i; - printk("%s: bad next pointer @%04X: ", dev->name, priv->rx_head); - printk("%02X %02X %02X %02X ", next_ptr >> 8, next_ptr & 255, status & 255, status >> 8); - for (i = 2; i < 14; i++) - printk("%02X ", addrs[i]); - printk("\n"); - next_ptr = priv->rx_head; - break; -} - /* - * ignore our own packets... - */ - if (!(*(unsigned long *)&dev->dev_addr[0] ^ *(unsigned long *)&addrs[2+6]) && - !(*(unsigned short *)&dev->dev_addr[4] ^ *(unsigned short *)&addrs[2+10])) { - maxcnt ++; /* compensate for loopedback packet */ - ether3_outw(next_ptr >> 8, REG_RECVEND); - } else - if (!(status & (RXSTAT_OVERSIZE|RXSTAT_CRCERROR|RXSTAT_DRIBBLEERROR|RXSTAT_SHORTPACKET))) { - unsigned int length = next_ptr - this_ptr; - struct sk_buff *skb; - - if (next_ptr <= this_ptr) - length += RX_END - RX_START; - - skb = dev_alloc_skb(length + 2); - if (skb) { - unsigned char *buf; - - skb->dev = dev; - skb_reserve(skb, 2); - buf = skb_put(skb, length); - ether3_readbuffer(dev, buf + 12, length - 12); - ether3_outw(next_ptr >> 8, REG_RECVEND); - *(unsigned short *)(buf + 0) = *(unsigned short *)(addrs + 2); - *(unsigned long *)(buf + 2) = *(unsigned long *)(addrs + 4); - *(unsigned long *)(buf + 6) = *(unsigned long *)(addrs + 8); - *(unsigned short *)(buf + 10) = *(unsigned short *)(addrs + 12); - skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); - received ++; - } else - goto dropping; - } else { - struct net_device_stats *stats = &priv->stats; - ether3_outw(next_ptr >> 8, REG_RECVEND); - if (status & RXSTAT_OVERSIZE) stats->rx_over_errors ++; - if (status & RXSTAT_CRCERROR) stats->rx_crc_errors ++; - if (status & RXSTAT_DRIBBLEERROR) stats->rx_fifo_errors ++; - if (status & RXSTAT_SHORTPACKET) stats->rx_length_errors ++; - stats->rx_errors++; - } - } - while (-- maxcnt); - -done: - priv->stats.rx_packets += received; - priv->rx_head = next_ptr; - /* - * If rx went off line, then that means that the buffer may be full. We - * have dropped at least one packet. - */ - if (!(ether3_inw(REG_STATUS) & STAT_RXON)) { - priv->stats.rx_dropped ++; - ether3_outw(next_ptr, REG_RECVPTR); - ether3_outw(priv->regs.command | CMD_RXON, REG_COMMAND); - } - - return maxcnt; - -dropping:{ - static unsigned long last_warned; - - ether3_outw(next_ptr >> 8, REG_RECVEND); - /* - * Don't print this message too many times... - */ - if (time_after(jiffies, last_warned + 10 * HZ)) { - last_warned = jiffies; - printk("%s: memory squeeze, dropping packet.\n", dev->name); - } - priv->stats.rx_dropped ++; - goto done; - } -} - -/* - * Update stats for the transmitted packet(s) - */ -static void -ether3_tx(struct net_device *dev, struct dev_priv *priv) -{ - unsigned int tx_tail = priv->tx_tail; - int max_work = 14; - - do { - unsigned long status; - - /* - * Read the packet header - */ - ether3_setbuffer(dev, buffer_read, tx_tail * 0x600); - status = ether3_readlong(dev); - - /* - * Check to see if this packet has been transmitted - */ - if ((status & (TXSTAT_DONE | TXHDR_TRANSMIT)) != - (TXSTAT_DONE | TXHDR_TRANSMIT)) - break; - - /* - * Update errors - */ - if (!(status & (TXSTAT_BABBLED | TXSTAT_16COLLISIONS))) - priv->stats.tx_packets++; - else { - priv->stats.tx_errors ++; - if (status & TXSTAT_16COLLISIONS) priv->stats.collisions += 16; - if (status & TXSTAT_BABBLED) priv->stats.tx_fifo_errors ++; - } - - tx_tail = (tx_tail + 1) & 15; - } while (--max_work); - - if (priv->tx_tail != tx_tail) { - priv->tx_tail = tx_tail; - netif_wake_queue(dev); - } -} - -static void __init ether3_banner(void) -{ - static unsigned version_printed = 0; - - if (net_debug && version_printed++ == 0) - printk(KERN_INFO "%s", version); -} - -static const char * __init -ether3_get_dev(struct net_device *dev, struct expansion_card *ec) -{ - const char *name = "ether3"; - - dev->base_addr = ecard_address(ec, ECARD_MEMC, 0); - dev->irq = ec->irq; - - if (ec->cid.manufacturer == MANU_ANT && - ec->cid.product == PROD_ANT_ETHERB) { - dev->base_addr += 0x200; - name = "etherb"; - } - - ec->irqaddr = (volatile unsigned char *)ioaddr(dev->base_addr); - ec->irqmask = 0xf0; - - ether3_addr(dev->dev_addr, ec); - - return name; -} - -static int __devinit -ether3_probe(struct expansion_card *ec, const struct ecard_id *id) -{ - struct net_device *dev; - struct dev_priv *priv; - const char *name; - int i, bus_type, ret; - - ether3_banner(); - - dev = init_etherdev(NULL, sizeof(struct dev_priv)); - if (!dev) { - ret = -ENOMEM; - goto out; - } - - SET_MODULE_OWNER(dev); - - name = ether3_get_dev(dev, ec); - if (!name) { - ret = -ENODEV; - goto free; - } - - /* - * this will not fail - the nature of the bus ensures this - */ - if (!request_region(dev->base_addr, 128, dev->name)) { - ret = -EBUSY; - goto free; - } - - priv = (struct dev_priv *) dev->priv; - init_timer(&priv->timer); - - /* Reset card... - */ - ether3_outb(0x80, REG_CONFIG2 + 1); - bus_type = BUS_UNKNOWN; - udelay(4); - - /* Test using Receive Pointer (16-bit register) to find out - * how the ether3 is connected to the bus... - */ - if (ether3_probe_bus_8(dev, 0x100) && - ether3_probe_bus_8(dev, 0x201)) - bus_type = BUS_8; - - if (bus_type == BUS_UNKNOWN && - ether3_probe_bus_16(dev, 0x101) && - ether3_probe_bus_16(dev, 0x201)) - bus_type = BUS_16; - - switch (bus_type) { - case BUS_UNKNOWN: - printk(KERN_ERR "%s: unable to identify bus width\n", dev->name); - ret = -ENODEV; - goto failed; - - case BUS_8: - printk(KERN_ERR "%s: %s found, but is an unsupported " - "8-bit card\n", dev->name, name); - ret = -ENODEV; - goto failed; - - default: - break; - } - - printk("%s: %s in slot %d, ", dev->name, name, ec->slot_no); - for (i = 0; i < 6; i++) - printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':'); - - if (ether3_init_2(dev)) { - ret = -ENODEV; - goto failed; - } - - dev->open = ether3_open; - dev->stop = ether3_close; - dev->hard_start_xmit = ether3_sendpacket; - dev->get_stats = ether3_getstats; - dev->set_multicast_list = ether3_setmulticastlist; - dev->tx_timeout = ether3_timeout; - dev->watchdog_timeo = 5 * HZ / 100; - - ecard_set_drvdata(ec, dev); - return 0; - -failed: - release_region(dev->base_addr, 128); -free: - unregister_netdev(dev); - kfree(dev); -out: - return ret; -} - -static void __devexit ether3_remove(struct expansion_card *ec) -{ - struct net_device *dev = ecard_get_drvdata(ec); - - ecard_set_drvdata(ec, NULL); - - unregister_netdev(dev); - release_region(dev->base_addr, 128); - kfree(dev); -} - -static const struct ecard_id ether3_ids[] = { - { MANU_ANT2, PROD_ANT_ETHER3 }, - { MANU_ANT, PROD_ANT_ETHER3 }, - { MANU_ANT, PROD_ANT_ETHERB }, - { 0xffff, 0xffff } -}; - -static struct ecard_driver ether3_driver = { - .probe = ether3_probe, - .remove = __devexit_p(ether3_remove), - .id_table = ether3_ids, - .drv = { - .name = "ether3", - }, -}; - -static int __init ether3_init(void) -{ - return ecard_register_driver(ðer3_driver); -} - -static void __exit ether3_exit(void) -{ - ecard_remove_driver(ðer3_driver); -} - -module_init(ether3_init); -module_exit(ether3_exit); - -MODULE_LICENSE("GPL"); diff -Nru a/drivers/acorn/net/ether3.h b/drivers/acorn/net/ether3.h --- a/drivers/acorn/net/ether3.h Sat May 24 12:48:32 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,168 +0,0 @@ -/* - * linux/drivers/acorn/net/ether3.h - * - * Copyright (C) 1995-2000 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * network driver for Acorn/ANT Ether3 cards - */ - -#ifndef _LINUX_ether3_H -#define _LINUX_ether3_H - -/* use 0 for production, 1 for verification, >2 for debug. debug flags: */ -#define DEBUG_TX 2 -#define DEBUG_RX 4 -#define DEBUG_INT 8 -#define DEBUG_IC 16 -#ifndef NET_DEBUG -#define NET_DEBUG 0 -#endif - -/* Command register definitions & bits */ -#define REG_COMMAND (dev->base_addr + 0x00) -#define CMD_ENINTDMA 0x0001 -#define CMD_ENINTRX 0x0002 -#define CMD_ENINTTX 0x0004 -#define CMD_ENINTBUFWIN 0x0008 -#define CMD_ACKINTDMA 0x0010 -#define CMD_ACKINTRX 0x0020 -#define CMD_ACKINTTX 0x0040 -#define CMD_ACKINTBUFWIN 0x0080 -#define CMD_DMAON 0x0100 -#define CMD_RXON 0x0200 -#define CMD_TXON 0x0400 -#define CMD_DMAOFF 0x0800 -#define CMD_RXOFF 0x1000 -#define CMD_TXOFF 0x2000 -#define CMD_FIFOREAD 0x4000 -#define CMD_FIFOWRITE 0x8000 - -/* status register */ -#define REG_STATUS (dev->base_addr + 0x00) -#define STAT_ENINTSTAT 0x0001 -#define STAT_ENINTRX 0x0002 -#define STAT_ENINTTX 0x0004 -#define STAT_ENINTBUFWIN 0x0008 -#define STAT_INTDMA 0x0010 -#define STAT_INTRX 0x0020 -#define STAT_INTTX 0x0040 -#define STAT_INTBUFWIN 0x0080 -#define STAT_DMAON 0x0100 -#define STAT_RXON 0x0200 -#define STAT_TXON 0x0400 -#define STAT_FIFOFULL 0x2000 -#define STAT_FIFOEMPTY 0x4000 -#define STAT_FIFODIR 0x8000 - -/* configuration register 1 */ -#define REG_CONFIG1 (dev->base_addr + 0x10) -#define CFG1_BUFSELSTAT0 0x0000 -#define CFG1_BUFSELSTAT1 0x0001 -#define CFG1_BUFSELSTAT2 0x0002 -#define CFG1_BUFSELSTAT3 0x0003 -#define CFG1_BUFSELSTAT4 0x0004 -#define CFG1_BUFSELSTAT5 0x0005 -#define CFG1_ADDRPROM 0x0006 -#define CFG1_TRANSEND 0x0007 -#define CFG1_LOCBUFMEM 0x0008 -#define CFG1_INTVECTOR 0x0009 -#define CFG1_RECVSPECONLY 0x0000 -#define CFG1_RECVSPECBROAD 0x4000 -#define CFG1_RECVSPECBRMULTI 0x8000 -#define CFG1_RECVPROMISC 0xC000 - -/* The following aren't in 8004 */ -#define CFG1_DMABURSTCONT 0x0000 -#define CFG1_DMABURST800NS 0x0010 -#define CFG1_DMABURST1600NS 0x0020 -#define CFG1_DMABURST3200NS 0x0030 -#define CFG1_DMABURST1 0x0000 -#define CFG1_DMABURST4 0x0040 -#define CFG1_DMABURST8 0x0080 -#define CFG1_DMABURST16 0x00C0 -#define CFG1_RECVCOMPSTAT0 0x0100 -#define CFG1_RECVCOMPSTAT1 0x0200 -#define CFG1_RECVCOMPSTAT2 0x0400 -#define CFG1_RECVCOMPSTAT3 0x0800 -#define CFG1_RECVCOMPSTAT4 0x1000 -#define CFG1_RECVCOMPSTAT5 0x2000 - -/* configuration register 2 */ -#define REG_CONFIG2 (dev->base_addr + 0x20) -#define CFG2_BYTESWAP 0x0001 -#define CFG2_ERRENCRC 0x0008 -#define CFG2_ERRENDRIBBLE 0x0010 -#define CFG2_ERRSHORTFRAME 0x0020 -#define CFG2_SLOTSELECT 0x0040 -#define CFG2_PREAMSELECT 0x0080 -#define CFG2_ADDRLENGTH 0x0100 -#define CFG2_RECVCRC 0x0200 -#define CFG2_XMITNOCRC 0x0400 -#define CFG2_LOOPBACK 0x0800 -#define CFG2_CTRLO 0x1000 -#define CFG2_RESET 0x8000 - -#define REG_RECVEND (dev->base_addr + 0x30) - -#define REG_BUFWIN (dev->base_addr + 0x40) - -#define REG_RECVPTR (dev->base_addr + 0x50) - -#define REG_TRANSMITPTR (dev->base_addr + 0x60) - -#define REG_DMAADDR (dev->base_addr + 0x70) - -/* - * Cards transmit/receive headers - */ -#define TX_NEXT (0xffff) -#define TXHDR_ENBABBLEINT (1 << 16) -#define TXHDR_ENCOLLISIONINT (1 << 17) -#define TXHDR_EN16COLLISION (1 << 18) -#define TXHDR_ENSUCCESS (1 << 19) -#define TXHDR_DATAFOLLOWS (1 << 21) -#define TXHDR_CHAINCONTINUE (1 << 22) -#define TXHDR_TRANSMIT (1 << 23) -#define TXSTAT_BABBLED (1 << 24) -#define TXSTAT_COLLISION (1 << 25) -#define TXSTAT_16COLLISIONS (1 << 26) -#define TXSTAT_DONE (1 << 31) - -#define RX_NEXT (0xffff) -#define RXHDR_CHAINCONTINUE (1 << 6) -#define RXHDR_RECEIVE (1 << 7) -#define RXSTAT_OVERSIZE (1 << 8) -#define RXSTAT_CRCERROR (1 << 9) -#define RXSTAT_DRIBBLEERROR (1 << 10) -#define RXSTAT_SHORTPACKET (1 << 11) -#define RXSTAT_DONE (1 << 15) - - -#define TX_START 0x0000 -#define TX_END 0x6000 -#define RX_START 0x6000 -#define RX_LEN 0xA000 -#define RX_END 0x10000 -/* must be a power of 2 and greater than MAX_TX_BUFFERED */ -#define MAX_TXED 16 -#define MAX_TX_BUFFERED 10 - -struct dev_priv { - struct { - unsigned int command; - unsigned int config1; - unsigned int config2; - } regs; - unsigned char tx_head; /* buffer nr to insert next packet */ - unsigned char tx_tail; /* buffer nr of transmitting packet */ - unsigned int rx_head; /* address to fetch next packet from */ - struct net_device_stats stats; - struct timer_list timer; - int broken; /* 0 = ok, 1 = something went wrong */ -}; - -#endif diff -Nru a/drivers/acorn/net/etherh.c b/drivers/acorn/net/etherh.c --- a/drivers/acorn/net/etherh.c Sat May 24 12:48:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,763 +0,0 @@ -/* - * linux/drivers/acorn/net/etherh.c - * - * Copyright (C) 2000-2002 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * NS8390 I-cubed EtherH and ANT EtherM specific driver - * Thanks to I-Cubed for information on their cards. - * EtherM conversion (C) 1999 Chris Kemp and Tim Watterton - * EtherM integration (C) 2000 Aleph One Ltd (Tak-Shing Chan) - * EtherM integration re-engineered by Russell King. - * - * Changelog: - * 08-12-1996 RMK 1.00 Created - * RMK 1.03 Added support for EtherLan500 cards - * 23-11-1997 RMK 1.04 Added media autodetection - * 16-04-1998 RMK 1.05 Improved media autodetection - * 10-02-2000 RMK 1.06 Updated for 2.3.43 - * 13-05-2000 RMK 1.07 Updated for 2.3.99-pre8 - * 12-10-1999 CK/TEW EtherM driver first release - * 21-12-2000 TTC EtherH/EtherM integration - * 25-12-2000 RMK 1.08 Clean integration of EtherM into this driver. - * 03-01-2002 RMK 1.09 Always enable IRQs if we're in the nic slot. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "../../net/8390.h" - -#define NET_DEBUG 0 -#define DEBUG_INIT 2 - -static unsigned int net_debug = NET_DEBUG; - -struct etherh_priv { - struct ei_device eidev; - unsigned int id; - unsigned int ctrl_port; - unsigned int ctrl; -}; - -MODULE_AUTHOR("Russell King"); -MODULE_DESCRIPTION("EtherH/EtherM driver"); -MODULE_LICENSE("GPL"); - -static char version[] __initdata = - "EtherH/EtherM Driver (c) 2002 Russell King v1.09\n"; - -#define ETHERH500_DATAPORT 0x200 /* MEMC */ -#define ETHERH500_NS8390 0x000 /* MEMC */ -#define ETHERH500_CTRLPORT 0x200 /* IOC */ - -#define ETHERH600_DATAPORT 16 /* MEMC */ -#define ETHERH600_NS8390 0x200 /* MEMC */ -#define ETHERH600_CTRLPORT 0x080 /* MEMC */ - -#define ETHERH_CP_IE 1 -#define ETHERH_CP_IF 2 -#define ETHERH_CP_HEARTBEAT 2 - -#define ETHERH_TX_START_PAGE 1 -#define ETHERH_STOP_PAGE 127 - -/* - * These came from CK/TEW - */ -#define ETHERM_DATAPORT 0x080 /* MEMC */ -#define ETHERM_NS8390 0x200 /* MEMC */ -#define ETHERM_CTRLPORT 0x08f /* MEMC */ - -#define ETHERM_TX_START_PAGE 64 -#define ETHERM_STOP_PAGE 127 - -/* ------------------------------------------------------------------------ */ - -static inline void etherh_set_ctrl(struct etherh_priv *eh, unsigned int mask) -{ - eh->ctrl |= mask; - outb(eh->ctrl, eh->ctrl_port); -} - -static inline void etherh_clr_ctrl(struct etherh_priv *eh, unsigned int mask) -{ - eh->ctrl &= ~mask; - outb(eh->ctrl, eh->ctrl_port); -} - -static inline unsigned int etherh_get_stat(struct etherh_priv *eh) -{ - return inb(eh->ctrl_port); -} - - - - -static void etherh_irq_enable(ecard_t *ec, int irqnr) -{ - struct etherh_priv *eh = ec->irq_data; - - etherh_set_ctrl(eh, ETHERH_CP_IE); -} - -static void etherh_irq_disable(ecard_t *ec, int irqnr) -{ - struct etherh_priv *eh = ec->irq_data; - - etherh_clr_ctrl(eh, ETHERH_CP_IE); -} - -static expansioncard_ops_t etherh_ops = { - .irqenable = etherh_irq_enable, - .irqdisable = etherh_irq_disable, -}; - - - - -static void -etherh_setif(struct net_device *dev) -{ - struct etherh_priv *eh = (struct etherh_priv *)dev->priv; - struct ei_device *ei_local = &eh->eidev; - unsigned long addr, flags; - - local_irq_save(flags); - - /* set the interface type */ - switch (eh->id) { - case PROD_I3_ETHERLAN600: - case PROD_I3_ETHERLAN600A: - addr = dev->base_addr + EN0_RCNTHI; - - switch (dev->if_port) { - case IF_PORT_10BASE2: - outb((inb(addr) & 0xf8) | 1, addr); - break; - case IF_PORT_10BASET: - outb((inb(addr) & 0xf8), addr); - break; - } - break; - - case PROD_I3_ETHERLAN500: - switch (dev->if_port) { - case IF_PORT_10BASE2: - etherh_clr_ctrl(eh, ETHERH_CP_IF); - break; - - case IF_PORT_10BASET: - etherh_set_ctrl(eh, ETHERH_CP_IF); - break; - } - break; - - default: - break; - } - - local_irq_restore(flags); -} - -static int -etherh_getifstat(struct net_device *dev) -{ - struct etherh_priv *eh = (struct etherh_priv *)dev->priv; - struct ei_device *ei_local = &eh->eidev; - int stat = 0; - - switch (eh->id) { - case PROD_I3_ETHERLAN600: - case PROD_I3_ETHERLAN600A: - switch (dev->if_port) { - case IF_PORT_10BASE2: - stat = 1; - break; - case IF_PORT_10BASET: - stat = inb(dev->base_addr+EN0_RCNTHI) & 4; - break; - } - break; - - case PROD_I3_ETHERLAN500: - switch (dev->if_port) { - case IF_PORT_10BASE2: - stat = 1; - break; - case IF_PORT_10BASET: - stat = etherh_get_stat(eh) & ETHERH_CP_HEARTBEAT; - break; - } - break; - - default: - stat = 0; - break; - } - - return stat != 0; -} - -/* - * Configure the interface. Note that we ignore the other - * parts of ifmap, since its mostly meaningless for this driver. - */ -static int etherh_set_config(struct net_device *dev, struct ifmap *map) -{ - switch (map->port) { - case IF_PORT_10BASE2: - case IF_PORT_10BASET: - /* - * If the user explicitly sets the interface - * media type, turn off automedia detection. - */ - dev->flags &= ~IFF_AUTOMEDIA; - dev->if_port = map->port; - break; - - default: - return -EINVAL; - } - - etherh_setif(dev); - - return 0; -} - -/* - * Reset the 8390 (hard reset). Note that we can't actually do this. - */ -static void -etherh_reset(struct net_device *dev) -{ - struct ei_device *ei_local = (struct ei_device *) dev->priv; - - outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, dev->base_addr); - - /* - * See if we need to change the interface type. - * Note that we use 'interface_num' as a flag - * to indicate that we need to change the media. - */ - if (dev->flags & IFF_AUTOMEDIA && ei_local->interface_num) { - ei_local->interface_num = 0; - - if (dev->if_port == IF_PORT_10BASET) - dev->if_port = IF_PORT_10BASE2; - else - dev->if_port = IF_PORT_10BASET; - - etherh_setif(dev); - } -} - -/* - * Write a block of data out to the 8390 - */ -static void -etherh_block_output (struct net_device *dev, int count, const unsigned char *buf, int start_page) -{ - struct ei_device *ei_local = (struct ei_device *) dev->priv; - unsigned int addr, dma_addr; - unsigned long dma_start; - - if (ei_local->dmaing) { - printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: " - " DMAstat %d irqlock %d\n", dev->name, - ei_local->dmaing, ei_local->irqlock); - return; - } - - /* - * Make sure we have a round number of bytes if we're in word mode. - */ - if (count & 1 && ei_local->word16) - count++; - - ei_local->dmaing = 1; - - addr = dev->base_addr; - dma_addr = dev->mem_start; - - count = (count + 1) & ~1; - outb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD); - - outb (0x42, addr + EN0_RCNTLO); - outb (0x00, addr + EN0_RCNTHI); - outb (0x42, addr + EN0_RSARLO); - outb (0x00, addr + EN0_RSARHI); - outb (E8390_RREAD | E8390_START, addr + E8390_CMD); - - udelay (1); - - outb (ENISR_RDC, addr + EN0_ISR); - outb (count, addr + EN0_RCNTLO); - outb (count >> 8, addr + EN0_RCNTHI); - outb (0, addr + EN0_RSARLO); - outb (start_page, addr + EN0_RSARHI); - outb (E8390_RWRITE | E8390_START, addr + E8390_CMD); - - if (ei_local->word16) - outsw (dma_addr, buf, count >> 1); - else - outsb (dma_addr, buf, count); - - dma_start = jiffies; - - while ((inb (addr + EN0_ISR) & ENISR_RDC) == 0) - if (jiffies - dma_start > 2*HZ/100) { /* 20ms */ - printk(KERN_ERR "%s: timeout waiting for TX RDC\n", - dev->name); - etherh_reset (dev); - NS8390_init (dev, 1); - break; - } - - outb (ENISR_RDC, addr + EN0_ISR); - ei_local->dmaing = 0; -} - -/* - * Read a block of data from the 8390 - */ -static void -etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int ring_offset) -{ - struct ei_device *ei_local = (struct ei_device *) dev->priv; - unsigned int addr, dma_addr; - unsigned char *buf; - - if (ei_local->dmaing) { - printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: " - " DMAstat %d irqlock %d\n", dev->name, - ei_local->dmaing, ei_local->irqlock); - return; - } - - ei_local->dmaing = 1; - - addr = dev->base_addr; - dma_addr = dev->mem_start; - - buf = skb->data; - outb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD); - outb (count, addr + EN0_RCNTLO); - outb (count >> 8, addr + EN0_RCNTHI); - outb (ring_offset, addr + EN0_RSARLO); - outb (ring_offset >> 8, addr + EN0_RSARHI); - outb (E8390_RREAD | E8390_START, addr + E8390_CMD); - - if (ei_local->word16) { - insw (dma_addr, buf, count >> 1); - if (count & 1) - buf[count - 1] = inb (dma_addr); - } else - insb (dma_addr, buf, count); - - outb (ENISR_RDC, addr + EN0_ISR); - ei_local->dmaing = 0; -} - -/* - * Read a header from the 8390 - */ -static void -etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page) -{ - struct ei_device *ei_local = (struct ei_device *) dev->priv; - unsigned int addr, dma_addr; - - if (ei_local->dmaing) { - printk(KERN_ERR "%s: DMAing conflict in etherh_get_header: " - " DMAstat %d irqlock %d\n", dev->name, - ei_local->dmaing, ei_local->irqlock); - return; - } - - ei_local->dmaing = 1; - - addr = dev->base_addr; - dma_addr = dev->mem_start; - - outb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD); - outb (sizeof (*hdr), addr + EN0_RCNTLO); - outb (0, addr + EN0_RCNTHI); - outb (0, addr + EN0_RSARLO); - outb (ring_page, addr + EN0_RSARHI); - outb (E8390_RREAD | E8390_START, addr + E8390_CMD); - - if (ei_local->word16) - insw (dma_addr, hdr, sizeof (*hdr) >> 1); - else - insb (dma_addr, hdr, sizeof (*hdr)); - - outb (ENISR_RDC, addr + EN0_ISR); - ei_local->dmaing = 0; -} - -/* - * Open/initialize the board. This is called (in the current kernel) - * sometime after booting when the 'ifconfig' program is run. - * - * This routine should set everything up anew at each open, even - * registers that "should" only need to be set once at boot, so that - * there is non-reboot way to recover if something goes wrong. - */ -static int -etherh_open(struct net_device *dev) -{ - struct ei_device *ei_local = (struct ei_device *) dev->priv; - - if (!is_valid_ether_addr(dev->dev_addr)) { - printk(KERN_WARNING "%s: invalid ethernet MAC address\n", - dev->name); - return -EINVAL; - } - - if (request_irq(dev->irq, ei_interrupt, 0, dev->name, dev)) - return -EAGAIN; - - /* - * Make sure that we aren't going to change the - * media type on the next reset - we are about to - * do automedia manually now. - */ - ei_local->interface_num = 0; - - /* - * If we are doing automedia detection, do it now. - * This is more reliable than the 8390's detection. - */ - if (dev->flags & IFF_AUTOMEDIA) { - dev->if_port = IF_PORT_10BASET; - etherh_setif(dev); - mdelay(1); - if (!etherh_getifstat(dev)) { - dev->if_port = IF_PORT_10BASE2; - etherh_setif(dev); - } - } else - etherh_setif(dev); - - etherh_reset(dev); - ei_open(dev); - - return 0; -} - -/* - * The inverse routine to etherh_open(). - */ -static int -etherh_close(struct net_device *dev) -{ - ei_close (dev); - free_irq (dev->irq, dev); - return 0; -} - -/* - * Initialisation - */ - -static void __init etherh_banner(void) -{ - static int version_printed; - - if (net_debug && version_printed++ == 0) - printk(KERN_INFO "%s", version); -} - -/* - * Read the ethernet address string from the on board rom. - * This is an ascii string... - */ -static int __init etherh_addr(char *addr, struct expansion_card *ec) -{ - struct in_chunk_dir cd; - char *s; - - if (ecard_readchunk(&cd, ec, 0xf5, 0) && (s = strchr(cd.d.string, '('))) { - int i; - for (i = 0; i < 6; i++) { - addr[i] = simple_strtoul(s + 1, &s, 0x10); - if (*s != (i == 5? ')' : ':')) - break; - } - if (i == 6) - return 0; - } - return -ENODEV; -} - -/* - * Create an ethernet address from the system serial number. - */ -static int __init etherm_addr(char *addr) -{ - unsigned int serial; - - if (system_serial_low == 0 && system_serial_high == 0) - return -ENODEV; - - serial = system_serial_low | system_serial_high; - - addr[0] = 0; - addr[1] = 0; - addr[2] = 0xa4; - addr[3] = 0x10 + (serial >> 24); - addr[4] = serial >> 16; - addr[5] = serial >> 8; - return 0; -} - -static u32 etherh_regoffsets[16]; -static u32 etherm_regoffsets[16]; - -static int __init -etherh_probe(struct expansion_card *ec, const struct ecard_id *id) -{ - struct ei_device *ei_local; - struct net_device *dev; - struct etherh_priv *eh; - const char *dev_type; - int i, size, ret; - - etherh_banner(); - - dev = init_etherdev(NULL, sizeof(struct etherh_priv)); - if (!dev) { - ret = -ENOMEM; - goto out; - } - - /* - * init_etherdev allocs and zeros dev->priv - */ - eh = dev->priv; - - spin_lock_init(&eh->eidev.page_lock); - - SET_MODULE_OWNER(dev); - - dev->open = etherh_open; - dev->stop = etherh_close; - dev->set_config = etherh_set_config; - dev->irq = ec->irq; - dev->base_addr = ecard_address(ec, ECARD_MEMC, 0); - - /* - * IRQ and control port handling - */ - if (ec->irq != 11) { - ec->ops = ðerh_ops; - ec->irq_data = eh; - } - eh->ctrl = 0; - eh->id = ec->cid.product; - - switch (ec->cid.product) { - case PROD_ANT_ETHERM: - etherm_addr(dev->dev_addr); - dev->base_addr += ETHERM_NS8390; - dev->mem_start = dev->base_addr + ETHERM_DATAPORT; - eh->ctrl_port = dev->base_addr + ETHERM_CTRLPORT; - break; - - case PROD_I3_ETHERLAN500: - etherh_addr(dev->dev_addr, ec); - dev->base_addr += ETHERH500_NS8390; - dev->mem_start = dev->base_addr + ETHERH500_DATAPORT; - eh->ctrl_port = ecard_address (ec, ECARD_IOC, ECARD_FAST) - + ETHERH500_CTRLPORT; - break; - - case PROD_I3_ETHERLAN600: - case PROD_I3_ETHERLAN600A: - etherh_addr(dev->dev_addr, ec); - dev->base_addr += ETHERH600_NS8390; - dev->mem_start = dev->base_addr + ETHERH600_DATAPORT; - eh->ctrl_port = dev->base_addr + ETHERH600_CTRLPORT; - break; - - default: - printk(KERN_ERR "%s: unknown card type %x\n", - dev->name, ec->cid.product); - ret = -ENODEV; - goto free; - } - - size = 16; - if (ec->cid.product == PROD_ANT_ETHERM) - size <<= 3; - - if (!request_region(dev->base_addr, size, dev->name)) { - ret = -EBUSY; - goto free; - } - - if (ethdev_init(dev)) { - ret = -ENODEV; - goto release; - } - - /* - * If we're in the NIC slot, make sure the IRQ is enabled - */ - if (dev->irq == 11) - etherh_set_ctrl(eh, ETHERH_CP_IE); - - /* - * Unfortunately, ethdev_init eventually calls - * ether_setup, which re-writes dev->flags. - */ - switch (ec->cid.product) { - case PROD_ANT_ETHERM: - dev_type = "ANT EtherM"; - dev->if_port = IF_PORT_UNKNOWN; - break; - - case PROD_I3_ETHERLAN500: - dev_type = "i3 EtherH 500"; - dev->if_port = IF_PORT_UNKNOWN; - break; - - case PROD_I3_ETHERLAN600: - dev_type = "i3 EtherH 600"; - dev->flags |= IFF_PORTSEL | IFF_AUTOMEDIA; - dev->if_port = IF_PORT_10BASET; - break; - - case PROD_I3_ETHERLAN600A: - dev_type = "i3 EtherH 600A"; - dev->flags |= IFF_PORTSEL | IFF_AUTOMEDIA; - dev->if_port = IF_PORT_10BASET; - break; - - default: - dev_type = "unknown"; - break; - } - - printk(KERN_INFO "%s: %s in slot %d, ", - dev->name, dev_type, ec->slot_no); - - for (i = 0; i < 6; i++) - printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':'); - - ei_local = (struct ei_device *) dev->priv; - if (ec->cid.product == PROD_ANT_ETHERM) { - ei_local->tx_start_page = ETHERM_TX_START_PAGE; - ei_local->stop_page = ETHERM_STOP_PAGE; - ei_local->reg_offset = etherm_regoffsets; - } else { - ei_local->tx_start_page = ETHERH_TX_START_PAGE; - ei_local->stop_page = ETHERH_STOP_PAGE; - ei_local->reg_offset = etherh_regoffsets; - } - - ei_local->name = dev->name; - ei_local->word16 = 1; - ei_local->rx_start_page = ei_local->tx_start_page + TX_PAGES; - ei_local->reset_8390 = etherh_reset; - ei_local->block_input = etherh_block_input; - ei_local->block_output = etherh_block_output; - ei_local->get_8390_hdr = etherh_get_header; - ei_local->interface_num = 0; - - etherh_reset(dev); - NS8390_init(dev, 0); - - ecard_set_drvdata(ec, dev); - - return 0; - -release: - release_region(dev->base_addr, 16); -free: - unregister_netdev(dev); - kfree(dev->priv); - kfree(dev); -out: - return ret; -} - -static void __devexit etherh_remove(struct expansion_card *ec) -{ - struct net_device *dev = ecard_get_drvdata(ec); - int size = 16; - - ecard_set_drvdata(ec, NULL); - - unregister_netdev(dev); - if (ec->cid.product == PROD_ANT_ETHERM) - size <<= 3; - release_region(dev->base_addr, size); - kfree(dev); - - ec->ops = NULL; - kfree(ec->irq_data); -} - -static const struct ecard_id etherh_ids[] = { - { MANU_ANT, PROD_ANT_ETHERM }, - { MANU_I3, PROD_I3_ETHERLAN500 }, - { MANU_I3, PROD_I3_ETHERLAN600 }, - { MANU_I3, PROD_I3_ETHERLAN600A }, - { 0xffff, 0xffff } -}; - -static struct ecard_driver etherh_driver = { - .probe = etherh_probe, - .remove = __devexit_p(etherh_remove), - .id_table = etherh_ids, - .drv = { - .name = "etherh", - }, -}; - -static int __init etherh_init(void) -{ - int i; - - for (i = 0; i < 16; i++) { - etherh_regoffsets[i] = i; - etherm_regoffsets[i] = i << 3; - } - - return ecard_register_driver(ðerh_driver); -} - -static void __exit etherh_exit(void) -{ - ecard_remove_driver(ðerh_driver); -} - -module_init(etherh_init); -module_exit(etherh_exit); diff -Nru a/drivers/acorn/scsi/Kconfig b/drivers/acorn/scsi/Kconfig --- a/drivers/acorn/scsi/Kconfig Sat May 24 12:48:20 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,89 +0,0 @@ -# -# SCSI driver configuration for Acorn -# -config SCSI_ACORNSCSI_3 - tristate "Acorn SCSI card (aka30) support" - depends on ARCH_ACORN && SCSI - help - This enables support for the Acorn SCSI card (aka30). If you have an - Acorn system with one of these, say Y. If unsure, say N. - -config SCSI_ACORNSCSI_TAGGED_QUEUE - bool "Support SCSI 2 Tagged queueing" - depends on SCSI_ACORNSCSI_3 - help - Say Y here to enable tagged queuing support on the Acorn SCSI card. - - This is a feature of SCSI-2 which improves performance: the host - adapter can send several SCSI commands to a device's queue even if - previous commands haven't finished yet. Some SCSI devices don't - implement this properly, so the safe answer is N. - -config SCSI_ACORNSCSI_SYNC - bool "Support SCSI 2 Synchronous Transfers" - depends on SCSI_ACORNSCSI_3 - help - Say Y here to enable synchronous transfer negotiation with all - targets on the Acorn SCSI card. - - In general, this improves performance; however some SCSI devices - don't implement it properly, so the safe answer is N. - -config SCSI_ARXESCSI - tristate "ARXE SCSI support" - depends on ARCH_ACORN && SCSI - help - Around 1991, Arxe Systems Limited released a high density floppy - disc interface for the Acorn Archimedes range, to allow the use of - HD discs from the then new A5000 on earlier models. This interface - was either sold on its own or with an integral SCSI controller. - Technical details on this NCR53c94-based device are available at - - Say Y here to compile in support for the SCSI controller. - -config SCSI_CUMANA_2 - tristate "CumanaSCSI II support" - depends on ARCH_ACORN && SCSI - help - This enables support for the Cumana SCSI II card. If you have an - Acorn system with one of these, say Y. If unsure, say N. - -config SCSI_EESOXSCSI - tristate "EESOX support" - depends on ARCH_ACORN && SCSI - help - This enables support for the EESOX SCSI card. If you have an Acorn - system with one of these, say Y, otherwise say N. - -config SCSI_POWERTECSCSI - tristate "PowerTec support" - depends on ARCH_ACORN && SCSI - help - This enables support for the Powertec SCSI card on Acorn systems. If - you have one of these, say Y. If unsure, say N. - -comment "The following drivers are not fully supported" - depends on ARCH_ACORN && EXPERIMENTAL - -config SCSI_CUMANA_1 - tristate "CumanaSCSI I support (EXPERIMENTAL)" - depends on ARCH_ACORN && EXPERIMENTAL && SCSI - help - This enables support for the Cumana SCSI I card. If you have an - Acorn system with one of these, say Y. If unsure, say N. - -config SCSI_ECOSCSI - tristate "EcoScsi support (EXPERIMENTAL)" - depends on ARCH_ACORN && EXPERIMENTAL && (ARCH_ARC || ARCH_A5K) && SCSI - help - This enables support for the EcoSCSI card -- a small card that sits - in the Econet socket. If you have an Acorn system with one of these, - say Y. If unsure, say N. - -config SCSI_OAK1 - tristate "Oak SCSI support (EXPERIMENTAL)" - depends on ARCH_ACORN && EXPERIMENTAL && SCSI - help - This enables support for the Oak SCSI card. If you have an Acorn - system with one of these, say Y. If unsure, say N. - diff -Nru a/drivers/acorn/scsi/Makefile b/drivers/acorn/scsi/Makefile --- a/drivers/acorn/scsi/Makefile Sat May 24 12:48:19 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,14 +0,0 @@ -# -# Makefile for drivers/acorn/scsi -# - -acornscsi_mod-objs := acornscsi.o acornscsi-io.o - -obj-$(CONFIG_SCSI_ACORNSCSI_3) += acornscsi_mod.o queue.o msgqueue.o -obj-$(CONFIG_SCSI_ARXESCSI) += arxescsi.o fas216.o queue.o msgqueue.o -obj-$(CONFIG_SCSI_CUMANA_1) += cumana_1.o -obj-$(CONFIG_SCSI_CUMANA_2) += cumana_2.o fas216.o queue.o msgqueue.o -obj-$(CONFIG_SCSI_ECOSCSI) += ecoscsi.o -obj-$(CONFIG_SCSI_OAK1) += oak.o -obj-$(CONFIG_SCSI_POWERTECSCSI) += powertec.o fas216.o queue.o msgqueue.o -obj-$(CONFIG_SCSI_EESOXSCSI) += eesox.o fas216.o queue.o msgqueue.o diff -Nru a/drivers/acorn/scsi/acornscsi-io.S b/drivers/acorn/scsi/acornscsi-io.S --- a/drivers/acorn/scsi/acornscsi-io.S Sat May 24 12:48:21 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,145 +0,0 @@ -/* - * linux/drivers/acorn/scsi/acornscsi-io.S: Acorn SCSI card IO - * - * 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. - */ -#include - -#include -#include - -#if (IO_BASE == (PCIO_BASE & 0xff000000)) -#define ADDR(off,reg) \ - tst off, $0x80000000 ;\ - mov reg, $IO_BASE ;\ - orreq reg, reg, $(PCIO_BASE & 0x00ff0000) -#else -#define ADDR(off,reg) \ - tst off, $0x80000000 ;\ - movne reg, $IO_BASE ;\ - moveq reg, $(PCIO_BASE & 0xff000000) ;\ - orreq reg, reg, $(PCIO_BASE & 0x00ff0000) -#endif - -@ Purpose: transfer a block of data from the acorn scsi card to memory -@ Proto : void acornscsi_in(unsigned int addr_start, char *buffer, int length) -@ Returns: nothing - - .align -ENTRY(__acornscsi_in) - stmfd sp!, {r4 - r7, lr} - bic r0, r0, #3 - mov lr, #0xff - orr lr, lr, #0xff00 -acornscsi_in16lp: - subs r2, r2, #16 - bmi acornscsi_in8 - ldmia r0!, {r3, r4, r5, r6} - and r3, r3, lr - orr r3, r3, r4, lsl #16 - and r4, r5, lr - orr r4, r4, r6, lsl #16 - ldmia r0!, {r5, r6, r7, ip} - and r5, r5, lr - orr r5, r5, r6, lsl #16 - and r6, r7, lr - orr r6, r6, ip, lsl #16 - stmia r1!, {r3 - r6} - bne acornscsi_in16lp - LOADREGS(fd, sp!, {r4 - r7, pc}) - -acornscsi_in8: adds r2, r2, #8 - bmi acornscsi_in4 - ldmia r0!, {r3, r4, r5, r6} - and r3, r3, lr - orr r3, r3, r4, lsl #16 - and r4, r5, lr - orr r4, r4, r6, lsl #16 - stmia r1!, {r3 - r4} - LOADREGS(eqfd, sp!, {r4 - r7, pc}) - sub r2, r2, #8 - -acornscsi_in4: adds r2, r2, #4 - bmi acornscsi_in2 - ldmia r0!, {r3, r4} - and r3, r3, lr - orr r3, r3, r4, lsl #16 - str r3, [r1], #4 - LOADREGS(eqfd, sp!, {r4 - r7, pc}) - sub r2, r2, #4 - -acornscsi_in2: adds r2, r2, #2 - ldr r3, [r0], #4 - and r3, r3, lr - strb r3, [r1], #1 - mov r3, r3, lsr #8 - strplb r3, [r1], #1 - LOADREGS(fd, sp!, {r4 - r7, pc}) - -@ Purpose: transfer a block of data from memory to the acorn scsi card -@ Proto : void acornscsi_in(unsigned int addr_start, char *buffer, int length) -@ Returns: nothing - -ENTRY(__acornscsi_out) - stmfd sp!, {r4 - r6, lr} - bic r0, r0, #3 -acornscsi_out16lp: - subs r2, r2, #16 - bmi acornscsi_out8 - ldmia r1!, {r4, r6, ip, lr} - mov r3, r4, lsl #16 - orr r3, r3, r3, lsr #16 - mov r4, r4, lsr #16 - orr r4, r4, r4, lsl #16 - mov r5, r6, lsl #16 - orr r5, r5, r5, lsr #16 - mov r6, r6, lsr #16 - orr r6, r6, r6, lsl #16 - stmia r0!, {r3, r4, r5, r6} - mov r3, ip, lsl #16 - orr r3, r3, r3, lsr #16 - mov r4, ip, lsr #16 - orr r4, r4, r4, lsl #16 - mov ip, lr, lsl #16 - orr ip, ip, ip, lsr #16 - mov lr, lr, lsr #16 - orr lr, lr, lr, lsl #16 - stmia r0!, {r3, r4, ip, lr} - bne acornscsi_out16lp - LOADREGS(fd, sp!, {r4 - r6, pc}) - -acornscsi_out8: adds r2, r2, #8 - bmi acornscsi_out4 - ldmia r1!, {r4, r6} - mov r3, r4, lsl #16 - orr r3, r3, r3, lsr #16 - mov r4, r4, lsr #16 - orr r4, r4, r4, lsl #16 - mov r5, r6, lsl #16 - orr r5, r5, r5, lsr #16 - mov r6, r6, lsr #16 - orr r6, r6, r6, lsl #16 - stmia r0!, {r3, r4, r5, r6} - LOADREGS(eqfd, sp!, {r4 - r6, pc}) - - sub r2, r2, #8 -acornscsi_out4: adds r2, r2, #4 - bmi acornscsi_out2 - ldr r4, [r1], #4 - mov r3, r4, lsl #16 - orr r3, r3, r3, lsr #16 - mov r4, r4, lsr #16 - orr r4, r4, r4, lsl #16 - stmia r0!, {r3, r4} - LOADREGS(eqfd, sp!, {r4 - r6, pc}) - - sub r2, r2, #4 -acornscsi_out2: adds r2, r2, #2 - ldr r3, [r1], #2 - strb r3, [r0], #1 - mov r3, r3, lsr #8 - strplb r3, [r0], #1 - LOADREGS(fd, sp!, {r4 - r6, pc}) - diff -Nru a/drivers/acorn/scsi/acornscsi.c b/drivers/acorn/scsi/acornscsi.c --- a/drivers/acorn/scsi/acornscsi.c Sat May 24 12:48:25 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,3133 +0,0 @@ -/* - * linux/drivers/acorn/scsi/acornscsi.c - * - * Acorn SCSI 3 driver - * By R.M.King. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Abandoned using the Select and Transfer command since there were - * some nasty races between our software and the target devices that - * were not easy to solve, and the device errata had a lot of entries - * for this command, some of them quite nasty... - * - * Changelog: - * 26-Sep-1997 RMK Re-jigged to use the queue module. - * Re-coded state machine to be based on driver - * state not scsi state. Should be easier to debug. - * Added acornscsi_release to clean up properly. - * Updated proc/scsi reporting. - * 05-Oct-1997 RMK Implemented writing to SCSI devices. - * 06-Oct-1997 RMK Corrected small (non-serious) bug with the connect/ - * reconnect race condition causing a warning message. - * 12-Oct-1997 RMK Added catch for re-entering interrupt routine. - * 15-Oct-1997 RMK Improved handling of commands. - * 27-Jun-1998 RMK Changed asm/delay.h to linux/delay.h. - * 13-Dec-1998 RMK Better abort code and command handling. Extra state - * transitions added to allow dodgy devices to work. - */ -#define DEBUG_NO_WRITE 1 -#define DEBUG_QUEUES 2 -#define DEBUG_DMA 4 -#define DEBUG_ABORT 8 -#define DEBUG_DISCON 16 -#define DEBUG_CONNECT 32 -#define DEBUG_PHASES 64 -#define DEBUG_WRITE 128 -#define DEBUG_LINK 256 -#define DEBUG_MESSAGES 512 -#define DEBUG_RESET 1024 -#define DEBUG_ALL (DEBUG_RESET|DEBUG_MESSAGES|DEBUG_LINK|DEBUG_WRITE|\ - DEBUG_PHASES|DEBUG_CONNECT|DEBUG_DISCON|DEBUG_ABORT|\ - DEBUG_DMA|DEBUG_QUEUES) - -/* DRIVER CONFIGURATION - * - * SCSI-II Tagged queue support. - * - * I don't have any SCSI devices that support it, so it is totally untested - * (except to make sure that it doesn't interfere with any non-tagging - * devices). It is not fully implemented either - what happens when a - * tagging device reconnects??? - * - * You can tell if you have a device that supports tagged queueing my - * cating (eg) /proc/scsi/acornscsi/0 and see if the SCSI revision is reported - * as '2 TAG'. - * - * Also note that CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE is normally set in the config - * scripts, but disabled here. Once debugged, remove the #undef, otherwise to debug, - * comment out the undef. - */ -#undef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE -/* - * SCSI-II Linked command support. - * - * The higher level code doesn't support linked commands yet, and so the option - * is undef'd here. - */ -#undef CONFIG_SCSI_ACORNSCSI_LINK -/* - * SCSI-II Synchronous transfer support. - * - * Tried and tested... - * - * SDTR_SIZE - maximum number of un-acknowledged bytes (0 = off, 12 = max) - * SDTR_PERIOD - period of REQ signal (min=125, max=1020) - * DEFAULT_PERIOD - default REQ period. - */ -#define SDTR_SIZE 12 -#define SDTR_PERIOD 125 -#define DEFAULT_PERIOD 500 - -/* - * Debugging information - * - * DEBUG - bit mask from list above - * DEBUG_TARGET - is defined to the target number if you want to debug - * a specific target. [only recon/write/dma]. - */ -#define DEBUG (DEBUG_RESET|DEBUG_WRITE|DEBUG_NO_WRITE) -/* only allow writing to SCSI device 0 */ -#define NO_WRITE 0xFE -/*#define DEBUG_TARGET 2*/ -/* - * Select timeout time (in 10ms units) - * - * This is the timeout used between the start of selection and the WD33C93 - * chip deciding that the device isn't responding. - */ -#define TIMEOUT_TIME 10 -/* - * Define this if you want to have verbose explaination of SCSI - * status/messages. - */ -#undef CONFIG_ACORNSCSI_CONSTANTS -/* - * Define this if you want to use the on board DMAC [don't remove this option] - * If not set, then use PIO mode (not currently supported). - */ -#define USE_DMAC - -/* - * ==================================================================================== - */ - -#ifdef DEBUG_TARGET -#define DBG(cmd,xxx...) \ - if (cmd->device->id == DEBUG_TARGET) { \ - xxx; \ - } -#else -#define DBG(cmd,xxx...) xxx -#endif - -#ifndef STRINGIFY -#define STRINGIFY(x) #x -#endif -#define STRx(x) STRINGIFY(x) -#define NO_WRITE_STR STRx(NO_WRITE) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "../../scsi/scsi.h" -#include "../../scsi/hosts.h" -#include "acornscsi.h" -#include "msgqueue.h" -#include "scsi.h" - -#include - -#define VER_MAJOR 2 -#define VER_MINOR 0 -#define VER_PATCH 6 - -#ifndef ABORT_TAG -#define ABORT_TAG 0xd -#else -#error "Yippee! ABORT TAG is now defined! Remove this error!" -#endif - -#ifdef CONFIG_SCSI_ACORNSCSI_LINK -#error SCSI2 LINKed commands not supported (yet)! -#endif - -#ifdef USE_DMAC -/* - * DMAC setup parameters - */ -#define INIT_DEVCON0 (DEVCON0_RQL|DEVCON0_EXW|DEVCON0_CMP) -#define INIT_DEVCON1 (DEVCON1_BHLD) -#define DMAC_READ (MODECON_READ) -#define DMAC_WRITE (MODECON_WRITE) -#define INIT_SBICDMA (CTRL_DMABURST) - -#define scsi_xferred have_data_in - -/* - * Size of on-board DMA buffer - */ -#define DMAC_BUFFER_SIZE 65536 -#endif - -#define STATUS_BUFFER_TO_PRINT 24 - -unsigned int sdtr_period = SDTR_PERIOD; -unsigned int sdtr_size = SDTR_SIZE; - -static void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result); -static int acornscsi_reconnect_finish(AS_Host *host); -static void acornscsi_dma_cleanup(AS_Host *host); -static void acornscsi_abortcmd(AS_Host *host, unsigned char tag); - -/* ==================================================================================== - * Miscellaneous - */ - -static inline void -sbic_arm_write(unsigned int io_port, int reg, int value) -{ - __raw_writeb(reg, io_port); - __raw_writeb(value, io_port + 4); -} - -#define sbic_arm_writenext(io,val) \ - __raw_writeb((val), (io) + 4) - -static inline -int sbic_arm_read(unsigned int io_port, int reg) -{ - if(reg == ASR) - return __raw_readl(io_port) & 255; - __raw_writeb(reg, io_port); - return __raw_readl(io_port + 4) & 255; -} - -#define sbic_arm_readnext(io) \ - __raw_readb((io) + 4) - -#ifdef USE_DMAC -#define dmac_read(io_port,reg) \ - inb((io_port) + (reg)) - -#define dmac_write(io_port,reg,value) \ - ({ outb((value), (io_port) + (reg)); }) - -#define dmac_clearintr(io_port) \ - ({ outb(0, (io_port)); }) - -static inline -unsigned int dmac_address(unsigned int io_port) -{ - return dmac_read(io_port, TXADRHI) << 16 | - dmac_read(io_port, TXADRMD) << 8 | - dmac_read(io_port, TXADRLO); -} - -static -void acornscsi_dumpdma(AS_Host *host, char *where) -{ - unsigned int mode, addr, len; - - mode = dmac_read(host->dma.io_port, MODECON); - addr = dmac_address(host->dma.io_port); - len = dmac_read(host->dma.io_port, TXCNTHI) << 8 | - dmac_read(host->dma.io_port, TXCNTLO); - - printk("scsi%d: %s: DMAC %02x @%06x+%04x msk %02x, ", - host->host->host_no, where, - mode, addr, (len + 1) & 0xffff, - dmac_read(host->dma.io_port, MASKREG)); - - printk("DMA @%06x, ", host->dma.start_addr); - printk("BH @%p +%04x, ", host->scsi.SCp.ptr, - host->scsi.SCp.this_residual); - printk("DT @+%04x ST @+%04x", host->dma.transferred, - host->scsi.SCp.scsi_xferred); - printk("\n"); -} -#endif - -static -unsigned long acornscsi_sbic_xfcount(AS_Host *host) -{ - unsigned long length; - - length = sbic_arm_read(host->scsi.io_port, TRANSCNTH) << 16; - length |= sbic_arm_readnext(host->scsi.io_port) << 8; - length |= sbic_arm_readnext(host->scsi.io_port); - - return length; -} - -static int -acornscsi_sbic_wait(AS_Host *host, int stat_mask, int stat, int timeout, char *msg) -{ - int asr; - - do { - asr = sbic_arm_read(host->scsi.io_port, ASR); - - if ((asr & stat_mask) == stat) - return 0; - - udelay(1); - } while (--timeout); - - printk("scsi%d: timeout while %s\n", host->host->host_no, msg); - - return -1; -} - -static -int acornscsi_sbic_issuecmd(AS_Host *host, int command) -{ - if (acornscsi_sbic_wait(host, ASR_CIP, 0, 1000, "issuing command")) - return -1; - - sbic_arm_write(host->scsi.io_port, CMND, command); - - return 0; -} - -static void -acornscsi_csdelay(unsigned int cs) -{ - unsigned long target_jiffies, flags; - - target_jiffies = jiffies + 1 + cs * HZ / 100; - - local_save_flags(flags); - local_irq_enable(); - - while (time_before(jiffies, target_jiffies)) barrier(); - - local_irq_restore(flags); -} - -static -void acornscsi_resetcard(AS_Host *host) -{ - unsigned int i, timeout; - - /* assert reset line */ - host->card.page_reg = 0x80; - outb(host->card.page_reg, host->card.io_page); - - /* wait 3 cs. SCSI standard says 25ms. */ - acornscsi_csdelay(3); - - host->card.page_reg = 0; - outb(host->card.page_reg, host->card.io_page); - - /* - * Should get a reset from the card - */ - timeout = 1000; - do { - if (inb(host->card.io_intr) & 8) - break; - udelay(1); - } while (--timeout); - - if (timeout == 0) - printk("scsi%d: timeout while resetting card\n", - host->host->host_no); - - sbic_arm_read(host->scsi.io_port, ASR); - sbic_arm_read(host->scsi.io_port, SSR); - - /* setup sbic - WD33C93A */ - sbic_arm_write(host->scsi.io_port, OWNID, OWNID_EAF | host->host->this_id); - sbic_arm_write(host->scsi.io_port, CMND, CMND_RESET); - - /* - * Command should cause a reset interrupt - */ - timeout = 1000; - do { - if (inb(host->card.io_intr) & 8) - break; - udelay(1); - } while (--timeout); - - if (timeout == 0) - printk("scsi%d: timeout while resetting card\n", - host->host->host_no); - - sbic_arm_read(host->scsi.io_port, ASR); - if (sbic_arm_read(host->scsi.io_port, SSR) != 0x01) - printk(KERN_CRIT "scsi%d: WD33C93A didn't give enhanced reset interrupt\n", - host->host->host_no); - - sbic_arm_write(host->scsi.io_port, CTRL, INIT_SBICDMA | CTRL_IDI); - sbic_arm_write(host->scsi.io_port, TIMEOUT, TIMEOUT_TIME); - sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, SYNCHTRANSFER_2DBA); - sbic_arm_write(host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP); - - host->card.page_reg = 0x40; - outb(host->card.page_reg, host->card.io_page); - - /* setup dmac - uPC71071 */ - dmac_write(host->dma.io_port, INIT, 0); -#ifdef USE_DMAC - dmac_write(host->dma.io_port, INIT, INIT_8BIT); - dmac_write(host->dma.io_port, CHANNEL, CHANNEL_0); - dmac_write(host->dma.io_port, DEVCON0, INIT_DEVCON0); - dmac_write(host->dma.io_port, DEVCON1, INIT_DEVCON1); -#endif - - host->SCpnt = NULL; - host->scsi.phase = PHASE_IDLE; - host->scsi.disconnectable = 0; - - memset(host->busyluns, 0, sizeof(host->busyluns)); - - for (i = 0; i < 8; i++) { - host->device[i].sync_state = SYNC_NEGOCIATE; - host->device[i].disconnect_ok = 1; - } - - /* wait 25 cs. SCSI standard says 250ms. */ - acornscsi_csdelay(25); -} - -/*============================================================================================= - * Utility routines (eg. debug) - */ -#ifdef CONFIG_ACORNSCSI_CONSTANTS -static char *acornscsi_interrupttype[] = { - "rst", "suc", "p/a", "3", - "term", "5", "6", "7", - "serv", "9", "a", "b", - "c", "d", "e", "f" -}; - -static signed char acornscsi_map[] = { - 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 2, -1, -1, -1, -1, 3, -1, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 14, -1, -1, -1, -1, -1, 4, 5, 6, 7, 8, 9, 10, 11, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 15, 16, 17, 18, 19, -1, -1, 20, 4, 5, 6, 7, 8, 9, 10, 11, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 21, 22, -1, -1, -1, 23, -1, -1, 4, 5, 6, 7, 8, 9, 10, 11, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 -}; - -static char *acornscsi_interruptcode[] = { - /* 0 */ - "reset - normal mode", /* 00 */ - "reset - advanced mode", /* 01 */ - - /* 2 */ - "sel", /* 11 */ - "sel+xfer", /* 16 */ - "data-out", /* 18 */ - "data-in", /* 19 */ - "cmd", /* 1A */ - "stat", /* 1B */ - "??-out", /* 1C */ - "??-in", /* 1D */ - "msg-out", /* 1E */ - "msg-in", /* 1F */ - - /* 12 */ - "/ACK asserted", /* 20 */ - "save-data-ptr", /* 21 */ - "{re}sel", /* 22 */ - - /* 15 */ - "inv cmd", /* 40 */ - "unexpected disconnect", /* 41 */ - "sel timeout", /* 42 */ - "P err", /* 43 */ - "P err+ATN", /* 44 */ - "bad status byte", /* 47 */ - - /* 21 */ - "resel, no id", /* 80 */ - "resel", /* 81 */ - "discon", /* 85 */ -}; - -static -void print_scsi_status(unsigned int ssr) -{ - if (acornscsi_map[ssr] != -1) - printk("%s:%s", - acornscsi_interrupttype[(ssr >> 4)], - acornscsi_interruptcode[acornscsi_map[ssr]]); - else - printk("%X:%X", ssr >> 4, ssr & 0x0f); -} -#endif - -static -void print_sbic_status(int asr, int ssr, int cmdphase) -{ -#ifdef CONFIG_ACORNSCSI_CONSTANTS - printk("sbic: %c%c%c%c%c%c ", - asr & ASR_INT ? 'I' : 'i', - asr & ASR_LCI ? 'L' : 'l', - asr & ASR_BSY ? 'B' : 'b', - asr & ASR_CIP ? 'C' : 'c', - asr & ASR_PE ? 'P' : 'p', - asr & ASR_DBR ? 'D' : 'd'); - printk("scsi: "); - print_scsi_status(ssr); - printk(" ph %02X\n", cmdphase); -#else - printk("sbic: %02X scsi: %X:%X ph: %02X\n", - asr, (ssr & 0xf0)>>4, ssr & 0x0f, cmdphase); -#endif -} - -static void -acornscsi_dumplogline(AS_Host *host, int target, int line) -{ - unsigned long prev; - signed int ptr; - - ptr = host->status_ptr[target] - STATUS_BUFFER_TO_PRINT; - if (ptr < 0) - ptr += STATUS_BUFFER_SIZE; - - printk("%c: %3s:", target == 8 ? 'H' : '0' + target, - line == 0 ? "ph" : line == 1 ? "ssr" : "int"); - - prev = host->status[target][ptr].when; - - for (; ptr != host->status_ptr[target]; ptr = (ptr + 1) & (STATUS_BUFFER_SIZE - 1)) { - unsigned long time_diff; - - if (!host->status[target][ptr].when) - continue; - - switch (line) { - case 0: - printk("%c%02X", host->status[target][ptr].irq ? '-' : ' ', - host->status[target][ptr].ph); - break; - - case 1: - printk(" %02X", host->status[target][ptr].ssr); - break; - - case 2: - time_diff = host->status[target][ptr].when - prev; - prev = host->status[target][ptr].when; - if (time_diff == 0) - printk("==^"); - else if (time_diff >= 100) - printk(" "); - else - printk(" %02ld", time_diff); - break; - } - } - - printk("\n"); -} - -static -void acornscsi_dumplog(AS_Host *host, int target) -{ - do { - acornscsi_dumplogline(host, target, 0); - acornscsi_dumplogline(host, target, 1); - acornscsi_dumplogline(host, target, 2); - - if (target == 8) - break; - - target = 8; - } while (1); -} - -static -char acornscsi_target(AS_Host *host) -{ - if (host->SCpnt) - return '0' + host->SCpnt->device->id; - return 'H'; -} - -/* - * Prototype: cmdtype_t acornscsi_cmdtype(int command) - * Purpose : differentiate READ from WRITE from other commands - * Params : command - command to interpret - * Returns : CMD_READ - command reads data, - * CMD_WRITE - command writes data, - * CMD_MISC - everything else - */ -static inline -cmdtype_t acornscsi_cmdtype(int command) -{ - switch (command) { - case WRITE_6: case WRITE_10: case WRITE_12: - return CMD_WRITE; - case READ_6: case READ_10: case READ_12: - return CMD_READ; - default: - return CMD_MISC; - } -} - -/* - * Prototype: int acornscsi_datadirection(int command) - * Purpose : differentiate between commands that have a DATA IN phase - * and a DATA OUT phase - * Params : command - command to interpret - * Returns : DATADIR_OUT - data out phase expected - * DATADIR_IN - data in phase expected - */ -static -datadir_t acornscsi_datadirection(int command) -{ - switch (command) { - case CHANGE_DEFINITION: case COMPARE: case COPY: - case COPY_VERIFY: case LOG_SELECT: case MODE_SELECT: - case MODE_SELECT_10: case SEND_DIAGNOSTIC: case WRITE_BUFFER: - case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE: - case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW: - case WRITE_6: case WRITE_10: case WRITE_VERIFY: - case UPDATE_BLOCK: case WRITE_LONG: case WRITE_SAME: - case SEARCH_HIGH_12: case SEARCH_EQUAL_12: case SEARCH_LOW_12: - case WRITE_12: case WRITE_VERIFY_12: case SET_WINDOW: - case MEDIUM_SCAN: case SEND_VOLUME_TAG: case 0xea: - return DATADIR_OUT; - default: - return DATADIR_IN; - } -} - -/* - * Purpose : provide values for synchronous transfers with 33C93. - * Copyright: Copyright (c) 1996 John Shifflett, GeoLog Consulting - * Modified by Russell King for 8MHz WD33C93A - */ -static struct sync_xfer_tbl { - unsigned int period_ns; - unsigned char reg_value; -} sync_xfer_table[] = { - { 1, 0x20 }, { 249, 0x20 }, { 374, 0x30 }, - { 499, 0x40 }, { 624, 0x50 }, { 749, 0x60 }, - { 874, 0x70 }, { 999, 0x00 }, { 0, 0 } -}; - -/* - * Prototype: int acornscsi_getperiod(unsigned char syncxfer) - * Purpose : period for the synchronous transfer setting - * Params : syncxfer SYNCXFER register value - * Returns : period in ns. - */ -static -int acornscsi_getperiod(unsigned char syncxfer) -{ - int i; - - syncxfer &= 0xf0; - if (syncxfer == 0x10) - syncxfer = 0; - - for (i = 1; sync_xfer_table[i].period_ns; i++) - if (syncxfer == sync_xfer_table[i].reg_value) - return sync_xfer_table[i].period_ns; - return 0; -} - -/* - * Prototype: int round_period(unsigned int period) - * Purpose : return index into above table for a required REQ period - * Params : period - time (ns) for REQ - * Returns : table index - * Copyright: Copyright (c) 1996 John Shifflett, GeoLog Consulting - */ -static inline -int round_period(unsigned int period) -{ - int i; - - for (i = 1; sync_xfer_table[i].period_ns; i++) { - if ((period <= sync_xfer_table[i].period_ns) && - (period > sync_xfer_table[i - 1].period_ns)) - return i; - } - return 7; -} - -/* - * Prototype: unsigned char calc_sync_xfer(unsigned int period, unsigned int offset) - * Purpose : calculate value for 33c93s SYNC register - * Params : period - time (ns) for REQ - * offset - offset in bytes between REQ/ACK - * Returns : value for SYNC register - * Copyright: Copyright (c) 1996 John Shifflett, GeoLog Consulting - */ -static -unsigned char calc_sync_xfer(unsigned int period, unsigned int offset) -{ - return sync_xfer_table[round_period(period)].reg_value | - ((offset < SDTR_SIZE) ? offset : SDTR_SIZE); -} - -/* ==================================================================================== - * Command functions - */ -/* - * Function: acornscsi_kick(AS_Host *host) - * Purpose : kick next command to interface - * Params : host - host to send command to - * Returns : INTR_IDLE if idle, otherwise INTR_PROCESSING - * Notes : interrupts are always disabled! - */ -static -intr_ret_t acornscsi_kick(AS_Host *host) -{ - int from_queue = 0; - Scsi_Cmnd *SCpnt; - - /* first check to see if a command is waiting to be executed */ - SCpnt = host->origSCpnt; - host->origSCpnt = NULL; - - /* retrieve next command */ - if (!SCpnt) { - SCpnt = queue_remove_exclude(&host->queues.issue, host->busyluns); - if (!SCpnt) - return INTR_IDLE; - - from_queue = 1; - } - - if (host->scsi.disconnectable && host->SCpnt) { - queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt); - host->scsi.disconnectable = 0; -#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON)) - DBG(host->SCpnt, printk("scsi%d.%c: moved command to disconnected queue\n", - host->host->host_no, acornscsi_target(host))); -#endif - host->SCpnt = NULL; - } - - /* - * If we have an interrupt pending, then we may have been reselected. - * In this case, we don't want to write to the registers - */ - if (!(sbic_arm_read(host->scsi.io_port, ASR) & (ASR_INT|ASR_BSY|ASR_CIP))) { - sbic_arm_write(host->scsi.io_port, DESTID, SCpnt->device->id); - sbic_arm_write(host->scsi.io_port, CMND, CMND_SELWITHATN); - } - - /* - * claim host busy - all of these must happen atomically wrt - * our interrupt routine. Failure means command loss. - */ - host->scsi.phase = PHASE_CONNECTING; - host->SCpnt = SCpnt; - host->scsi.SCp = SCpnt->SCp; - host->dma.xfer_setup = 0; - host->dma.xfer_required = 0; - host->dma.xfer_done = 0; - -#if (DEBUG & (DEBUG_ABORT|DEBUG_CONNECT)) - DBG(SCpnt,printk("scsi%d.%c: starting cmd %02X\n", - host->host->host_no, '0' + SCpnt->device->id, - SCpnt->cmnd[0])); -#endif - - if (from_queue) { -#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE - /* - * tagged queueing - allocate a new tag to this command - */ - if (SCpnt->device->tagged_queue) { - SCpnt->device->current_tag += 1; - if (SCpnt->device->current_tag == 0) - SCpnt->device->current_tag = 1; - SCpnt->tag = SCpnt->device->current_tag; - } else -#endif - set_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns); - - host->stats.removes += 1; - - switch (acornscsi_cmdtype(SCpnt->cmnd[0])) { - case CMD_WRITE: - host->stats.writes += 1; - break; - case CMD_READ: - host->stats.reads += 1; - break; - case CMD_MISC: - host->stats.miscs += 1; - break; - } - } - - return INTR_PROCESSING; -} - -/* - * Function: void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result) - * Purpose : complete processing for command - * Params : host - interface that completed - * result - driver byte of result - */ -static -void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result) -{ - Scsi_Cmnd *SCpnt = *SCpntp; - - /* clean up */ - sbic_arm_write(host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP); - - host->stats.fins += 1; - - if (SCpnt) { - *SCpntp = NULL; - - acornscsi_dma_cleanup(host); - - SCpnt->result = result << 16 | host->scsi.SCp.Message << 8 | host->scsi.SCp.Status; - - /* - * In theory, this should not happen. In practice, it seems to. - * Only trigger an error if the device attempts to report all happy - * but with untransferred buffers... If we don't do something, then - * data loss will occur. Should we check SCpnt->underflow here? - * It doesn't appear to be set to something meaningful by the higher - * levels all the time. - */ - if (result == DID_OK) { - int xfer_warn = 0; - - if (SCpnt->underflow == 0) { - if (host->scsi.SCp.ptr && - acornscsi_cmdtype(SCpnt->cmnd[0]) != CMD_MISC) - xfer_warn = 1; - } else { - if (host->scsi.SCp.scsi_xferred < SCpnt->underflow || - host->scsi.SCp.scsi_xferred != host->dma.transferred) - xfer_warn = 1; - } - - /* ANSI standard says: (SCSI-2 Rev 10c Sect 5.6.6) - * Targets which break data transfers into multiple - * connections shall end each successful connection - * (except possibly the last) with a SAVE DATA - * POINTER - DISCONNECT message sequence. - * - * This makes it difficult to ensure that a transfer has - * completed. If we reach the end of a transfer during - * the command, then we can only have finished the transfer. - * therefore, if we seem to have some data remaining, this - * is not a problem. - */ - if (host->dma.xfer_done) - xfer_warn = 0; - - if (xfer_warn) { - switch (status_byte(SCpnt->result)) { - case CHECK_CONDITION: - case COMMAND_TERMINATED: - case BUSY: - case QUEUE_FULL: - case RESERVATION_CONFLICT: - break; - - default: - printk(KERN_ERR "scsi%d.H: incomplete data transfer detected: result=%08X command=", - host->host->host_no, SCpnt->result); - print_command(SCpnt->cmnd); - acornscsi_dumpdma(host, "done"); - acornscsi_dumplog(host, SCpnt->device->id); - SCpnt->result &= 0xffff; - SCpnt->result |= DID_ERROR << 16; - } - } - } - - if (!SCpnt->scsi_done) - panic("scsi%d.H: null scsi_done function in acornscsi_done", host->host->host_no); - - clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns); - - SCpnt->scsi_done(SCpnt); - } else - printk("scsi%d: null command in acornscsi_done", host->host->host_no); - - host->scsi.phase = PHASE_IDLE; -} - -/* ==================================================================================== - * DMA routines - */ -/* - * Purpose : update SCSI Data Pointer - * Notes : this will only be one SG entry or less - */ -static -void acornscsi_data_updateptr(AS_Host *host, Scsi_Pointer *SCp, unsigned int length) -{ - SCp->ptr += length; - SCp->this_residual -= length; - - if (SCp->this_residual == 0 && next_SCp(SCp) == 0) - host->dma.xfer_done = 1; -} - -/* - * Prototype: void acornscsi_data_read(AS_Host *host, char *ptr, - * unsigned int start_addr, unsigned int length) - * Purpose : read data from DMA RAM - * Params : host - host to transfer from - * ptr - DRAM address - * start_addr - host mem address - * length - number of bytes to transfer - * Notes : this will only be one SG entry or less - */ -static -void acornscsi_data_read(AS_Host *host, char *ptr, - unsigned int start_addr, unsigned int length) -{ - extern void __acornscsi_in(int port, char *buf, int len); - unsigned int page, offset, len = length; - - page = (start_addr >> 12); - offset = start_addr & ((1 << 12) - 1); - - outb((page & 0x3f) | host->card.page_reg, host->card.io_page); - - while (len > 0) { - unsigned int this_len; - - if (len + offset > (1 << 12)) - this_len = (1 << 12) - offset; - else - this_len = len; - - __acornscsi_in(host->card.io_ram + (offset << 1), ptr, this_len); - - offset += this_len; - ptr += this_len; - len -= this_len; - - if (offset == (1 << 12)) { - offset = 0; - page ++; - outb((page & 0x3f) | host->card.page_reg, host->card.io_page); - } - } - outb(host->card.page_reg, host->card.io_page); -} - -/* - * Prototype: void acornscsi_data_write(AS_Host *host, char *ptr, - * unsigned int start_addr, unsigned int length) - * Purpose : write data to DMA RAM - * Params : host - host to transfer from - * ptr - DRAM address - * start_addr - host mem address - * length - number of bytes to transfer - * Notes : this will only be one SG entry or less - */ -static -void acornscsi_data_write(AS_Host *host, char *ptr, - unsigned int start_addr, unsigned int length) -{ - extern void __acornscsi_out(int port, char *buf, int len); - unsigned int page, offset, len = length; - - page = (start_addr >> 12); - offset = start_addr & ((1 << 12) - 1); - - outb((page & 0x3f) | host->card.page_reg, host->card.io_page); - - while (len > 0) { - unsigned int this_len; - - if (len + offset > (1 << 12)) - this_len = (1 << 12) - offset; - else - this_len = len; - - __acornscsi_out(host->card.io_ram + (offset << 1), ptr, this_len); - - offset += this_len; - ptr += this_len; - len -= this_len; - - if (offset == (1 << 12)) { - offset = 0; - page ++; - outb((page & 0x3f) | host->card.page_reg, host->card.io_page); - } - } - outb(host->card.page_reg, host->card.io_page); -} - -/* ========================================================================================= - * On-board DMA routines - */ -#ifdef USE_DMAC -/* - * Prototype: void acornscsi_dmastop(AS_Host *host) - * Purpose : stop all DMA - * Params : host - host on which to stop DMA - * Notes : This is called when leaving DATA IN/OUT phase, - * or when interface is RESET - */ -static inline -void acornscsi_dma_stop(AS_Host *host) -{ - dmac_write(host->dma.io_port, MASKREG, MASK_ON); - dmac_clearintr(host->dma.io_intr_clear); - -#if (DEBUG & DEBUG_DMA) - DBG(host->SCpnt, acornscsi_dumpdma(host, "stop")); -#endif -} - -/* - * Function: void acornscsi_dma_setup(AS_Host *host, dmadir_t direction) - * Purpose : setup DMA controller for data transfer - * Params : host - host to setup - * direction - data transfer direction - * Notes : This is called when entering DATA I/O phase, not - * while we're in a DATA I/O phase - */ -static -void acornscsi_dma_setup(AS_Host *host, dmadir_t direction) -{ - unsigned int address, length, mode; - - host->dma.direction = direction; - - dmac_write(host->dma.io_port, MASKREG, MASK_ON); - - if (direction == DMA_OUT) { -#if (DEBUG & DEBUG_NO_WRITE) - if (NO_WRITE & (1 << host->SCpnt->device->id)) { - printk(KERN_CRIT "scsi%d.%c: I can't handle DMA_OUT!\n", - host->host->host_no, acornscsi_target(host)); - return; - } -#endif - mode = DMAC_WRITE; - } else - mode = DMAC_READ; - - /* - * Allocate some buffer space, limited to half the buffer size - */ - length = min_t(unsigned int, host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2); - if (length) { - host->dma.start_addr = address = host->dma.free_addr; - host->dma.free_addr = (host->dma.free_addr + length) & - (DMAC_BUFFER_SIZE - 1); - - /* - * Transfer data to DMA memory - */ - if (direction == DMA_OUT) - acornscsi_data_write(host, host->scsi.SCp.ptr, host->dma.start_addr, - length); - - length -= 1; - dmac_write(host->dma.io_port, TXCNTLO, length); - dmac_write(host->dma.io_port, TXCNTHI, length >> 8); - dmac_write(host->dma.io_port, TXADRLO, address); - dmac_write(host->dma.io_port, TXADRMD, address >> 8); - dmac_write(host->dma.io_port, TXADRHI, 0); - dmac_write(host->dma.io_port, MODECON, mode); - dmac_write(host->dma.io_port, MASKREG, MASK_OFF); - -#if (DEBUG & DEBUG_DMA) - DBG(host->SCpnt, acornscsi_dumpdma(host, "strt")); -#endif - host->dma.xfer_setup = 1; - } -} - -/* - * Function: void acornscsi_dma_cleanup(AS_Host *host) - * Purpose : ensure that all DMA transfers are up-to-date & host->scsi.SCp is correct - * Params : host - host to finish - * Notes : This is called when a command is: - * terminating, RESTORE_POINTERS, SAVE_POINTERS, DISCONECT - * : This must not return until all transfers are completed. - */ -static -void acornscsi_dma_cleanup(AS_Host *host) -{ - dmac_write(host->dma.io_port, MASKREG, MASK_ON); - dmac_clearintr(host->dma.io_intr_clear); - - /* - * Check for a pending transfer - */ - if (host->dma.xfer_required) { - host->dma.xfer_required = 0; - if (host->dma.direction == DMA_IN) - acornscsi_data_read(host, host->dma.xfer_ptr, - host->dma.xfer_start, host->dma.xfer_length); - } - - /* - * Has a transfer been setup? - */ - if (host->dma.xfer_setup) { - unsigned int transferred; - - host->dma.xfer_setup = 0; - -#if (DEBUG & DEBUG_DMA) - DBG(host->SCpnt, acornscsi_dumpdma(host, "cupi")); -#endif - - /* - * Calculate number of bytes transferred from DMA. - */ - transferred = dmac_address(host->dma.io_port) - host->dma.start_addr; - host->dma.transferred += transferred; - - if (host->dma.direction == DMA_IN) - acornscsi_data_read(host, host->scsi.SCp.ptr, - host->dma.start_addr, transferred); - - /* - * Update SCSI pointers - */ - acornscsi_data_updateptr(host, &host->scsi.SCp, transferred); -#if (DEBUG & DEBUG_DMA) - DBG(host->SCpnt, acornscsi_dumpdma(host, "cupo")); -#endif - } -} - -/* - * Function: void acornscsi_dmacintr(AS_Host *host) - * Purpose : handle interrupts from DMAC device - * Params : host - host to process - * Notes : If reading, we schedule the read to main memory & - * allow the transfer to continue. - * : If writing, we fill the onboard DMA memory from main - * memory. - * : Called whenever DMAC finished it's current transfer. - */ -static -void acornscsi_dma_intr(AS_Host *host) -{ - unsigned int address, length, transferred; - -#if (DEBUG & DEBUG_DMA) - DBG(host->SCpnt, acornscsi_dumpdma(host, "inti")); -#endif - - dmac_write(host->dma.io_port, MASKREG, MASK_ON); - dmac_clearintr(host->dma.io_intr_clear); - - /* - * Calculate amount transferred via DMA - */ - transferred = dmac_address(host->dma.io_port) - host->dma.start_addr; - host->dma.transferred += transferred; - - /* - * Schedule DMA transfer off board - */ - if (host->dma.direction == DMA_IN) { - host->dma.xfer_start = host->dma.start_addr; - host->dma.xfer_length = transferred; - host->dma.xfer_ptr = host->scsi.SCp.ptr; - host->dma.xfer_required = 1; - } - - acornscsi_data_updateptr(host, &host->scsi.SCp, transferred); - - /* - * Allocate some buffer space, limited to half the on-board RAM size - */ - length = min_t(unsigned int, host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2); - if (length) { - host->dma.start_addr = address = host->dma.free_addr; - host->dma.free_addr = (host->dma.free_addr + length) & - (DMAC_BUFFER_SIZE - 1); - - /* - * Transfer data to DMA memory - */ - if (host->dma.direction == DMA_OUT) - acornscsi_data_write(host, host->scsi.SCp.ptr, host->dma.start_addr, - length); - - length -= 1; - dmac_write(host->dma.io_port, TXCNTLO, length); - dmac_write(host->dma.io_port, TXCNTHI, length >> 8); - dmac_write(host->dma.io_port, TXADRLO, address); - dmac_write(host->dma.io_port, TXADRMD, address >> 8); - dmac_write(host->dma.io_port, TXADRHI, 0); - dmac_write(host->dma.io_port, MASKREG, MASK_OFF); - -#if (DEBUG & DEBUG_DMA) - DBG(host->SCpnt, acornscsi_dumpdma(host, "into")); -#endif - } else { - host->dma.xfer_setup = 0; -#if 0 - /* - * If the interface still wants more, then this is an error. - * We give it another byte, but we also attempt to raise an - * attention condition. We continue giving one byte until - * the device recognises the attention. - */ - if (dmac_read(host->dma.io_port, STATUS) & STATUS_RQ0) { - acornscsi_abortcmd(host, host->SCpnt->tag); - - dmac_write(host->dma.io_port, TXCNTLO, 0); - dmac_write(host->dma.io_port, TXCNTHI, 0); - dmac_write(host->dma.io_port, TXADRLO, 0); - dmac_write(host->dma.io_port, TXADRMD, 0); - dmac_write(host->dma.io_port, TXADRHI, 0); - dmac_write(host->dma.io_port, MASKREG, MASK_OFF); - } -#endif - } -} - -/* - * Function: void acornscsi_dma_xfer(AS_Host *host) - * Purpose : transfer data between AcornSCSI and memory - * Params : host - host to process - */ -static -void acornscsi_dma_xfer(AS_Host *host) -{ - host->dma.xfer_required = 0; - - if (host->dma.direction == DMA_IN) - acornscsi_data_read(host, host->dma.xfer_ptr, - host->dma.xfer_start, host->dma.xfer_length); -} - -/* - * Function: void acornscsi_dma_adjust(AS_Host *host) - * Purpose : adjust DMA pointers & count for bytes transferred to - * SBIC but not SCSI bus. - * Params : host - host to adjust DMA count for - */ -static -void acornscsi_dma_adjust(AS_Host *host) -{ - if (host->dma.xfer_setup) { - signed long transferred; -#if (DEBUG & (DEBUG_DMA|DEBUG_WRITE)) - DBG(host->SCpnt, acornscsi_dumpdma(host, "adji")); -#endif - /* - * Calculate correct DMA address - DMA is ahead of SCSI bus while - * writing. - * host->scsi.SCp.scsi_xferred is the number of bytes - * actually transferred to/from the SCSI bus. - * host->dma.transferred is the number of bytes transferred - * over DMA since host->dma.start_addr was last set. - * - * real_dma_addr = host->dma.start_addr + host->scsi.SCp.scsi_xferred - * - host->dma.transferred - */ - transferred = host->scsi.SCp.scsi_xferred - host->dma.transferred; - if (transferred < 0) - printk("scsi%d.%c: Ack! DMA write correction %ld < 0!\n", - host->host->host_no, acornscsi_target(host), transferred); - else if (transferred == 0) - host->dma.xfer_setup = 0; - else { - transferred += host->dma.start_addr; - dmac_write(host->dma.io_port, TXADRLO, transferred); - dmac_write(host->dma.io_port, TXADRMD, transferred >> 8); - dmac_write(host->dma.io_port, TXADRHI, transferred >> 16); -#if (DEBUG & (DEBUG_DMA|DEBUG_WRITE)) - DBG(host->SCpnt, acornscsi_dumpdma(host, "adjo")); -#endif - } - } -} -#endif - -/* ========================================================================================= - * Data I/O - */ -static int -acornscsi_write_pio(AS_Host *host, char *bytes, int *ptr, int len, unsigned int max_timeout) -{ - unsigned int asr, timeout = max_timeout; - int my_ptr = *ptr; - - while (my_ptr < len) { - asr = sbic_arm_read(host->scsi.io_port, ASR); - - if (asr & ASR_DBR) { - timeout = max_timeout; - - sbic_arm_write(host->scsi.io_port, DATA, bytes[my_ptr++]); - } else if (asr & ASR_INT) - break; - else if (--timeout == 0) - break; - udelay(1); - } - - *ptr = my_ptr; - - return (timeout == 0) ? -1 : 0; -} - -/* - * Function: void acornscsi_sendcommand(AS_Host *host) - * Purpose : send a command to a target - * Params : host - host which is connected to target - */ -static void -acornscsi_sendcommand(AS_Host *host) -{ - Scsi_Cmnd *SCpnt = host->SCpnt; - - sbic_arm_write(host->scsi.io_port, TRANSCNTH, 0); - sbic_arm_writenext(host->scsi.io_port, 0); - sbic_arm_writenext(host->scsi.io_port, SCpnt->cmd_len - host->scsi.SCp.sent_command); - - acornscsi_sbic_issuecmd(host, CMND_XFERINFO); - - if (acornscsi_write_pio(host, SCpnt->cmnd, - (int *)&host->scsi.SCp.sent_command, SCpnt->cmd_len, 1000000)) - printk("scsi%d: timeout while sending command\n", host->host->host_no); - - host->scsi.phase = PHASE_COMMAND; -} - -static -void acornscsi_sendmessage(AS_Host *host) -{ - unsigned int message_length = msgqueue_msglength(&host->scsi.msgs); - unsigned int msgnr; - struct message *msg; - -#if (DEBUG & DEBUG_MESSAGES) - printk("scsi%d.%c: sending message ", - host->host->host_no, acornscsi_target(host)); -#endif - - switch (message_length) { - case 0: - acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT); - - acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 1"); - - sbic_arm_write(host->scsi.io_port, DATA, NOP); - - host->scsi.last_message = NOP; -#if (DEBUG & DEBUG_MESSAGES) - printk("NOP"); -#endif - break; - - case 1: - acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT); - msg = msgqueue_getmsg(&host->scsi.msgs, 0); - - acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 2"); - - sbic_arm_write(host->scsi.io_port, DATA, msg->msg[0]); - - host->scsi.last_message = msg->msg[0]; -#if (DEBUG & DEBUG_MESSAGES) - print_msg(msg->msg); -#endif - break; - - default: - /* - * ANSI standard says: (SCSI-2 Rev 10c Sect 5.6.14) - * 'When a target sends this (MESSAGE_REJECT) message, it - * shall change to MESSAGE IN phase and send this message - * prior to requesting additional message bytes from the - * initiator. This provides an interlock so that the - * initiator can determine which message byte is rejected. - */ - sbic_arm_write(host->scsi.io_port, TRANSCNTH, 0); - sbic_arm_writenext(host->scsi.io_port, 0); - sbic_arm_writenext(host->scsi.io_port, message_length); - acornscsi_sbic_issuecmd(host, CMND_XFERINFO); - - msgnr = 0; - while ((msg = msgqueue_getmsg(&host->scsi.msgs, msgnr++)) != NULL) { - unsigned int i; -#if (DEBUG & DEBUG_MESSAGES) - print_msg(msg); -#endif - i = 0; - if (acornscsi_write_pio(host, msg->msg, &i, msg->length, 1000000)) - printk("scsi%d: timeout while sending message\n", host->host->host_no); - - host->scsi.last_message = msg->msg[0]; - if (msg->msg[0] == EXTENDED_MESSAGE) - host->scsi.last_message |= msg->msg[2] << 8; - - if (i != msg->length) - break; - } - break; - } -#if (DEBUG & DEBUG_MESSAGES) - printk("\n"); -#endif -} - -/* - * Function: void acornscsi_readstatusbyte(AS_Host *host) - * Purpose : Read status byte from connected target - * Params : host - host connected to target - */ -static -void acornscsi_readstatusbyte(AS_Host *host) -{ - acornscsi_sbic_issuecmd(host, CMND_XFERINFO|CMND_SBT); - acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "reading status byte"); - host->scsi.SCp.Status = sbic_arm_read(host->scsi.io_port, DATA); -} - -/* - * Function: unsigned char acornscsi_readmessagebyte(AS_Host *host) - * Purpose : Read one message byte from connected target - * Params : host - host connected to target - */ -static -unsigned char acornscsi_readmessagebyte(AS_Host *host) -{ - unsigned char message; - - acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT); - - acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "for message byte"); - - message = sbic_arm_read(host->scsi.io_port, DATA); - - /* wait for MSGIN-XFER-PAUSED */ - acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after message byte"); - - sbic_arm_read(host->scsi.io_port, SSR); - - return message; -} - -/* - * Function: void acornscsi_message(AS_Host *host) - * Purpose : Read complete message from connected target & action message - * Params : host - host connected to target - */ -static -void acornscsi_message(AS_Host *host) -{ - unsigned char message[16]; - unsigned int msgidx = 0, msglen = 1; - - do { - message[msgidx] = acornscsi_readmessagebyte(host); - - switch (msgidx) { - case 0: - if (message[0] == EXTENDED_MESSAGE || - (message[0] >= 0x20 && message[0] <= 0x2f)) - msglen = 2; - break; - - case 1: - if (message[0] == EXTENDED_MESSAGE) - msglen += message[msgidx]; - break; - } - msgidx += 1; - if (msgidx < msglen) { - acornscsi_sbic_issuecmd(host, CMND_NEGATEACK); - - /* wait for next msg-in */ - acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after negate ack"); - sbic_arm_read(host->scsi.io_port, SSR); - } - } while (msgidx < msglen); - -#if (DEBUG & DEBUG_MESSAGES) - printk("scsi%d.%c: message in: ", - host->host->host_no, acornscsi_target(host)); - print_msg(message); - printk("\n"); -#endif - - if (host->scsi.phase == PHASE_RECONNECTED) { - /* - * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.17) - * 'Whenever a target reconnects to an initiator to continue - * a tagged I/O process, the SIMPLE QUEUE TAG message shall - * be sent immediately following the IDENTIFY message...' - */ - if (message[0] == SIMPLE_QUEUE_TAG) - host->scsi.reconnected.tag = message[1]; - if (acornscsi_reconnect_finish(host)) - host->scsi.phase = PHASE_MSGIN; - } - - switch (message[0]) { - case ABORT: - case ABORT_TAG: - case COMMAND_COMPLETE: - if (host->scsi.phase != PHASE_STATUSIN) { - printk(KERN_ERR "scsi%d.%c: command complete following non-status in phase?\n", - host->host->host_no, acornscsi_target(host)); - acornscsi_dumplog(host, host->SCpnt->device->id); - } - host->scsi.phase = PHASE_DONE; - host->scsi.SCp.Message = message[0]; - break; - - case SAVE_POINTERS: - /* - * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.20) - * 'The SAVE DATA POINTER message is sent from a target to - * direct the initiator to copy the active data pointer to - * the saved data pointer for the current I/O process. - */ - acornscsi_dma_cleanup(host); - host->SCpnt->SCp = host->scsi.SCp; - host->SCpnt->SCp.sent_command = 0; - host->scsi.phase = PHASE_MSGIN; - break; - - case RESTORE_POINTERS: - /* - * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.19) - * 'The RESTORE POINTERS message is sent from a target to - * direct the initiator to copy the most recently saved - * command, data, and status pointers for the I/O process - * to the corresponding active pointers. The command and - * status pointers shall be restored to the beginning of - * the present command and status areas.' - */ - acornscsi_dma_cleanup(host); - host->scsi.SCp = host->SCpnt->SCp; - host->scsi.phase = PHASE_MSGIN; - break; - - case DISCONNECT: - /* - * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 6.4.2) - * 'On those occasions when an error or exception condition occurs - * and the target elects to repeat the information transfer, the - * target may repeat the transfer either issuing a RESTORE POINTERS - * message or by disconnecting without issuing a SAVE POINTERS - * message. When reconnection is completed, the most recent - * saved pointer values are restored.' - */ - acornscsi_dma_cleanup(host); - host->scsi.phase = PHASE_DISCONNECT; - break; - - case MESSAGE_REJECT: -#if 0 /* this isn't needed any more */ - /* - * If we were negociating sync transfer, we don't yet know if - * this REJECT is for the sync transfer or for the tagged queue/wide - * transfer. Re-initiate sync transfer negociation now, and if - * we got a REJECT in response to SDTR, then it'll be set to DONE. - */ - if (host->device[host->SCpnt->device->id].sync_state == SYNC_SENT_REQUEST) - host->device[host->SCpnt->device->id].sync_state = SYNC_NEGOCIATE; -#endif - - /* - * If we have any messages waiting to go out, then assert ATN now - */ - if (msgqueue_msglength(&host->scsi.msgs)) - acornscsi_sbic_issuecmd(host, CMND_ASSERTATN); - - switch (host->scsi.last_message) { -#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE - case HEAD_OF_QUEUE_TAG: - case ORDERED_QUEUE_TAG: - case SIMPLE_QUEUE_TAG: - /* - * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.17) - * If a target does not implement tagged queuing and a queue tag - * message is received, it shall respond with a MESSAGE REJECT - * message and accept the I/O process as if it were untagged. - */ - printk(KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n", - host->host->host_no, acornscsi_target(host)); - host->SCpnt->device->tagged_queue = 0; - set_bit(host->SCpnt->device->id * 8 + host->SCpnt->device->lun, host->busyluns); - break; -#endif - case EXTENDED_MESSAGE | (EXTENDED_SDTR << 8): - /* - * Target can't handle synchronous transfers - */ - printk(KERN_NOTICE "scsi%d.%c: Using asynchronous transfer\n", - host->host->host_no, acornscsi_target(host)); - host->device[host->SCpnt->device->id].sync_xfer = SYNCHTRANSFER_2DBA; - host->device[host->SCpnt->device->id].sync_state = SYNC_ASYNCHRONOUS; - sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); - break; - - default: - break; - } - break; - - case QUEUE_FULL: - /* TODO: target queue is full */ - break; - - case SIMPLE_QUEUE_TAG: - /* tag queue reconnect... message[1] = queue tag. Print something to indicate something happened! */ - printk("scsi%d.%c: reconnect queue tag %02X\n", - host->host->host_no, acornscsi_target(host), - message[1]); - break; - - case EXTENDED_MESSAGE: - switch (message[2]) { -#ifdef CONFIG_SCSI_ACORNSCSI_SYNC - case EXTENDED_SDTR: - if (host->device[host->SCpnt->device->id].sync_state == SYNC_SENT_REQUEST) { - /* - * We requested synchronous transfers. This isn't quite right... - * We can only say if this succeeded if we proceed on to execute the - * command from this message. If we get a MESSAGE PARITY ERROR, - * and the target retries fail, then we fallback to asynchronous mode - */ - host->device[host->SCpnt->device->id].sync_state = SYNC_COMPLETED; - printk(KERN_NOTICE "scsi%d.%c: Using synchronous transfer, offset %d, %d ns\n", - host->host->host_no, acornscsi_target(host), - message[4], message[3] * 4); - host->device[host->SCpnt->device->id].sync_xfer = - calc_sync_xfer(message[3] * 4, message[4]); - } else { - unsigned char period, length; - /* - * Target requested synchronous transfers. The agreement is only - * to be in operation AFTER the target leaves message out phase. - */ - acornscsi_sbic_issuecmd(host, CMND_ASSERTATN); - period = max_t(unsigned int, message[3], sdtr_period / 4); - length = min_t(unsigned int, message[4], sdtr_size); - msgqueue_addmsg(&host->scsi.msgs, 5, EXTENDED_MESSAGE, 3, - EXTENDED_SDTR, period, length); - host->device[host->SCpnt->device->id].sync_xfer = - calc_sync_xfer(period * 4, length); - } - sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); - break; -#else - /* We do not accept synchronous transfers. Respond with a - * MESSAGE_REJECT. - */ -#endif - - case EXTENDED_WDTR: - /* The WD33C93A is only 8-bit. We respond with a MESSAGE_REJECT - * to a wide data transfer request. - */ - default: - acornscsi_sbic_issuecmd(host, CMND_ASSERTATN); - msgqueue_flush(&host->scsi.msgs); - msgqueue_addmsg(&host->scsi.msgs, 1, MESSAGE_REJECT); - break; - } - break; - -#ifdef CONFIG_SCSI_ACORNSCSI_LINK - case LINKED_CMD_COMPLETE: - case LINKED_FLG_CMD_COMPLETE: - /* - * We don't support linked commands yet - */ - if (0) { -#if (DEBUG & DEBUG_LINK) - printk("scsi%d.%c: lun %d tag %d linked command complete\n", - host->host->host_no, acornscsi_target(host), host->SCpnt->tag); -#endif - /* - * A linked command should only terminate with one of these messages - * if there are more linked commands available. - */ - if (!host->SCpnt->next_link) { - printk(KERN_WARNING "scsi%d.%c: lun %d tag %d linked command complete, but no next_link\n", - instance->host_no, acornscsi_target(host), host->SCpnt->tag); - acornscsi_sbic_issuecmd(host, CMND_ASSERTATN); - msgqueue_addmsg(&host->scsi.msgs, 1, ABORT); - } else { - Scsi_Cmnd *SCpnt = host->SCpnt; - - acornscsi_dma_cleanup(host); - - host->SCpnt = host->SCpnt->next_link; - host->SCpnt->tag = SCpnt->tag; - SCpnt->result = DID_OK | host->scsi.SCp.Message << 8 | host->Scsi.SCp.Status; - SCpnt->done(SCpnt); - - /* initialise host->SCpnt->SCp */ - } - break; - } -#endif - - default: /* reject message */ - printk(KERN_ERR "scsi%d.%c: unrecognised message %02X, rejecting\n", - host->host->host_no, acornscsi_target(host), - message[0]); - acornscsi_sbic_issuecmd(host, CMND_ASSERTATN); - msgqueue_flush(&host->scsi.msgs); - msgqueue_addmsg(&host->scsi.msgs, 1, MESSAGE_REJECT); - host->scsi.phase = PHASE_MSGIN; - break; - } - acornscsi_sbic_issuecmd(host, CMND_NEGATEACK); -} - -/* - * Function: int acornscsi_buildmessages(AS_Host *host) - * Purpose : build the connection messages for a host - * Params : host - host to add messages to - */ -static -void acornscsi_buildmessages(AS_Host *host) -{ -#if 0 - /* does the device need resetting? */ - if (cmd_reset) { - msgqueue_addmsg(&host->scsi.msgs, 1, BUS_DEVICE_RESET); - return; - } -#endif - - msgqueue_addmsg(&host->scsi.msgs, 1, - IDENTIFY(host->device[host->SCpnt->device->id].disconnect_ok, - host->SCpnt->device->lun)); - -#if 0 - /* does the device need the current command aborted */ - if (cmd_aborted) { - acornscsi_abortcmd(host->SCpnt->tag); - return; - } -#endif - -#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE - if (host->SCpnt->tag) { - unsigned int tag_type; - - if (host->SCpnt->cmnd[0] == REQUEST_SENSE || - host->SCpnt->cmnd[0] == TEST_UNIT_READY || - host->SCpnt->cmnd[0] == INQUIRY) - tag_type = HEAD_OF_QUEUE_TAG; - else - tag_type = SIMPLE_QUEUE_TAG; - msgqueue_addmsg(&host->scsi.msgs, 2, tag_type, host->SCpnt->tag); - } -#endif - -#ifdef CONFIG_SCSI_ACORNSCSI_SYNC - if (host->device[host->SCpnt->device->id].sync_state == SYNC_NEGOCIATE) { - host->device[host->SCpnt->device->id].sync_state = SYNC_SENT_REQUEST; - msgqueue_addmsg(&host->scsi.msgs, 5, - EXTENDED_MESSAGE, 3, EXTENDED_SDTR, - sdtr_period / 4, sdtr_size); - } -#endif -} - -/* - * Function: int acornscsi_starttransfer(AS_Host *host) - * Purpose : transfer data to/from connected target - * Params : host - host to which target is connected - * Returns : 0 if failure - */ -static -int acornscsi_starttransfer(AS_Host *host) -{ - int residual; - - if (!host->scsi.SCp.ptr /*&& host->scsi.SCp.this_residual*/) { - printk(KERN_ERR "scsi%d.%c: null buffer passed to acornscsi_starttransfer\n", - host->host->host_no, acornscsi_target(host)); - return 0; - } - - residual = host->SCpnt->request_bufflen - host->scsi.SCp.scsi_xferred; - - sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); - sbic_arm_writenext(host->scsi.io_port, residual >> 16); - sbic_arm_writenext(host->scsi.io_port, residual >> 8); - sbic_arm_writenext(host->scsi.io_port, residual); - acornscsi_sbic_issuecmd(host, CMND_XFERINFO); - return 1; -} - -/* ========================================================================================= - * Connection & Disconnection - */ -/* - * Function : acornscsi_reconnect(AS_Host *host) - * Purpose : reconnect a previously disconnected command - * Params : host - host specific data - * Remarks : SCSI spec says: - * 'The set of active pointers is restored from the set - * of saved pointers upon reconnection of the I/O process' - */ -static -int acornscsi_reconnect(AS_Host *host) -{ - unsigned int target, lun, ok = 0; - - target = sbic_arm_read(host->scsi.io_port, SOURCEID); - - if (!(target & 8)) - printk(KERN_ERR "scsi%d: invalid source id after reselection " - "- device fault?\n", - host->host->host_no); - - target &= 7; - - if (host->SCpnt && !host->scsi.disconnectable) { - printk(KERN_ERR "scsi%d.%d: reconnected while command in " - "progress to target %d?\n", - host->host->host_no, target, host->SCpnt->device->id); - host->SCpnt = NULL; - } - - lun = sbic_arm_read(host->scsi.io_port, DATA) & 7; - - host->scsi.reconnected.target = target; - host->scsi.reconnected.lun = lun; - host->scsi.reconnected.tag = 0; - - if (host->scsi.disconnectable && host->SCpnt && - host->SCpnt->device->id == target && host->SCpnt->device->lun == lun) - ok = 1; - - if (!ok && queue_probetgtlun(&host->queues.disconnected, target, lun)) - ok = 1; - - ADD_STATUS(target, 0x81, host->scsi.phase, 0); - - if (ok) { - host->scsi.phase = PHASE_RECONNECTED; - } else { - /* this doesn't seem to work */ - printk(KERN_ERR "scsi%d.%c: reselected with no command " - "to reconnect with\n", - host->host->host_no, '0' + target); - acornscsi_dumplog(host, target); - acornscsi_abortcmd(host, 0); - if (host->SCpnt) { - queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt); - host->SCpnt = NULL; - } - } - acornscsi_sbic_issuecmd(host, CMND_NEGATEACK); - return !ok; -} - -/* - * Function: int acornscsi_reconect_finish(AS_Host *host) - * Purpose : finish reconnecting a command - * Params : host - host to complete - * Returns : 0 if failed - */ -static -int acornscsi_reconnect_finish(AS_Host *host) -{ - if (host->scsi.disconnectable && host->SCpnt) { - host->scsi.disconnectable = 0; - if (host->SCpnt->device->id == host->scsi.reconnected.target && - host->SCpnt->device->lun == host->scsi.reconnected.lun && - host->SCpnt->tag == host->scsi.reconnected.tag) { -#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON)) - DBG(host->SCpnt, printk("scsi%d.%c: reconnected", - host->host->host_no, acornscsi_target(host))); -#endif - } else { - queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt); -#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON)) - DBG(host->SCpnt, printk("scsi%d.%c: had to move command " - "to disconnected queue\n", - host->host->host_no, acornscsi_target(host))); -#endif - host->SCpnt = NULL; - } - } - if (!host->SCpnt) { - host->SCpnt = queue_remove_tgtluntag(&host->queues.disconnected, - host->scsi.reconnected.target, - host->scsi.reconnected.lun, - host->scsi.reconnected.tag); -#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON)) - DBG(host->SCpnt, printk("scsi%d.%c: had to get command", - host->host->host_no, acornscsi_target(host))); -#endif - } - - if (!host->SCpnt) - acornscsi_abortcmd(host, host->scsi.reconnected.tag); - else { - /* - * Restore data pointer from SAVED pointers. - */ - host->scsi.SCp = host->SCpnt->SCp; -#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON)) - printk(", data pointers: [%p, %X]", - host->scsi.SCp.ptr, host->scsi.SCp.this_residual); -#endif - } -#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON)) - printk("\n"); -#endif - - host->dma.transferred = host->scsi.SCp.scsi_xferred; - - return host->SCpnt != NULL; -} - -/* - * Function: void acornscsi_disconnect_unexpected(AS_Host *host) - * Purpose : handle an unexpected disconnect - * Params : host - host on which disconnect occurred - */ -static -void acornscsi_disconnect_unexpected(AS_Host *host) -{ - printk(KERN_ERR "scsi%d.%c: unexpected disconnect\n", - host->host->host_no, acornscsi_target(host)); -#if (DEBUG & DEBUG_ABORT) - acornscsi_dumplog(host, 8); -#endif - - acornscsi_done(host, &host->SCpnt, DID_ERROR); -} - -/* - * Function: void acornscsi_abortcmd(AS_host *host, unsigned char tag) - * Purpose : abort a currently executing command - * Params : host - host with connected command to abort - * tag - tag to abort - */ -static -void acornscsi_abortcmd(AS_Host *host, unsigned char tag) -{ - host->scsi.phase = PHASE_ABORTED; - sbic_arm_write(host->scsi.io_port, CMND, CMND_ASSERTATN); - - msgqueue_flush(&host->scsi.msgs); -#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE - if (tag) - msgqueue_addmsg(&host->scsi.msgs, 2, ABORT_TAG, tag); - else -#endif - msgqueue_addmsg(&host->scsi.msgs, 1, ABORT); -} - -/* ========================================================================================== - * Interrupt routines. - */ -/* - * Function: int acornscsi_sbicintr(AS_Host *host) - * Purpose : handle interrupts from SCSI device - * Params : host - host to process - * Returns : INTR_PROCESS if expecting another SBIC interrupt - * INTR_IDLE if no interrupt - * INTR_NEXT_COMMAND if we have finished processing the command - */ -static -intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq) -{ - unsigned int asr, ssr; - - asr = sbic_arm_read(host->scsi.io_port, ASR); - if (!(asr & ASR_INT)) - return INTR_IDLE; - - ssr = sbic_arm_read(host->scsi.io_port, SSR); - -#if (DEBUG & DEBUG_PHASES) - print_sbic_status(asr, ssr, host->scsi.phase); -#endif - - ADD_STATUS(8, ssr, host->scsi.phase, in_irq); - - if (host->SCpnt && !host->scsi.disconnectable) - ADD_STATUS(host->SCpnt->device->id, ssr, host->scsi.phase, in_irq); - - switch (ssr) { - case 0x00: /* reset state - not advanced */ - printk(KERN_ERR "scsi%d: reset in standard mode but wanted advanced mode.\n", - host->host->host_no); - /* setup sbic - WD33C93A */ - sbic_arm_write(host->scsi.io_port, OWNID, OWNID_EAF | host->host->this_id); - sbic_arm_write(host->scsi.io_port, CMND, CMND_RESET); - return INTR_IDLE; - - case 0x01: /* reset state - advanced */ - sbic_arm_write(host->scsi.io_port, CTRL, INIT_SBICDMA | CTRL_IDI); - sbic_arm_write(host->scsi.io_port, TIMEOUT, TIMEOUT_TIME); - sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, SYNCHTRANSFER_2DBA); - sbic_arm_write(host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP); - msgqueue_flush(&host->scsi.msgs); - return INTR_IDLE; - - case 0x41: /* unexpected disconnect aborted command */ - acornscsi_disconnect_unexpected(host); - return INTR_NEXT_COMMAND; - } - - switch (host->scsi.phase) { - case PHASE_CONNECTING: /* STATE: command removed from issue queue */ - switch (ssr) { - case 0x11: /* -> PHASE_CONNECTED */ - /* BUS FREE -> SELECTION */ - host->scsi.phase = PHASE_CONNECTED; - msgqueue_flush(&host->scsi.msgs); - host->dma.transferred = host->scsi.SCp.scsi_xferred; - /* 33C93 gives next interrupt indicating bus phase */ - asr = sbic_arm_read(host->scsi.io_port, ASR); - if (!(asr & ASR_INT)) - break; - ssr = sbic_arm_read(host->scsi.io_port, SSR); - ADD_STATUS(8, ssr, host->scsi.phase, 1); - ADD_STATUS(host->SCpnt->device->id, ssr, host->scsi.phase, 1); - goto connected; - - case 0x42: /* select timed out */ - /* -> PHASE_IDLE */ - acornscsi_done(host, &host->SCpnt, DID_NO_CONNECT); - return INTR_NEXT_COMMAND; - - case 0x81: /* -> PHASE_RECONNECTED or PHASE_ABORTED */ - /* BUS FREE -> RESELECTION */ - host->origSCpnt = host->SCpnt; - host->SCpnt = NULL; - msgqueue_flush(&host->scsi.msgs); - acornscsi_reconnect(host); - break; - - default: - printk(KERN_ERR "scsi%d.%c: PHASE_CONNECTING, SSR %02X?\n", - host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); - acornscsi_abortcmd(host, host->SCpnt->tag); - } - return INTR_PROCESSING; - - connected: - case PHASE_CONNECTED: /* STATE: device selected ok */ - switch (ssr) { -#ifdef NONSTANDARD - case 0x8a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */ - /* SELECTION -> COMMAND */ - acornscsi_sendcommand(host); - break; - - case 0x8b: /* -> PHASE_STATUS */ - /* SELECTION -> STATUS */ - acornscsi_readstatusbyte(host); - host->scsi.phase = PHASE_STATUSIN; - break; -#endif - - case 0x8e: /* -> PHASE_MSGOUT */ - /* SELECTION ->MESSAGE OUT */ - host->scsi.phase = PHASE_MSGOUT; - acornscsi_buildmessages(host); - acornscsi_sendmessage(host); - break; - - /* these should not happen */ - case 0x85: /* target disconnected */ - acornscsi_done(host, &host->SCpnt, DID_ERROR); - break; - - default: - printk(KERN_ERR "scsi%d.%c: PHASE_CONNECTED, SSR %02X?\n", - host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); - acornscsi_abortcmd(host, host->SCpnt->tag); - } - return INTR_PROCESSING; - - case PHASE_MSGOUT: /* STATE: connected & sent IDENTIFY message */ - /* - * SCSI standard says that MESSAGE OUT phases can be followed by a - * DATA phase, STATUS phase, MESSAGE IN phase or COMMAND phase - */ - switch (ssr) { - case 0x8a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */ - case 0x1a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */ - /* MESSAGE OUT -> COMMAND */ - acornscsi_sendcommand(host); - break; - - case 0x8b: /* -> PHASE_STATUS */ - case 0x1b: /* -> PHASE_STATUS */ - /* MESSAGE OUT -> STATUS */ - acornscsi_readstatusbyte(host); - host->scsi.phase = PHASE_STATUSIN; - break; - - case 0x8e: /* -> PHASE_MSGOUT */ - /* MESSAGE_OUT(MESSAGE_IN) ->MESSAGE OUT */ - acornscsi_sendmessage(host); - break; - - case 0x4f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */ - case 0x1f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */ - /* MESSAGE OUT -> MESSAGE IN */ - acornscsi_message(host); - break; - - default: - printk(KERN_ERR "scsi%d.%c: PHASE_MSGOUT, SSR %02X?\n", - host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); - } - return INTR_PROCESSING; - - case PHASE_COMMAND: /* STATE: connected & command sent */ - switch (ssr) { - case 0x18: /* -> PHASE_DATAOUT */ - /* COMMAND -> DATA OUT */ - if (host->scsi.SCp.sent_command != host->SCpnt->cmd_len) - acornscsi_abortcmd(host, host->SCpnt->tag); - acornscsi_dma_setup(host, DMA_OUT); - if (!acornscsi_starttransfer(host)) - acornscsi_abortcmd(host, host->SCpnt->tag); - host->scsi.phase = PHASE_DATAOUT; - return INTR_IDLE; - - case 0x19: /* -> PHASE_DATAIN */ - /* COMMAND -> DATA IN */ - if (host->scsi.SCp.sent_command != host->SCpnt->cmd_len) - acornscsi_abortcmd(host, host->SCpnt->tag); - acornscsi_dma_setup(host, DMA_IN); - if (!acornscsi_starttransfer(host)) - acornscsi_abortcmd(host, host->SCpnt->tag); - host->scsi.phase = PHASE_DATAIN; - return INTR_IDLE; - - case 0x1b: /* -> PHASE_STATUS */ - /* COMMAND -> STATUS */ - acornscsi_readstatusbyte(host); - host->scsi.phase = PHASE_STATUSIN; - break; - - case 0x1e: /* -> PHASE_MSGOUT */ - /* COMMAND -> MESSAGE OUT */ - acornscsi_sendmessage(host); - break; - - case 0x1f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */ - /* COMMAND -> MESSAGE IN */ - acornscsi_message(host); - break; - - default: - printk(KERN_ERR "scsi%d.%c: PHASE_COMMAND, SSR %02X?\n", - host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); - } - return INTR_PROCESSING; - - case PHASE_DISCONNECT: /* STATE: connected, received DISCONNECT msg */ - if (ssr == 0x85) { /* -> PHASE_IDLE */ - host->scsi.disconnectable = 1; - host->scsi.reconnected.tag = 0; - host->scsi.phase = PHASE_IDLE; - host->stats.disconnects += 1; - } else { - printk(KERN_ERR "scsi%d.%c: PHASE_DISCONNECT, SSR %02X instead of disconnect?\n", - host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); - } - return INTR_NEXT_COMMAND; - - case PHASE_IDLE: /* STATE: disconnected */ - if (ssr == 0x81) /* -> PHASE_RECONNECTED or PHASE_ABORTED */ - acornscsi_reconnect(host); - else { - printk(KERN_ERR "scsi%d.%c: PHASE_IDLE, SSR %02X while idle?\n", - host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); - } - return INTR_PROCESSING; - - case PHASE_RECONNECTED: /* STATE: device reconnected to initiator */ - /* - * Command reconnected - if MESGIN, get message - it may be - * the tag. If not, get command out of disconnected queue - */ - /* - * If we reconnected and we're not in MESSAGE IN phase after IDENTIFY, - * reconnect I_T_L command - */ - if (ssr != 0x8f && !acornscsi_reconnect_finish(host)) - return INTR_IDLE; - ADD_STATUS(host->SCpnt->device->id, ssr, host->scsi.phase, in_irq); - switch (ssr) { - case 0x88: /* data out phase */ - /* -> PHASE_DATAOUT */ - /* MESSAGE IN -> DATA OUT */ - acornscsi_dma_setup(host, DMA_OUT); - if (!acornscsi_starttransfer(host)) - acornscsi_abortcmd(host, host->SCpnt->tag); - host->scsi.phase = PHASE_DATAOUT; - return INTR_IDLE; - - case 0x89: /* data in phase */ - /* -> PHASE_DATAIN */ - /* MESSAGE IN -> DATA IN */ - acornscsi_dma_setup(host, DMA_IN); - if (!acornscsi_starttransfer(host)) - acornscsi_abortcmd(host, host->SCpnt->tag); - host->scsi.phase = PHASE_DATAIN; - return INTR_IDLE; - - case 0x8a: /* command out */ - /* MESSAGE IN -> COMMAND */ - acornscsi_sendcommand(host);/* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */ - break; - - case 0x8b: /* status in */ - /* -> PHASE_STATUSIN */ - /* MESSAGE IN -> STATUS */ - acornscsi_readstatusbyte(host); - host->scsi.phase = PHASE_STATUSIN; - break; - - case 0x8e: /* message out */ - /* -> PHASE_MSGOUT */ - /* MESSAGE IN -> MESSAGE OUT */ - acornscsi_sendmessage(host); - break; - - case 0x8f: /* message in */ - acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */ - break; - - default: - printk(KERN_ERR "scsi%d.%c: PHASE_RECONNECTED, SSR %02X after reconnect?\n", - host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); - } - return INTR_PROCESSING; - - case PHASE_DATAIN: /* STATE: transferred data in */ - /* - * This is simple - if we disconnect then the DMA address & count is - * correct. - */ - switch (ssr) { - case 0x19: /* -> PHASE_DATAIN */ - case 0x89: /* -> PHASE_DATAIN */ - acornscsi_abortcmd(host, host->SCpnt->tag); - return INTR_IDLE; - - case 0x1b: /* -> PHASE_STATUSIN */ - case 0x4b: /* -> PHASE_STATUSIN */ - case 0x8b: /* -> PHASE_STATUSIN */ - /* DATA IN -> STATUS */ - host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - - acornscsi_sbic_xfcount(host); - acornscsi_dma_stop(host); - acornscsi_readstatusbyte(host); - host->scsi.phase = PHASE_STATUSIN; - break; - - case 0x1e: /* -> PHASE_MSGOUT */ - case 0x4e: /* -> PHASE_MSGOUT */ - case 0x8e: /* -> PHASE_MSGOUT */ - /* DATA IN -> MESSAGE OUT */ - host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - - acornscsi_sbic_xfcount(host); - acornscsi_dma_stop(host); - acornscsi_sendmessage(host); - break; - - case 0x1f: /* message in */ - case 0x4f: /* message in */ - case 0x8f: /* message in */ - /* DATA IN -> MESSAGE IN */ - host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - - acornscsi_sbic_xfcount(host); - acornscsi_dma_stop(host); - acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */ - break; - - default: - printk(KERN_ERR "scsi%d.%c: PHASE_DATAIN, SSR %02X?\n", - host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); - } - return INTR_PROCESSING; - - case PHASE_DATAOUT: /* STATE: transferred data out */ - /* - * This is more complicated - if we disconnect, the DMA could be 12 - * bytes ahead of us. We need to correct this. - */ - switch (ssr) { - case 0x18: /* -> PHASE_DATAOUT */ - case 0x88: /* -> PHASE_DATAOUT */ - acornscsi_abortcmd(host, host->SCpnt->tag); - return INTR_IDLE; - - case 0x1b: /* -> PHASE_STATUSIN */ - case 0x4b: /* -> PHASE_STATUSIN */ - case 0x8b: /* -> PHASE_STATUSIN */ - /* DATA OUT -> STATUS */ - host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - - acornscsi_sbic_xfcount(host); - acornscsi_dma_stop(host); - acornscsi_dma_adjust(host); - acornscsi_readstatusbyte(host); - host->scsi.phase = PHASE_STATUSIN; - break; - - case 0x1e: /* -> PHASE_MSGOUT */ - case 0x4e: /* -> PHASE_MSGOUT */ - case 0x8e: /* -> PHASE_MSGOUT */ - /* DATA OUT -> MESSAGE OUT */ - host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - - acornscsi_sbic_xfcount(host); - acornscsi_dma_stop(host); - acornscsi_dma_adjust(host); - acornscsi_sendmessage(host); - break; - - case 0x1f: /* message in */ - case 0x4f: /* message in */ - case 0x8f: /* message in */ - /* DATA OUT -> MESSAGE IN */ - host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - - acornscsi_sbic_xfcount(host); - acornscsi_dma_stop(host); - acornscsi_dma_adjust(host); - acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */ - break; - - default: - printk(KERN_ERR "scsi%d.%c: PHASE_DATAOUT, SSR %02X?\n", - host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); - } - return INTR_PROCESSING; - - case PHASE_STATUSIN: /* STATE: status in complete */ - switch (ssr) { - case 0x1f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */ - case 0x8f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */ - /* STATUS -> MESSAGE IN */ - acornscsi_message(host); - break; - - case 0x1e: /* -> PHASE_MSGOUT */ - case 0x8e: /* -> PHASE_MSGOUT */ - /* STATUS -> MESSAGE OUT */ - acornscsi_sendmessage(host); - break; - - default: - printk(KERN_ERR "scsi%d.%c: PHASE_STATUSIN, SSR %02X instead of MESSAGE_IN?\n", - host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); - } - return INTR_PROCESSING; - - case PHASE_MSGIN: /* STATE: message in */ - switch (ssr) { - case 0x1e: /* -> PHASE_MSGOUT */ - case 0x4e: /* -> PHASE_MSGOUT */ - case 0x8e: /* -> PHASE_MSGOUT */ - /* MESSAGE IN -> MESSAGE OUT */ - acornscsi_sendmessage(host); - break; - - case 0x1f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */ - case 0x2f: - case 0x4f: - case 0x8f: - acornscsi_message(host); - break; - - case 0x85: - printk("scsi%d.%c: strange message in disconnection\n", - host->host->host_no, acornscsi_target(host)); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); - acornscsi_done(host, &host->SCpnt, DID_ERROR); - break; - - default: - printk(KERN_ERR "scsi%d.%c: PHASE_MSGIN, SSR %02X after message in?\n", - host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); - } - return INTR_PROCESSING; - - case PHASE_DONE: /* STATE: received status & message */ - switch (ssr) { - case 0x85: /* -> PHASE_IDLE */ - acornscsi_done(host, &host->SCpnt, DID_OK); - return INTR_NEXT_COMMAND; - - case 0x1e: - case 0x8e: - acornscsi_sendmessage(host); - break; - - default: - printk(KERN_ERR "scsi%d.%c: PHASE_DONE, SSR %02X instead of disconnect?\n", - host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); - } - return INTR_PROCESSING; - - case PHASE_ABORTED: - switch (ssr) { - case 0x85: - if (host->SCpnt) - acornscsi_done(host, &host->SCpnt, DID_ABORT); - else { - clear_bit(host->scsi.reconnected.target * 8 + host->scsi.reconnected.lun, - host->busyluns); - host->scsi.phase = PHASE_IDLE; - } - return INTR_NEXT_COMMAND; - - case 0x1e: - case 0x2e: - case 0x4e: - case 0x8e: - acornscsi_sendmessage(host); - break; - - default: - printk(KERN_ERR "scsi%d.%c: PHASE_ABORTED, SSR %02X?\n", - host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); - } - return INTR_PROCESSING; - - default: - printk(KERN_ERR "scsi%d.%c: unknown driver phase %d\n", - host->host->host_no, acornscsi_target(host), ssr); - acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); - } - return INTR_PROCESSING; -} - -/* - * Prototype: void acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs) - * Purpose : handle interrupts from Acorn SCSI card - * Params : irq - interrupt number - * dev_id - device specific data (AS_Host structure) - * regs - processor registers when interrupt occurred - */ -static -void acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - AS_Host *host = (AS_Host *)dev_id; - intr_ret_t ret; - int iostatus; - int in_irq = 0; - - if (host->scsi.interrupt) - printk("scsi%d: interrupt re-entered\n", host->host->host_no); - host->scsi.interrupt = 1; - - do { - ret = INTR_IDLE; - - iostatus = inb(host->card.io_intr); - - if (iostatus & 2) { - acornscsi_dma_intr(host); - iostatus = inb(host->card.io_intr); - } - - if (iostatus & 8) - ret = acornscsi_sbicintr(host, in_irq); - - /* - * If we have a transfer pending, start it. - * Only start it if the interface has already started transferring - * it's data - */ - if (host->dma.xfer_required) - acornscsi_dma_xfer(host); - - if (ret == INTR_NEXT_COMMAND) - ret = acornscsi_kick(host); - - in_irq = 1; - } while (ret != INTR_IDLE); - - host->scsi.interrupt = 0; -} - -/*============================================================================================= - * Interfaces between interrupt handler and rest of scsi code - */ - -/* - * Function : acornscsi_queuecmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) - * Purpose : queues a SCSI command - * Params : cmd - SCSI command - * done - function called on completion, with pointer to command descriptor - * Returns : 0, or < 0 on error. - */ -int acornscsi_queuecmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) -{ - AS_Host *host = (AS_Host *)SCpnt->device->host->hostdata; - - if (!done) { - /* there should be some way of rejecting errors like this without panicing... */ - panic("scsi%d: queuecommand called with NULL done function [cmd=%p]", - host->host->host_no, SCpnt); - return -EINVAL; - } - -#if (DEBUG & DEBUG_NO_WRITE) - if (acornscsi_cmdtype(SCpnt->cmnd[0]) == CMD_WRITE && (NO_WRITE & (1 << SCpnt->device->id))) { - printk(KERN_CRIT "scsi%d.%c: WRITE attempted with NO_WRITE flag set\n", - host->host->host_no, '0' + SCpnt->device->id); - SCpnt->result = DID_NO_CONNECT << 16; - done(SCpnt); - return 0; - } -#endif - - SCpnt->scsi_done = done; - SCpnt->host_scribble = NULL; - SCpnt->result = 0; - SCpnt->tag = 0; - SCpnt->SCp.phase = (int)acornscsi_datadirection(SCpnt->cmnd[0]); - SCpnt->SCp.sent_command = 0; - SCpnt->SCp.scsi_xferred = 0; - - init_SCp(SCpnt); - - host->stats.queues += 1; - - { - unsigned long flags; - - if (!queue_add_cmd_ordered(&host->queues.issue, SCpnt)) { - SCpnt->result = DID_ERROR << 16; - done(SCpnt); - return 0; - } - local_irq_save(flags); - if (host->scsi.phase == PHASE_IDLE) - acornscsi_kick(host); - local_irq_restore(flags); - } - return 0; -} - -/* - * Prototype: void acornscsi_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result) - * Purpose : pass a result to *SCpntp1, and check if *SCpntp1 = *SCpntp2 - * Params : SCpntp1 - pointer to command to return - * SCpntp2 - pointer to command to check - * result - result to pass back to mid-level done function - * Returns : *SCpntp2 = NULL if *SCpntp1 is the same command structure as *SCpntp2. - */ -static inline -void acornscsi_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result) -{ - Scsi_Cmnd *SCpnt = *SCpntp1; - - if (SCpnt) { - *SCpntp1 = NULL; - - SCpnt->result = result; - SCpnt->scsi_done(SCpnt); - } - - if (SCpnt == *SCpntp2) - *SCpntp2 = NULL; -} - -enum res_abort { res_not_running, res_success, res_success_clear, res_snooze }; - -/* - * Prototype: enum res acornscsi_do_abort(Scsi_Cmnd *SCpnt) - * Purpose : abort a command on this host - * Params : SCpnt - command to abort - * Returns : our abort status - */ -static enum res_abort -acornscsi_do_abort(AS_Host *host, Scsi_Cmnd *SCpnt) -{ - enum res_abort res = res_not_running; - - if (queue_remove_cmd(&host->queues.issue, SCpnt)) { - /* - * The command was on the issue queue, and has not been - * issued yet. We can remove the command from the queue, - * and acknowledge the abort. Neither the devices nor the - * interface know about the command. - */ -//#if (DEBUG & DEBUG_ABORT) - printk("on issue queue "); -//#endif - res = res_success; - } else if (queue_remove_cmd(&host->queues.disconnected, SCpnt)) { - /* - * The command was on the disconnected queue. Simply - * acknowledge the abort condition, and when the target - * reconnects, we will give it an ABORT message. The - * target should then disconnect, and we will clear - * the busylun bit. - */ -//#if (DEBUG & DEBUG_ABORT) - printk("on disconnected queue "); -//#endif - res = res_success; - } else if (host->SCpnt == SCpnt) { - unsigned long flags; - -//#if (DEBUG & DEBUG_ABORT) - printk("executing "); -//#endif - - local_irq_save(flags); - switch (host->scsi.phase) { - /* - * If the interface is idle, and the command is 'disconnectable', - * then it is the same as on the disconnected queue. We simply - * remove all traces of the command. When the target reconnects, - * we will give it an ABORT message since the command could not - * be found. When the target finally disconnects, we will clear - * the busylun bit. - */ - case PHASE_IDLE: - if (host->scsi.disconnectable) { - host->scsi.disconnectable = 0; - host->SCpnt = NULL; - res = res_success; - } - break; - - /* - * If the command has connected and done nothing further, - * simply force a disconnect. We also need to clear the - * busylun bit. - */ - case PHASE_CONNECTED: - sbic_arm_write(host->scsi.io_port, CMND, CMND_DISCONNECT); - host->SCpnt = NULL; - res = res_success_clear; - break; - - default: - acornscsi_abortcmd(host, host->SCpnt->tag); - res = res_snooze; - } - local_irq_restore(flags); - } else if (host->origSCpnt == SCpnt) { - /* - * The command will be executed next, but a command - * is currently using the interface. This is similar to - * being on the issue queue, except the busylun bit has - * been set. - */ - host->origSCpnt = NULL; -//#if (DEBUG & DEBUG_ABORT) - printk("waiting for execution "); -//#endif - res = res_success_clear; - } else - printk("unknown "); - - return res; -} - -/* - * Prototype: int acornscsi_abort(Scsi_Cmnd *SCpnt) - * Purpose : abort a command on this host - * Params : SCpnt - command to abort - * Returns : one of SCSI_ABORT_ macros - */ -int acornscsi_abort(Scsi_Cmnd *SCpnt) -{ - AS_Host *host = (AS_Host *) SCpnt->device->host->hostdata; - int result; - - host->stats.aborts += 1; - -#if (DEBUG & DEBUG_ABORT) - { - int asr, ssr; - asr = sbic_arm_read(host->scsi.io_port, ASR); - ssr = sbic_arm_read(host->scsi.io_port, SSR); - - printk(KERN_WARNING "acornscsi_abort: "); - print_sbic_status(asr, ssr, host->scsi.phase); - acornscsi_dumplog(host, SCpnt->device->id); - } -#endif - - printk("scsi%d: ", host->host->host_no); - - switch (acornscsi_do_abort(host, SCpnt)) { - /* - * We managed to find the command and cleared it out. - * We do not expect the command to be executing on the - * target, but we have set the busylun bit. - */ - case res_success_clear: -//#if (DEBUG & DEBUG_ABORT) - printk("clear "); -//#endif - clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns); - - /* - * We found the command, and cleared it out. Either - * the command is still known to be executing on the - * target, or the busylun bit is not set. - */ - case res_success: -//#if (DEBUG & DEBUG_ABORT) - printk("success\n"); -//#endif - SCpnt->result = DID_ABORT << 16; - SCpnt->scsi_done(SCpnt); - result = SCSI_ABORT_SUCCESS; - break; - - /* - * We did find the command, but unfortunately we couldn't - * unhook it from ourselves. Wait some more, and if it - * still doesn't complete, reset the interface. - */ - case res_snooze: -//#if (DEBUG & DEBUG_ABORT) - printk("snooze\n"); -//#endif - result = SCSI_ABORT_SNOOZE; - break; - - /* - * The command could not be found (either because it completed, - * or it got dropped. - */ - default: - case res_not_running: - acornscsi_dumplog(host, SCpnt->device->id); -#if (DEBUG & DEBUG_ABORT) - result = SCSI_ABORT_SNOOZE; -#else - result = SCSI_ABORT_NOT_RUNNING; -#endif -//#if (DEBUG & DEBUG_ABORT) - printk("not running\n"); -//#endif - break; - } - - return result; -} - -/* - * Prototype: int acornscsi_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags) - * Purpose : reset a command on this host/reset this host - * Params : SCpnt - command causing reset - * result - what type of reset to perform - * Returns : one of SCSI_RESET_ macros - */ -int acornscsi_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags) -{ - AS_Host *host = (AS_Host *)SCpnt->device->host->hostdata; - Scsi_Cmnd *SCptr; - - host->stats.resets += 1; - -#if (DEBUG & DEBUG_RESET) - { - int asr, ssr; - - asr = sbic_arm_read(host->scsi.io_port, ASR); - ssr = sbic_arm_read(host->scsi.io_port, SSR); - - printk(KERN_WARNING "acornscsi_reset: "); - print_sbic_status(asr, ssr, host->scsi.phase); - acornscsi_dumplog(host, SCpnt->device->id); - } -#endif - - acornscsi_dma_stop(host); - - SCptr = host->SCpnt; - - /* - * do hard reset. This resets all devices on this host, and so we - * must set the reset status on all commands. - */ - acornscsi_resetcard(host); - - /* - * report reset on commands current connected/disconnected - */ - acornscsi_reportstatus(&host->SCpnt, &SCptr, DID_RESET); - - while ((SCptr = queue_remove(&host->queues.disconnected)) != NULL) - acornscsi_reportstatus(&SCptr, &SCpnt, DID_RESET); - - if (SCpnt) { - SCpnt->result = DID_RESET << 16; - SCpnt->scsi_done(SCpnt); - } - - return SCSI_RESET_BUS_RESET | SCSI_RESET_HOST_RESET | SCSI_RESET_SUCCESS; -} - -/*============================================================================================== - * initialisation & miscellaneous support - */ - -/* - * Function: char *acornscsi_info(struct Scsi_Host *host) - * Purpose : return a string describing this interface - * Params : host - host to give information on - * Returns : a constant string - */ -const -char *acornscsi_info(struct Scsi_Host *host) -{ - static char string[100], *p; - - p = string; - - p += sprintf(string, "%s at port %08lX irq %d v%d.%d.%d" -#ifdef CONFIG_SCSI_ACORNSCSI_SYNC - " SYNC" -#endif -#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE - " TAG" -#endif -#ifdef CONFIG_SCSI_ACORNSCSI_LINK - " LINK" -#endif -#if (DEBUG & DEBUG_NO_WRITE) - " NOWRITE ("NO_WRITE_STR")" -#endif - , host->hostt->name, host->io_port, host->irq, - VER_MAJOR, VER_MINOR, VER_PATCH); - return string; -} - -int acornscsi_proc_info(char *buffer, char **start, off_t offset, - int length, int host_no, int inout) -{ - int pos, begin = 0, devidx; - struct Scsi_Host *instance; - Scsi_Device *scd; - AS_Host *host; - char *p = buffer; - - instance = scsi_host_hn_get(host_no); - - if (inout == 1 || !instance) - return -EINVAL; - - host = (AS_Host *)instance->hostdata; - - p += sprintf(p, "AcornSCSI driver v%d.%d.%d" -#ifdef CONFIG_SCSI_ACORNSCSI_SYNC - " SYNC" -#endif -#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE - " TAG" -#endif -#ifdef CONFIG_SCSI_ACORNSCSI_LINK - " LINK" -#endif -#if (DEBUG & DEBUG_NO_WRITE) - " NOWRITE ("NO_WRITE_STR")" -#endif - "\n\n", VER_MAJOR, VER_MINOR, VER_PATCH); - - p += sprintf(p, "SBIC: WD33C93A Address: %08X IRQ : %d\n", - host->scsi.io_port, host->scsi.irq); -#ifdef USE_DMAC - p += sprintf(p, "DMAC: uPC71071 Address: %08X IRQ : %d\n\n", - host->dma.io_port, host->scsi.irq); -#endif - - p += sprintf(p, "Statistics:\n" - "Queued commands: %-10u Issued commands: %-10u\n" - "Done commands : %-10u Reads : %-10u\n" - "Writes : %-10u Others : %-10u\n" - "Disconnects : %-10u Aborts : %-10u\n" - "Resets : %-10u\n\nLast phases:", - host->stats.queues, host->stats.removes, - host->stats.fins, host->stats.reads, - host->stats.writes, host->stats.miscs, - host->stats.disconnects, host->stats.aborts, - host->stats.resets); - - for (devidx = 0; devidx < 9; devidx ++) { - unsigned int statptr, prev; - - p += sprintf(p, "\n%c:", devidx == 8 ? 'H' : ('0' + devidx)); - statptr = host->status_ptr[devidx] - 10; - - if ((signed int)statptr < 0) - statptr += STATUS_BUFFER_SIZE; - - prev = host->status[devidx][statptr].when; - - for (; statptr != host->status_ptr[devidx]; statptr = (statptr + 1) & (STATUS_BUFFER_SIZE - 1)) { - if (host->status[devidx][statptr].when) { - p += sprintf(p, "%c%02X:%02X+%2ld", - host->status[devidx][statptr].irq ? '-' : ' ', - host->status[devidx][statptr].ph, - host->status[devidx][statptr].ssr, - (host->status[devidx][statptr].when - prev) < 100 ? - (host->status[devidx][statptr].when - prev) : 99); - prev = host->status[devidx][statptr].when; - } - } - } - - p += sprintf(p, "\nAttached devices:\n"); - - list_for_each_entry(scd, &instance->my_devices, siblings) { - int len; - - proc_print_scsidevice(scd, p, &len, 0); - p += len; - - p += sprintf(p, "Extensions: "); - - if (scd->tagged_supported) - p += sprintf(p, "TAG %sabled [%d] ", - scd->tagged_queue ? "en" : "dis", scd->current_tag); - p += sprintf(p, "\nTransfers: "); - if (host->device[scd->id].sync_xfer & 15) - p += sprintf(p, "sync, offset %d, %d ns\n", - host->device[scd->id].sync_xfer & 15, - acornscsi_getperiod(host->device[scd->id].sync_xfer)); - else - p += sprintf(p, "async\n"); - - pos = p - buffer; - if (pos + begin < offset) { - begin += pos; - p = buffer; - } - pos = p - buffer; - if (pos + begin > offset + length) - break; - } - - pos = p - buffer; - - *start = buffer + (offset - begin); - pos -= offset - begin; - - if (pos > length) - pos = length; - - return pos; -} - -static Scsi_Host_Template acornscsi_template = { - .module = THIS_MODULE, - .proc_info = acornscsi_proc_info, - .name = "AcornSCSI", - .info = acornscsi_info, - .queuecommand = acornscsi_queuecmd, -#warning fixme - .abort = acornscsi_abort, - .reset = acornscsi_reset, - .can_queue = 16, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 2, - .unchecked_isa_dma = 0, - .use_clustering = DISABLE_CLUSTERING, - .proc_name = "acornscsi", -}; - -static int __devinit -acornscsi_probe(struct expansion_card *ec, const struct ecard_id *id) -{ - struct Scsi_Host *host; - AS_Host *ashost; - int ret = -ENOMEM; - - host = scsi_register(&acornscsi_template, sizeof(AS_Host)); - if (!host) - goto out; - - ashost = (AS_Host *)host->hostdata; - - host->io_port = ecard_address(ec, ECARD_MEMC, 0); - host->irq = ec->irq; - - ashost->host = host; - ashost->scsi.io_port = ioaddr(host->io_port + 0x800); - ashost->scsi.irq = host->irq; - ashost->card.io_intr = POD_SPACE(host->io_port) + 0x800; - ashost->card.io_page = POD_SPACE(host->io_port) + 0xc00; - ashost->card.io_ram = ioaddr(host->io_port); - ashost->dma.io_port = host->io_port + 0xc00; - ashost->dma.io_intr_clear = POD_SPACE(host->io_port) + 0x800; - - ec->irqaddr = (char *)ioaddr(ashost->card.io_intr); - ec->irqmask = 0x0a; - - ret = -EBUSY; - if (!request_region(host->io_port + 0x800, 2, "acornscsi(sbic)")) - goto err_1; - if (!request_region(ashost->card.io_intr, 1, "acornscsi(intr)")) - goto err_2; - if (!request_region(ashost->card.io_page, 1, "acornscsi(page)")) - goto err_3; -#ifdef USE_DMAC - if (!request_region(ashost->dma.io_port, 256, "acornscsi(dmac)")) - goto err_4; -#endif - if (!request_region(host->io_port, 2048, "acornscsi(ram)")) - goto err_5; - - ret = request_irq(host->irq, acornscsi_intr, SA_INTERRUPT, "acornscsi", ashost); - if (ret) { - printk(KERN_CRIT "scsi%d: IRQ%d not free: %d\n", - host->host_no, ashost->scsi.irq, ret); - goto err_6; - } - - memset(&ashost->stats, 0, sizeof (ashost->stats)); - queue_initialise(&ashost->queues.issue); - queue_initialise(&ashost->queues.disconnected); - msgqueue_initialise(&ashost->scsi.msgs); - - acornscsi_resetcard(ashost); - - ret = scsi_add_host(host, &ec->dev); - if (ret == 0) - goto out; - - free_irq(host->irq, ashost); - err_6: - release_region(host->io_port, 2048); - err_5: -#ifdef USE_DMAC - release_region(ashost->dma.io_port, 256); -#endif - err_4: - release_region(ashost->card.io_page, 1); - err_3: - release_region(ashost->card.io_intr, 1); - err_2: - release_region(host->io_port + 0x800, 2); - err_1: - scsi_unregister(host); - out: - return ret; -} - -static void __devexit acornscsi_remove(struct expansion_card *ec) -{ - struct Scsi_Host *host = ecard_get_drvdata(ec); - AS_Host *ashost = (AS_Host *)host->hostdata; - - ecard_set_drvdata(ec, NULL); - scsi_remove_host(host); - - /* - * Put card into RESET state - */ - outb(0x80, ashost->card.io_page); - - free_irq(host->irq, ashost); - - release_region(host->io_port + 0x800, 2); - release_region(ashost->card.io_intr, 1); - release_region(ashost->card.io_page, 1); - release_region(ashost->dma.io_port, 256); - release_region(host->io_port, 2048); - - msgqueue_free(&ashost->scsi.msgs); - queue_free(&ashost->queues.disconnected); - queue_free(&ashost->queues.issue); -} - -static const struct ecard_id acornscsi_cids[] = { - { MANU_ACORN, PROD_ACORN_SCSI }, - { 0xffff, 0xffff }, -}; - -static struct ecard_driver acornscsi_driver = { - .probe = acornscsi_probe, - .remove = __devexit_p(acornscsi_remove), - .id_table = acornscsi_cids, - .drv = { - .devclass = &shost_devclass, - .name = "acornscsi", - }, -}; - -static int __init acornscsi_init(void) -{ - return ecard_register_driver(&acornscsi_driver); -} - -static void __exit acornscsi_exit(void) -{ - ecard_remove_driver(&acornscsi_driver); -} - -module_init(acornscsi_init); -module_exit(acornscsi_exit); - -MODULE_AUTHOR("Russell King"); -MODULE_DESCRIPTION("AcornSCSI driver"); -MODULE_LICENSE("GPL"); diff -Nru a/drivers/acorn/scsi/acornscsi.h b/drivers/acorn/scsi/acornscsi.h --- a/drivers/acorn/scsi/acornscsi.h Sat May 24 12:48:23 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,359 +0,0 @@ -/* - * linux/drivers/acorn/scsi/acornscsi.h - * - * Copyright (C) 1997 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Acorn SCSI driver - */ -#ifndef ACORNSCSI_H -#define ACORNSCSI_H - -/* SBIC registers */ -#define OWNID 0 -#define OWNID_FS1 (1<<7) -#define OWNID_FS2 (1<<6) -#define OWNID_EHP (1<<4) -#define OWNID_EAF (1<<3) - -#define CTRL 1 -#define CTRL_DMAMODE (1<<7) -#define CTRL_DMADBAMODE (1<<6) -#define CTRL_DMABURST (1<<5) -#define CTRL_DMAPOLLED 0 -#define CTRL_HHP (1<<4) -#define CTRL_EDI (1<<3) -#define CTRL_IDI (1<<2) -#define CTRL_HA (1<<1) -#define CTRL_HSP (1<<0) - -#define TIMEOUT 2 -#define TOTSECTS 3 -#define TOTHEADS 4 -#define TOTCYLH 5 -#define TOTCYLL 6 -#define LOGADDRH 7 -#define LOGADDRM2 8 -#define LOGADDRM1 9 -#define LOGADDRL 10 -#define SECTORNUM 11 -#define HEADNUM 12 -#define CYLH 13 -#define CYLL 14 -#define TARGETLUN 15 -#define TARGETLUN_TLV (1<<7) -#define TARGETLUN_DOK (1<<6) - -#define CMNDPHASE 16 -#define SYNCHTRANSFER 17 -#define SYNCHTRANSFER_OF0 0x00 -#define SYNCHTRANSFER_OF1 0x01 -#define SYNCHTRANSFER_OF2 0x02 -#define SYNCHTRANSFER_OF3 0x03 -#define SYNCHTRANSFER_OF4 0x04 -#define SYNCHTRANSFER_OF5 0x05 -#define SYNCHTRANSFER_OF6 0x06 -#define SYNCHTRANSFER_OF7 0x07 -#define SYNCHTRANSFER_OF8 0x08 -#define SYNCHTRANSFER_OF9 0x09 -#define SYNCHTRANSFER_OF10 0x0A -#define SYNCHTRANSFER_OF11 0x0B -#define SYNCHTRANSFER_OF12 0x0C -#define SYNCHTRANSFER_8DBA 0x00 -#define SYNCHTRANSFER_2DBA 0x20 -#define SYNCHTRANSFER_3DBA 0x30 -#define SYNCHTRANSFER_4DBA 0x40 -#define SYNCHTRANSFER_5DBA 0x50 -#define SYNCHTRANSFER_6DBA 0x60 -#define SYNCHTRANSFER_7DBA 0x70 - -#define TRANSCNTH 18 -#define TRANSCNTM 19 -#define TRANSCNTL 20 -#define DESTID 21 -#define DESTID_SCC (1<<7) -#define DESTID_DPD (1<<6) - -#define SOURCEID 22 -#define SOURCEID_ER (1<<7) -#define SOURCEID_ES (1<<6) -#define SOURCEID_DSP (1<<5) -#define SOURCEID_SIV (1<<4) - -#define SSR 23 -#define CMND 24 -#define CMND_RESET 0x00 -#define CMND_ABORT 0x01 -#define CMND_ASSERTATN 0x02 -#define CMND_NEGATEACK 0x03 -#define CMND_DISCONNECT 0x04 -#define CMND_RESELECT 0x05 -#define CMND_SELWITHATN 0x06 -#define CMND_SELECT 0x07 -#define CMND_SELECTATNTRANSFER 0x08 -#define CMND_SELECTTRANSFER 0x09 -#define CMND_RESELECTRXDATA 0x0A -#define CMND_RESELECTTXDATA 0x0B -#define CMND_WAITFORSELRECV 0x0C -#define CMND_SENDSTATCMD 0x0D -#define CMND_SENDDISCONNECT 0x0E -#define CMND_SETIDI 0x0F -#define CMND_RECEIVECMD 0x10 -#define CMND_RECEIVEDTA 0x11 -#define CMND_RECEIVEMSG 0x12 -#define CMND_RECEIVEUSP 0x13 -#define CMND_SENDCMD 0x14 -#define CMND_SENDDATA 0x15 -#define CMND_SENDMSG 0x16 -#define CMND_SENDUSP 0x17 -#define CMND_TRANSLATEADDR 0x18 -#define CMND_XFERINFO 0x20 -#define CMND_SBT (1<<7) - -#define DATA 25 -#define ASR 26 -#define ASR_INT (1<<7) -#define ASR_LCI (1<<6) -#define ASR_BSY (1<<5) -#define ASR_CIP (1<<4) -#define ASR_PE (1<<1) -#define ASR_DBR (1<<0) - -/* DMAC registers */ -#define INIT 0x00 -#define INIT_8BIT (1) - -#define CHANNEL 0x80 -#define CHANNEL_0 0x00 -#define CHANNEL_1 0x01 -#define CHANNEL_2 0x02 -#define CHANNEL_3 0x03 - -#define TXCNTLO 0x01 -#define TXCNTHI 0x81 -#define TXADRLO 0x02 -#define TXADRMD 0x82 -#define TXADRHI 0x03 - -#define DEVCON0 0x04 -#define DEVCON0_AKL (1<<7) -#define DEVCON0_RQL (1<<6) -#define DEVCON0_EXW (1<<5) -#define DEVCON0_ROT (1<<4) -#define DEVCON0_CMP (1<<3) -#define DEVCON0_DDMA (1<<2) -#define DEVCON0_AHLD (1<<1) -#define DEVCON0_MTM (1<<0) - -#define DEVCON1 0x84 -#define DEVCON1_WEV (1<<1) -#define DEVCON1_BHLD (1<<0) - -#define MODECON 0x05 -#define MODECON_WOED 0x01 -#define MODECON_VERIFY 0x00 -#define MODECON_READ 0x04 -#define MODECON_WRITE 0x08 -#define MODECON_AUTOINIT 0x10 -#define MODECON_ADDRDIR 0x20 -#define MODECON_DEMAND 0x00 -#define MODECON_SINGLE 0x40 -#define MODECON_BLOCK 0x80 -#define MODECON_CASCADE 0xC0 - -#define STATUS 0x85 -#define STATUS_TC0 (1<<0) -#define STATUS_RQ0 (1<<4) - -#define TEMPLO 0x06 -#define TEMPHI 0x86 -#define REQREG 0x07 -#define MASKREG 0x87 -#define MASKREG_M0 0x01 -#define MASKREG_M1 0x02 -#define MASKREG_M2 0x04 -#define MASKREG_M3 0x08 - -/* miscellaneous internal variables */ - -#define POD_SPACE(x) ((x) + 0xd0000) -#define MASK_ON (MASKREG_M3|MASKREG_M2|MASKREG_M1|MASKREG_M0) -#define MASK_OFF (MASKREG_M3|MASKREG_M2|MASKREG_M1) - -/* - * SCSI driver phases - */ -typedef enum { - PHASE_IDLE, /* we're not planning on doing anything */ - PHASE_CONNECTING, /* connecting to a target */ - PHASE_CONNECTED, /* connected to a target */ - PHASE_MSGOUT, /* message out to device */ - PHASE_RECONNECTED, /* reconnected */ - PHASE_COMMANDPAUSED, /* command partly sent */ - PHASE_COMMAND, /* command all sent */ - PHASE_DATAOUT, /* data out to device */ - PHASE_DATAIN, /* data in from device */ - PHASE_STATUSIN, /* status in from device */ - PHASE_MSGIN, /* message in from device */ - PHASE_DONE, /* finished */ - PHASE_ABORTED, /* aborted */ - PHASE_DISCONNECT, /* disconnecting */ -} phase_t; - -/* - * After interrupt, what to do now - */ -typedef enum { - INTR_IDLE, /* not expecting another IRQ */ - INTR_NEXT_COMMAND, /* start next command */ - INTR_PROCESSING, /* interrupt routine still processing */ -} intr_ret_t; - -/* - * DMA direction - */ -typedef enum { - DMA_OUT, /* DMA from memory to chip */ - DMA_IN /* DMA from chip to memory */ -} dmadir_t; - -/* - * Synchronous transfer state - */ -typedef enum { /* Synchronous transfer state */ - SYNC_ASYNCHRONOUS, /* don't negociate synchronous transfers*/ - SYNC_NEGOCIATE, /* start negociation */ - SYNC_SENT_REQUEST, /* sent SDTR message */ - SYNC_COMPLETED, /* received SDTR reply */ -} syncxfer_t; - -/* - * Command type - */ -typedef enum { /* command type */ - CMD_READ, /* READ_6, READ_10, READ_12 */ - CMD_WRITE, /* WRITE_6, WRITE_10, WRITE_12 */ - CMD_MISC, /* Others */ -} cmdtype_t; - -/* - * Data phase direction - */ -typedef enum { /* Data direction */ - DATADIR_IN, /* Data in phase expected */ - DATADIR_OUT /* Data out phase expected */ -} datadir_t; - -#include "queue.h" -#include "msgqueue.h" - -#define STATUS_BUFFER_SIZE 32 -/* - * This is used to dump the previous states of the SBIC - */ -struct status_entry { - unsigned long when; - unsigned char ssr; - unsigned char ph; - unsigned char irq; - unsigned char unused; -}; - -#define ADD_STATUS(_q,_ssr,_ph,_irq) \ -({ \ - host->status[(_q)][host->status_ptr[(_q)]].when = jiffies; \ - host->status[(_q)][host->status_ptr[(_q)]].ssr = (_ssr); \ - host->status[(_q)][host->status_ptr[(_q)]].ph = (_ph); \ - host->status[(_q)][host->status_ptr[(_q)]].irq = (_irq); \ - host->status_ptr[(_q)] = (host->status_ptr[(_q)] + 1) & (STATUS_BUFFER_SIZE - 1); \ -}) - -/* - * AcornSCSI host specific data - */ -typedef struct acornscsi_hostdata { - /* miscellaneous */ - struct Scsi_Host *host; /* host */ - Scsi_Cmnd *SCpnt; /* currently processing command */ - Scsi_Cmnd *origSCpnt; /* original connecting command */ - - /* driver information */ - struct { - unsigned int io_port; /* base address of WD33C93 */ - unsigned int irq; /* interrupt */ - phase_t phase; /* current phase */ - - struct { - unsigned char target; /* reconnected target */ - unsigned char lun; /* reconnected lun */ - unsigned char tag; /* reconnected tag */ - } reconnected; - - Scsi_Pointer SCp; /* current commands data pointer */ - - MsgQueue_t msgs; - - unsigned short last_message; /* last message to be sent */ - unsigned char disconnectable:1; /* this command can be disconnected */ - unsigned char interrupt:1; /* interrupt active */ - } scsi; - - /* statistics information */ - struct { - unsigned int queues; - unsigned int removes; - unsigned int fins; - unsigned int reads; - unsigned int writes; - unsigned int miscs; - unsigned int disconnects; - unsigned int aborts; - unsigned int resets; - } stats; - - /* queue handling */ - struct { - Queue_t issue; /* issue queue */ - Queue_t disconnected; /* disconnected command queue */ - } queues; - - /* per-device info */ - struct { - unsigned char sync_xfer; /* synchronous transfer (SBIC value) */ - syncxfer_t sync_state; /* sync xfer negociation state */ - unsigned char disconnect_ok:1; /* device can disconnect */ - } device[8]; - unsigned long busyluns[64 / sizeof(unsigned long)];/* array of bits indicating LUNs busy */ - - /* DMA info */ - struct { - unsigned int io_port; /* base address of DMA controller */ - unsigned int io_intr_clear; /* address of DMA interrupt clear */ - unsigned int free_addr; /* next free address */ - unsigned int start_addr; /* start address of current transfer */ - dmadir_t direction; /* dma direction */ - unsigned int transferred; /* number of bytes transferred */ - unsigned int xfer_start; /* scheduled DMA transfer start */ - unsigned int xfer_length; /* scheduled DMA transfer length */ - char *xfer_ptr; /* pointer to area */ - unsigned char xfer_required:1; /* set if we need to transfer something */ - unsigned char xfer_setup:1; /* set if DMA is setup */ - unsigned char xfer_done:1; /* set if DMA reached end of BH list */ - } dma; - - /* card info */ - struct { - unsigned int io_intr; /* base address of interrupt id reg */ - unsigned int io_page; /* base address of page reg */ - unsigned int io_ram; /* base address of RAM access */ - unsigned char page_reg; /* current setting of page reg */ - } card; - - unsigned char status_ptr[9]; - struct status_entry status[9][STATUS_BUFFER_SIZE]; -} AS_Host; - -#endif /* ACORNSCSI_H */ diff -Nru a/drivers/acorn/scsi/arxescsi.c b/drivers/acorn/scsi/arxescsi.c --- a/drivers/acorn/scsi/arxescsi.c Sat May 24 12:48:25 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,421 +0,0 @@ -/* - * linux/arch/arm/drivers/scsi/arxescsi.c - * - * Copyright (C) 1997-2000 Russell King, Stefan Hanske - * - * This driver is based on experimentation. Hence, it may have made - * assumptions about the particular card that I have available, and - * may not be reliable! - * - * Changelog: - * 30-08-1997 RMK 0.0.0 Created, READONLY version as cumana_2.c - * 22-01-1998 RMK 0.0.1 Updated to 2.1.80 - * 15-04-1998 RMK 0.0.1 Only do PIO if FAS216 will allow it. - * 11-06-1998 SH 0.0.2 Changed to support ARXE 16-bit SCSI card - * enabled writing - * 01-01-2000 SH 0.1.0 Added *real* pseudo dma writing - * (arxescsi_pseudo_dma_write) - * 02-04-2000 RMK 0.1.1 Updated for new error handling code. - * 22-10-2000 SH Updated for new registering scheme. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "../../scsi/scsi.h" -#include "../../scsi/hosts.h" -#include "fas216.h" - -struct arxescsi_info { - FAS216_Info info; - struct expansion_card *ec; -}; - -#define DMADATA_OFFSET (0x200) - -#define DMASTAT_OFFSET (0x600) -#define DMASTAT_DRQ (1 << 0) - -#define CSTATUS_IRQ (1 << 0) - -#define VERSION "1.10 (23/01/2003 2.5.57)" - -/* - * Function: int arxescsi_dma_setup(host, SCpnt, direction, min_type) - * Purpose : initialises DMA/PIO - * Params : host - host - * SCpnt - command - * direction - DMA on to/off of card - * min_type - minimum DMA support that we must have for this transfer - * Returns : 0 if we should not set CMD_WITHDMA for transfer info command - */ -static fasdmatype_t -arxescsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp, - fasdmadir_t direction, fasdmatype_t min_type) -{ - /* - * We don't do real DMA - */ - return fasdma_pseudo; -} - -static void arxescsi_pseudo_dma_write(unsigned char *addr, unsigned char *base) -{ - __asm__ __volatile__( - " stmdb sp!, {r0-r12}\n" - " mov r3, %0\n" - " mov r1, %1\n" - " add r2, r1, #512\n" - " mov r4, #256\n" - ".loop_1: ldmia r3!, {r6, r8, r10, r12}\n" - " mov r5, r6, lsl #16\n" - " mov r7, r8, lsl #16\n" - ".loop_2: ldrb r0, [r1, #1536]\n" - " tst r0, #1\n" - " beq .loop_2\n" - " stmia r2, {r5-r8}\n\t" - " mov r9, r10, lsl #16\n" - " mov r11, r12, lsl #16\n" - ".loop_3: ldrb r0, [r1, #1536]\n" - " tst r0, #1\n" - " beq .loop_3\n" - " stmia r2, {r9-r12}\n" - " subs r4, r4, #16\n" - " bne .loop_1\n" - " ldmia sp!, {r0-r12}\n" - : - : "r" (addr), "r" (base)); -} - -/* - * Function: int arxescsi_dma_pseudo(host, SCpnt, direction, transfer) - * Purpose : handles pseudo DMA - * Params : host - host - * SCpnt - command - * direction - DMA on to/off of card - * transfer - minimum number of bytes we expect to transfer - */ -static void -arxescsi_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp, - fasdmadir_t direction, int transfer) -{ - struct arxescsi_info *info = (struct arxescsi_info *)host->hostdata; - unsigned int length, error = 0; - unsigned char *base = info->info.scsi.io_base; - unsigned char *addr; - - length = SCp->this_residual; - addr = SCp->ptr; - - if (direction == DMA_OUT) { - unsigned int word; - while (length > 256) { - if (readb(base + 0x80) & STAT_INT) { - error = 1; - break; - } - arxescsi_pseudo_dma_write(addr, base); - addr += 256; - length -= 256; - } - - if (!error) - while (length > 0) { - if (readb(base + 0x80) & STAT_INT) - break; - - if (!(readb(base + DMASTAT_OFFSET) & DMASTAT_DRQ)) - continue; - - word = *addr | *(addr + 1) << 8; - - writew(word, base + DMADATA_OFFSET); - if (length > 1) { - addr += 2; - length -= 2; - } else { - addr += 1; - length -= 1; - } - } - } - else { - if (transfer && (transfer & 255)) { - while (length >= 256) { - if (readb(base + 0x80) & STAT_INT) { - error = 1; - break; - } - - if (!(readb(base + DMASTAT_OFFSET) & DMASTAT_DRQ)) - continue; - - readsw(base + DMADATA_OFFSET, addr, 256 >> 1); - addr += 256; - length -= 256; - } - } - - if (!(error)) - while (length > 0) { - unsigned long word; - - if (readb(base + 0x80) & STAT_INT) - break; - - if (!(readb(base + DMASTAT_OFFSET) & DMASTAT_DRQ)) - continue; - - word = readw(base + DMADATA_OFFSET); - *addr++ = word; - if (--length > 0) { - *addr++ = word >> 8; - length --; - } - } - } -} - -/* - * Function: int arxescsi_dma_stop(host, SCpnt) - * Purpose : stops DMA/PIO - * Params : host - host - * SCpnt - command - */ -static void arxescsi_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp) -{ - /* - * no DMA to stop - */ -} - -/* - * Function: const char *arxescsi_info(struct Scsi_Host * host) - * Purpose : returns a descriptive string about this interface, - * Params : host - driver host structure to return info for. - * Returns : pointer to a static buffer containing null terminated string. - */ -static const char *arxescsi_info(struct Scsi_Host *host) -{ - struct arxescsi_info *info = (struct arxescsi_info *)host->hostdata; - static char string[150]; - - sprintf(string, "%s (%s) in slot %d v%s", - host->hostt->name, info->info.scsi.type, info->ec->slot_no, - VERSION); - - return string; -} - -/* - * Function: int arxescsi_proc_info(char *buffer, char **start, off_t offset, - * int length, int host_no, int inout) - * Purpose : Return information about the driver to a user process accessing - * the /proc filesystem. - * Params : buffer - a buffer to write information to - * start - a pointer into this buffer set by this routine to the start - * of the required information. - * offset - offset into information that we have read upto. - * length - length of buffer - * host_no - host number to return information for - * inout - 0 for reading, 1 for writing. - * Returns : length of data written to buffer. - */ -static int -arxescsi_proc_info(char *buffer, char **start, off_t offset, int length, - int host_no, int inout) -{ - int pos, begin; - struct Scsi_Host *host; - struct arxescsi_info *info; - Scsi_Device *scd; - - host = scsi_host_hn_get(host_no); - if (!host) - return 0; - - info = (struct arxescsi_info *)host->hostdata; - if (inout == 1) - return -EINVAL; - - begin = 0; - pos = sprintf(buffer, "ARXE 16-bit SCSI driver v%s\n", VERSION); - pos += fas216_print_host(&info->info, buffer + pos); - pos += fas216_print_stats(&info->info, buffer + pos); - - pos += sprintf (buffer+pos, "\nAttached devices:\n"); - - list_for_each_entry(scd, &host->my_devices, siblings) { - pos += fas216_print_device(&info->info, scd, buffer + pos); - - if (pos + begin < offset) { - begin += pos; - pos = 0; - } - if (pos + begin > offset + length) - break; - } - - *start = buffer + (offset - begin); - pos -= offset - begin; - if (pos > length) - pos = length; - - return pos; -} - -static Scsi_Host_Template arxescsi_template = { - .proc_info = arxescsi_proc_info, - .name = "ARXE SCSI card", - .info = arxescsi_info, - .command = fas216_command, - .queuecommand = fas216_queue_command, - .eh_host_reset_handler = fas216_eh_host_reset, - .eh_bus_reset_handler = fas216_eh_bus_reset, - .eh_device_reset_handler = fas216_eh_device_reset, - .eh_abort_handler = fas216_eh_abort, - .can_queue = 0, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 1, - .use_clustering = DISABLE_CLUSTERING, - .proc_name = "arxescsi", -}; - -static int __devinit -arxescsi_probe(struct expansion_card *ec, const struct ecard_id *id) -{ - struct Scsi_Host *host; - struct arxescsi_info *info; - unsigned long resbase, reslen; - unsigned char *base; - int ret; - - resbase = ecard_resource_start(ec, ECARD_RES_MEMC); - reslen = ecard_resource_len(ec, ECARD_RES_MEMC); - - if (!request_mem_region(resbase, reslen, "arxescsi")) { - ret = -EBUSY; - goto out; - } - - base = ioremap(resbase, reslen); - if (!base) { - ret = -ENOMEM; - goto out_region; - } - - host = scsi_register(&arxescsi_template, sizeof(struct arxescsi_info)); - if (!host) { - ret = -ENOMEM; - goto out_unmap; - } - - host->base = (unsigned long)base; - host->irq = NO_IRQ; - host->dma_channel = NO_DMA; - - info = (struct arxescsi_info *)host->hostdata; - info->ec = ec; - - info->info.scsi.io_base = base + 0x2000; - info->info.scsi.irq = host->irq; - info->info.scsi.io_shift = 5; - info->info.ifcfg.clockrate = 24; /* MHz */ - info->info.ifcfg.select_timeout = 255; - info->info.ifcfg.asyncperiod = 200; /* ns */ - info->info.ifcfg.sync_max_depth = 0; - info->info.ifcfg.cntl3 = CNTL3_FASTSCSI | CNTL3_FASTCLK; - info->info.ifcfg.disconnect_ok = 0; - info->info.ifcfg.wide_max_size = 0; - info->info.ifcfg.capabilities = FASCAP_PSEUDODMA; - info->info.dma.setup = arxescsi_dma_setup; - info->info.dma.pseudo = arxescsi_dma_pseudo; - info->info.dma.stop = arxescsi_dma_stop; - - ec->irqaddr = base; - ec->irqmask = CSTATUS_IRQ; - - ret = fas216_init(host); - if (ret) - goto out_unregister; - - ret = fas216_add(host, &ec->dev); - if (ret == 0) - goto out; - - fas216_release(host); - out_unregister: - scsi_unregister(host); - out_unmap: - iounmap(base); - out_region: - release_mem_region(resbase, reslen); - out: - return ret; -} - -static void __devexit arxescsi_remove(struct expansion_card *ec) -{ - struct Scsi_Host *host = ecard_get_drvdata(ec); - unsigned long resbase, reslen; - - ecard_set_drvdata(ec, NULL); - fas216_remove(host); - - iounmap((void *)host->base); - - resbase = ecard_resource_start(ec, ECARD_RES_MEMC); - reslen = ecard_resource_len(ec, ECARD_RES_MEMC); - - release_mem_region(resbase, reslen); - - fas216_release(host); - scsi_unregister(host); -} - -static const struct ecard_id arxescsi_cids[] = { - { MANU_ARXE, PROD_ARXE_SCSI }, - { 0xffff, 0xffff }, -}; - -static struct ecard_driver arxescsi_driver = { - .probe = arxescsi_probe, - .remove = __devexit_p(arxescsi_remove), - .id_table = arxescsi_cids, - .drv = { - .devclass = &shost_devclass, - .name = "arxescsi", - }, -}; - -static int __init init_arxe_scsi_driver(void) -{ - return ecard_register_driver(&arxescsi_driver); -} - -static void __exit exit_arxe_scsi_driver(void) -{ - ecard_remove_driver(&arxescsi_driver); -} - -module_init(init_arxe_scsi_driver); -module_exit(exit_arxe_scsi_driver); - -MODULE_AUTHOR("Stefan Hanske"); -MODULE_DESCRIPTION("ARXESCSI driver for Acorn machines"); -MODULE_LICENSE("GPL"); - diff -Nru a/drivers/acorn/scsi/cumana_1.c b/drivers/acorn/scsi/cumana_1.c --- a/drivers/acorn/scsi/cumana_1.c Sat May 24 12:48:20 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,356 +0,0 @@ -/* - * Generic Generic NCR5380 driver - * - * Copyright 1995-2002, Russell King - */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "../../scsi/scsi.h" -#include "../../scsi/hosts.h" - -#include - -#define AUTOSENSE -#define PSEUDO_DMA - -#define CUMANASCSI_PUBLIC_RELEASE 1 - -#define NCR5380_implementation_fields int port, ctrl -#define NCR5380_local_declare() struct Scsi_Host *_instance -#define NCR5380_setup(instance) _instance = instance -#define NCR5380_read(reg) cumanascsi_read(_instance, reg) -#define NCR5380_write(reg, value) cumanascsi_write(_instance, reg, value) -#define NCR5380_intr cumanascsi_intr -#define NCR5380_queue_command cumanascsi_queue_command -#define NCR5380_proc_info cumanascsi_proc_info - -int NCR5380_proc_info(char *buffer, char **start, off_t offset, - int length, int hostno, int inout); - -#define BOARD_NORMAL 0 -#define BOARD_NCR53C400 1 - -#include "../../scsi/NCR5380.h" - -void cumanascsi_setup(char *str, int *ints) -{ -} - -const char *cumanascsi_info(struct Scsi_Host *spnt) -{ - return ""; -} - -#ifdef NOT_EFFICIENT -#define CTRL(p,v) outb(*ctrl = (v), (p) - 577) -#define STAT(p) inb((p)+1) -#define IN(p) inb((p)) -#define OUT(v,p) outb((v), (p)) -#else -#define CTRL(p,v) (p[-2308] = (*ctrl = (v))) -#define STAT(p) (p[4]) -#define IN(p) (*(p)) -#define IN2(p) ((unsigned short)(*(volatile unsigned long *)(p))) -#define OUT(v,p) (*(p) = (v)) -#define OUT2(v,p) (*((volatile unsigned long *)(p)) = (v)) -#endif -#define L(v) (((v)<<16)|((v) & 0x0000ffff)) -#define H(v) (((v)>>16)|((v) & 0xffff0000)) - -static inline int -NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr, int len) -{ - int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; - int oldctrl = *ctrl; - unsigned long *laddr; -#ifdef NOT_EFFICIENT - int iobase = instance->io_port; - int dma_io = iobase & ~(0x3C0000>>2); -#else - volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port); - volatile unsigned char *dma_io = (unsigned char *)((int)iobase & ~0x3C0000); -#endif - - if(!len) return 0; - - CTRL(iobase, 0x02); - laddr = (unsigned long *)addr; - while(len >= 32) - { - int status; - unsigned long v; - status = STAT(iobase); - if(status & 0x80) - goto end; - if(!(status & 0x40)) - continue; - v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); - v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); - v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); - v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); - v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); - v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); - v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); - v=*laddr++; OUT2(L(v),dma_io); OUT2(H(v),dma_io); - len -= 32; - if(len == 0) - break; - } - - addr = (unsigned char *)laddr; - CTRL(iobase, 0x12); - while(len > 0) - { - int status; - status = STAT(iobase); - if(status & 0x80) - goto end; - if(status & 0x40) - { - OUT(*addr++, dma_io); - if(--len == 0) - break; - } - - status = STAT(iobase); - if(status & 0x80) - goto end; - if(status & 0x40) - { - OUT(*addr++, dma_io); - if(--len == 0) - break; - } - } -end: - CTRL(iobase, oldctrl|0x40); - return len; -} - -static inline int -NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr, int len) -{ - int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; - int oldctrl = *ctrl; - unsigned long *laddr; -#ifdef NOT_EFFICIENT - int iobase = instance->io_port; - int dma_io = iobase & ~(0x3C0000>>2); -#else - volatile unsigned char *iobase = (unsigned char *)ioaddr(instance->io_port); - volatile unsigned char *dma_io = (unsigned char *)((int)iobase & ~0x3C0000); -#endif - - if(!len) return 0; - - CTRL(iobase, 0x00); - laddr = (unsigned long *)addr; - while(len >= 32) - { - int status; - status = STAT(iobase); - if(status & 0x80) - goto end; - if(!(status & 0x40)) - continue; - *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); - *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); - *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); - *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); - *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); - *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); - *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); - *laddr++ = IN2(dma_io)|(IN2(dma_io)<<16); - len -= 32; - if(len == 0) - break; - } - - addr = (unsigned char *)laddr; - CTRL(iobase, 0x10); - while(len > 0) - { - int status; - status = STAT(iobase); - if(status & 0x80) - goto end; - if(status & 0x40) - { - *addr++ = IN(dma_io); - if(--len == 0) - break; - } - - status = STAT(iobase); - if(status & 0x80) - goto end; - if(status & 0x40) - { - *addr++ = IN(dma_io); - if(--len == 0) - break; - } - } -end: - CTRL(iobase, oldctrl|0x40); - return len; -} - -#undef STAT -#undef CTRL -#undef IN -#undef OUT - -#define CTRL(p,v) outb(*ctrl = (v), (p) - 577) - -static char cumanascsi_read(struct Scsi_Host *instance, int reg) -{ - unsigned int iobase = instance->io_port; - int i; - int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; - - CTRL(iobase, 0); - i = inb(iobase + 64 + reg); - CTRL(iobase, 0x40); - - return i; -} - -static void cumanascsi_write(struct Scsi_Host *instance, int reg, int value) -{ - int iobase = instance->io_port; - int *ctrl = &((struct NCR5380_hostdata *)instance->hostdata)->ctrl; - - CTRL(iobase, 0); - outb(value, iobase + 64 + reg); - CTRL(iobase, 0x40); -} - -#undef CTRL - -#include "../../scsi/NCR5380.c" - -static Scsi_Host_Template cumanascsi_template = { - .module = THIS_MODULE, - .name = "Cumana 16-bit SCSI", - .info = cumanascsi_info, - .queuecommand = cumanascsi_queue_command, - .eh_abort_handler = NCR5380_abort, - .eh_device_reset_handler= NCR5380_device_reset, - .eh_bus_reset_handler = NCR5380_bus_reset, - .eh_host_reset_handler = NCR5380_host_reset, - .can_queue = 16, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 2, - .unchecked_isa_dma = 0, - .use_clustering = DISABLE_CLUSTERING, - .proc_name = "CumanaSCSI-1", -}; - -static int __devinit -cumanascsi1_probe(struct expansion_card *ec, const struct ecard_id *id) -{ - struct Scsi_Host *host; - int ret = -ENOMEM; - - host = scsi_register(&cumanascsi_template, sizeof(struct NCR5380_hostdata)); - if (!host) - goto out; - - host->io_port = ecard_address(ec, ECARD_IOC, ECARD_SLOW) + 0x800; - host->irq = ec->irq; - - NCR5380_init(host, 0); - - host->n_io_port = 255; - if (!(request_region(host->io_port, host->n_io_port, "CumanaSCSI-1"))) { - ret = -EBUSY; - goto out_free; - } - - ((struct NCR5380_hostdata *)host->hostdata)->ctrl = 0; - outb(0x00, host->io_port - 577); - - ret = request_irq(host->irq, cumanascsi_intr, SA_INTERRUPT, - "CumanaSCSI-1", host); - if (ret) { - printk("scsi%d: IRQ%d not free: %d\n", - host->host_no, host->irq, ret); - goto out_release; - } - - printk("scsi%d: at port 0x%08lx irq %d", - host->host_no, host->io_port, host->irq); - printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", - host->can_queue, host->cmd_per_lun, CUMANASCSI_PUBLIC_RELEASE); - printk("\nscsi%d:", host->host_no); - NCR5380_print_options(host); - printk("\n"); - - ret = scsi_add_host(host, &ec->dev); - if (ret == 0) - goto out; - - free_irq(host->irq, host); - out_release: - release_region(host->io_port, host->n_io_port); - out_free: - scsi_unregister(host); - out: - return ret; -} - -static void __devexit cumanascsi1_remove(struct expansion_card *ec) -{ - struct Scsi_Host *host = ecard_get_drvdata(ec); - - ecard_set_drvdata(ec, NULL); - - scsi_remove_host(host); - free_irq(host->irq, host); - release_region(host->io_port, host->n_io_port); - scsi_unregister(host); -} - -static const struct ecard_id cumanascsi1_cids[] = { - { MANU_CUMANA, PROD_CUMANA_SCSI_1 }, - { 0xffff, 0xffff } -}; - -static struct ecard_driver cumanascsi1_driver = { - .probe = cumanascsi1_probe, - .remove = __devexit_p(cumanascsi1_remove), - .id_table = cumanascsi1_cids, - .drv = { - .devclass = &shost_devclass, - .name = "cumanascsi1", - }, -}; - -static int __init cumanascsi_init(void) -{ - return ecard_register_driver(&cumanascsi1_driver); -} - -static void __exit cumanascsi_exit(void) -{ - ecard_remove_driver(&cumanascsi1_driver); -} - -module_init(cumanascsi_init); -module_exit(cumanascsi_exit); - -MODULE_DESCRIPTION("Cumana SCSI-1 driver for Acorn machines"); -MODULE_LICENSE("GPL"); diff -Nru a/drivers/acorn/scsi/cumana_2.c b/drivers/acorn/scsi/cumana_2.c --- a/drivers/acorn/scsi/cumana_2.c Sat May 24 12:48:29 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,597 +0,0 @@ -/* - * linux/drivers/acorn/scsi/cumana_2.c - * - * Copyright (C) 1997-2002 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Changelog: - * 30-08-1997 RMK 0.0.0 Created, READONLY version. - * 22-01-1998 RMK 0.0.1 Updated to 2.1.80. - * 15-04-1998 RMK 0.0.1 Only do PIO if FAS216 will allow it. - * 02-05-1998 RMK 0.0.2 Updated & added DMA support. - * 27-06-1998 RMK Changed asm/delay.h to linux/delay.h - * 18-08-1998 RMK 0.0.3 Fixed synchronous transfer depth. - * 02-04-2000 RMK 0.0.4 Updated for new error handling code. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "../../scsi/scsi.h" -#include "../../scsi/hosts.h" -#include "fas216.h" -#include "scsi.h" - -#include - -#define CUMANASCSI2_STATUS (0x0000) -#define STATUS_INT (1 << 0) -#define STATUS_DRQ (1 << 1) -#define STATUS_LATCHED (1 << 3) - -#define CUMANASCSI2_ALATCH (0x0014) -#define ALATCH_ENA_INT (3) -#define ALATCH_DIS_INT (2) -#define ALATCH_ENA_TERM (5) -#define ALATCH_DIS_TERM (4) -#define ALATCH_ENA_BIT32 (11) -#define ALATCH_DIS_BIT32 (10) -#define ALATCH_ENA_DMA (13) -#define ALATCH_DIS_DMA (12) -#define ALATCH_DMA_OUT (15) -#define ALATCH_DMA_IN (14) - -#define CUMANASCSI2_PSEUDODMA (0x0200) - -#define CUMANASCSI2_FAS216_OFFSET (0x0300) -#define CUMANASCSI2_FAS216_SHIFT 2 - -/* - * Version - */ -#define VERSION "1.00 (13/11/2002 2.5.47)" - -/* - * Use term=0,1,0,0,0 to turn terminators on/off - */ -static int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 }; - -#define NR_SG 256 - -struct cumanascsi2_info { - FAS216_Info info; - struct expansion_card *ec; - - void *status; /* card status register */ - void *alatch; /* Control register */ - unsigned int terms; /* Terminator state */ - void *dmaarea; /* Pseudo DMA area */ - struct scatterlist sg[NR_SG]; /* Scatter DMA list */ -}; - -#define CSTATUS_IRQ (1 << 0) -#define CSTATUS_DRQ (1 << 1) - -/* Prototype: void cumanascsi_2_irqenable(ec, irqnr) - * Purpose : Enable interrupts on Cumana SCSI 2 card - * Params : ec - expansion card structure - * : irqnr - interrupt number - */ -static void -cumanascsi_2_irqenable(struct expansion_card *ec, int irqnr) -{ - writeb(ALATCH_ENA_INT, ec->irq_data); -} - -/* Prototype: void cumanascsi_2_irqdisable(ec, irqnr) - * Purpose : Disable interrupts on Cumana SCSI 2 card - * Params : ec - expansion card structure - * : irqnr - interrupt number - */ -static void -cumanascsi_2_irqdisable(struct expansion_card *ec, int irqnr) -{ - writeb(ALATCH_DIS_INT, ec->irq_data); -} - -static const expansioncard_ops_t cumanascsi_2_ops = { - .irqenable = cumanascsi_2_irqenable, - .irqdisable = cumanascsi_2_irqdisable, -}; - -/* Prototype: void cumanascsi_2_terminator_ctl(host, on_off) - * Purpose : Turn the Cumana SCSI 2 terminators on or off - * Params : host - card to turn on/off - * : on_off - !0 to turn on, 0 to turn off - */ -static void -cumanascsi_2_terminator_ctl(struct Scsi_Host *host, int on_off) -{ - struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata; - - if (on_off) { - info->terms = 1; - writeb(ALATCH_ENA_TERM, info->alatch); - } else { - info->terms = 0; - writeb(ALATCH_DIS_TERM, info->alatch); - } -} - -/* Prototype: void cumanascsi_2_intr(irq, *dev_id, *regs) - * Purpose : handle interrupts from Cumana SCSI 2 card - * Params : irq - interrupt number - * dev_id - user-defined (Scsi_Host structure) - * regs - processor registers at interrupt - */ -static void -cumanascsi_2_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - struct cumanascsi2_info *info = dev_id; - - fas216_intr(&info->info); -} - -/* Prototype: fasdmatype_t cumanascsi_2_dma_setup(host, SCpnt, direction, min_type) - * Purpose : initialises DMA/PIO - * Params : host - host - * SCpnt - command - * direction - DMA on to/off of card - * min_type - minimum DMA support that we must have for this transfer - * Returns : type of transfer to be performed - */ -static fasdmatype_t -cumanascsi_2_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp, - fasdmadir_t direction, fasdmatype_t min_type) -{ - struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata; - struct device *dev = scsi_get_device(host); - int dmach = host->dma_channel; - - writeb(ALATCH_DIS_DMA, info->alatch); - - if (dmach != NO_DMA && - (min_type == fasdma_real_all || SCp->this_residual >= 512)) { - int bufs, map_dir, dma_dir, alatch_dir; - - bufs = copy_SCp_to_sg(&info->sg[0], SCp, NR_SG); - - if (direction == DMA_OUT) - map_dir = DMA_TO_DEVICE, - dma_dir = DMA_MODE_WRITE, - alatch_dir = ALATCH_DMA_OUT; - else - map_dir = DMA_FROM_DEVICE, - dma_dir = DMA_MODE_READ, - alatch_dir = ALATCH_DMA_IN; - - dma_map_sg(dev, info->sg, bufs + 1, map_dir); - - disable_dma(dmach); - set_dma_sg(dmach, info->sg, bufs + 1); - writeb(alatch_dir, info->alatch); - set_dma_mode(dmach, dma_dir); - enable_dma(dmach); - writeb(ALATCH_ENA_DMA, info->alatch); - writeb(ALATCH_DIS_BIT32, info->alatch); - return fasdma_real_all; - } - - /* - * If we're not doing DMA, - * we'll do pseudo DMA - */ - return fasdma_pio; -} - -/* - * Prototype: void cumanascsi_2_dma_pseudo(host, SCpnt, direction, transfer) - * Purpose : handles pseudo DMA - * Params : host - host - * SCpnt - command - * direction - DMA on to/off of card - * transfer - minimum number of bytes we expect to transfer - */ -static void -cumanascsi_2_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp, - fasdmadir_t direction, int transfer) -{ - struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata; - unsigned int length; - unsigned char *addr; - - length = SCp->this_residual; - addr = SCp->ptr; - - if (direction == DMA_OUT) -#if 0 - while (length > 1) { - unsigned long word; - unsigned int status = readb(info->status); - - if (status & STATUS_INT) - goto end; - - if (!(status & STATUS_DRQ)) - continue; - - word = *addr | *(addr + 1) << 8; - writew(word, info->dmaarea); - addr += 2; - length -= 2; - } -#else - printk ("PSEUDO_OUT???\n"); -#endif - else { - if (transfer && (transfer & 255)) { - while (length >= 256) { - unsigned int status = readb(info->status); - - if (status & STATUS_INT) - return; - - if (!(status & STATUS_DRQ)) - continue; - - readsw(info->dmaarea, addr, 256 >> 1); - addr += 256; - length -= 256; - } - } - - while (length > 0) { - unsigned long word; - unsigned int status = readb(info->status); - - if (status & STATUS_INT) - return; - - if (!(status & STATUS_DRQ)) - continue; - - word = readw(info->dmaarea); - *addr++ = word; - if (--length > 0) { - *addr++ = word >> 8; - length --; - } - } - } -} - -/* Prototype: int cumanascsi_2_dma_stop(host, SCpnt) - * Purpose : stops DMA/PIO - * Params : host - host - * SCpnt - command - */ -static void -cumanascsi_2_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp) -{ - struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata; - if (host->dma_channel != NO_DMA) { - writeb(ALATCH_DIS_DMA, info->alatch); - disable_dma(host->dma_channel); - } -} - -/* Prototype: const char *cumanascsi_2_info(struct Scsi_Host * host) - * Purpose : returns a descriptive string about this interface, - * Params : host - driver host structure to return info for. - * Returns : pointer to a static buffer containing null terminated string. - */ -const char *cumanascsi_2_info(struct Scsi_Host *host) -{ - struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata; - static char string[150]; - - sprintf(string, "%s (%s) in slot %d v%s terminators o%s", - host->hostt->name, info->info.scsi.type, info->ec->slot_no, - VERSION, info->terms ? "n" : "ff"); - - return string; -} - -/* Prototype: int cumanascsi_2_set_proc_info(struct Scsi_Host *host, char *buffer, int length) - * Purpose : Set a driver specific function - * Params : host - host to setup - * : buffer - buffer containing string describing operation - * : length - length of string - * Returns : -EINVAL, or 0 - */ -static int -cumanascsi_2_set_proc_info(struct Scsi_Host *host, char *buffer, int length) -{ - int ret = length; - - if (length >= 11 && strcmp(buffer, "CUMANASCSI2") == 0) { - buffer += 11; - length -= 11; - - if (length >= 5 && strncmp(buffer, "term=", 5) == 0) { - if (buffer[5] == '1') - cumanascsi_2_terminator_ctl(host, 1); - else if (buffer[5] == '0') - cumanascsi_2_terminator_ctl(host, 0); - else - ret = -EINVAL; - } else - ret = -EINVAL; - } else - ret = -EINVAL; - - return ret; -} - -/* Prototype: int cumanascsi_2_proc_info(char *buffer, char **start, off_t offset, - * int length, int host_no, int inout) - * Purpose : Return information about the driver to a user process accessing - * the /proc filesystem. - * Params : buffer - a buffer to write information to - * start - a pointer into this buffer set by this routine to the start - * of the required information. - * offset - offset into information that we have read upto. - * length - length of buffer - * host_no - host number to return information for - * inout - 0 for reading, 1 for writing. - * Returns : length of data written to buffer. - */ -int cumanascsi_2_proc_info (char *buffer, char **start, off_t offset, - int length, int host_no, int inout) -{ - int pos, begin; - struct Scsi_Host *host; - struct cumanascsi2_info *info; - Scsi_Device *scd; - - host = scsi_host_hn_get(host_no); - if (!host) - return 0; - - if (inout == 1) - return cumanascsi_2_set_proc_info(host, buffer, length); - - info = (struct cumanascsi2_info *)host->hostdata; - - begin = 0; - pos = sprintf(buffer, "Cumana SCSI II driver v%s\n", VERSION); - pos += fas216_print_host(&info->info, buffer + pos); - pos += sprintf(buffer + pos, "Term : o%s\n", - info->terms ? "n" : "ff"); - - pos += fas216_print_stats(&info->info, buffer + pos); - - pos += sprintf(buffer+pos, "\nAttached devices:\n"); - - list_for_each_entry(scd, &host->my_devices, siblings) { - int len; - - proc_print_scsidevice(scd, buffer, &len, pos); - pos += len; - pos += sprintf(buffer+pos, "Extensions: "); - if (scd->tagged_supported) - pos += sprintf(buffer+pos, "TAG %sabled [%d] ", - scd->tagged_queue ? "en" : "dis", - scd->current_tag); - pos += sprintf(buffer+pos, "\n"); - - if (pos + begin < offset) { - begin += pos; - pos = 0; - } - if (pos + begin > offset + length) - break; - } - - *start = buffer + (offset - begin); - pos -= offset - begin; - if (pos > length) - pos = length; - - return pos; -} - -static Scsi_Host_Template cumanascsi2_template = { - .module = THIS_MODULE, - .proc_info = cumanascsi_2_proc_info, - .name = "Cumana SCSI II", - .info = cumanascsi_2_info, - .command = fas216_command, - .queuecommand = fas216_queue_command, - .eh_host_reset_handler = fas216_eh_host_reset, - .eh_bus_reset_handler = fas216_eh_bus_reset, - .eh_device_reset_handler = fas216_eh_device_reset, - .eh_abort_handler = fas216_eh_abort, - .can_queue = 1, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 1, - .use_clustering = DISABLE_CLUSTERING, - .proc_name = "cumanascsi2", -}; - -static int __devinit -cumanascsi2_probe(struct expansion_card *ec, const struct ecard_id *id) -{ - struct Scsi_Host *host; - struct cumanascsi2_info *info; - unsigned long resbase, reslen; - unsigned char *base; - int ret; - - resbase = ecard_resource_start(ec, ECARD_RES_MEMC); - reslen = ecard_resource_len(ec, ECARD_RES_MEMC); - - if (!request_mem_region(resbase, reslen, "cumanascsi2")) { - ret = -EBUSY; - goto out; - } - - base = ioremap(resbase, reslen); - if (!base) { - ret = -ENOMEM; - goto out_region; - } - - host = scsi_register(&cumanascsi2_template, - sizeof(struct cumanascsi2_info)); - if (!host) { - ret = -ENOMEM; - goto out_unmap; - } - - host->base = (unsigned long)base; - host->irq = ec->irq; - host->dma_channel = ec->dma; - - ecard_set_drvdata(ec, host); - - info = (struct cumanascsi2_info *)host->hostdata; - info->ec = ec; - info->dmaarea = base + CUMANASCSI2_PSEUDODMA; - info->status = base + CUMANASCSI2_STATUS; - info->alatch = base + CUMANASCSI2_ALATCH; - - ec->irqaddr = info->status; - ec->irqmask = STATUS_INT; - ec->irq_data = base + CUMANASCSI2_ALATCH; - ec->ops = &cumanascsi_2_ops; - - cumanascsi_2_terminator_ctl(host, term[ec->slot_no]); - - info->info.scsi.io_base = base + CUMANASCSI2_FAS216_OFFSET; - info->info.scsi.io_shift = CUMANASCSI2_FAS216_SHIFT; - info->info.scsi.irq = host->irq; - info->info.ifcfg.clockrate = 40; /* MHz */ - info->info.ifcfg.select_timeout = 255; - info->info.ifcfg.asyncperiod = 200; /* ns */ - info->info.ifcfg.sync_max_depth = 7; - info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK; - info->info.ifcfg.disconnect_ok = 1; - info->info.ifcfg.wide_max_size = 0; - info->info.ifcfg.capabilities = FASCAP_PSEUDODMA; - info->info.dma.setup = cumanascsi_2_dma_setup; - info->info.dma.pseudo = cumanascsi_2_dma_pseudo; - info->info.dma.stop = cumanascsi_2_dma_stop; - - ret = fas216_init(host); - if (ret) - goto out_free; - - ret = request_irq(host->irq, cumanascsi_2_intr, - SA_INTERRUPT, "cumanascsi2", info); - if (ret) { - printk("scsi%d: IRQ%d not free: %d\n", - host->host_no, host->irq, ret); - goto out_release; - } - - if (host->dma_channel != NO_DMA) { - if (request_dma(host->dma_channel, "cumanascsi2")) { - printk("scsi%d: DMA%d not free, using PIO\n", - host->host_no, host->dma_channel); - host->dma_channel = NO_DMA; - } else { - set_dma_speed(host->dma_channel, 180); - info->info.ifcfg.capabilities |= FASCAP_DMA; - } - } - - ret = fas216_add(host, &ec->dev); - if (ret == 0) - goto out; - - if (host->dma_channel != NO_DMA) - free_dma(host->dma_channel); - free_irq(host->irq, host); - - out_release: - fas216_release(host); - - out_free: - scsi_unregister(host); - - out_unmap: - iounmap(base); - - out_region: - release_mem_region(resbase, reslen); - - out: - return ret; -} - -static void __devexit cumanascsi2_remove(struct expansion_card *ec) -{ - struct Scsi_Host *host = ecard_get_drvdata(ec); - struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata; - unsigned long resbase, reslen; - - ecard_set_drvdata(ec, NULL); - fas216_remove(host); - - if (host->dma_channel != NO_DMA) - free_dma(host->dma_channel); - free_irq(host->irq, info); - - iounmap((void *)host->base); - - resbase = ecard_resource_start(ec, ECARD_RES_MEMC); - reslen = ecard_resource_len(ec, ECARD_RES_MEMC); - - release_mem_region(resbase, reslen); - - fas216_release(host); - scsi_unregister(host); -} - -static const struct ecard_id cumanascsi2_cids[] = { - { MANU_CUMANA, PROD_CUMANA_SCSI_2 }, - { 0xffff, 0xffff }, -}; - -static struct ecard_driver cumanascsi2_driver = { - .probe = cumanascsi2_probe, - .remove = __devexit_p(cumanascsi2_remove), - .id_table = cumanascsi2_cids, - .drv = { - .devclass = &shost_devclass, - .name = "cumanascsi2", - }, -}; - -static int __init cumanascsi2_init(void) -{ - return ecard_register_driver(&cumanascsi2_driver); -} - -static void __exit cumanascsi2_exit(void) -{ - ecard_remove_driver(&cumanascsi2_driver); -} - -module_init(cumanascsi2_init); -module_exit(cumanascsi2_exit); - -MODULE_AUTHOR("Russell King"); -MODULE_DESCRIPTION("Cumana SCSI-2 driver for Acorn machines"); -MODULE_PARM(term, "1-8i"); -MODULE_PARM_DESC(term, "SCSI bus termination"); -MODULE_LICENSE("GPL"); diff -Nru a/drivers/acorn/scsi/ecoscsi.c b/drivers/acorn/scsi/ecoscsi.c --- a/drivers/acorn/scsi/ecoscsi.c Sat May 24 12:48:32 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,283 +0,0 @@ -#define AUTOSENSE -/* #define PSEUDO_DMA */ - -/* - * EcoSCSI Generic NCR5380 driver - * - * Copyright 1995, Russell King - * - * ALPHA RELEASE 1. - * - * For more information, please consult - * - * NCR 5380 Family - * SCSI Protocol Controller - * Databook - * - * NCR Microelectronics - * 1635 Aeroplaza Drive - * Colorado Springs, CO 80916 - * 1+ (719) 578-3400 - * 1+ (800) 334-5454 - */ - -/* - * Options : - * - * PARITY - enable parity checking. Not supported. - * - * SCSI2 - enable support for SCSI-II tagged queueing. Untested. - * - * USLEEP - enable support for devices that don't disconnect. Untested. - */ - -/* - * $Log: ecoscsi.c,v $ - * Revision 1.2 1998/03/08 05:49:47 davem - * Merge to 2.1.89 - * - * Revision 1.1 1998/02/23 02:45:24 davem - * Merge to 2.1.88 - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "../../scsi/scsi.h" -#include "../../scsi/hosts.h" - -#define NCR5380_implementation_fields int port, ctrl -#define NCR5380_local_declare() struct Scsi_Host *_instance -#define NCR5380_setup(instance) _instance = instance - -#define NCR5380_read(reg) ecoscsi_read(_instance, reg) -#define NCR5380_write(reg, value) ecoscsi_write(_instance, reg, value) - -#define NCR5380_intr ecoscsi_intr -#define NCR5380_queue_command ecoscsi_queue_command -#define NCR5380_proc_info ecoscsi_proc_info - -#include "../../scsi/NCR5380.h" - -#define ECOSCSI_PUBLIC_RELEASE 1 - -static char ecoscsi_read(struct Scsi_Host *instance, int reg) -{ - int iobase = instance->io_port; - outb(reg | 8, iobase); - return inb(iobase + 1); -} - -static void ecoscsi_write(struct Scsi_Host *instance, int reg, int value) -{ - int iobase = instance->io_port; - outb(reg | 8, iobase); - outb(value, iobase + 1); -} - -/* - * Function : ecoscsi_setup(char *str, int *ints) - * - * Purpose : LILO command line initialization of the overrides array, - * - * Inputs : str - unused, ints - array of integer parameters with ints[0] - * equal to the number of ints. - * - */ - -void ecoscsi_setup(char *str, int *ints) { -} - -/* - * Function : int ecoscsi_detect(Scsi_Host_Template * tpnt) - * - * Purpose : initializes ecoscsi NCR5380 driver based on the - * command line / compile time port and irq definitions. - * - * Inputs : tpnt - template for this SCSI adapter. - * - * Returns : 1 if a host adapter was found, 0 if not. - * - */ - -int ecoscsi_detect(Scsi_Host_Template * tpnt) -{ - struct Scsi_Host *host; - - tpnt->proc_name = "ecoscsi"; - - host = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); - if (!host) - return 0; - - host->io_port = 0x80ce8000; - host->n_io_port = 144; - host->irq = IRQ_NONE; - - if ( !(request_region(host->io_port, host->n_io_port, "ecoscsi")) ) - goto unregister_scsi; - - ecoscsi_write (host, MODE_REG, 0x20); /* Is it really SCSI? */ - if (ecoscsi_read (host, MODE_REG) != 0x20) /* Write to a reg. */ - goto release_reg; - - ecoscsi_write( host, MODE_REG, 0x00 ); /* it back. */ - if (ecoscsi_read (host, MODE_REG) != 0x00) - goto release_reg; - - NCR5380_init(host, 0); - - printk("scsi%d: at port 0x%08lx irqs disabled", host->host_no, host->io_port); - printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", - host->can_queue, host->cmd_per_lun, ECOSCSI_PUBLIC_RELEASE); - printk("\nscsi%d:", host->host_no); - NCR5380_print_options(host); - printk("\n"); - - return 1; - -release_reg: - release_region(host->io_port, host->n_io_port); -unregister_scsi: - scsi_unregister(host); - return 0; -} - -int ecoscsi_release (struct Scsi_Host *shpnt) -{ - if (shpnt->irq != IRQ_NONE) - free_irq (shpnt->irq, NULL); - if (shpnt->io_port) - release_region (shpnt->io_port, shpnt->n_io_port); - return 0; -} - -const char * ecoscsi_info (struct Scsi_Host *spnt) -{ - return ""; -} - -#if 0 -#define STAT(p) inw(p + 144) - -static inline int NCR5380_pwrite(struct Scsi_Host *host, unsigned char *addr, - int len) -{ - int iobase = host->io_port; -printk("writing %p len %d\n",addr, len); - if(!len) return -1; - - while(1) - { - int status; - while(((status = STAT(iobase)) & 0x100)==0); - } -} - -static inline int NCR5380_pread(struct Scsi_Host *host, unsigned char *addr, - int len) -{ - int iobase = host->io_port; - int iobase2= host->io_port + 0x100; - unsigned char *start = addr; - int s; -printk("reading %p len %d\n",addr, len); - outb(inb(iobase + 128), iobase + 135); - while(len > 0) - { - int status,b,i, timeout; - timeout = 0x07FFFFFF; - while(((status = STAT(iobase)) & 0x100)==0) - { - timeout--; - if(status & 0x200 || !timeout) - { - printk("status = %p\n",status); - outb(0, iobase + 135); - return 1; - } - } - if(len >= 128) - { - for(i=0; i<64; i++) - { - b = inw(iobase + 136); - *addr++ = b; - *addr++ = b>>8; - } - len -= 128; - } - else - { - b = inw(iobase + 136); - *addr ++ = b; - len -= 1; - if(len) - *addr ++ = b>>8; - len -= 1; - } - } - outb(0, iobase + 135); - printk("first bytes = %02X %02X %02X %20X %02X %02X %02X\n",*start, start[1], start[2], start[3], start[4], start[5], start[6]); - return 1; -} -#endif -#undef STAT - -int NCR5380_proc_info(char *buffer, char **start, off_t offset, - int length, int hostno, int inout); - -#define BOARD_NORMAL 0 -#define BOARD_NCR53C400 1 - -#include "../../scsi/NCR5380.c" - -static Scsi_Host_Template ecoscsi_template = { - .module = THIS_MODULE, - .name = "Serial Port EcoSCSI NCR5380", - .detect = ecoscsi_detect, - .release = ecoscsi_release, - .info = ecoscsi_info, - .queuecommand = ecoscsi_queue_command, - .eh_abort_handler = NCR5380_abort, - .eh_device_reset_handler= NCR5380_device_reset, - .eh_bus_reset_handler = NCR5380_bus_reset, - .eh_host_reset_handler = NCR5380_host_reset, - .can_queue = 16, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 2, - .use_clustering = DISABLE_CLUSTERING -}; - -static int __init ecoscsi_init(void) -{ - scsi_register_host(&ecoscsi_template); - if (ecoscsi_template.present) - return 0; - - scsi_unregister_host(&ecoscsi_template); - return -ENODEV; -} - -static void __exit ecoscsi_exit(void) -{ - scsi_unregister_host(&ecoscsi_template); -} - -module_init(ecoscsi_init); -module_exit(ecoscsi_exit); - -MODULE_AUTHOR("Russell King"); -MODULE_DESCRIPTION("Econet-SCSI driver for Acorn machines"); -MODULE_LICENSE("GPL"); - diff -Nru a/drivers/acorn/scsi/eesox.c b/drivers/acorn/scsi/eesox.c --- a/drivers/acorn/scsi/eesox.c Sat May 24 12:48:33 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,705 +0,0 @@ -/* - * linux/drivers/acorn/scsi/eesox.c - * - * Copyright (C) 1997-2003 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This driver is based on experimentation. Hence, it may have made - * assumptions about the particular card that I have available, and - * may not be reliable! - * - * Changelog: - * 01-10-1997 RMK Created, READONLY version - * 15-02-1998 RMK READ/WRITE version - * added DMA support and hardware definitions - * 14-03-1998 RMK Updated DMA support - * Added terminator control - * 15-04-1998 RMK Only do PIO if FAS216 will allow it. - * 27-06-1998 RMK Changed asm/delay.h to linux/delay.h - * 02-04-2000 RMK 0.0.3 Fixed NO_IRQ/NO_DMA problem, updated for new - * error handling code. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "../../scsi/scsi.h" -#include "../../scsi/hosts.h" -#include "fas216.h" -#include "scsi.h" - -#include - -#define EESOX_FAS216_OFFSET 0x3000 -#define EESOX_FAS216_SHIFT 5 - -#define EESOX_DMASTAT 0x2800 -#define EESOX_STAT_INTR 0x01 -#define EESOX_STAT_DMA 0x02 - -#define EESOX_CONTROL 0x2800 -#define EESOX_INTR_ENABLE 0x04 -#define EESOX_TERM_ENABLE 0x02 -#define EESOX_RESET 0x01 - -#define EESOX_DMADATA 0x3800 - -#define VERSION "1.10 (17/01/2003 2.5.59)" - -/* - * Use term=0,1,0,0,0 to turn terminators on/off - */ -static int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 }; - -#define NR_SG 256 - -struct eesoxscsi_info { - FAS216_Info info; - struct expansion_card *ec; - - void *ctl_port; - unsigned int control; - struct scatterlist sg[NR_SG]; /* Scatter DMA list */ -}; - -/* Prototype: void eesoxscsi_irqenable(ec, irqnr) - * Purpose : Enable interrupts on EESOX SCSI card - * Params : ec - expansion card structure - * : irqnr - interrupt number - */ -static void -eesoxscsi_irqenable(struct expansion_card *ec, int irqnr) -{ - struct eesoxscsi_info *info = (struct eesoxscsi_info *)ec->irq_data; - - info->control |= EESOX_INTR_ENABLE; - - writeb(info->control, info->ctl_port); -} - -/* Prototype: void eesoxscsi_irqdisable(ec, irqnr) - * Purpose : Disable interrupts on EESOX SCSI card - * Params : ec - expansion card structure - * : irqnr - interrupt number - */ -static void -eesoxscsi_irqdisable(struct expansion_card *ec, int irqnr) -{ - struct eesoxscsi_info *info = (struct eesoxscsi_info *)ec->irq_data; - - info->control &= ~EESOX_INTR_ENABLE; - - writeb(info->control, info->ctl_port); -} - -static const expansioncard_ops_t eesoxscsi_ops = { - .irqenable = eesoxscsi_irqenable, - .irqdisable = eesoxscsi_irqdisable, -}; - -/* Prototype: void eesoxscsi_terminator_ctl(*host, on_off) - * Purpose : Turn the EESOX SCSI terminators on or off - * Params : host - card to turn on/off - * : on_off - !0 to turn on, 0 to turn off - */ -static void -eesoxscsi_terminator_ctl(struct Scsi_Host *host, int on_off) -{ - struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata; - unsigned long flags; - - spin_lock_irqsave(host->host_lock, flags); - if (on_off) - info->control |= EESOX_TERM_ENABLE; - else - info->control &= ~EESOX_TERM_ENABLE; - - writeb(info->control, info->ctl_port); - spin_unlock_irqrestore(host->host_lock, flags); -} - -/* Prototype: void eesoxscsi_intr(irq, *dev_id, *regs) - * Purpose : handle interrupts from EESOX SCSI card - * Params : irq - interrupt number - * dev_id - user-defined (Scsi_Host structure) - * regs - processor registers at interrupt - */ -static void -eesoxscsi_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - struct eesoxscsi_info *info = dev_id; - - fas216_intr(&info->info); -} - -/* Prototype: fasdmatype_t eesoxscsi_dma_setup(host, SCpnt, direction, min_type) - * Purpose : initialises DMA/PIO - * Params : host - host - * SCpnt - command - * direction - DMA on to/off of card - * min_type - minimum DMA support that we must have for this transfer - * Returns : type of transfer to be performed - */ -static fasdmatype_t -eesoxscsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp, - fasdmadir_t direction, fasdmatype_t min_type) -{ - struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata; - struct device *dev = scsi_get_device(host); - int dmach = host->dma_channel; - - if (dmach != NO_DMA && - (min_type == fasdma_real_all || SCp->this_residual >= 512)) { - int bufs, map_dir, dma_dir; - - bufs = copy_SCp_to_sg(&info->sg[0], SCp, NR_SG); - - if (direction == DMA_OUT) - map_dir = DMA_TO_DEVICE, - dma_dir = DMA_MODE_WRITE; - else - map_dir = DMA_FROM_DEVICE, - dma_dir = DMA_MODE_READ; - - dma_map_sg(dev, info->sg, bufs + 1, map_dir); - - disable_dma(dmach); - set_dma_sg(dmach, info->sg, bufs + 1); - set_dma_mode(dmach, dma_dir); - enable_dma(dmach); - return fasdma_real_all; - } - /* - * We don't do DMA, we only do slow PIO - * - * Some day, we will do Pseudo DMA - */ - return fasdma_pseudo; -} - -static void eesoxscsi_buffer_in(void *buf, int length, void *base) -{ - const void *reg_fas = base + EESOX_FAS216_OFFSET; - const void *reg_dmastat = base + EESOX_DMASTAT; - const void *reg_dmadata = base + EESOX_DMADATA; - const register unsigned long mask = 0xffff; - - do { - unsigned int status; - - /* - * Interrupt request? - */ - status = readb(reg_fas + (REG_STAT << EESOX_FAS216_SHIFT)); - if (status & STAT_INT) - break; - - /* - * DMA request active? - */ - status = readb(reg_dmastat); - if (!(status & EESOX_STAT_DMA)) - continue; - - /* - * Get number of bytes in FIFO - */ - status = readb(reg_fas + (REG_CFIS << EESOX_FAS216_SHIFT)) & CFIS_CF; - if (status > 16) - status = 16; - if (status > length) - status = length; - - /* - * Align buffer. - */ - if (((u32)buf) & 2 && status >= 2) { - *((u16 *)buf)++ = readl(reg_dmadata); - status -= 2; - length -= 2; - } - - if (status >= 8) { - unsigned long l1, l2; - - l1 = readl(reg_dmadata) & mask; - l1 |= readl(reg_dmadata) << 16; - l2 = readl(reg_dmadata) & mask; - l2 |= readl(reg_dmadata) << 16; - *((u32 *)buf)++ = l1; - *((u32 *)buf)++ = l2; - length -= 8; - continue; - } - - if (status >= 4) { - unsigned long l1; - - l1 = readl(reg_dmadata) & mask; - l1 |= readl(reg_dmadata) << 16; - - *((u32 *)buf)++ = l1; - length -= 4; - continue; - } - - if (status >= 2) { - *((u16 *)buf)++ = readl(reg_dmadata); - length -= 2; - } - } while (length); -} - -static void eesoxscsi_buffer_out(void *buf, int length, void *base) -{ - const void *reg_fas = base + EESOX_FAS216_OFFSET; - const void *reg_dmastat = base + EESOX_DMASTAT; - const void *reg_dmadata = base + EESOX_DMADATA; - - do { - unsigned int status; - - /* - * Interrupt request? - */ - status = readb(reg_fas + (REG_STAT << EESOX_FAS216_SHIFT)); - if (status & STAT_INT) - break; - - /* - * DMA request active? - */ - status = readb(reg_dmastat); - if (!(status & EESOX_STAT_DMA)) - continue; - - /* - * Get number of bytes in FIFO - */ - status = readb(reg_fas + (REG_CFIS << EESOX_FAS216_SHIFT)) & CFIS_CF; - if (status > 16) - status = 16; - status = 16 - status; - if (status > length) - status = length; - status &= ~1; - - /* - * Align buffer. - */ - if (((u32)buf) & 2 && status >= 2) { - writel(*((u16 *)buf)++ << 16, reg_dmadata); - status -= 2; - length -= 2; - } - - if (status >= 8) { - unsigned long l1, l2; - - l1 = *((u32 *)buf)++; - l2 = *((u32 *)buf)++; - - writel(l1 << 16, reg_dmadata); - writel(l1, reg_dmadata); - writel(l2 << 16, reg_dmadata); - writel(l2, reg_dmadata); - length -= 8; - continue; - } - - if (status >= 4) { - unsigned long l1; - - l1 = *((u32 *)buf)++; - - writel(l1 << 16, reg_dmadata); - writel(l1, reg_dmadata); - length -= 4; - continue; - } - - if (status >= 2) { - writel(*((u16 *)buf)++ << 16, reg_dmadata); - length -= 2; - } - } while (length); -} - -static void -eesoxscsi_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp, - fasdmadir_t dir, int transfer_size) -{ - void *base = (void *)host->base; - if (dir == DMA_IN) { - eesoxscsi_buffer_in(SCp->ptr, SCp->this_residual, base); - } else { - eesoxscsi_buffer_out(SCp->ptr, SCp->this_residual, base); - } -} - -/* Prototype: int eesoxscsi_dma_stop(host, SCpnt) - * Purpose : stops DMA/PIO - * Params : host - host - * SCpnt - command - */ -static void -eesoxscsi_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp) -{ - if (host->dma_channel != NO_DMA) - disable_dma(host->dma_channel); -} - -/* Prototype: const char *eesoxscsi_info(struct Scsi_Host * host) - * Purpose : returns a descriptive string about this interface, - * Params : host - driver host structure to return info for. - * Returns : pointer to a static buffer containing null terminated string. - */ -const char *eesoxscsi_info(struct Scsi_Host *host) -{ - struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata; - static char string[150]; - - sprintf(string, "%s (%s) in slot %d v%s terminators o%s", - host->hostt->name, info->info.scsi.type, info->ec->slot_no, - VERSION, info->control & EESOX_TERM_ENABLE ? "n" : "ff"); - - return string; -} - -/* Prototype: int eesoxscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length) - * Purpose : Set a driver specific function - * Params : host - host to setup - * : buffer - buffer containing string describing operation - * : length - length of string - * Returns : -EINVAL, or 0 - */ -static int -eesoxscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length) -{ - int ret = length; - - if (length >= 9 && strncmp(buffer, "EESOXSCSI", 9) == 0) { - buffer += 9; - length -= 9; - - if (length >= 5 && strncmp(buffer, "term=", 5) == 0) { - if (buffer[5] == '1') - eesoxscsi_terminator_ctl(host, 1); - else if (buffer[5] == '0') - eesoxscsi_terminator_ctl(host, 0); - else - ret = -EINVAL; - } else - ret = -EINVAL; - } else - ret = -EINVAL; - - return ret; -} - -/* Prototype: int eesoxscsi_proc_info(char *buffer, char **start, off_t offset, - * int length, int host_no, int inout) - * Purpose : Return information about the driver to a user process accessing - * the /proc filesystem. - * Params : buffer - a buffer to write information to - * start - a pointer into this buffer set by this routine to the start - * of the required information. - * offset - offset into information that we have read upto. - * length - length of buffer - * host_no - host number to return information for - * inout - 0 for reading, 1 for writing. - * Returns : length of data written to buffer. - */ -int eesoxscsi_proc_info(char *buffer, char **start, off_t offset, - int length, int host_no, int inout) -{ - int pos, begin; - struct Scsi_Host *host; - struct eesoxscsi_info *info; - Scsi_Device *scd; - - host = scsi_host_hn_get(host_no); - if (!host) - return 0; - - if (inout == 1) - return eesoxscsi_set_proc_info(host, buffer, length); - - info = (struct eesoxscsi_info *)host->hostdata; - - begin = 0; - pos = sprintf(buffer, "EESOX SCSI driver v%s\n", VERSION); - pos += fas216_print_host(&info->info, buffer + pos); - pos += sprintf(buffer + pos, "Term : o%s\n", - info->control & EESOX_TERM_ENABLE ? "n" : "ff"); - - pos += fas216_print_stats(&info->info, buffer + pos); - - pos += sprintf(buffer+pos, "\nAttached devices:\n"); - - list_for_each_entry(scd, &host->my_devices, siblings) { - int len; - - proc_print_scsidevice(scd, buffer, &len, pos); - pos += len; - pos += sprintf(buffer+pos, "Extensions: "); - if (scd->tagged_supported) - pos += sprintf(buffer+pos, "TAG %sabled [%d] ", - scd->tagged_queue ? "en" : "dis", - scd->current_tag); - pos += sprintf (buffer+pos, "\n"); - - if (pos + begin < offset) { - begin += pos; - pos = 0; - } - } - *start = buffer + (offset - begin); - pos -= offset - begin; - if (pos > length) - pos = length; - - return pos; -} - -static ssize_t eesoxscsi_show_term(struct device *dev, char *buf) -{ - struct expansion_card *ec = ECARD_DEV(dev); - struct Scsi_Host *host = ecard_get_drvdata(ec); - struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata; - - return sprintf(buf, "%d\n", info->control & EESOX_TERM_ENABLE ? 1 : 0); -} - -static ssize_t eesoxscsi_store_term(struct device *dev, const char *buf, size_t len) -{ - struct expansion_card *ec = ECARD_DEV(dev); - struct Scsi_Host *host = ecard_get_drvdata(ec); - struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata; - unsigned long flags; - - if (len > 1) { - spin_lock_irqsave(host->host_lock, flags); - if (buf[0] != '0') { - info->control |= EESOX_TERM_ENABLE; - } else { - info->control &= ~EESOX_TERM_ENABLE; - } - writeb(info->control, info->ctl_port); - spin_unlock_irqrestore(host->host_lock, flags); - } - - return len; -} - -static DEVICE_ATTR(bus_term, S_IRUGO | S_IWUSR, - eesoxscsi_show_term, eesoxscsi_store_term); - -static Scsi_Host_Template eesox_template = { - .module = THIS_MODULE, - .proc_info = eesoxscsi_proc_info, - .name = "EESOX SCSI", - .info = eesoxscsi_info, - .command = fas216_command, - .queuecommand = fas216_queue_command, - .eh_host_reset_handler = fas216_eh_host_reset, - .eh_bus_reset_handler = fas216_eh_bus_reset, - .eh_device_reset_handler = fas216_eh_device_reset, - .eh_abort_handler = fas216_eh_abort, - .can_queue = 1, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 1, - .use_clustering = DISABLE_CLUSTERING, - .proc_name = "eesox", -}; - -static int __devinit -eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id) -{ - struct Scsi_Host *host; - struct eesoxscsi_info *info; - unsigned long resbase, reslen; - unsigned char *base; - int ret; - - resbase = ecard_resource_start(ec, ECARD_RES_IOCFAST); - reslen = ecard_resource_len(ec, ECARD_RES_IOCFAST); - - if (!request_mem_region(resbase, reslen, "eesoxscsi")) { - ret = -EBUSY; - goto out; - } - - base = ioremap(resbase, reslen); - if (!base) { - ret = -ENOMEM; - goto out_region; - } - - host = scsi_register(&eesox_template, - sizeof(struct eesoxscsi_info)); - if (!host) { - ret = -ENOMEM; - goto out_unmap; - } - - host->base = (unsigned long)base; - host->irq = ec->irq; - host->dma_channel = ec->dma; - - ecard_set_drvdata(ec, host); - - info = (struct eesoxscsi_info *)host->hostdata; - info->ec = ec; - info->ctl_port = base + EESOX_CONTROL; - info->control = term[ec->slot_no] ? EESOX_TERM_ENABLE : 0; - writeb(info->control, info->ctl_port); - - ec->irqaddr = base + EESOX_DMASTAT; - ec->irqmask = EESOX_STAT_INTR; - ec->irq_data = info; - ec->ops = &eesoxscsi_ops; - - info->info.scsi.io_base = base + EESOX_FAS216_OFFSET; - info->info.scsi.io_shift = EESOX_FAS216_SHIFT; - info->info.scsi.irq = host->irq; - info->info.ifcfg.clockrate = 40; /* MHz */ - info->info.ifcfg.select_timeout = 255; - info->info.ifcfg.asyncperiod = 200; /* ns */ - info->info.ifcfg.sync_max_depth = 7; - info->info.ifcfg.cntl3 = CNTL3_FASTSCSI | CNTL3_FASTCLK; - info->info.ifcfg.disconnect_ok = 1; - info->info.ifcfg.wide_max_size = 0; - info->info.ifcfg.capabilities = FASCAP_PSEUDODMA; - info->info.dma.setup = eesoxscsi_dma_setup; - info->info.dma.pseudo = eesoxscsi_dma_pseudo; - info->info.dma.stop = eesoxscsi_dma_stop; - - device_create_file(&ec->dev, &dev_attr_bus_term); - - ret = fas216_init(host); - if (ret) - goto out_free; - - ret = request_irq(host->irq, eesoxscsi_intr, 0, "eesoxscsi", info); - if (ret) { - printk("scsi%d: IRQ%d not free: %d\n", - host->host_no, host->irq, ret); - goto out_remove; - } - - if (host->dma_channel != NO_DMA) { - if (request_dma(host->dma_channel, "eesox")) { - printk("scsi%d: DMA%d not free, DMA disabled\n", - host->host_no, host->dma_channel); - host->dma_channel = NO_DMA; - } else { - set_dma_speed(host->dma_channel, 180); - info->info.ifcfg.capabilities |= FASCAP_DMA; - info->info.ifcfg.cntl3 |= CNTL3_BS8; - } - } - - ret = fas216_add(host, &ec->dev); - if (ret == 0) - goto out; - - if (host->dma_channel != NO_DMA) - free_dma(host->dma_channel); - free_irq(host->irq, host); - - out_remove: - fas216_remove(host); - - out_free: - device_remove_file(&ec->dev, &dev_attr_bus_term); - scsi_unregister(host); - - out_unmap: - iounmap(base); - - out_region: - release_mem_region(resbase, reslen); - - out: - return ret; -} - -static void __devexit eesoxscsi_remove(struct expansion_card *ec) -{ - struct Scsi_Host *host = ecard_get_drvdata(ec); - struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata; - unsigned long resbase, reslen; - - ecard_set_drvdata(ec, NULL); - fas216_remove(host); - - if (host->dma_channel != NO_DMA) - free_dma(host->dma_channel); - free_irq(host->irq, info); - - device_remove_file(&ec->dev, &dev_attr_bus_term); - - iounmap((void *)host->base); - - resbase = ecard_resource_start(ec, ECARD_RES_IOCFAST); - reslen = ecard_resource_len(ec, ECARD_RES_IOCFAST); - - release_mem_region(resbase, reslen); - - fas216_release(host); - scsi_unregister(host); -} - -static const struct ecard_id eesoxscsi_cids[] = { - { MANU_EESOX, PROD_EESOX_SCSI2 }, - { 0xffff, 0xffff }, -}; - -static struct ecard_driver eesoxscsi_driver = { - .probe = eesoxscsi_probe, - .remove = __devexit_p(eesoxscsi_remove), - .id_table = eesoxscsi_cids, - .drv = { - .devclass = &shost_devclass, - .name = "eesoxscsi", - }, -}; - -static int __init eesox_init(void) -{ - return ecard_register_driver(&eesoxscsi_driver); -} - -static void __exit eesox_exit(void) -{ - ecard_remove_driver(&eesoxscsi_driver); -} - -module_init(eesox_init); -module_exit(eesox_exit); - -MODULE_AUTHOR("Russell King"); -MODULE_DESCRIPTION("EESOX 'Fast' SCSI driver for Acorn machines"); -MODULE_PARM(term, "1-8i"); -MODULE_PARM_DESC(term, "SCSI bus termination"); -MODULE_LICENSE("GPL"); - diff -Nru a/drivers/acorn/scsi/fas216.c b/drivers/acorn/scsi/fas216.c --- a/drivers/acorn/scsi/fas216.c Sat May 24 12:48:23 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,3228 +0,0 @@ -/* - * linux/drivers/acorn/scsi/fas216.c - * - * Copyright (C) 1997-2003 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Based on information in qlogicfas.c by Tom Zerucha, Michael Griffith, and - * other sources, including: - * the AMD Am53CF94 data sheet - * the AMD Am53C94 data sheet - * - * This is a generic driver. To use it, have a look at cumana_2.c. You - * should define your own structure that overlays FAS216_Info, eg: - * struct my_host_data { - * FAS216_Info info; - * ... my host specific data ... - * }; - * - * Changelog: - * 30-08-1997 RMK Created - * 14-09-1997 RMK Started disconnect support - * 08-02-1998 RMK Corrected real DMA support - * 15-02-1998 RMK Started sync xfer support - * 06-04-1998 RMK Tightened conditions for printing incomplete - * transfers - * 02-05-1998 RMK Added extra checks in fas216_reset - * 24-05-1998 RMK Fixed synchronous transfers with period >= 200ns - * 27-06-1998 RMK Changed asm/delay.h to linux/delay.h - * 26-08-1998 RMK Improved message support wrt MESSAGE_REJECT - * 02-04-2000 RMK Converted to use the new error handling, and - * automatically request sense data upon check - * condition status from targets. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "../../scsi/scsi.h" -#include "../../scsi/hosts.h" -#include "fas216.h" -#include "scsi.h" - -/* NOTE: SCSI2 Synchronous transfers *require* DMA according to - * the data sheet. This restriction is crazy, especially when - * you only want to send 16 bytes! What were the guys who - * designed this chip on at that time? Did they read the SCSI2 - * spec at all? The following sections are taken from the SCSI2 - * standard (s2r10) concerning this: - * - * > IMPLEMENTORS NOTES: - * > (1) Re-negotiation at every selection is not recommended, since a - * > significant performance impact is likely. - * - * > The implied synchronous agreement shall remain in effect until a BUS DEVICE - * > RESET message is received, until a hard reset condition occurs, or until one - * > of the two SCSI devices elects to modify the agreement. The default data - * > transfer mode is asynchronous data transfer mode. The default data transfer - * > mode is entered at power on, after a BUS DEVICE RESET message, or after a hard - * > reset condition. - * - * In total, this means that once you have elected to use synchronous - * transfers, you must always use DMA. - * - * I was thinking that this was a good chip until I found this restriction ;( - */ -#define SCSI2_SYNC -#undef SCSI2_WIDE -#undef SCSI2_TAG - -#undef DEBUG_CONNECT -#undef DEBUG_MESSAGES - -#undef CHECK_STRUCTURE - -#define LOG_CONNECT (1 << 0) -#define LOG_BUSSERVICE (1 << 1) -#define LOG_FUNCTIONDONE (1 << 2) -#define LOG_MESSAGES (1 << 3) -#define LOG_BUFFER (1 << 4) -#define LOG_ERROR (1 << 8) - -static int level_mask = LOG_ERROR; - -static int __init fas216_log_setup(char *str) -{ - char *s; - - level_mask = 0; - - while ((s = strsep(&str, ",")) != NULL) { - switch (s[0]) { - case 'a': - if (strcmp(s, "all") == 0) - level_mask |= -1; - break; - case 'b': - if (strncmp(s, "bus", 3) == 0) - level_mask |= LOG_BUSSERVICE; - if (strncmp(s, "buf", 3) == 0) - level_mask |= LOG_BUFFER; - break; - case 'c': - level_mask |= LOG_CONNECT; - break; - case 'e': - level_mask |= LOG_ERROR; - break; - case 'm': - level_mask |= LOG_MESSAGES; - break; - case 'n': - if (strcmp(s, "none") == 0) - level_mask = 0; - break; - case 's': - level_mask |= LOG_FUNCTIONDONE; - break; - } - } - return 1; -} - -__setup("fas216_logging=", fas216_log_setup); - -static inline unsigned char fas216_readb(FAS216_Info *info, unsigned int reg) -{ - unsigned int off = reg << info->scsi.io_shift; - if (info->scsi.io_base) - return readb(info->scsi.io_base + off); - else - return inb(info->scsi.io_port + off); -} - -static inline void fas216_writeb(FAS216_Info *info, unsigned int reg, unsigned int val) -{ - unsigned int off = reg << info->scsi.io_shift; - if (info->scsi.io_base) - writeb(val, info->scsi.io_base + off); - else - outb(val, info->scsi.io_port + off); -} - -static void fas216_dumpstate(FAS216_Info *info) -{ - unsigned char is, stat, inst; - - is = fas216_readb(info, REG_IS); - stat = fas216_readb(info, REG_STAT); - inst = fas216_readb(info, REG_INST); - - printk("FAS216: CTCL=%02X CTCM=%02X CMD=%02X STAT=%02X" - " INST=%02X IS=%02X CFIS=%02X", - fas216_readb(info, REG_CTCL), - fas216_readb(info, REG_CTCM), - fas216_readb(info, REG_CMD), stat, inst, is, - fas216_readb(info, REG_CFIS)); - printk(" CNTL1=%02X CNTL2=%02X CNTL3=%02X CTCH=%02X\n", - fas216_readb(info, REG_CNTL1), - fas216_readb(info, REG_CNTL2), - fas216_readb(info, REG_CNTL3), - fas216_readb(info, REG_CTCH)); -} - -static void print_SCp(Scsi_Pointer *SCp, const char *prefix, const char *suffix) -{ - printk("%sptr %p this_residual 0x%x buffer %p buffers_residual 0x%x%s", - prefix, SCp->ptr, SCp->this_residual, SCp->buffer, - SCp->buffers_residual, suffix); -} - -static void fas216_dumpinfo(FAS216_Info *info) -{ - static int used = 0; - int i; - - if (used++) - return; - - printk("FAS216_Info=\n"); - printk(" { magic_start=%lX host=%p SCpnt=%p origSCpnt=%p\n", - info->magic_start, info->host, info->SCpnt, - info->origSCpnt); - printk(" scsi={ io_port=%X io_shift=%X irq=%X cfg={ %X %X %X %X }\n", - info->scsi.io_port, info->scsi.io_shift, info->scsi.irq, - info->scsi.cfg[0], info->scsi.cfg[1], info->scsi.cfg[2], - info->scsi.cfg[3]); - printk(" type=%p phase=%X reconnected={ target=%d lun=%d tag=%d }\n", - info->scsi.type, info->scsi.phase, - info->scsi.reconnected.target, - info->scsi.reconnected.lun, info->scsi.reconnected.tag); - print_SCp(&info->scsi.SCp, " SCp={ ", " }\n"); - printk(" msgs async_stp=%X disconnectable=%d aborting=%d }\n", - info->scsi.async_stp, - info->scsi.disconnectable, info->scsi.aborting); - printk(" stats={ queues=%X removes=%X fins=%X reads=%X writes=%X miscs=%X\n" - " disconnects=%X aborts=%X bus_resets=%X host_resets=%X}\n", - info->stats.queues, info->stats.removes, info->stats.fins, - info->stats.reads, info->stats.writes, info->stats.miscs, - info->stats.disconnects, info->stats.aborts, info->stats.bus_resets, - info->stats.host_resets); - printk(" ifcfg={ clockrate=%X select_timeout=%X asyncperiod=%X sync_max_depth=%X }\n", - info->ifcfg.clockrate, info->ifcfg.select_timeout, - info->ifcfg.asyncperiod, info->ifcfg.sync_max_depth); - for (i = 0; i < 8; i++) { - printk(" busyluns[%d]=%08lx dev[%d]={ disconnect_ok=%d stp=%X sof=%X sync_state=%X }\n", - i, info->busyluns[i], i, - info->device[i].disconnect_ok, info->device[i].stp, - info->device[i].sof, info->device[i].sync_state); - } - printk(" dma={ transfer_type=%X setup=%p pseudo=%p stop=%p }\n", - info->dma.transfer_type, info->dma.setup, - info->dma.pseudo, info->dma.stop); - printk(" internal_done=%X magic_end=%lX }\n", - info->internal_done, info->magic_end); -} - -#ifdef CHECK_STRUCTURE -static void __fas216_checkmagic(FAS216_Info *info, const char *func) -{ - int corruption = 0; - if (info->magic_start != MAGIC) { - printk(KERN_CRIT "FAS216 Error: magic at start corrupted\n"); - corruption++; - } - if (info->magic_end != MAGIC) { - printk(KERN_CRIT "FAS216 Error: magic at end corrupted\n"); - corruption++; - } - if (corruption) { - fas216_dumpinfo(info); - panic("scsi memory space corrupted in %s", func); - } -} -#define fas216_checkmagic(info) __fas216_checkmagic((info), __FUNCTION__) -#else -#define fas216_checkmagic(info) -#endif - -static const char *fas216_bus_phase(int stat) -{ - static const char *phases[] = { - "DATA OUT", "DATA IN", - "COMMAND", "STATUS", - "MISC OUT", "MISC IN", - "MESG OUT", "MESG IN" - }; - - return phases[stat & STAT_BUSMASK]; -} - -static const char *fas216_drv_phase(FAS216_Info *info) -{ - switch (info->scsi.phase) { - case PHASE_IDLE: return "idle"; - case PHASE_SELECTION: return "selection"; - case PHASE_COMMAND: return "command"; - case PHASE_RECONNECTED: return "reconnected"; - case PHASE_DATAOUT: return "data out"; - case PHASE_DATAIN: return "data in"; - case PHASE_MSGIN: return "message in"; - case PHASE_MSGIN_DISCONNECT: return "disconnect"; - case PHASE_MSGOUT_EXPECT: return "expect message out"; - case PHASE_MSGOUT: return "message out"; - case PHASE_STATUS: return "status"; - case PHASE_DONE: return "done"; - default: return "???"; - } -} - -static char fas216_target(FAS216_Info *info) -{ - if (info->SCpnt) - return '0' + info->SCpnt->device->id; - else - return 'H'; -} - -static void -fas216_do_log(FAS216_Info *info, char target, char *fmt, va_list ap) -{ - static char buf[1024]; - - vsnprintf(buf, sizeof(buf), fmt, ap); - printk("scsi%d.%c: %s", info->host->host_no, target, buf); -} - -static void -fas216_log_command(FAS216_Info *info, int level, Scsi_Cmnd *SCpnt, char *fmt, ...) -{ - va_list args; - - if (level != 0 && !(level & level_mask)) - return; - - va_start(args, fmt); - fas216_do_log(info, '0' + SCpnt->device->id, fmt, args); - va_end(args); - - printk(" CDB: "); - print_command(SCpnt->cmnd); -} - -static void -fas216_log_target(FAS216_Info *info, int level, int target, char *fmt, ...) -{ - va_list args; - - if (level != 0 && !(level & level_mask)) - return; - - if (target < 0) - target = 'H'; - else - target += '0'; - - va_start(args, fmt); - fas216_do_log(info, target, fmt, args); - va_end(args); - - printk("\n"); -} - -static void fas216_log(FAS216_Info *info, int level, char *fmt, ...) -{ - va_list args; - - if (level != 0 && !(level & level_mask)) - return; - - va_start(args, fmt); - fas216_do_log(info, fas216_target(info), fmt, args); - va_end(args); - - printk("\n"); -} - -#define PH_SIZE 32 - -static struct { int stat, ssr, isr, ph; } ph_list[PH_SIZE]; -static int ph_ptr; - -static void add_debug_list(int stat, int ssr, int isr, int ph) -{ - ph_list[ph_ptr].stat = stat; - ph_list[ph_ptr].ssr = ssr; - ph_list[ph_ptr].isr = isr; - ph_list[ph_ptr].ph = ph; - - ph_ptr = (ph_ptr + 1) & (PH_SIZE-1); -} - -static struct { int command; void *from; } cmd_list[8]; -static int cmd_ptr; - -static void fas216_cmd(FAS216_Info *info, unsigned int command) -{ - cmd_list[cmd_ptr].command = command; - cmd_list[cmd_ptr].from = __builtin_return_address(0); - - cmd_ptr = (cmd_ptr + 1) & 7; - - fas216_writeb(info, REG_CMD, command); -} - -static void print_debug_list(void) -{ - int i; - - i = ph_ptr; - - printk(KERN_ERR "SCSI IRQ trail\n"); - do { - printk(" %02x:%02x:%02x:%1x", - ph_list[i].stat, ph_list[i].ssr, - ph_list[i].isr, ph_list[i].ph); - i = (i + 1) & (PH_SIZE - 1); - if (((i ^ ph_ptr) & 7) == 0) - printk("\n"); - } while (i != ph_ptr); - if ((i ^ ph_ptr) & 7) - printk("\n"); - - i = cmd_ptr; - printk(KERN_ERR "FAS216 commands: "); - do { - printk("%02x:%p ", cmd_list[i].command, cmd_list[i].from); - i = (i + 1) & 7; - } while (i != cmd_ptr); - printk("\n"); -} - -static void fas216_done(FAS216_Info *info, unsigned int result); - -/** - * fas216_clockrate - calculate clock conversion factor - * @clock: clock speed in MHz - * - * Calculate correct value to be written into clock conversion factor - * register. Returns CLKF_ value. - */ -static int fas216_clockrate(int clock) -{ - if (clock <= 10 || clock > 40) { - printk(KERN_CRIT - "fas216: invalid clock rate: check your driver!\n"); - clock = -1; - } else - clock = ((clock - 1) / 5 + 1) & 7; - - return clock; -} - -/** - * fas216_get_last_msg - retrive last message from the list - * @info: interface to search - * @pos: current fifo position - * - * Retrieve a last message from the list, using position in fifo. - */ -static inline unsigned short -fas216_get_last_msg(FAS216_Info *info, int pos) -{ - unsigned short packed_msg = NOP; - struct message *msg; - int msgnr = 0; - - while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) { - if (pos >= msg->fifo) - break; - } - - if (msg) { - if (msg->msg[0] == EXTENDED_MESSAGE) - packed_msg = EXTENDED_MESSAGE | msg->msg[2] << 8; - else - packed_msg = msg->msg[0]; - } - - fas216_log(info, LOG_MESSAGES, - "Message: %04x found at position %02x\n", packed_msg, pos); - - return packed_msg; -} - -/** - * fas216_syncperiod - calculate STP register value - * @info: state structure for interface connected to device - * @ns: period in ns (between subsequent bytes) - * - * Calculate value to be loaded into the STP register for a given period - * in ns. Returns a value suitable for REG_STP. - */ -static int fas216_syncperiod(FAS216_Info *info, int ns) -{ - int value = (info->ifcfg.clockrate * ns) / 1000; - - fas216_checkmagic(info); - - if (value < 4) - value = 4; - else if (value > 35) - value = 35; - - return value & 31; -} - -/** - * fas216_set_sync - setup FAS216 chip for specified transfer period. - * @info: state structure for interface connected to device - * @target: target - * - * Correctly setup FAS216 chip for specified transfer period. - * Notes : we need to switch the chip out of FASTSCSI mode if we have - * a transfer period >= 200ns - otherwise the chip will violate - * the SCSI timings. - */ -static void fas216_set_sync(FAS216_Info *info, int target) -{ - unsigned int cntl3; - - fas216_writeb(info, REG_SOF, info->device[target].sof); - fas216_writeb(info, REG_STP, info->device[target].stp); - - cntl3 = info->scsi.cfg[2]; - if (info->device[target].period >= (200 / 4)) - cntl3 = cntl3 & ~CNTL3_FASTSCSI; - - fas216_writeb(info, REG_CNTL3, cntl3); -} - -/* Synchronous transfer support - * - * Note: The SCSI II r10 spec says (5.6.12): - * - * (2) Due to historical problems with early host adapters that could - * not accept an SDTR message, some targets may not initiate synchronous - * negotiation after a power cycle as required by this standard. Host - * adapters that support synchronous mode may avoid the ensuing failure - * modes when the target is independently power cycled by initiating a - * synchronous negotiation on each REQUEST SENSE and INQUIRY command. - * This approach increases the SCSI bus overhead and is not recommended - * for new implementations. The correct method is to respond to an - * SDTR message with a MESSAGE REJECT message if the either the - * initiator or target devices does not support synchronous transfers - * or does not want to negotiate for synchronous transfers at the time. - * Using the correct method assures compatibility with wide data - * transfers and future enhancements. - * - * We will always initiate a synchronous transfer negotiation request on - * every INQUIRY or REQUEST SENSE message, unless the target itself has - * at some point performed a synchronous transfer negotiation request, or - * we have synchronous transfers disabled for this device. - */ - -/** - * fas216_handlesync - Handle a synchronous transfer message - * @info: state structure for interface - * @msg: message from target - * - * Handle a synchronous transfer message from the target - */ -static void fas216_handlesync(FAS216_Info *info, char *msg) -{ - struct fas216_device *dev = &info->device[info->SCpnt->device->id]; - enum { sync, async, none, reject } res = none; - -#ifdef SCSI2_SYNC - switch (msg[0]) { - case MESSAGE_REJECT: - /* Synchronous transfer request failed. - * Note: SCSI II r10: - * - * SCSI devices that are capable of synchronous - * data transfers shall not respond to an SDTR - * message with a MESSAGE REJECT message. - * - * Hence, if we get this condition, we disable - * negotiation for this device. - */ - if (dev->sync_state == neg_inprogress) { - dev->sync_state = neg_invalid; - res = async; - } - break; - - case EXTENDED_MESSAGE: - switch (dev->sync_state) { - /* We don't accept synchronous transfer requests. - * Respond with a MESSAGE_REJECT to prevent a - * synchronous transfer agreement from being reached. - */ - case neg_invalid: - res = reject; - break; - - /* We were not negotiating a synchronous transfer, - * but the device sent us a negotiation request. - * Honour the request by sending back a SDTR - * message containing our capability, limited by - * the targets capability. - */ - default: - fas216_cmd(info, CMD_SETATN); - if (msg[4] > info->ifcfg.sync_max_depth) - msg[4] = info->ifcfg.sync_max_depth; - if (msg[3] < 1000 / info->ifcfg.clockrate) - msg[3] = 1000 / info->ifcfg.clockrate; - - msgqueue_flush(&info->scsi.msgs); - msgqueue_addmsg(&info->scsi.msgs, 5, - EXTENDED_MESSAGE, 3, EXTENDED_SDTR, - msg[3], msg[4]); - info->scsi.phase = PHASE_MSGOUT_EXPECT; - - /* This is wrong. The agreement is not in effect - * until this message is accepted by the device - */ - dev->sync_state = neg_targcomplete; - res = sync; - break; - - /* We initiated the synchronous transfer negotiation, - * and have successfully received a response from the - * target. The synchronous transfer agreement has been - * reached. Note: if the values returned are out of our - * bounds, we must reject the message. - */ - case neg_inprogress: - res = reject; - if (msg[4] <= info->ifcfg.sync_max_depth && - msg[3] >= 1000 / info->ifcfg.clockrate) { - dev->sync_state = neg_complete; - res = sync; - } - break; - } - } -#else - res = reject; -#endif - - switch (res) { - case sync: - dev->period = msg[3]; - dev->sof = msg[4]; - dev->stp = fas216_syncperiod(info, msg[3] * 4); - fas216_set_sync(info, info->SCpnt->device->id); - break; - - case reject: - fas216_cmd(info, CMD_SETATN); - msgqueue_flush(&info->scsi.msgs); - msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); - info->scsi.phase = PHASE_MSGOUT_EXPECT; - - case async: - dev->period = info->ifcfg.asyncperiod / 4; - dev->sof = 0; - dev->stp = info->scsi.async_stp; - fas216_set_sync(info, info->SCpnt->device->id); - break; - - case none: - break; - } -} - -/** - * fas216_handlewide - Handle a wide transfer message - * @info: state structure for interface - * @msg: message from target - * - * Handle a wide transfer message from the target - */ -static void fas216_handlewide(FAS216_Info *info, char *msg) -{ - struct fas216_device *dev = &info->device[info->SCpnt->device->id]; - enum { wide, bit8, none, reject } res = none; - -#ifdef SCSI2_WIDE - switch (msg[0]) { - case MESSAGE_REJECT: - /* Wide transfer request failed. - * Note: SCSI II r10: - * - * SCSI devices that are capable of wide - * data transfers shall not respond to a - * WDTR message with a MESSAGE REJECT message. - * - * Hence, if we get this condition, we never - * reattempt negotiation for this device. - */ - if (dev->wide_state == neg_inprogress) { - dev->wide_state = neg_invalid; - res = bit8; - } - break; - - case EXTENDED_MESSAGE: - switch (dev->wide_state) { - /* We don't accept wide data transfer requests. - * Respond with a MESSAGE REJECT to prevent a - * wide data transfer agreement from being reached. - */ - case neg_invalid: - res = reject; - break; - - /* We were not negotiating a wide data transfer, - * but the device sent is a negotiation request. - * Honour the request by sending back a WDTR - * message containing our capability, limited by - * the targets capability. - */ - default: - fas216_cmd(info, CMD_SETATN); - if (msg[3] > info->ifcfg.wide_max_size) - msg[3] = info->ifcfg.wide_max_size; - - msgqueue_flush(&info->scsi.msgs); - msgqueue_addmsg(&info->scsi.msgs, 4, - EXTENDED_MESSAGE, 2, EXTENDED_WDTR, - msg[3]); - info->scsi.phase = PHASE_MSGOUT_EXPECT; - res = wide; - break; - - /* We initiated the wide data transfer negotiation, - * and have successfully received a response from the - * target. The synchronous transfer agreement has been - * reached. Note: if the values returned are out of our - * bounds, we must reject the message. - */ - case neg_inprogress: - res = reject; - if (msg[3] <= info->ifcfg.wide_max_size) { - dev->wide_state = neg_complete; - res = wide; - } - break; - } - } -#else - res = reject; -#endif - - switch (res) { - case wide: - dev->wide_xfer = msg[3]; - break; - - case reject: - fas216_cmd(info, CMD_SETATN); - msgqueue_flush(&info->scsi.msgs); - msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); - info->scsi.phase = PHASE_MSGOUT_EXPECT; - - case bit8: - dev->wide_xfer = 0; - break; - - case none: - break; - } -} - -/** - * fas216_updateptrs - update data pointers after transfer suspended/paused - * @info: interface's local pointer to update - * @bytes_transferred: number of bytes transferred - * - * Update data pointers after transfer suspended/paused - */ -static void fas216_updateptrs(FAS216_Info *info, int bytes_transferred) -{ - Scsi_Pointer *SCp = &info->scsi.SCp; - - fas216_checkmagic(info); - - BUG_ON(bytes_transferred < 0); - - info->SCpnt->request_bufflen -= bytes_transferred; - - while (bytes_transferred != 0) { - if (SCp->this_residual > bytes_transferred) - break; - /* - * We have used up this buffer. Move on to the - * next buffer. - */ - bytes_transferred -= SCp->this_residual; - if (!next_SCp(SCp) && bytes_transferred) { - printk(KERN_WARNING "scsi%d.%c: out of buffers\n", - info->host->host_no, '0' + info->SCpnt->device->id); - return; - } - } - - SCp->this_residual -= bytes_transferred; - if (SCp->this_residual) - SCp->ptr += bytes_transferred; - else - SCp->ptr = NULL; -} - -/** - * fas216_pio - transfer data off of/on to card using programmed IO - * @info: interface to transfer data to/from - * @direction: direction to transfer data (DMA_OUT/DMA_IN) - * - * Transfer data off of/on to card using programmed IO. - * Notes: this is incredibly slow. - */ -static void fas216_pio(FAS216_Info *info, fasdmadir_t direction) -{ - Scsi_Pointer *SCp = &info->scsi.SCp; - - fas216_checkmagic(info); - - if (direction == DMA_OUT) - fas216_writeb(info, REG_FF, get_next_SCp_byte(SCp)); - else - put_next_SCp_byte(SCp, fas216_readb(info, REG_FF)); - - if (SCp->this_residual == 0) - next_SCp(SCp); -} - -static void fas216_set_stc(FAS216_Info *info, unsigned int length) -{ - fas216_writeb(info, REG_STCL, length); - fas216_writeb(info, REG_STCM, length >> 8); - fas216_writeb(info, REG_STCH, length >> 16); -} - -static unsigned int fas216_get_ctc(FAS216_Info *info) -{ - return fas216_readb(info, REG_CTCL) + - (fas216_readb(info, REG_CTCM) << 8) + - (fas216_readb(info, REG_CTCH) << 16); -} - -/** - * fas216_cleanuptransfer - clean up after a transfer has completed. - * @info: interface to clean up - * - * Update the data pointers according to the number of bytes transferred - * on the SCSI bus. - */ -static void fas216_cleanuptransfer(FAS216_Info *info) -{ - unsigned long total, residual, fifo; - fasdmatype_t dmatype = info->dma.transfer_type; - - info->dma.transfer_type = fasdma_none; - - /* - * PIO transfers do not need to be cleaned up. - */ - if (dmatype == fasdma_pio || dmatype == fasdma_none) - return; - - if (dmatype == fasdma_real_all) - total = info->SCpnt->request_bufflen; - else - total = info->scsi.SCp.this_residual; - - residual = fas216_get_ctc(info); - - fifo = fas216_readb(info, REG_CFIS) & CFIS_CF; - - fas216_log(info, LOG_BUFFER, "cleaning up from previous " - "transfer: length 0x%06x, residual 0x%x, fifo %d", - total, residual, fifo); - - /* - * If we were performing Data-Out, the transfer counter - * counts down each time a byte is transferred by the - * host to the FIFO. This means we must include the - * bytes left in the FIFO from the transfer counter. - */ - if (info->scsi.phase == PHASE_DATAOUT) - residual += fifo; - - fas216_updateptrs(info, total - residual); -} - -/** - * fas216_transfer - Perform a DMA/PIO transfer off of/on to card - * @info: interface from which device disconnected from - * - * Start a DMA/PIO transfer off of/on to card - */ -static void fas216_transfer(FAS216_Info *info) -{ - fasdmadir_t direction; - fasdmatype_t dmatype; - - fas216_log(info, LOG_BUFFER, - "starttransfer: buffer %p length 0x%06x reqlen 0x%06x", - info->scsi.SCp.ptr, info->scsi.SCp.this_residual, - info->SCpnt->request_bufflen); - - if (!info->scsi.SCp.ptr) { - fas216_log(info, LOG_ERROR, "null buffer passed to " - "fas216_starttransfer"); - print_SCp(&info->scsi.SCp, "SCp: ", "\n"); - print_SCp(&info->SCpnt->SCp, "Cmnd SCp: ", "\n"); - return; - } - - /* - * If we have a synchronous transfer agreement in effect, we must - * use DMA mode. If we are using asynchronous transfers, we may - * use DMA mode or PIO mode. - */ - if (info->device[info->SCpnt->device->id].sof) - dmatype = fasdma_real_all; - else - dmatype = fasdma_pio; - - if (info->scsi.phase == PHASE_DATAOUT) - direction = DMA_OUT; - else - direction = DMA_IN; - - if (info->dma.setup) - dmatype = info->dma.setup(info->host, &info->scsi.SCp, - direction, dmatype); - info->dma.transfer_type = dmatype; - - if (dmatype == fasdma_real_all) - fas216_set_stc(info, info->SCpnt->request_bufflen); - else - fas216_set_stc(info, info->scsi.SCp.this_residual); - - switch (dmatype) { - case fasdma_pio: - fas216_log(info, LOG_BUFFER, "PIO transfer"); - fas216_writeb(info, REG_SOF, 0); - fas216_writeb(info, REG_STP, info->scsi.async_stp); - fas216_cmd(info, CMD_TRANSFERINFO); - fas216_pio(info, direction); - break; - - case fasdma_pseudo: - fas216_log(info, LOG_BUFFER, "pseudo transfer"); - fas216_cmd(info, CMD_TRANSFERINFO | CMD_WITHDMA); - info->dma.pseudo(info->host, &info->scsi.SCp, - direction, info->SCpnt->transfersize); - break; - - case fasdma_real_block: - fas216_log(info, LOG_BUFFER, "block dma transfer"); - fas216_cmd(info, CMD_TRANSFERINFO | CMD_WITHDMA); - break; - - case fasdma_real_all: - fas216_log(info, LOG_BUFFER, "total dma transfer"); - fas216_cmd(info, CMD_TRANSFERINFO | CMD_WITHDMA); - break; - - default: - fas216_log(info, LOG_BUFFER | LOG_ERROR, - "invalid FAS216 DMA type"); - break; - } -} - -/** - * fas216_stoptransfer - Stop a DMA transfer onto / off of the card - * @info: interface from which device disconnected from - * - * Called when we switch away from DATA IN or DATA OUT phases. - */ -static void fas216_stoptransfer(FAS216_Info *info) -{ - fas216_checkmagic(info); - - if (info->dma.transfer_type == fasdma_real_all || - info->dma.transfer_type == fasdma_real_block) - info->dma.stop(info->host, &info->scsi.SCp); - - fas216_cleanuptransfer(info); - - if (info->scsi.phase == PHASE_DATAIN) { - unsigned int fifo; - - /* - * If we were performing Data-In, then the FIFO counter - * contains the number of bytes not transferred via DMA - * from the on-board FIFO. Read them manually. - */ - fifo = fas216_readb(info, REG_CFIS) & CFIS_CF; - while (fifo && info->scsi.SCp.ptr) { - *info->scsi.SCp.ptr = fas216_readb(info, REG_FF); - fas216_updateptrs(info, 1); - fifo--; - } - } else { - /* - * After a Data-Out phase, there may be unsent - * bytes left in the FIFO. Flush them out. - */ - fas216_cmd(info, CMD_FLUSHFIFO); - } -} - -static void fas216_aborttransfer(FAS216_Info *info) -{ - fas216_checkmagic(info); - - if (info->dma.transfer_type == fasdma_real_all || - info->dma.transfer_type == fasdma_real_block) - info->dma.stop(info->host, &info->scsi.SCp); - - info->dma.transfer_type = fasdma_none; - fas216_cmd(info, CMD_FLUSHFIFO); -} - -/** - * fas216_disconnected_intr - handle device disconnection - * @info: interface from which device disconnected from - * - * Handle device disconnection - */ -static void fas216_disconnect_intr(FAS216_Info *info) -{ - fas216_checkmagic(info); - - fas216_log(info, LOG_CONNECT, "disconnect phase=%02x", - info->scsi.phase); - - msgqueue_flush(&info->scsi.msgs); - - fas216_cmd(info, CMD_ENABLESEL); - - switch (info->scsi.phase) { - case PHASE_SELECTION: /* while selecting - no target */ - case PHASE_SELSTEPS: - fas216_done(info, DID_NO_CONNECT); - break; - - case PHASE_MSGIN_DISCONNECT: /* message in - disconnecting */ - info->scsi.disconnectable = 1; - info->scsi.reconnected.tag = 0; - info->scsi.phase = PHASE_IDLE; - info->stats.disconnects += 1; - break; - - case PHASE_DONE: /* at end of command - complete */ - fas216_done(info, DID_OK); - break; - - case PHASE_MSGOUT: /* message out - possible ABORT message */ - if (fas216_get_last_msg(info, info->scsi.msgin_fifo) == ABORT) { - info->scsi.aborting = 0; - fas216_done(info, DID_ABORT); - break; - } - - default: /* huh? */ - printk(KERN_ERR "scsi%d.%c: unexpected disconnect in phase %s\n", - info->host->host_no, fas216_target(info), fas216_drv_phase(info)); - print_debug_list(); - fas216_stoptransfer(info); - fas216_done(info, DID_ERROR); - break; - } -} - -/** - * fas216_reselected_intr - start reconnection of a device - * @info: interface which was reselected - * - * Start reconnection of a device - */ -static void -fas216_reselected_intr(FAS216_Info *info) -{ - unsigned char target, identify_msg, ok; - - fas216_checkmagic(info); - - if ((info->scsi.phase == PHASE_SELECTION || - info->scsi.phase == PHASE_SELSTEPS) && info->SCpnt) { - Scsi_Cmnd *SCpnt = info->SCpnt; - - info->origSCpnt = SCpnt; - info->SCpnt = NULL; - - if (info->device[SCpnt->device->id].wide_state == neg_inprogress) - info->device[SCpnt->device->id].wide_state = neg_wait; - if (info->device[SCpnt->device->id].sync_state == neg_inprogress) - info->device[SCpnt->device->id].sync_state = neg_wait; - } - - fas216_log(info, LOG_CONNECT, "reconnect phase=%02X", info->scsi.phase); - - if ((fas216_readb(info, REG_CFIS) & CFIS_CF) != 2) { - printk(KERN_ERR "scsi%d.H: incorrect number of bytes after reselect\n", - info->host->host_no); - goto initiator_error; - } - - target = fas216_readb(info, REG_FF); - identify_msg = fas216_readb(info, REG_FF); - - ok = 1; - if (!(target & (1 << info->host->this_id))) { - printk(KERN_ERR "scsi%d.H: invalid host id on reselect\n", info->host->host_no); - ok = 0; - } - - if (!(identify_msg & 0x80)) { - printk(KERN_ERR "scsi%d.H: no IDENTIFY message on reselect, got msg %02X\n", - info->host->host_no, identify_msg); - ok = 0; - } - - if (!ok) { - /* - * Something went wrong - send an initiator error to - * the target. - */ - goto initiator_error; - } - - target &= ~(1 << info->host->this_id); - target = ffs(target) - 1; - - identify_msg &= 7; - info->scsi.reconnected.target = target; - info->scsi.reconnected.lun = identify_msg; - info->scsi.reconnected.tag = 0; - - /* set up for synchronous transfers */ - fas216_set_sync(info, target); - - ok = 0; - if (info->scsi.disconnectable && info->SCpnt && - info->SCpnt->device->id == target && info->SCpnt->device->lun == identify_msg) - ok = 1; - - if (!ok && queue_probetgtlun(&info->queues.disconnected, target, identify_msg)) - ok = 1; - - msgqueue_flush(&info->scsi.msgs); - if (ok) { - info->scsi.phase = PHASE_RECONNECTED; - fas216_writeb(info, REG_SDID, target); - } else { - /* - * Our command structure not found - abort the - * command on the target. Since we have no - * record of this command, we can't send - * an INITIATOR DETECTED ERROR message. - */ - fas216_cmd(info, CMD_SETATN); - msgqueue_addmsg(&info->scsi.msgs, 1, ABORT); - info->scsi.phase = PHASE_MSGOUT_EXPECT; - } - - fas216_cmd(info, CMD_MSGACCEPTED); - return; - - initiator_error: - fas216_cmd(info, CMD_SETATN); - msgqueue_flush(&info->scsi.msgs); - msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); - info->scsi.phase = PHASE_MSGOUT_EXPECT; - fas216_cmd(info, CMD_MSGACCEPTED); -} - -/** - * fas216_finish_reconnect - finish reconnection sequence for device - * @info: interface which caused function done interrupt - * - * Finish reconnection sequence for device - */ -static void -fas216_finish_reconnect(FAS216_Info *info) -{ - fas216_checkmagic(info); - - fas216_log(info, LOG_CONNECT, "Connected: %1x %1x %02x, reconnected: %1x %1x %02x", - info->SCpnt->device->id, info->SCpnt->device->lun, info->SCpnt->tag, - info->scsi.reconnected.target, info->scsi.reconnected.lun, - info->scsi.reconnected.tag); - - if (info->scsi.disconnectable && info->SCpnt) { - info->scsi.disconnectable = 0; - if (info->SCpnt->device->id == info->scsi.reconnected.target && - info->SCpnt->device->lun == info->scsi.reconnected.lun && - info->SCpnt->tag == info->scsi.reconnected.tag) { - fas216_log(info, LOG_CONNECT, "reconnected"); - } else { - queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt); - fas216_log(info, LOG_CONNECT, "had to move command to disconnected queue"); - info->SCpnt = NULL; - } - } - if (!info->SCpnt) { - info->SCpnt = queue_remove_tgtluntag(&info->queues.disconnected, - info->scsi.reconnected.target, - info->scsi.reconnected.lun, - info->scsi.reconnected.tag); - fas216_log(info, LOG_CONNECT, "had to get command"); - } - if (!info->SCpnt) { - fas216_cmd(info, CMD_SETATN); - msgqueue_flush(&info->scsi.msgs); - -#if 0 - if (info->scsi.reconnected.tag) - msgqueue_addmsg(&info->scsi.msgs, 2, ABORT_TAG, info->scsi.reconnected.tag); - else -#endif - msgqueue_addmsg(&info->scsi.msgs, 1, ABORT); - - info->scsi.phase = PHASE_MSGOUT_EXPECT; - info->scsi.aborting = 1; - } else { - /* - * Restore data pointer from SAVED data pointer - */ - info->scsi.SCp = info->SCpnt->SCp; - fas216_log(info, LOG_CONNECT, "data pointers: [%p, %X]", - info->scsi.SCp.ptr, info->scsi.SCp.this_residual); - } -} - -static void fas216_parse_message(FAS216_Info *info, unsigned char *message, int msglen) -{ - int i; - - switch (message[0]) { - case COMMAND_COMPLETE: - if (msglen != 1) - goto unrecognised; - - printk(KERN_ERR "scsi%d.%c: command complete with no " - "status in MESSAGE_IN?\n", - info->host->host_no, fas216_target(info)); - break; - - case SAVE_POINTERS: - if (msglen != 1) - goto unrecognised; - - /* - * Save current data pointer to SAVED data pointer - * SCSI II standard says that we must not acknowledge - * this until we have really saved pointers. - * NOTE: we DO NOT save the command nor status pointers - * as required by the SCSI II standard. These always - * point to the start of their respective areas. - */ - info->SCpnt->SCp = info->scsi.SCp; - info->SCpnt->SCp.sent_command = 0; - fas216_log(info, LOG_CONNECT | LOG_MESSAGES | LOG_BUFFER, - "save data pointers: [%p, %X]", - info->scsi.SCp.ptr, info->scsi.SCp.this_residual); - break; - - case RESTORE_POINTERS: - if (msglen != 1) - goto unrecognised; - - /* - * Restore current data pointer from SAVED data pointer - */ - info->scsi.SCp = info->SCpnt->SCp; - fas216_log(info, LOG_CONNECT | LOG_MESSAGES | LOG_BUFFER, - "restore data pointers: [%p, 0x%x]", - info->scsi.SCp.ptr, info->scsi.SCp.this_residual); - break; - - case DISCONNECT: - if (msglen != 1) - goto unrecognised; - - info->scsi.phase = PHASE_MSGIN_DISCONNECT; - break; - - case MESSAGE_REJECT: - if (msglen != 1) - goto unrecognised; - - switch (fas216_get_last_msg(info, info->scsi.msgin_fifo)) { - case EXTENDED_MESSAGE | EXTENDED_SDTR << 8: - fas216_handlesync(info, message); - break; - - case EXTENDED_MESSAGE | EXTENDED_WDTR << 8: - fas216_handlewide(info, message); - break; - - default: - fas216_log(info, 0, "reject, last message 0x%04x", - fas216_get_last_msg(info, info->scsi.msgin_fifo)); - } - break; - - case NOP: - break; - - case SIMPLE_QUEUE_TAG: - if (msglen < 2) - goto unrecognised; - - /* handled above - print a warning since this is untested */ - fas216_log(info, 0, "reconnect queue tag 0x%02x", message[1]); - break; - - case EXTENDED_MESSAGE: - if (msglen < 3) - goto unrecognised; - - switch (message[2]) { - case EXTENDED_SDTR: /* Sync transfer negotiation request/reply */ - fas216_handlesync(info, message); - break; - - case EXTENDED_WDTR: /* Wide transfer negotiation request/reply */ - fas216_handlewide(info, message); - break; - - default: - goto unrecognised; - } - break; - - default: - goto unrecognised; - } - return; - -unrecognised: - fas216_log(info, 0, "unrecognised message, rejecting"); - printk("scsi%d.%c: message was", info->host->host_no, fas216_target(info)); - for (i = 0; i < msglen; i++) - printk("%s%02X", i & 31 ? " " : "\n ", message[i]); - printk("\n"); - - /* - * Something strange seems to be happening here - - * I can't use SETATN since the chip gives me an - * invalid command interrupt when I do. Weird. - */ -fas216_cmd(info, CMD_NOP); -fas216_dumpstate(info); - fas216_cmd(info, CMD_SETATN); - msgqueue_flush(&info->scsi.msgs); - msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); - info->scsi.phase = PHASE_MSGOUT_EXPECT; -fas216_dumpstate(info); -} - -static int fas216_wait_cmd(FAS216_Info *info, int cmd) -{ - int tout; - int stat; - - fas216_cmd(info, cmd); - - for (tout = 1000; tout; tout -= 1) { - stat = fas216_readb(info, REG_STAT); - if (stat & (STAT_INT|STAT_PARITYERROR)) - break; - udelay(1); - } - - return stat; -} - -static int fas216_get_msg_byte(FAS216_Info *info) -{ - unsigned int stat = fas216_wait_cmd(info, CMD_MSGACCEPTED); - - if ((stat & STAT_INT) == 0) - goto timedout; - - if ((stat & STAT_BUSMASK) != STAT_MESGIN) - goto unexpected_phase_change; - - fas216_readb(info, REG_INST); - - stat = fas216_wait_cmd(info, CMD_TRANSFERINFO); - - if ((stat & STAT_INT) == 0) - goto timedout; - - if (stat & STAT_PARITYERROR) - goto parity_error; - - if ((stat & STAT_BUSMASK) != STAT_MESGIN) - goto unexpected_phase_change; - - fas216_readb(info, REG_INST); - - return fas216_readb(info, REG_FF); - -timedout: - fas216_log(info, LOG_ERROR, "timed out waiting for message byte"); - return -1; - -unexpected_phase_change: - fas216_log(info, LOG_ERROR, "unexpected phase change: status = %02x", stat); - return -2; - -parity_error: - fas216_log(info, LOG_ERROR, "parity error during message in phase"); - return -3; -} - -/** - * fas216_message - handle a function done interrupt from FAS216 chip - * @info: interface which caused function done interrupt - * - * Handle a function done interrupt from FAS216 chip - */ -static void fas216_message(FAS216_Info *info) -{ - unsigned char *message = info->scsi.message; - unsigned int msglen = 1; - int msgbyte = 0; - - fas216_checkmagic(info); - - message[0] = fas216_readb(info, REG_FF); - - if (message[0] == EXTENDED_MESSAGE) { - msgbyte = fas216_get_msg_byte(info); - - if (msgbyte >= 0) { - message[1] = msgbyte; - - for (msglen = 2; msglen < message[1] + 2; msglen++) { - msgbyte = fas216_get_msg_byte(info); - - if (msgbyte >= 0) - message[msglen] = msgbyte; - else - break; - } - } - } - - if (msgbyte == -3) - goto parity_error; - -#ifdef DEBUG_MESSAGES - { - int i; - - printk("scsi%d.%c: message in: ", - info->host->host_no, fas216_target(info)); - for (i = 0; i < msglen; i++) - printk("%02X ", message[i]); - printk("\n"); - } -#endif - - if (info->scsi.phase == PHASE_RECONNECTED) { - if (message[0] == SIMPLE_QUEUE_TAG) - info->scsi.reconnected.tag = message[1]; - fas216_finish_reconnect(info); - info->scsi.phase = PHASE_MSGIN; - } - - fas216_parse_message(info, message, msglen); - fas216_cmd(info, CMD_MSGACCEPTED); - return; - -parity_error: - fas216_cmd(info, CMD_SETATN); - msgqueue_flush(&info->scsi.msgs); - msgqueue_addmsg(&info->scsi.msgs, 1, MSG_PARITY_ERROR); - info->scsi.phase = PHASE_MSGOUT_EXPECT; - fas216_cmd(info, CMD_MSGACCEPTED); - return; -} - -/** - * fas216_send_command - send command after all message bytes have been sent - * @info: interface which caused bus service - * - * Send a command to a target after all message bytes have been sent - */ -static void fas216_send_command(FAS216_Info *info) -{ - int i; - - fas216_checkmagic(info); - - fas216_cmd(info, CMD_NOP|CMD_WITHDMA); - fas216_cmd(info, CMD_FLUSHFIFO); - - /* load command */ - for (i = info->scsi.SCp.sent_command; i < info->SCpnt->cmd_len; i++) - fas216_writeb(info, REG_FF, info->SCpnt->cmnd[i]); - - fas216_cmd(info, CMD_TRANSFERINFO); - - info->scsi.phase = PHASE_COMMAND; -} - -/** - * fas216_send_messageout - handle bus service to send a message - * @info: interface which caused bus service - * - * Handle bus service to send a message. - * Note: We do not allow the device to change the data direction! - */ -static void fas216_send_messageout(FAS216_Info *info, int start) -{ - unsigned int tot_msglen = msgqueue_msglength(&info->scsi.msgs); - - fas216_checkmagic(info); - - fas216_cmd(info, CMD_FLUSHFIFO); - - if (tot_msglen) { - struct message *msg; - int msgnr = 0; - - while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) { - int i; - - for (i = start; i < msg->length; i++) - fas216_writeb(info, REG_FF, msg->msg[i]); - - msg->fifo = tot_msglen - (fas216_readb(info, REG_CFIS) & CFIS_CF); - start = 0; - } - } else - fas216_writeb(info, REG_FF, NOP); - - fas216_cmd(info, CMD_TRANSFERINFO); - - info->scsi.phase = PHASE_MSGOUT; -} - -/** - * fas216_busservice_intr - handle bus service interrupt from FAS216 chip - * @info: interface which caused bus service interrupt - * @stat: Status register contents - * @ssr: SCSI Status register contents - * - * Handle a bus service interrupt from FAS216 chip - */ -static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr) -{ - fas216_checkmagic(info); - - fas216_log(info, LOG_BUSSERVICE, - "bus service: stat=%02x ssr=%02x phase=%02x", - stat, ssr, info->scsi.phase); - - switch (info->scsi.phase) { - case PHASE_SELECTION: - if ((ssr & IS_BITS) != IS_MSGBYTESENT) - goto bad_is; - break; - - case PHASE_SELSTEPS: - switch (ssr & IS_BITS) { - case IS_SELARB: - case IS_MSGBYTESENT: - goto bad_is; - - case IS_NOTCOMMAND: - case IS_EARLYPHASE: - if ((stat & STAT_BUSMASK) == STAT_MESGIN) - break; - goto bad_is; - - case IS_COMPLETE: - break; - } - - default: - break; - } - - fas216_cmd(info, CMD_NOP); - -#define STATE(st,ph) ((ph) << 3 | (st)) - /* This table describes the legal SCSI state transitions, - * as described by the SCSI II spec. - */ - switch (STATE(stat & STAT_BUSMASK, info->scsi.phase)) { - /* Reselmsgin -> Data In */ - case STATE(STAT_DATAIN, PHASE_RECONNECTED): - fas216_finish_reconnect(info); - case STATE(STAT_DATAIN, PHASE_SELSTEPS):/* Sel w/ steps -> Data In */ - case STATE(STAT_DATAIN, PHASE_MSGOUT): /* Message Out -> Data In */ - case STATE(STAT_DATAIN, PHASE_COMMAND): /* Command -> Data In */ - case STATE(STAT_DATAIN, PHASE_MSGIN): /* Message In -> Data In */ - info->scsi.phase = PHASE_DATAIN; - fas216_transfer(info); - return; - - case STATE(STAT_DATAIN, PHASE_DATAIN): /* Data In -> Data In */ - case STATE(STAT_DATAOUT, PHASE_DATAOUT):/* Data Out -> Data Out */ - fas216_cleanuptransfer(info); - fas216_transfer(info); - return; - - /* Reselmsgin -> Data Out */ - case STATE(STAT_DATAOUT, PHASE_RECONNECTED): - fas216_finish_reconnect(info); - case STATE(STAT_DATAOUT, PHASE_SELSTEPS):/* Sel w/ steps-> Data Out */ - case STATE(STAT_DATAOUT, PHASE_MSGOUT): /* Message Out -> Data Out */ - case STATE(STAT_DATAOUT, PHASE_COMMAND):/* Command -> Data Out */ - case STATE(STAT_DATAOUT, PHASE_MSGIN): /* Message In -> Data Out */ - fas216_cmd(info, CMD_FLUSHFIFO); - info->scsi.phase = PHASE_DATAOUT; - fas216_transfer(info); - return; - - /* Reselmsgin -> Status */ - case STATE(STAT_STATUS, PHASE_RECONNECTED): - fas216_finish_reconnect(info); - goto status; - case STATE(STAT_STATUS, PHASE_DATAOUT): /* Data Out -> Status */ - case STATE(STAT_STATUS, PHASE_DATAIN): /* Data In -> Status */ - fas216_stoptransfer(info); - case STATE(STAT_STATUS, PHASE_SELSTEPS):/* Sel w/ steps -> Status */ - case STATE(STAT_STATUS, PHASE_MSGOUT): /* Message Out -> Status */ - case STATE(STAT_STATUS, PHASE_COMMAND): /* Command -> Status */ - case STATE(STAT_STATUS, PHASE_MSGIN): /* Message In -> Status */ - status: - fas216_cmd(info, CMD_INITCMDCOMPLETE); - info->scsi.phase = PHASE_STATUS; - return; - - case STATE(STAT_MESGIN, PHASE_DATAOUT): /* Data Out -> Message In */ - case STATE(STAT_MESGIN, PHASE_DATAIN): /* Data In -> Message In */ - fas216_stoptransfer(info); - case STATE(STAT_MESGIN, PHASE_COMMAND): /* Command -> Message In */ - case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps -> Message In */ - case STATE(STAT_MESGIN, PHASE_MSGOUT): /* Message Out -> Message In */ - info->scsi.msgin_fifo = fas216_readb(info, REG_CFIS) & CFIS_CF; - fas216_cmd(info, CMD_FLUSHFIFO); - fas216_cmd(info, CMD_TRANSFERINFO); - info->scsi.phase = PHASE_MSGIN; - return; - - /* Reselmsgin -> Message In */ - case STATE(STAT_MESGIN, PHASE_RECONNECTED): - case STATE(STAT_MESGIN, PHASE_MSGIN): - info->scsi.msgin_fifo = fas216_readb(info, REG_CFIS) & CFIS_CF; - fas216_cmd(info, CMD_TRANSFERINFO); - return; - - /* Reselmsgin -> Command */ - case STATE(STAT_COMMAND, PHASE_RECONNECTED): - fas216_finish_reconnect(info); - case STATE(STAT_COMMAND, PHASE_MSGOUT): /* Message Out -> Command */ - case STATE(STAT_COMMAND, PHASE_MSGIN): /* Message In -> Command */ - fas216_send_command(info); - info->scsi.phase = PHASE_COMMAND; - return; - - - /* - * Selection -> Message Out - */ - case STATE(STAT_MESGOUT, PHASE_SELECTION): - fas216_send_messageout(info, 1); - return; - - /* - * Message Out -> Message Out - */ - case STATE(STAT_MESGOUT, PHASE_SELSTEPS): - case STATE(STAT_MESGOUT, PHASE_MSGOUT): - /* - * If we get another message out phase, this usually - * means some parity error occurred. Resend complete - * set of messages. If we have more than one byte to - * send, we need to assert ATN again. - */ - if (info->device[info->SCpnt->device->id].parity_check) { - /* - * We were testing... good, the device - * supports parity checking. - */ - info->device[info->SCpnt->device->id].parity_check = 0; - info->device[info->SCpnt->device->id].parity_enabled = 1; - fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]); - } - - if (msgqueue_msglength(&info->scsi.msgs) > 1) - fas216_cmd(info, CMD_SETATN); - /*FALLTHROUGH*/ - - /* - * Any -> Message Out - */ - case STATE(STAT_MESGOUT, PHASE_MSGOUT_EXPECT): - fas216_send_messageout(info, 0); - return; - - /* Error recovery rules. - * These either attempt to abort or retry the operation. - * TODO: we need more of these - */ - case STATE(STAT_COMMAND, PHASE_COMMAND):/* Command -> Command */ - /* error - we've sent out all the command bytes - * we have. - * NOTE: we need SAVE DATA POINTERS/RESTORE DATA POINTERS - * to include the command bytes sent for this to work - * correctly. - */ - printk(KERN_ERR "scsi%d.%c: " - "target trying to receive more command bytes\n", - info->host->host_no, fas216_target(info)); - fas216_cmd(info, CMD_SETATN); - fas216_set_stc(info, 15); - fas216_cmd(info, CMD_PADBYTES | CMD_WITHDMA); - msgqueue_flush(&info->scsi.msgs); - msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); - info->scsi.phase = PHASE_MSGOUT_EXPECT; - return; - } - - if (info->scsi.phase == PHASE_MSGIN_DISCONNECT) { - printk(KERN_ERR "scsi%d.%c: disconnect message received, but bus service %s?\n", - info->host->host_no, fas216_target(info), - fas216_bus_phase(stat)); - msgqueue_flush(&info->scsi.msgs); - fas216_cmd(info, CMD_SETATN); - msgqueue_addmsg(&info->scsi.msgs, 1, INITIATOR_ERROR); - info->scsi.phase = PHASE_MSGOUT_EXPECT; - info->scsi.aborting = 1; - fas216_cmd(info, CMD_TRANSFERINFO); - return; - } - printk(KERN_ERR "scsi%d.%c: bus phase %s after %s?\n", - info->host->host_no, fas216_target(info), - fas216_bus_phase(stat), - fas216_drv_phase(info)); - print_debug_list(); - return; - -bad_is: - fas216_log(info, 0, "bus service at step %d?", ssr & IS_BITS); - fas216_dumpstate(info); - print_debug_list(); - - fas216_done(info, DID_ERROR); -} - -/** - * fas216_funcdone_intr - handle a function done interrupt from FAS216 chip - * @info: interface which caused function done interrupt - * @stat: Status register contents - * @ssr: SCSI Status register contents - * - * Handle a function done interrupt from FAS216 chip - */ -static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned int ssr) -{ - unsigned int fifo_len = fas216_readb(info, REG_CFIS) & CFIS_CF; - unsigned int status, message; - - fas216_checkmagic(info); - - fas216_log(info, LOG_FUNCTIONDONE, - "function done: stat=%02x ssr=%02x phase=%02x", - stat, ssr, info->scsi.phase); - - switch (info->scsi.phase) { - case PHASE_STATUS: /* status phase - read status and msg */ - if (fifo_len != 2) { - fas216_log(info, 0, "odd number of bytes in FIFO: %d", fifo_len); - } - status = fas216_readb(info, REG_FF); - message = fas216_readb(info, REG_FF); - info->scsi.SCp.Message = message; - info->scsi.SCp.Status = status; - info->scsi.phase = PHASE_DONE; - fas216_cmd(info, CMD_MSGACCEPTED); - break; - - case PHASE_IDLE: /* reselected? */ - case PHASE_MSGIN: /* message in phase */ - case PHASE_RECONNECTED: /* reconnected command */ - if ((stat & STAT_BUSMASK) == STAT_MESGIN) { - info->scsi.msgin_fifo = fifo_len; - fas216_message(info); - break; - } - - default: - fas216_log(info, 0, "internal phase %s for function done?" - " What do I do with this?", - fas216_target(info), fas216_drv_phase(info)); - } -} - -static void fas216_bus_reset(FAS216_Info *info) -{ - neg_t sync_state, wide_state; - int i; - - msgqueue_flush(&info->scsi.msgs); - - info->scsi.reconnected.target = 0; - info->scsi.reconnected.lun = 0; - info->scsi.reconnected.tag = 0; - - wide_state = neg_invalid; - sync_state = neg_invalid; - -#ifdef SCSI2_WIDE - if (info->ifcfg.wide_max_size != 0) - wide_state = neg_wait; -#endif -#ifdef SCSI2_SYNC - if (info->ifcfg.capabilities & (FASCAP_DMA|FASCAP_PSEUDODMA)) - sync_state = neg_wait; -#endif - - info->scsi.phase = PHASE_IDLE; - info->SCpnt = NULL; /* bug! */ - memset(&info->scsi.SCp, 0, sizeof(info->scsi.SCp)); - - for (i = 0; i < 8; i++) { - info->device[i].disconnect_ok = info->ifcfg.disconnect_ok; - info->device[i].sync_state = sync_state; - info->device[i].wide_state = wide_state; - info->device[i].period = info->ifcfg.asyncperiod / 4; - info->device[i].stp = info->scsi.async_stp; - info->device[i].sof = 0; - info->device[i].wide_xfer = 0; - } - - info->rst_bus_status = 1; - wake_up(&info->eh_wait); -} - -/** - * fas216_intr - handle interrupts to progress a command - * @info: interface to service - * - * Handle interrupts from the interface to progress a command - */ -void fas216_intr(FAS216_Info *info) -{ - unsigned char isr, ssr, stat; - - fas216_checkmagic(info); - - stat = fas216_readb(info, REG_STAT); - ssr = fas216_readb(info, REG_IS); - isr = fas216_readb(info, REG_INST); - - add_debug_list(stat, ssr, isr, info->scsi.phase); - - if (stat & STAT_INT) { - if (isr & INST_BUSRESET) { - fas216_log(info, 0, "bus reset detected"); - fas216_bus_reset(info); - scsi_report_bus_reset(info->host, 0); - } else if (isr & INST_ILLEGALCMD) { - fas216_log(info, LOG_ERROR, "illegal command given\n"); - fas216_dumpstate(info); - print_debug_list(); - } else if (isr & INST_DISCONNECT) - fas216_disconnect_intr(info); - else if (isr & INST_RESELECTED) /* reselected */ - fas216_reselected_intr(info); - else if (isr & INST_BUSSERVICE) /* bus service request */ - fas216_busservice_intr(info, stat, ssr); - else if (isr & INST_FUNCDONE) /* function done */ - fas216_funcdone_intr(info, stat, ssr); - else - fas216_log(info, 0, "unknown interrupt received:" - " phase %s isr %02X ssr %02X stat %02X", - fas216_drv_phase(info), isr, ssr, stat); - } -} - -static void __fas216_start_command(FAS216_Info *info, Scsi_Cmnd *SCpnt) -{ - int tot_msglen; - - /* following what the ESP driver says */ - fas216_set_stc(info, 0); - fas216_cmd(info, CMD_NOP | CMD_WITHDMA); - - /* flush FIFO */ - fas216_cmd(info, CMD_FLUSHFIFO); - - /* load bus-id and timeout */ - fas216_writeb(info, REG_SDID, BUSID(SCpnt->device->id)); - fas216_writeb(info, REG_STIM, info->ifcfg.select_timeout); - - /* synchronous transfers */ - fas216_set_sync(info, SCpnt->device->id); - - tot_msglen = msgqueue_msglength(&info->scsi.msgs); - -#ifdef DEBUG_MESSAGES - { - struct message *msg; - int msgnr = 0, i; - - printk("scsi%d.%c: message out: ", - info->host->host_no, '0' + SCpnt->device->id); - while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) { - printk("{ "); - for (i = 0; i < msg->length; i++) - printk("%02x ", msg->msg[i]); - printk("} "); - } - printk("\n"); - } -#endif - - if (tot_msglen == 1 || tot_msglen == 3) { - /* - * We have an easy message length to send... - */ - struct message *msg; - int msgnr = 0, i; - - info->scsi.phase = PHASE_SELSTEPS; - - /* load message bytes */ - while ((msg = msgqueue_getmsg(&info->scsi.msgs, msgnr++)) != NULL) { - for (i = 0; i < msg->length; i++) - fas216_writeb(info, REG_FF, msg->msg[i]); - msg->fifo = tot_msglen - (fas216_readb(info, REG_CFIS) & CFIS_CF); - } - - /* load command */ - for (i = 0; i < SCpnt->cmd_len; i++) - fas216_writeb(info, REG_FF, SCpnt->cmnd[i]); - - if (tot_msglen == 1) - fas216_cmd(info, CMD_SELECTATN); - else - fas216_cmd(info, CMD_SELECTATN3); - } else { - /* - * We have an unusual number of message bytes to send. - * Load first byte into fifo, and issue SELECT with ATN and - * stop steps. - */ - struct message *msg = msgqueue_getmsg(&info->scsi.msgs, 0); - - fas216_writeb(info, REG_FF, msg->msg[0]); - msg->fifo = 1; - - fas216_cmd(info, CMD_SELECTATNSTOP); - } -} - -/* - * Decide whether we need to perform a parity test on this device. - * Can also be used to force parity error conditions during initial - * information transfer phase (message out) for test purposes. - */ -static int parity_test(FAS216_Info *info, int target) -{ -#if 0 - if (target == 3) { - info->device[3].parity_check = 0; - return 1; - } -#endif - return info->device[target].parity_check; -} - -static void fas216_start_command(FAS216_Info *info, Scsi_Cmnd *SCpnt) -{ - int disconnect_ok; - - /* - * claim host busy - */ - info->scsi.phase = PHASE_SELECTION; - info->scsi.SCp = SCpnt->SCp; - info->SCpnt = SCpnt; - info->dma.transfer_type = fasdma_none; - - if (parity_test(info, SCpnt->device->id)) - fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0] | CNTL1_PTE); - else - fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]); - - /* - * Don't allow request sense commands to disconnect. - */ - disconnect_ok = SCpnt->cmnd[0] != REQUEST_SENSE && - info->device[SCpnt->device->id].disconnect_ok; - - /* - * build outgoing message bytes - */ - msgqueue_flush(&info->scsi.msgs); - msgqueue_addmsg(&info->scsi.msgs, 1, IDENTIFY(disconnect_ok, SCpnt->device->lun)); - - /* - * add tag message if required - */ - if (SCpnt->tag) - msgqueue_addmsg(&info->scsi.msgs, 2, SIMPLE_QUEUE_TAG, SCpnt->tag); - - do { -#ifdef SCSI2_WIDE - if (info->device[SCpnt->device->id].wide_state == neg_wait) { - info->device[SCpnt->device->id].wide_state = neg_inprogress; - msgqueue_addmsg(&info->scsi.msgs, 4, - EXTENDED_MESSAGE, 2, EXTENDED_WDTR, - info->ifcfg.wide_max_size); - break; - } -#endif -#ifdef SCSI2_SYNC - if ((info->device[SCpnt->device->id].sync_state == neg_wait || - info->device[SCpnt->device->id].sync_state == neg_complete) && - (SCpnt->cmnd[0] == REQUEST_SENSE || - SCpnt->cmnd[0] == INQUIRY)) { - info->device[SCpnt->device->id].sync_state = neg_inprogress; - msgqueue_addmsg(&info->scsi.msgs, 5, - EXTENDED_MESSAGE, 3, EXTENDED_SDTR, - 1000 / info->ifcfg.clockrate, - info->ifcfg.sync_max_depth); - break; - } -#endif - } while (0); - - __fas216_start_command(info, SCpnt); -} - -static void fas216_allocate_tag(FAS216_Info *info, Scsi_Cmnd *SCpnt) -{ -#ifdef SCSI2_TAG - /* - * tagged queuing - allocate a new tag to this command - */ - if (SCpnt->device->tagged_queue && SCpnt->cmnd[0] != REQUEST_SENSE && - SCpnt->cmnd[0] != INQUIRY) { - SCpnt->device->current_tag += 1; - if (SCpnt->device->current_tag == 0) - SCpnt->device->current_tag = 1; - SCpnt->tag = SCpnt->device->current_tag; - } else -#endif - set_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns); - - info->stats.removes += 1; - switch (SCpnt->cmnd[0]) { - case WRITE_6: - case WRITE_10: - case WRITE_12: - info->stats.writes += 1; - break; - case READ_6: - case READ_10: - case READ_12: - info->stats.reads += 1; - break; - default: - info->stats.miscs += 1; - break; - } -} - -static void fas216_do_bus_device_reset(FAS216_Info *info, Scsi_Cmnd *SCpnt) -{ - struct message *msg; - - /* - * claim host busy - */ - info->scsi.phase = PHASE_SELECTION; - info->scsi.SCp = SCpnt->SCp; - info->SCpnt = SCpnt; - info->dma.transfer_type = fasdma_none; - - fas216_log(info, LOG_ERROR, "sending bus device reset"); - - msgqueue_flush(&info->scsi.msgs); - msgqueue_addmsg(&info->scsi.msgs, 1, BUS_DEVICE_RESET); - - /* following what the ESP driver says */ - fas216_set_stc(info, 0); - fas216_cmd(info, CMD_NOP | CMD_WITHDMA); - - /* flush FIFO */ - fas216_cmd(info, CMD_FLUSHFIFO); - - /* load bus-id and timeout */ - fas216_writeb(info, REG_SDID, BUSID(SCpnt->device->id)); - fas216_writeb(info, REG_STIM, info->ifcfg.select_timeout); - - /* synchronous transfers */ - fas216_set_sync(info, SCpnt->device->id); - - msg = msgqueue_getmsg(&info->scsi.msgs, 0); - - fas216_writeb(info, REG_FF, BUS_DEVICE_RESET); - msg->fifo = 1; - - fas216_cmd(info, CMD_SELECTATNSTOP); -} - -/** - * fas216_kick - kick a command to the interface - * @info: our host interface to kick - * - * Kick a command to the interface, interface should be idle. - * Notes: Interrupts are always disabled! - */ -static void fas216_kick(FAS216_Info *info) -{ - Scsi_Cmnd *SCpnt = NULL; -#define TYPE_OTHER 0 -#define TYPE_RESET 1 -#define TYPE_QUEUE 2 - int where_from = TYPE_OTHER; - - fas216_checkmagic(info); - - /* - * Obtain the next command to process. - */ - do { - if (info->rstSCpnt) { - SCpnt = info->rstSCpnt; - /* don't remove it */ - where_from = TYPE_RESET; - break; - } - - if (info->reqSCpnt) { - SCpnt = info->reqSCpnt; - info->reqSCpnt = NULL; - break; - } - - if (info->origSCpnt) { - SCpnt = info->origSCpnt; - info->origSCpnt = NULL; - break; - } - - /* retrieve next command */ - if (!SCpnt) { - SCpnt = queue_remove_exclude(&info->queues.issue, - info->busyluns); - where_from = TYPE_QUEUE; - break; - } - } while (0); - - if (!SCpnt) /* no command pending - just exit */ - return; - - if (info->scsi.disconnectable && info->SCpnt) { - fas216_log(info, LOG_CONNECT, - "moved command for %d to disconnected queue", - info->SCpnt->device->id); - queue_add_cmd_tail(&info->queues.disconnected, info->SCpnt); - info->scsi.disconnectable = 0; - info->SCpnt = NULL; - } - - fas216_log_command(info, LOG_CONNECT | LOG_MESSAGES, SCpnt, - "starting"); - - switch (where_from) { - case TYPE_QUEUE: - fas216_allocate_tag(info, SCpnt); - case TYPE_OTHER: - fas216_start_command(info, SCpnt); - break; - case TYPE_RESET: - fas216_do_bus_device_reset(info, SCpnt); - break; - } - - fas216_log(info, LOG_CONNECT, "select: data pointers [%p, %X]", - info->scsi.SCp.ptr, info->scsi.SCp.this_residual); - - /* - * should now get either DISCONNECT or - * (FUNCTION DONE with BUS SERVICE) interrupt - */ -} - -/* - * Clean up from issuing a BUS DEVICE RESET message to a device. - */ -static void -fas216_devicereset_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result) -{ - fas216_log(info, LOG_ERROR, "fas216 device reset complete"); - - info->rstSCpnt = NULL; - info->rst_dev_status = 1; - wake_up(&info->eh_wait); -} - -/** - * fas216_rq_sns_done - Finish processing automatic request sense command - * @info: interface that completed - * @SCpnt: command that completed - * @result: driver byte of result - * - * Finish processing automatic request sense command - */ -static void -fas216_rq_sns_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result) -{ - fas216_log_target(info, LOG_CONNECT, SCpnt->device->id, - "request sense complete, result=0x%04x%02x%02x", - result, SCpnt->SCp.Message, SCpnt->SCp.Status); - - if (result != DID_OK || SCpnt->SCp.Status != GOOD) - /* - * Something went wrong. Make sure that we don't - * have valid data in the sense buffer that could - * confuse the higher levels. - */ - memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer)); -//printk("scsi%d.%c: sense buffer: ", info->host->host_no, '0' + SCpnt->device->id); -//{ int i; for (i = 0; i < 32; i++) printk("%02x ", SCpnt->sense_buffer[i]); printk("\n"); } - /* - * Note that we don't set SCpnt->result, since that should - * reflect the status of the command that we were asked by - * the upper layers to process. This would have been set - * correctly by fas216_std_done. - */ - SCpnt->scsi_done(SCpnt); -} - -/** - * fas216_std_done - finish processing of standard command - * @info: interface that completed - * @SCpnt: command that completed - * @result: driver byte of result - * - * Finish processing of standard command - */ -static void -fas216_std_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result) -{ - info->stats.fins += 1; - - SCpnt->result = result << 16 | info->scsi.SCp.Message << 8 | - info->scsi.SCp.Status; - - fas216_log_command(info, LOG_CONNECT, SCpnt, - "command complete, result=0x%08x", SCpnt->result); - - /* - * If the driver detected an error, we're all done. - */ - if (host_byte(SCpnt->result) != DID_OK || - msg_byte(SCpnt->result) != COMMAND_COMPLETE) - goto done; - - /* - * If the command returned CHECK_CONDITION or COMMAND_TERMINATED - * status, request the sense information. - */ - if (status_byte(SCpnt->result) == CHECK_CONDITION || - status_byte(SCpnt->result) == COMMAND_TERMINATED) - goto request_sense; - - /* - * If the command did not complete with GOOD status, - * we are all done here. - */ - if (status_byte(SCpnt->result) != GOOD) - goto done; - - /* - * We have successfully completed a command. Make sure that - * we do not have any buffers left to transfer. The world - * is not perfect, and we seem to occasionally hit this. - * It can be indicative of a buggy driver, target or the upper - * levels of the SCSI code. - */ - if (info->scsi.SCp.ptr) { - switch (SCpnt->cmnd[0]) { - case INQUIRY: - case START_STOP: - case MODE_SENSE: - break; - - default: - printk(KERN_ERR "scsi%d.%c: incomplete data transfer " - "detected: res=%08X ptr=%p len=%X CDB: ", - info->host->host_no, '0' + SCpnt->device->id, - SCpnt->result, info->scsi.SCp.ptr, - info->scsi.SCp.this_residual); - print_command(SCpnt->cmnd); - SCpnt->result &= ~(255 << 16); - SCpnt->result |= DID_BAD_TARGET << 16; - goto request_sense; - } - } - -done: - if (SCpnt->scsi_done) { - SCpnt->scsi_done(SCpnt); - return; - } - - panic("scsi%d.H: null scsi_done function in fas216_done", - info->host->host_no); - - -request_sense: - if (SCpnt->cmnd[0] == REQUEST_SENSE) - goto done; - - fas216_log_target(info, LOG_CONNECT, SCpnt->device->id, - "requesting sense"); - memset(SCpnt->cmnd, 0, sizeof (SCpnt->cmnd)); - SCpnt->cmnd[0] = REQUEST_SENSE; - SCpnt->cmnd[1] = SCpnt->device->lun << 5; - SCpnt->cmnd[4] = sizeof(SCpnt->sense_buffer); - SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]); - SCpnt->SCp.buffer = NULL; - SCpnt->SCp.buffers_residual = 0; - SCpnt->SCp.ptr = (char *)SCpnt->sense_buffer; - SCpnt->SCp.this_residual = sizeof(SCpnt->sense_buffer); - SCpnt->SCp.Message = 0; - SCpnt->SCp.Status = 0; - SCpnt->request_bufflen = sizeof(SCpnt->sense_buffer); - SCpnt->sc_data_direction = SCSI_DATA_READ; - SCpnt->use_sg = 0; - SCpnt->tag = 0; - SCpnt->host_scribble = (void *)fas216_rq_sns_done; - - /* - * Place this command into the high priority "request - * sense" slot. This will be the very next command - * executed, unless a target connects to us. - */ - if (info->reqSCpnt) - printk(KERN_WARNING "scsi%d.%c: loosing request command\n", - info->host->host_no, '0' + SCpnt->device->id); - info->reqSCpnt = SCpnt; -} - -/** - * fas216_done - complete processing for current command - * @info: interface that completed - * @result: driver byte of result - * - * Complete processing for current command - */ -static void fas216_done(FAS216_Info *info, unsigned int result) -{ - void (*fn)(FAS216_Info *, Scsi_Cmnd *, unsigned int); - Scsi_Cmnd *SCpnt; - unsigned long flags; - - fas216_checkmagic(info); - - if (!info->SCpnt) - goto no_command; - - SCpnt = info->SCpnt; - info->SCpnt = NULL; - info->scsi.phase = PHASE_IDLE; - - if (info->scsi.aborting) { - fas216_log(info, 0, "uncaught abort - returning DID_ABORT"); - result = DID_ABORT; - info->scsi.aborting = 0; - } - - /* - * Sanity check the completion - if we have zero bytes left - * to transfer, we should not have a valid pointer. - */ - if (info->scsi.SCp.ptr && info->scsi.SCp.this_residual == 0) { - printk("scsi%d.%c: zero bytes left to transfer, but " - "buffer pointer still valid: ptr=%p len=%08x CDB: ", - info->host->host_no, '0' + SCpnt->device->id, - info->scsi.SCp.ptr, info->scsi.SCp.this_residual); - info->scsi.SCp.ptr = NULL; - print_command(SCpnt->cmnd); - } - - /* - * Clear down this command as completed. If we need to request - * the sense information, fas216_kick will re-assert the busy - * status. - */ - info->device[SCpnt->device->id].parity_check = 0; - clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns); - - fn = (void (*)(FAS216_Info *, Scsi_Cmnd *, unsigned int))SCpnt->host_scribble; - fn(info, SCpnt, result); - - if (info->scsi.irq != NO_IRQ) { - spin_lock_irqsave(&info->host_lock, flags); - if (info->scsi.phase == PHASE_IDLE) - fas216_kick(info); - spin_unlock_irqrestore(&info->host_lock, flags); - } - return; - -no_command: - panic("scsi%d.H: null command in fas216_done", - info->host->host_no); -} - -/** - * fas216_queue_command - queue a command for adapter to process. - * @SCpnt: Command to queue - * @done: done function to call once command is complete - * - * Queue a command for adapter to process. - * Returns: 0 on success, else error. - * Notes: io_request_lock is held, interrupts are disabled. - */ -int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) -{ - FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata; - int result; - - fas216_checkmagic(info); - - fas216_log_command(info, LOG_CONNECT, SCpnt, - "received command (%p)", SCpnt); - - SCpnt->scsi_done = done; - SCpnt->host_scribble = (void *)fas216_std_done; - SCpnt->result = 0; - - init_SCp(SCpnt); - - info->stats.queues += 1; - SCpnt->tag = 0; - - spin_lock(&info->host_lock); - - /* - * Add command into execute queue and let it complete under - * whatever scheme we're using. - */ - result = !queue_add_cmd_ordered(&info->queues.issue, SCpnt); - - /* - * If we successfully added the command, - * kick the interface to get it moving. - */ - if (result == 0 && info->scsi.phase == PHASE_IDLE) - fas216_kick(info); - spin_unlock(&info->host_lock); - - fas216_log_target(info, LOG_CONNECT, -1, "queue %s", - result ? "failure" : "success"); - - return result; -} - -/** - * fas216_internal_done - trigger restart of a waiting thread in fas216_command - * @SCpnt: Command to wake - * - * Trigger restart of a waiting thread in fas216_command - */ -static void fas216_internal_done(Scsi_Cmnd *SCpnt) -{ - FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata; - - fas216_checkmagic(info); - - info->internal_done = 1; -} - -/** - * fas216_command - queue a command for adapter to process. - * @SCpnt: Command to queue - * - * Queue a command for adapter to process. - * Returns: scsi result code. - * Notes: io_request_lock is held, interrupts are disabled. - */ -int fas216_command(Scsi_Cmnd *SCpnt) -{ - FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata; - - fas216_checkmagic(info); - - /* - * We should only be using this if we don't have an interrupt. - * Provide some "incentive" to use the queueing code. - */ - if (info->scsi.irq != NO_IRQ) - BUG(); - - info->internal_done = 0; - fas216_queue_command(SCpnt, fas216_internal_done); - - /* - * This wastes time, since we can't return until the command is - * complete. We can't sleep either since we may get re-entered! - * However, we must re-enable interrupts, or else we'll be - * waiting forever. - */ - spin_unlock_irq(info->host->host_lock); - - while (!info->internal_done) { - /* - * If we don't have an IRQ, then we must poll the card for - * it's interrupt, and use that to call this driver's - * interrupt routine. That way, we keep the command - * progressing. Maybe we can add some inteligence here - * and go to sleep if we know that the device is going - * to be some time (eg, disconnected). - */ - if (fas216_readb(info, REG_STAT) & STAT_INT) { - spin_lock_irq(info->host->host_lock); - fas216_intr(info); - spin_unlock_irq(info->host->host_lock); - } - } - - spin_lock_irq(info->host->host_lock); - - return SCpnt->result; -} - -/* - * Error handler timeout function. Indicate that we timed out, - * and wake up any error handler process so it can continue. - */ -static void fas216_eh_timer(unsigned long data) -{ - FAS216_Info *info = (FAS216_Info *)data; - - fas216_log(info, LOG_ERROR, "error handling timed out\n"); - - del_timer(&info->eh_timer); - - if (info->rst_bus_status == 0) - info->rst_bus_status = -1; - if (info->rst_dev_status == 0) - info->rst_dev_status = -1; - - wake_up(&info->eh_wait); -} - -enum res_find { - res_failed, /* not found */ - res_success, /* command on issue queue */ - res_hw_abort /* command on disconnected dev */ -}; - -/** - * fas216_do_abort - decide how to abort a command - * @SCpnt: command to abort - * - * Decide how to abort a command. - * Returns: abort status - */ -static enum res_find fas216_find_command(FAS216_Info *info, Scsi_Cmnd *SCpnt) -{ - enum res_find res = res_failed; - - if (queue_remove_cmd(&info->queues.issue, SCpnt)) { - /* - * The command was on the issue queue, and has not been - * issued yet. We can remove the command from the queue, - * and acknowledge the abort. Neither the device nor the - * interface know about the command. - */ - printk("on issue queue "); - - res = res_success; - } else if (queue_remove_cmd(&info->queues.disconnected, SCpnt)) { - /* - * The command was on the disconnected queue. We must - * reconnect with the device if possible, and send it - * an abort message. - */ - printk("on disconnected queue "); - - res = res_hw_abort; - } else if (info->SCpnt == SCpnt) { - printk("executing "); - - switch (info->scsi.phase) { - /* - * If the interface is idle, and the command is 'disconnectable', - * then it is the same as on the disconnected queue. - */ - case PHASE_IDLE: - if (info->scsi.disconnectable) { - info->scsi.disconnectable = 0; - info->SCpnt = NULL; - res = res_hw_abort; - } - break; - - default: - break; - } - } else if (info->origSCpnt == SCpnt) { - /* - * The command will be executed next, but a command - * is currently using the interface. This is similar to - * being on the issue queue, except the busylun bit has - * been set. - */ - info->origSCpnt = NULL; - clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns); - printk("waiting for execution "); - res = res_success; - } else - printk("unknown "); - - return res; -} - -/** - * fas216_eh_abort - abort this command - * @SCpnt: command to abort - * - * Abort this command. - * Returns: FAILED if unable to abort - * Notes: io_request_lock is taken, and irqs are disabled - */ -int fas216_eh_abort(Scsi_Cmnd *SCpnt) -{ - FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata; - int result = FAILED; - - fas216_checkmagic(info); - - info->stats.aborts += 1; - - printk(KERN_WARNING "scsi%d: abort command ", info->host->host_no); - print_command(SCpnt->data_cmnd); - - print_debug_list(); - fas216_dumpstate(info); - - printk(KERN_WARNING "scsi%d: abort %p ", info->host->host_no, SCpnt); - - switch (fas216_find_command(info, SCpnt)) { - /* - * We found the command, and cleared it out. Either - * the command is still known to be executing on the - * target, or the busylun bit is not set. - */ - case res_success: - printk("success\n"); - result = SUCCESS; - break; - - /* - * We need to reconnect to the target and send it an - * ABORT or ABORT_TAG message. We can only do this - * if the bus is free. - */ - case res_hw_abort: - - - /* - * We are unable to abort the command for some reason. - */ - default: - case res_failed: - printk("failed\n"); - break; - } - - return result; -} - -/** - * fas216_eh_device_reset - Reset the device associated with this command - * @SCpnt: command specifing device to reset - * - * Reset the device associated with this command. - * Returns: FAILED if unable to reset. - * Notes: We won't be re-entered, so we'll only have one device - * reset on the go at one time. - */ -int fas216_eh_device_reset(Scsi_Cmnd *SCpnt) -{ - FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata; - unsigned long flags; - int i, res = FAILED, target = SCpnt->device->id; - - fas216_log(info, LOG_ERROR, "device reset for target %d", target); - - spin_lock_irqsave(&info->host_lock, flags); - - do { - /* - * If we are currently connected to a device, and - * it is the device we want to reset, there is - * nothing we can do here. Chances are it is stuck, - * and we need a bus reset. - */ - if (info->SCpnt && !info->scsi.disconnectable && - info->SCpnt->device->id == SCpnt->device->id) - break; - - /* - * We're going to be resetting this device. Remove - * all pending commands from the driver. By doing - * so, we guarantee that we won't touch the command - * structures except to process the reset request. - */ - queue_remove_all_target(&info->queues.issue, target); - queue_remove_all_target(&info->queues.disconnected, target); - if (info->origSCpnt && info->origSCpnt->device->id == target) - info->origSCpnt = NULL; - if (info->reqSCpnt && info->reqSCpnt->device->id == target) - info->reqSCpnt = NULL; - for (i = 0; i < 8; i++) - clear_bit(target * 8 + i, info->busyluns); - - /* - * Hijack this SCSI command structure to send - * a bus device reset message to this device. - */ - SCpnt->host_scribble = (void *)fas216_devicereset_done; - - info->rst_dev_status = 0; - info->rstSCpnt = SCpnt; - - if (info->scsi.phase == PHASE_IDLE) - fas216_kick(info); - - mod_timer(&info->eh_timer, 30 * HZ); - spin_unlock_irqrestore(&info->host_lock, flags); - - /* - * Wait up to 30 seconds for the reset to complete. - */ - wait_event(info->eh_wait, info->rst_dev_status); - - del_timer_sync(&info->eh_timer); - spin_lock_irqsave(&info->host_lock, flags); - info->rstSCpnt = NULL; - - if (info->rst_dev_status == 1) - res = SUCCESS; - } while (0); - - SCpnt->host_scribble = NULL; - spin_unlock_irqrestore(&info->host_lock, flags); - - fas216_log(info, LOG_ERROR, "device reset complete: %s\n", - res == SUCCESS ? "success" : "failed"); - - return res; -} - -/** - * fas216_eh_bus_reset - Reset the bus associated with the command - * @SCpnt: command specifing bus to reset - * - * Reset the bus associated with the command. - * Returns: FAILED if unable to reset. - * Notes: Further commands are blocked. - */ -int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt) -{ - FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata; - unsigned long flags; - Scsi_Device *SDpnt; - - fas216_checkmagic(info); - fas216_log(info, LOG_ERROR, "resetting bus"); - - info->stats.bus_resets += 1; - - spin_lock_irqsave(&info->host_lock, flags); - - /* - * Stop all activity on this interface. - */ - fas216_aborttransfer(info); - fas216_writeb(info, REG_CNTL3, info->scsi.cfg[2]); - - /* - * Clear any pending interrupts. - */ - while (fas216_readb(info, REG_STAT) & STAT_INT) - fas216_readb(info, REG_INST); - - info->rst_bus_status = 0; - - /* - * For each attached hard-reset device, clear out - * all command structures. Leave the running - * command in place. - */ - list_for_each_entry(SDpnt, &info->host->my_devices, siblings) { - int i; - - if (SDpnt->soft_reset) - continue; - - queue_remove_all_target(&info->queues.issue, SDpnt->id); - queue_remove_all_target(&info->queues.disconnected, SDpnt->id); - if (info->origSCpnt && info->origSCpnt->device->id == SDpnt->id) - info->origSCpnt = NULL; - if (info->reqSCpnt && info->reqSCpnt->device->id == SDpnt->id) - info->reqSCpnt = NULL; - info->SCpnt = NULL; - - for (i = 0; i < 8; i++) - clear_bit(SDpnt->id * 8 + i, info->busyluns); - } - - /* - * Reset the SCSI bus. Device cleanup happens in - * the interrupt handler. - */ - fas216_cmd(info, CMD_RESETSCSI); - - mod_timer(&info->eh_timer, jiffies + HZ); - spin_unlock_irqrestore(&info->host_lock, flags); - - /* - * Wait one second for the interrupt. - */ - wait_event(info->eh_wait, info->rst_bus_status); - del_timer_sync(&info->eh_timer); - - fas216_log(info, LOG_ERROR, "bus reset complete: %s\n", - info->rst_bus_status == 1 ? "success" : "failed"); - - return info->rst_bus_status == 1 ? SUCCESS : FAILED; -} - -/** - * fas216_init_chip - Initialise FAS216 state after reset - * @info: state structure for interface - * - * Initialise FAS216 state after reset - */ -static void fas216_init_chip(FAS216_Info *info) -{ - fas216_writeb(info, REG_CLKF, fas216_clockrate(info->ifcfg.clockrate)); - fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]); - fas216_writeb(info, REG_CNTL2, info->scsi.cfg[1]); - fas216_writeb(info, REG_CNTL3, info->scsi.cfg[2]); - fas216_writeb(info, REG_STIM, info->ifcfg.select_timeout); - fas216_writeb(info, REG_SOF, 0); - fas216_writeb(info, REG_STP, info->scsi.async_stp); - fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]); -} - -/** - * fas216_eh_host_reset - Reset the host associated with this command - * @SCpnt: command specifing host to reset - * - * Reset the host associated with this command. - * Returns: FAILED if unable to reset. - * Notes: io_request_lock is taken, and irqs are disabled - */ -int fas216_eh_host_reset(Scsi_Cmnd *SCpnt) -{ - FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata; - - fas216_checkmagic(info); - - printk("scsi%d.%c: %s: resetting host\n", - info->host->host_no, '0' + SCpnt->device->id, __FUNCTION__); - - /* - * Reset the SCSI chip. - */ - fas216_cmd(info, CMD_RESETCHIP); - - /* - * Ugly ugly ugly! - * We need to release the host_lock and enable - * IRQs if we sleep, but we must relock and disable - * IRQs after the sleep. - */ - spin_unlock_irq(info->host->host_lock); - scsi_sleep(50 * HZ/100); - spin_lock_irq(info->host->host_lock); - - /* - * Release the SCSI reset. - */ - fas216_cmd(info, CMD_NOP); - - fas216_init_chip(info); - - return SUCCESS; -} - -#define TYPE_UNKNOWN 0 -#define TYPE_NCR53C90 1 -#define TYPE_NCR53C90A 2 -#define TYPE_NCR53C9x 3 -#define TYPE_Am53CF94 4 -#define TYPE_EmFAS216 5 -#define TYPE_QLFAS216 6 - -static char *chip_types[] = { - "unknown", - "NS NCR53C90", - "NS NCR53C90A", - "NS NCR53C9x", - "AMD Am53CF94", - "Emulex FAS216", - "QLogic FAS216" -}; - -static int fas216_detect_type(FAS216_Info *info) -{ - int family, rev; - - /* - * Reset the chip. - */ - fas216_writeb(info, REG_CMD, CMD_RESETCHIP); - udelay(50); - fas216_writeb(info, REG_CMD, CMD_NOP); - - /* - * Check to see if control reg 2 is present. - */ - fas216_writeb(info, REG_CNTL3, 0); - fas216_writeb(info, REG_CNTL2, CNTL2_S2FE); - - /* - * If we are unable to read back control reg 2 - * correctly, it is not present, and we have a - * NCR53C90. - */ - if ((fas216_readb(info, REG_CNTL2) & (~0xe0)) != CNTL2_S2FE) - return TYPE_NCR53C90; - - /* - * Now, check control register 3 - */ - fas216_writeb(info, REG_CNTL2, 0); - fas216_writeb(info, REG_CNTL3, 0); - fas216_writeb(info, REG_CNTL3, 5); - - /* - * If we are unable to read the register back - * correctly, we have a NCR53C90A - */ - if (fas216_readb(info, REG_CNTL3) != 5) - return TYPE_NCR53C90A; - - /* - * Now read the ID from the chip. - */ - fas216_writeb(info, REG_CNTL3, 0); - - fas216_writeb(info, REG_CNTL3, CNTL3_ADIDCHK); - fas216_writeb(info, REG_CNTL3, 0); - - fas216_writeb(info, REG_CMD, CMD_RESETCHIP); - udelay(50); - fas216_writeb(info, REG_CMD, CMD_WITHDMA | CMD_NOP); - - fas216_writeb(info, REG_CNTL2, CNTL2_ENF); - fas216_writeb(info, REG_CMD, CMD_RESETCHIP); - udelay(50); - fas216_writeb(info, REG_CMD, CMD_NOP); - - rev = fas216_readb(info, REG_ID); - family = rev >> 3; - rev &= 7; - - switch (family) { - case 0x01: - if (rev == 4) - return TYPE_Am53CF94; - break; - - case 0x02: - switch (rev) { - case 2: - return TYPE_EmFAS216; - case 3: - return TYPE_QLFAS216; - } - break; - - default: - break; - } - printk("family %x rev %x\n", family, rev); - return TYPE_NCR53C9x; -} - -/** - * fas216_reset_state - Initialise driver internal state - * @info: state to initialise - * - * Initialise driver internal state - */ -static void fas216_reset_state(FAS216_Info *info) -{ - int i; - - fas216_checkmagic(info); - - fas216_bus_reset(info); - - /* - * Clear out all stale info in our state structure - */ - memset(info->busyluns, 0, sizeof(info->busyluns)); - info->scsi.disconnectable = 0; - info->scsi.aborting = 0; - - for (i = 0; i < 8; i++) { - info->device[i].parity_enabled = 0; - info->device[i].parity_check = 1; - } - - /* - * Drain all commands on disconnected queue - */ - while (queue_remove(&info->queues.disconnected) != NULL); - - /* - * Remove executing commands. - */ - info->SCpnt = NULL; - info->reqSCpnt = NULL; - info->rstSCpnt = NULL; - info->origSCpnt = NULL; -} - -/** - * fas216_init - initialise FAS/NCR/AMD SCSI structures. - * @host: a driver-specific filled-out structure - * - * Initialise FAS/NCR/AMD SCSI structures. - * Returns: 0 on success - */ -int fas216_init(struct Scsi_Host *host) -{ - FAS216_Info *info = (FAS216_Info *)host->hostdata; - - info->magic_start = MAGIC; - info->magic_end = MAGIC; - info->host = host; - info->scsi.cfg[0] = host->this_id | CNTL1_PERE; - info->scsi.cfg[1] = CNTL2_ENF | CNTL2_S2FE; - info->scsi.cfg[2] = info->ifcfg.cntl3 | - CNTL3_ADIDCHK | CNTL3_G2CB | CNTL3_LBTM; - info->scsi.async_stp = fas216_syncperiod(info, info->ifcfg.asyncperiod); - - info->rst_dev_status = -1; - info->rst_bus_status = -1; - init_waitqueue_head(&info->eh_wait); - init_timer(&info->eh_timer); - info->eh_timer.data = (unsigned long)info; - info->eh_timer.function = fas216_eh_timer; - - spin_lock_init(&info->host_lock); - - memset(&info->stats, 0, sizeof(info->stats)); - - msgqueue_initialise(&info->scsi.msgs); - - if (!queue_initialise(&info->queues.issue)) - return -ENOMEM; - - if (!queue_initialise(&info->queues.disconnected)) { - queue_free(&info->queues.issue); - return -ENOMEM; - } - - return 0; -} - -/** - * fas216_add - initialise FAS/NCR/AMD SCSI ic. - * @host: a driver-specific filled-out structure - * @dev: parent device - * - * Initialise FAS/NCR/AMD SCSI ic. - * Returns: 0 on success - */ -int fas216_add(struct Scsi_Host *host, struct device *dev) -{ - FAS216_Info *info = (FAS216_Info *)host->hostdata; - int type, ret; - - fas216_reset_state(info); - type = fas216_detect_type(info); - info->scsi.type = chip_types[type]; - - udelay(300); - - /* - * Initialise the chip correctly. - */ - fas216_init_chip(info); - - /* - * Reset the SCSI bus. We don't want to see - * the resulting reset interrupt, so mask it - * out. - */ - fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0] | CNTL1_DISR); - fas216_writeb(info, REG_CMD, CMD_RESETSCSI); - - /* - * scsi standard says wait 250ms - */ - spin_unlock_irq(info->host->host_lock); - scsi_sleep(100*HZ/100); - spin_lock_irq(info->host->host_lock); - - fas216_writeb(info, REG_CNTL1, info->scsi.cfg[0]); - fas216_readb(info, REG_INST); - - fas216_checkmagic(info); - - ret = scsi_add_host(host, dev); - if (ret) - fas216_writeb(info, REG_CMD, CMD_RESETCHIP); - - return ret; -} - -void fas216_remove(struct Scsi_Host *host) -{ - FAS216_Info *info = (FAS216_Info *)host->hostdata; - - fas216_checkmagic(info); - scsi_remove_host(host); - - fas216_writeb(info, REG_CMD, CMD_RESETCHIP); -} - -/** - * fas216_release - release all resources for FAS/NCR/AMD SCSI ic. - * @host: a driver-specific filled-out structure - * - * release all resources and put everything to bed for FAS/NCR/AMD SCSI ic. - */ -void fas216_release(struct Scsi_Host *host) -{ - FAS216_Info *info = (FAS216_Info *)host->hostdata; - - queue_free(&info->queues.disconnected); - queue_free(&info->queues.issue); -} - -int fas216_print_host(FAS216_Info *info, char *buffer) -{ - return sprintf(buffer, - "\n" - "Chip : %s\n" - " Address: 0x%08lx\n" - " IRQ : %d\n" - " DMA : %d\n", - info->scsi.type, info->host->io_port, - info->host->irq, info->host->dma_channel); -} - -int fas216_print_stats(FAS216_Info *info, char *buffer) -{ - char *p = buffer; - - p += sprintf(p, "\n" - "Command Statistics:\n" - " Queued : %u\n" - " Issued : %u\n" - " Completed : %u\n" - " Reads : %u\n" - " Writes : %u\n" - " Others : %u\n" - " Disconnects: %u\n" - " Aborts : %u\n" - " Bus resets : %u\n" - " Host resets: %u\n", - info->stats.queues, info->stats.removes, - info->stats.fins, info->stats.reads, - info->stats.writes, info->stats.miscs, - info->stats.disconnects, info->stats.aborts, - info->stats.bus_resets, info->stats.host_resets); - - return p - buffer; -} - -int fas216_print_device(FAS216_Info *info, Scsi_Device *scd, char *buffer) -{ - struct fas216_device *dev = &info->device[scd->id]; - int len = 0; - char *p; - - proc_print_scsidevice(scd, buffer, &len, 0); - p = buffer + len; - - p += sprintf(p, " Extensions: "); - - if (scd->tagged_supported) - p += sprintf(p, "TAG %sabled [%d] ", - scd->tagged_queue ? "en" : "dis", - scd->current_tag); - - p += sprintf(p, "%s\n", dev->parity_enabled ? "parity" : ""); - - p += sprintf(p, " Transfers : %d-bit ", - 8 << dev->wide_xfer); - - if (dev->sof) - p += sprintf(p, "sync offset %d, %d ns\n", - dev->sof, dev->period * 4); - else - p += sprintf(p, "async\n"); - - return p - buffer; -} - -EXPORT_SYMBOL(fas216_init); -EXPORT_SYMBOL(fas216_add); -EXPORT_SYMBOL(fas216_queue_command); -EXPORT_SYMBOL(fas216_command); -EXPORT_SYMBOL(fas216_intr); -EXPORT_SYMBOL(fas216_remove); -EXPORT_SYMBOL(fas216_release); -EXPORT_SYMBOL(fas216_eh_abort); -EXPORT_SYMBOL(fas216_eh_device_reset); -EXPORT_SYMBOL(fas216_eh_bus_reset); -EXPORT_SYMBOL(fas216_eh_host_reset); -EXPORT_SYMBOL(fas216_print_host); -EXPORT_SYMBOL(fas216_print_stats); -EXPORT_SYMBOL(fas216_print_device); - -MODULE_AUTHOR("Russell King"); -MODULE_DESCRIPTION("Generic FAS216/NCR53C9x driver core"); -MODULE_LICENSE("GPL"); diff -Nru a/drivers/acorn/scsi/fas216.h b/drivers/acorn/scsi/fas216.h --- a/drivers/acorn/scsi/fas216.h Sat May 24 12:48:33 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,401 +0,0 @@ -/* - * linux/drivers/acorn/scsi/fas216.h - * - * Copyright (C) 1997-2000 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * FAS216 generic driver - */ -#ifndef FAS216_H -#define FAS216_H - -#ifndef NO_IRQ -#define NO_IRQ 255 -#endif - -#include "queue.h" -#include "msgqueue.h" - -/* FAS register definitions */ - -/* transfer count low */ -#define REG_CTCL (0) -#define REG_STCL (0) - -/* transfer count medium */ -#define REG_CTCM (1) -#define REG_STCM (1) - -/* fifo data */ -#define REG_FF (2) - -/* command */ -#define REG_CMD (3) -#define CMD_NOP 0x00 -#define CMD_FLUSHFIFO 0x01 -#define CMD_RESETCHIP 0x02 -#define CMD_RESETSCSI 0x03 - -#define CMD_TRANSFERINFO 0x10 -#define CMD_INITCMDCOMPLETE 0x11 -#define CMD_MSGACCEPTED 0x12 -#define CMD_PADBYTES 0x18 -#define CMD_SETATN 0x1a -#define CMD_RSETATN 0x1b - -#define CMD_SELECTWOATN 0x41 -#define CMD_SELECTATN 0x42 -#define CMD_SELECTATNSTOP 0x43 -#define CMD_ENABLESEL 0x44 -#define CMD_DISABLESEL 0x45 -#define CMD_SELECTATN3 0x46 -#define CMD_RESEL3 0x47 - -#define CMD_WITHDMA 0x80 - -/* status register (read) */ -#define REG_STAT (4) -#define STAT_IO (1 << 0) /* IO phase */ -#define STAT_CD (1 << 1) /* CD phase */ -#define STAT_MSG (1 << 2) /* MSG phase */ -#define STAT_TRANSFERDONE (1 << 3) /* Transfer completed */ -#define STAT_TRANSFERCNTZ (1 << 4) /* Transfer counter is zero */ -#define STAT_PARITYERROR (1 << 5) /* Parity error */ -#define STAT_REALBAD (1 << 6) /* Something bad */ -#define STAT_INT (1 << 7) /* Interrupt */ - -#define STAT_BUSMASK (STAT_MSG|STAT_CD|STAT_IO) -#define STAT_DATAOUT (0) /* Data out */ -#define STAT_DATAIN (STAT_IO) /* Data in */ -#define STAT_COMMAND (STAT_CD) /* Command out */ -#define STAT_STATUS (STAT_CD|STAT_IO) /* Status In */ -#define STAT_MESGOUT (STAT_MSG|STAT_CD) /* Message out */ -#define STAT_MESGIN (STAT_MSG|STAT_CD|STAT_IO) /* Message In */ - -/* bus ID for select / reselect */ -#define REG_SDID (4) -#define BUSID(target) ((target) & 7) - -/* Interrupt status register (read) */ -#define REG_INST (5) -#define INST_SELWOATN (1 << 0) /* Select w/o ATN */ -#define INST_SELATN (1 << 1) /* Select w/ATN */ -#define INST_RESELECTED (1 << 2) /* Reselected */ -#define INST_FUNCDONE (1 << 3) /* Function done */ -#define INST_BUSSERVICE (1 << 4) /* Bus service */ -#define INST_DISCONNECT (1 << 5) /* Disconnect */ -#define INST_ILLEGALCMD (1 << 6) /* Illegal command */ -#define INST_BUSRESET (1 << 7) /* SCSI Bus reset */ - -/* Timeout register (write) */ -#define REG_STIM (5) - -/* Sequence step register (read) */ -#define REG_IS (6) -#define IS_BITS 0x07 -#define IS_SELARB 0x00 /* Select & Arb ok */ -#define IS_MSGBYTESENT 0x01 /* One byte message sent*/ -#define IS_NOTCOMMAND 0x02 /* Not in command state */ -#define IS_EARLYPHASE 0x03 /* Early phase change */ -#define IS_COMPLETE 0x04 /* Command ok */ -#define IS_SOF 0x08 /* Sync off flag */ - -/* Transfer period step (write) */ -#define REG_STP (6) - -/* Synchronous Offset (write) */ -#define REG_SOF (7) - -/* Fifo state register (read) */ -#define REG_CFIS (7) -#define CFIS_CF 0x1f /* Num bytes in FIFO */ -#define CFIS_IS 0xe0 /* Step */ - -/* config register 1 */ -#define REG_CNTL1 (8) -#define CNTL1_CID (7 << 0) /* Chip ID */ -#define CNTL1_STE (1 << 3) /* Self test enable */ -#define CNTL1_PERE (1 << 4) /* Parity enable reporting en. */ -#define CNTL1_PTE (1 << 5) /* Parity test enable */ -#define CNTL1_DISR (1 << 6) /* Disable Irq on SCSI reset */ -#define CNTL1_ETM (1 << 7) /* Extended Timing Mode */ - -/* Clock conversion factor (read) */ -#define REG_CLKF (9) -#define CLKF_F37MHZ 0x00 /* 35.01 - 40 MHz */ -#define CLKF_F10MHZ 0x02 /* 10 MHz */ -#define CLKF_F12MHZ 0x03 /* 10.01 - 15 MHz */ -#define CLKF_F17MHZ 0x04 /* 15.01 - 20 MHz */ -#define CLKF_F22MHZ 0x05 /* 20.01 - 25 MHz */ -#define CLKF_F27MHZ 0x06 /* 25.01 - 30 MHz */ -#define CLKF_F32MHZ 0x07 /* 30.01 - 35 MHz */ - -/* Chip test register (write) */ -#define REG_FTM (10) -#define TEST_FTM 0x01 /* Force target mode */ -#define TEST_FIM 0x02 /* Force initiator mode */ -#define TEST_FHI 0x04 /* Force high impedance mode */ - -/* Configuration register 2 (read/write) */ -#define REG_CNTL2 (11) -#define CNTL2_PGDP (1 << 0) /* Pass Th/Generate Data Parity */ -#define CNTL2_PGRP (1 << 1) /* Pass Th/Generate Reg Parity */ -#define CNTL2_ACDPE (1 << 2) /* Abort on Cmd/Data Parity Err */ -#define CNTL2_S2FE (1 << 3) /* SCSI2 Features Enable */ -#define CNTL2_TSDR (1 << 4) /* Tristate DREQ */ -#define CNTL2_SBO (1 << 5) /* Select Byte Order */ -#define CNTL2_ENF (1 << 6) /* Enable features */ -#define CNTL2_DAE (1 << 7) /* Data Alignment Enable */ - -/* Configuration register 3 (read/write) */ -#define REG_CNTL3 (12) -#define CNTL3_BS8 (1 << 0) /* Burst size 8 */ -#define CNTL3_MDM (1 << 1) /* Modify DMA mode */ -#define CNTL3_LBTM (1 << 2) /* Last Byte Transfer mode */ -#define CNTL3_FASTCLK (1 << 3) /* Fast SCSI clocking */ -#define CNTL3_FASTSCSI (1 << 4) /* Fast SCSI */ -#define CNTL3_G2CB (1 << 5) /* Group2 SCSI support */ -#define CNTL3_QTAG (1 << 6) /* Enable 3 byte msgs */ -#define CNTL3_ADIDCHK (1 << 7) /* Additional ID check */ - -/* High transfer count (read/write) */ -#define REG_CTCH (14) -#define REG_STCH (14) - -/* ID register (read only) */ -#define REG_ID (14) - -/* Data alignment */ -#define REG_DAL (15) - -typedef enum { - PHASE_IDLE, /* we're not planning on doing anything */ - PHASE_SELECTION, /* selecting a device */ - PHASE_SELSTEPS, /* selection with command steps */ - PHASE_COMMAND, /* command sent */ - PHASE_MESSAGESENT, /* selected, and we're sending cmd */ - PHASE_RECONNECTED, /* reconnected */ - PHASE_DATAOUT, /* data out to device */ - PHASE_DATAIN, /* data in from device */ - PHASE_MSGIN, /* message in from device */ - PHASE_MSGIN_DISCONNECT, /* disconnecting from bus */ - PHASE_MSGOUT, /* after message out phase */ - PHASE_MSGOUT_EXPECT, /* expecting message out */ - PHASE_STATUS, /* status from device */ - PHASE_DONE /* Command complete */ -} phase_t; - -typedef enum { - DMA_OUT, /* DMA from memory to chip */ - DMA_IN /* DMA from chip to memory */ -} fasdmadir_t; - -typedef enum { - fasdma_none, /* No dma */ - fasdma_pio, /* PIO mode */ - fasdma_pseudo, /* Pseudo DMA */ - fasdma_real_block, /* Real DMA, on block by block basis */ - fasdma_real_all /* Real DMA, on request by request */ -} fasdmatype_t; - -typedef enum { - neg_wait, /* Negociate with device */ - neg_inprogress, /* Negociation sent */ - neg_complete, /* Negociation complete */ - neg_targcomplete, /* Target completed negociation */ - neg_invalid /* Negociation not supported */ -} neg_t; - -#define MAGIC 0x441296bdUL -#define NR_MSGS 8 - -#define FASCAP_DMA (1 << 0) -#define FASCAP_PSEUDODMA (1 << 1) - -typedef struct { - unsigned long magic_start; - spinlock_t host_lock; - struct Scsi_Host *host; /* host */ - Scsi_Cmnd *SCpnt; /* currently processing command */ - Scsi_Cmnd *origSCpnt; /* original connecting command */ - Scsi_Cmnd *reqSCpnt; /* request sense command */ - Scsi_Cmnd *rstSCpnt; /* reset command */ - Scsi_Cmnd *pending_SCpnt[8]; /* per-device pending commands */ - int next_pending; /* next pending device */ - - /* - * Error recovery - */ - wait_queue_head_t eh_wait; - struct timer_list eh_timer; - unsigned int rst_dev_status; - unsigned int rst_bus_status; - - /* driver information */ - struct { - phase_t phase; /* current phase */ - void *io_base; /* iomem base of FAS216 */ - unsigned int io_port; /* base address of FAS216 */ - unsigned int io_shift; /* shift to adjust reg offsets by */ - unsigned char cfg[4]; /* configuration registers */ - const char *type; /* chip type */ - unsigned int irq; /* interrupt */ - - struct { - unsigned char target; /* reconnected target */ - unsigned char lun; /* reconnected lun */ - unsigned char tag; /* reconnected tag */ - } reconnected; - - Scsi_Pointer SCp; /* current commands data pointer */ - - MsgQueue_t msgs; /* message queue for connected device */ - - unsigned int async_stp; /* Async transfer STP value */ - unsigned char msgin_fifo; /* bytes in fifo at time of message in */ - unsigned char message[256]; /* last message received from device */ - - unsigned char disconnectable:1; /* this command can be disconnected */ - unsigned char aborting:1; /* aborting command */ - } scsi; - - /* statistics information */ - struct { - unsigned int queues; - unsigned int removes; - unsigned int fins; - unsigned int reads; - unsigned int writes; - unsigned int miscs; - unsigned int disconnects; - unsigned int aborts; - unsigned int bus_resets; - unsigned int host_resets; - } stats; - - /* configuration information */ - struct { - unsigned char clockrate; /* clock rate of FAS device (MHz) */ - unsigned char select_timeout; /* timeout (R5) */ - unsigned char sync_max_depth; /* Synchronous xfer max fifo depth */ - unsigned char wide_max_size; /* Maximum wide transfer size */ - unsigned char cntl3; /* Control Reg 3 */ - unsigned int asyncperiod; /* Async transfer period (ns) */ - unsigned int capabilities; /* driver capabilities */ - unsigned int disconnect_ok:1; /* Disconnects allowed? */ - } ifcfg; - - /* queue handling */ - struct { - Queue_t issue; /* issue queue */ - Queue_t disconnected; /* disconnected command queue */ - } queues; - - /* per-device info */ - struct fas216_device { - unsigned char disconnect_ok:1; /* device can disconnect */ - unsigned char parity_enabled:1; /* parity checking enabled */ - unsigned char parity_check:1; /* need to check parity checking */ - unsigned char period; /* sync xfer period in (*4ns) */ - unsigned char stp; /* synchronous transfer period */ - unsigned char sof; /* synchronous offset register */ - unsigned char wide_xfer; /* currently negociated wide transfer */ - neg_t sync_state; /* synchronous transfer mode */ - neg_t wide_state; /* wide transfer mode */ - } device[8]; - unsigned long busyluns[64/sizeof(unsigned long)];/* array of bits indicating LUNs busy */ - - /* dma */ - struct { - fasdmatype_t transfer_type; /* current type of DMA transfer */ - fasdmatype_t (*setup) (struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction, fasdmatype_t min_dma); - void (*pseudo)(struct Scsi_Host *host, Scsi_Pointer *SCp, fasdmadir_t direction, int transfer); - void (*stop) (struct Scsi_Host *host, Scsi_Pointer *SCp); - } dma; - - /* miscellaneous */ - int internal_done; /* flag to indicate request done */ - - unsigned long magic_end; -} FAS216_Info; - -/* Function: int fas216_init (struct Scsi_Host *instance) - * Purpose : initialise FAS/NCR/AMD SCSI structures. - * Params : instance - a driver-specific filled-out structure - * Returns : 0 on success - */ -extern int fas216_init (struct Scsi_Host *instance); - -/* Function: int fas216_add (struct Scsi_Host *instance, struct device *dev) - * Purpose : initialise FAS/NCR/AMD SCSI ic. - * Params : instance - a driver-specific filled-out structure - * Returns : 0 on success - */ -extern int fas216_add (struct Scsi_Host *instance, struct device *dev); - -/* Function: int fas216_queue_command (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) - * Purpose : queue a command for adapter to process. - * Params : SCpnt - Command to queue - * done - done function to call once command is complete - * Returns : 0 - success, else error - */ -extern int fas216_queue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); - -/* Function: int fas216_command (Scsi_Cmnd *SCpnt) - * Purpose : queue a command for adapter to process. - * Params : SCpnt - Command to queue - * Returns : scsi result code - */ -extern int fas216_command (Scsi_Cmnd *); - -/* Function: void fas216_intr (FAS216_Info *info) - * Purpose : handle interrupts from the interface to progress a command - * Params : info - interface to service - */ -extern void fas216_intr (FAS216_Info *info); - -extern void fas216_remove (struct Scsi_Host *instance); - -/* Function: void fas216_release (struct Scsi_Host *instance) - * Purpose : release all resources and put everything to bed for FAS/NCR/AMD SCSI ic. - * Params : instance - a driver-specific filled-out structure - * Returns : 0 on success - */ -extern void fas216_release (struct Scsi_Host *instance); - -extern int fas216_print_host(FAS216_Info *info, char *buffer); -extern int fas216_print_stats(FAS216_Info *info, char *buffer); -extern int fas216_print_device(FAS216_Info *info, Scsi_Device *scd, char *buffer); - -/* Function: int fas216_eh_abort(Scsi_Cmnd *SCpnt) - * Purpose : abort this command - * Params : SCpnt - command to abort - * Returns : FAILED if unable to abort - */ -extern int fas216_eh_abort(Scsi_Cmnd *SCpnt); - -/* Function: int fas216_eh_device_reset(Scsi_Cmnd *SCpnt) - * Purpose : Reset the device associated with this command - * Params : SCpnt - command specifing device to reset - * Returns : FAILED if unable to reset - */ -extern int fas216_eh_device_reset(Scsi_Cmnd *SCpnt); - -/* Function: int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt) - * Purpose : Reset the complete bus associated with this command - * Params : SCpnt - command specifing bus to reset - * Returns : FAILED if unable to reset - */ -extern int fas216_eh_bus_reset(Scsi_Cmnd *SCpnt); - -/* Function: int fas216_eh_host_reset(Scsi_Cmnd *SCpnt) - * Purpose : Reset the host associated with this command - * Params : SCpnt - command specifing host to reset - * Returns : FAILED if unable to reset - */ -extern int fas216_eh_host_reset(Scsi_Cmnd *SCpnt); - -#endif /* FAS216_H */ diff -Nru a/drivers/acorn/scsi/msgqueue.c b/drivers/acorn/scsi/msgqueue.c --- a/drivers/acorn/scsi/msgqueue.c Sat May 24 12:48:24 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,171 +0,0 @@ -/* - * linux/drivers/acorn/scsi/msgqueue.c - * - * Copyright (C) 1997-1998 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * message queue handling - */ -#include -#include -#include -#include - -#include "msgqueue.h" - -/* - * Function: struct msgqueue_entry *mqe_alloc(MsgQueue_t *msgq) - * Purpose : Allocate a message queue entry - * Params : msgq - message queue to claim entry for - * Returns : message queue entry or NULL. - */ -static struct msgqueue_entry *mqe_alloc(MsgQueue_t *msgq) -{ - struct msgqueue_entry *mq; - - if ((mq = msgq->free) != NULL) - msgq->free = mq->next; - - return mq; -} - -/* - * Function: void mqe_free(MsgQueue_t *msgq, struct msgqueue_entry *mq) - * Purpose : free a message queue entry - * Params : msgq - message queue to free entry from - * mq - message queue entry to free - */ -static void mqe_free(MsgQueue_t *msgq, struct msgqueue_entry *mq) -{ - if (mq) { - mq->next = msgq->free; - msgq->free = mq; - } -} - -/* - * Function: void msgqueue_initialise(MsgQueue_t *msgq) - * Purpose : initialise a message queue - * Params : msgq - queue to initialise - */ -void msgqueue_initialise(MsgQueue_t *msgq) -{ - int i; - - msgq->qe = NULL; - msgq->free = &msgq->entries[0]; - - for (i = 0; i < NR_MESSAGES; i++) - msgq->entries[i].next = &msgq->entries[i + 1]; - - msgq->entries[NR_MESSAGES - 1].next = NULL; -} - - -/* - * Function: void msgqueue_free(MsgQueue_t *msgq) - * Purpose : free a queue - * Params : msgq - queue to free - */ -void msgqueue_free(MsgQueue_t *msgq) -{ -} - -/* - * Function: int msgqueue_msglength(MsgQueue_t *msgq) - * Purpose : calculate the total length of all messages on the message queue - * Params : msgq - queue to examine - * Returns : number of bytes of messages in queue - */ -int msgqueue_msglength(MsgQueue_t *msgq) -{ - struct msgqueue_entry *mq = msgq->qe; - int length = 0; - - for (mq = msgq->qe; mq; mq = mq->next) - length += mq->msg.length; - - return length; -} - -/* - * Function: struct message *msgqueue_getmsg(MsgQueue_t *msgq, int msgno) - * Purpose : return a message - * Params : msgq - queue to obtain message from - * : msgno - message number - * Returns : pointer to message string, or NULL - */ -struct message *msgqueue_getmsg(MsgQueue_t *msgq, int msgno) -{ - struct msgqueue_entry *mq; - - for (mq = msgq->qe; mq && msgno; mq = mq->next, msgno--); - - return mq ? &mq->msg : NULL; -} - -/* - * Function: int msgqueue_addmsg(MsgQueue_t *msgq, int length, ...) - * Purpose : add a message onto a message queue - * Params : msgq - queue to add message on - * length - length of message - * ... - message bytes - * Returns : != 0 if successful - */ -int msgqueue_addmsg(MsgQueue_t *msgq, int length, ...) -{ - struct msgqueue_entry *mq = mqe_alloc(msgq); - va_list ap; - - if (mq) { - struct msgqueue_entry **mqp; - int i; - - va_start(ap, length); - for (i = 0; i < length; i++) - mq->msg.msg[i] = va_arg(ap, unsigned int); - va_end(ap); - - mq->msg.length = length; - mq->msg.fifo = 0; - mq->next = NULL; - - mqp = &msgq->qe; - while (*mqp) - mqp = &(*mqp)->next; - - *mqp = mq; - } - - return mq != NULL; -} - -/* - * Function: void msgqueue_flush(MsgQueue_t *msgq) - * Purpose : flush all messages from message queue - * Params : msgq - queue to flush - */ -void msgqueue_flush(MsgQueue_t *msgq) -{ - struct msgqueue_entry *mq, *mqnext; - - for (mq = msgq->qe; mq; mq = mqnext) { - mqnext = mq->next; - mqe_free(msgq, mq); - } - msgq->qe = NULL; -} - -EXPORT_SYMBOL(msgqueue_initialise); -EXPORT_SYMBOL(msgqueue_free); -EXPORT_SYMBOL(msgqueue_msglength); -EXPORT_SYMBOL(msgqueue_getmsg); -EXPORT_SYMBOL(msgqueue_addmsg); -EXPORT_SYMBOL(msgqueue_flush); - -MODULE_AUTHOR("Russell King"); -MODULE_DESCRIPTION("SCSI message queue handling"); -MODULE_LICENSE("GPL"); diff -Nru a/drivers/acorn/scsi/msgqueue.h b/drivers/acorn/scsi/msgqueue.h --- a/drivers/acorn/scsi/msgqueue.h Sat May 24 12:48:33 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,82 +0,0 @@ -/* - * linux/drivers/acorn/scsi/msgqueue.h - * - * Copyright (C) 1997 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * message queue handling - */ -#ifndef MSGQUEUE_H -#define MSGQUEUE_H - -struct message { - char msg[8]; - int length; - int fifo; -}; - -struct msgqueue_entry { - struct message msg; - struct msgqueue_entry *next; -}; - -#define NR_MESSAGES 4 - -typedef struct { - struct msgqueue_entry *qe; - struct msgqueue_entry *free; - struct msgqueue_entry entries[NR_MESSAGES]; -} MsgQueue_t; - -/* - * Function: void msgqueue_initialise(MsgQueue_t *msgq) - * Purpose : initialise a message queue - * Params : msgq - queue to initialise - */ -extern void msgqueue_initialise(MsgQueue_t *msgq); - -/* - * Function: void msgqueue_free(MsgQueue_t *msgq) - * Purpose : free a queue - * Params : msgq - queue to free - */ -extern void msgqueue_free(MsgQueue_t *msgq); - -/* - * Function: int msgqueue_msglength(MsgQueue_t *msgq) - * Purpose : calculate the total length of all messages on the message queue - * Params : msgq - queue to examine - * Returns : number of bytes of messages in queue - */ -extern int msgqueue_msglength(MsgQueue_t *msgq); - -/* - * Function: struct message *msgqueue_getmsg(MsgQueue_t *msgq, int msgno) - * Purpose : return a message & its length - * Params : msgq - queue to obtain message from - * : msgno - message number - * Returns : pointer to message string, or NULL - */ -extern struct message *msgqueue_getmsg(MsgQueue_t *msgq, int msgno); - -/* - * Function: int msgqueue_addmsg(MsgQueue_t *msgq, int length, ...) - * Purpose : add a message onto a message queue - * Params : msgq - queue to add message on - * length - length of message - * ... - message bytes - * Returns : != 0 if successful - */ -extern int msgqueue_addmsg(MsgQueue_t *msgq, int length, ...); - -/* - * Function: void msgqueue_flush(MsgQueue_t *msgq) - * Purpose : flush all messages from message queue - * Params : msgq - queue to flush - */ -extern void msgqueue_flush(MsgQueue_t *msgq); - -#endif diff -Nru a/drivers/acorn/scsi/oak.c b/drivers/acorn/scsi/oak.c --- a/drivers/acorn/scsi/oak.c Sat May 24 12:48:19 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,216 +0,0 @@ -/* - * Oak Generic NCR5380 driver - * - * Copyright 1995-2002, Russell King - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "../../scsi/scsi.h" -#include "../../scsi/hosts.h" - -#define AUTOSENSE -/*#define PSEUDO_DMA*/ - -#define OAKSCSI_PUBLIC_RELEASE 1 - -#define NCR5380_read(reg) oakscsi_read(_instance, reg) -#define NCR5380_write(reg, value) oakscsi_write(_instance, reg, value) -#define NCR5380_intr oakscsi_intr -#define NCR5380_queue_command oakscsi_queue_command -#define NCR5380_proc_info oakscsi_proc_info - -int NCR5380_proc_info(char *buffer, char **start, off_t offset, - int length, int hostno, int inout); - -#define NCR5380_implementation_fields int port, ctrl -#define NCR5380_local_declare() struct Scsi_Host *_instance -#define NCR5380_setup(instance) _instance = instance - -#define BOARD_NORMAL 0 -#define BOARD_NCR53C400 1 - -#include "../../scsi/NCR5380.h" - -#undef START_DMA_INITIATOR_RECEIVE_REG -#define START_DMA_INITIATOR_RECEIVE_REG (7 + 128) - -const char * oakscsi_info (struct Scsi_Host *spnt) -{ - return ""; -} - -#define STAT(p) inw(p + 144) -extern void inswb(int from, void *to, int len); - -static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *addr, - int len) -{ - int iobase = instance->io_port; -printk("writing %p len %d\n",addr, len); - if(!len) return -1; - - while(1) - { - int status; - while(((status = STAT(iobase)) & 0x100)==0); - } -} - -static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *addr, - int len) -{ - int iobase = instance->io_port; -printk("reading %p len %d\n", addr, len); - while(len > 0) - { - int status, timeout; - unsigned long b; - - timeout = 0x01FFFFFF; - - while(((status = STAT(iobase)) & 0x100)==0) - { - timeout--; - if(status & 0x200 || !timeout) - { - printk("status = %08X\n",status); - return 1; - } - } - if(len >= 128) - { - inswb(iobase + 136, addr, 128); - addr += 128; - len -= 128; - } - else - { - b = (unsigned long) inw(iobase + 136); - *addr ++ = b; - len -= 1; - if(len) - *addr ++ = b>>8; - len -= 1; - } - } - return 0; -} - -#define oakscsi_read(instance,reg) (inb((instance)->io_port + (reg))) -#define oakscsi_write(instance,reg,val) (outb((val), (instance)->io_port + (reg))) - -#undef STAT - -#include "../../scsi/NCR5380.c" - -static Scsi_Host_Template oakscsi_template = { - .module = THIS_MODULE, - .proc_info = oakscsi_proc_info, - .name = "Oak 16-bit SCSI", - .info = oakscsi_info, - .queuecommand = oakscsi_queue_command, - .eh_abort_handler = NCR5380_abort, - .eh_device_reset_handler= NCR5380_device_reset, - .eh_bus_reset_handler = NCR5380_bus_reset, - .eh_host_reset_handler = NCR5380_host_reset, - .can_queue = 16, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 2, - .use_clustering = DISABLE_CLUSTERING, - .proc_name = "oakscsi", -}; - -static int __devinit -oakscsi_probe(struct expansion_card *ec, const struct ecard_id *id) -{ - struct Scsi_Host *host; - int ret = -ENOMEM; - - host = scsi_register(&oakscsi_template, sizeof(struct NCR5380_hostdata)); - if (!host) - goto out; - - host->io_port = ecard_address(ec, ECARD_MEMC, 0); - host->irq = IRQ_NONE; - host->n_io_port = 255; - - ret = -EBUSY; - if (!request_region (host->io_port, host->n_io_port, "Oak SCSI")) - goto unreg; - - NCR5380_init(host, 0); - - printk("scsi%d: at port 0x%08lx irqs disabled", - host->host_no, host->io_port); - printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", - host->can_queue, host->cmd_per_lun, OAKSCSI_PUBLIC_RELEASE); - printk("\nscsi%d:", host->host_no); - NCR5380_print_options(host); - printk("\n"); - - ret = scsi_add_host(host, &ec->dev); - if (ret == 0) - goto out; - - release_region(host->io_port, host->n_io_port); - unreg: - scsi_unregister(host); - out: - return ret; -} - -static void __devexit oakscsi_remove(struct expansion_card *ec) -{ - struct Scsi_Host *host = ecard_get_drvdata(ec); - - ecard_set_drvdata(ec, NULL); - scsi_remove_host(host); - - release_region(host->io_port, host->n_io_port); - scsi_unregister(host); -} - -static const struct ecard_id oakscsi_cids[] = { - { MANU_OAK, PROD_OAK_SCSI }, - { 0xffff, 0xffff } -}; - -static struct ecard_driver oakscsi_driver = { - .probe = oakscsi_probe, - .remove = __devexit_p(oakscsi_remove), - .id_table = oakscsi_cids, - .drv = { - .devclass = &shost_devclass, - .name = "oakscsi", - }, -}; - -static int __init oakscsi_init(void) -{ - return ecard_register_driver(&oakscsi_driver); -} - -static void __exit oakscsi_exit(void) -{ - ecard_remove_driver(&oakscsi_driver); -} - -module_init(oakscsi_init); -module_exit(oakscsi_exit); - -MODULE_AUTHOR("Russell King"); -MODULE_DESCRIPTION("Oak SCSI driver"); -MODULE_LICENSE("GPL"); - diff -Nru a/drivers/acorn/scsi/powertec.c b/drivers/acorn/scsi/powertec.c --- a/drivers/acorn/scsi/powertec.c Sat May 24 12:48:27 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,500 +0,0 @@ -/* - * linux/drivers/acorn/scsi/powertec.c - * - * Copyright (C) 1997-2003 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "../../scsi/scsi.h" -#include "../../scsi/hosts.h" -#include "fas216.h" -#include "scsi.h" - -#include - -#define POWERTEC_FAS216_OFFSET 0x3000 -#define POWERTEC_FAS216_SHIFT 6 - -#define POWERTEC_INTR_STATUS 0x2000 -#define POWERTEC_INTR_BIT 0x80 - -#define POWERTEC_RESET_CONTROL 0x1018 -#define POWERTEC_RESET_BIT 1 - -#define POWERTEC_TERM_CONTROL 0x2018 -#define POWERTEC_TERM_ENABLE 1 - -#define POWERTEC_INTR_CONTROL 0x101c -#define POWERTEC_INTR_ENABLE 1 -#define POWERTEC_INTR_DISABLE 0 - -#define VERSION "1.10 (19/01/2003 2.5.59)" - -/* - * Use term=0,1,0,0,0 to turn terminators on/off. - * One entry per slot. - */ -static int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 }; - -#define NR_SG 256 - -struct powertec_info { - FAS216_Info info; - struct expansion_card *ec; - void *term_port; - unsigned int term_ctl; - struct scatterlist sg[NR_SG]; -}; - -/* Prototype: void powertecscsi_irqenable(ec, irqnr) - * Purpose : Enable interrupts on Powertec SCSI card - * Params : ec - expansion card structure - * : irqnr - interrupt number - */ -static void -powertecscsi_irqenable(struct expansion_card *ec, int irqnr) -{ - writeb(POWERTEC_INTR_ENABLE, ec->irq_data); -} - -/* Prototype: void powertecscsi_irqdisable(ec, irqnr) - * Purpose : Disable interrupts on Powertec SCSI card - * Params : ec - expansion card structure - * : irqnr - interrupt number - */ -static void -powertecscsi_irqdisable(struct expansion_card *ec, int irqnr) -{ - writeb(POWERTEC_INTR_DISABLE, ec->irq_data); -} - -static const expansioncard_ops_t powertecscsi_ops = { - .irqenable = powertecscsi_irqenable, - .irqdisable = powertecscsi_irqdisable, -}; - -/* Prototype: void powertecscsi_terminator_ctl(host, on_off) - * Purpose : Turn the Powertec SCSI terminators on or off - * Params : host - card to turn on/off - * : on_off - !0 to turn on, 0 to turn off - */ -static void -powertecscsi_terminator_ctl(struct Scsi_Host *host, int on_off) -{ - struct powertec_info *info = (struct powertec_info *)host->hostdata; - - info->term_ctl = on_off ? POWERTEC_TERM_ENABLE : 0; - writeb(info->term_ctl, info->term_port); -} - -/* Prototype: void powertecscsi_intr(irq, *dev_id, *regs) - * Purpose : handle interrupts from Powertec SCSI card - * Params : irq - interrupt number - * dev_id - user-defined (Scsi_Host structure) - * regs - processor registers at interrupt - */ -static void -powertecscsi_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - struct powertec_info *info = dev_id; - - fas216_intr(&info->info); -} - -/* Prototype: fasdmatype_t powertecscsi_dma_setup(host, SCpnt, direction, min_type) - * Purpose : initialises DMA/PIO - * Params : host - host - * SCpnt - command - * direction - DMA on to/off of card - * min_type - minimum DMA support that we must have for this transfer - * Returns : type of transfer to be performed - */ -static fasdmatype_t -powertecscsi_dma_setup(struct Scsi_Host *host, Scsi_Pointer *SCp, - fasdmadir_t direction, fasdmatype_t min_type) -{ - struct powertec_info *info = (struct powertec_info *)host->hostdata; - struct device *dev = scsi_get_device(host); - int dmach = host->dma_channel; - - if (info->info.ifcfg.capabilities & FASCAP_DMA && - min_type == fasdma_real_all) { - int bufs, map_dir, dma_dir; - - bufs = copy_SCp_to_sg(&info->sg[0], SCp, NR_SG); - - if (direction == DMA_OUT) - map_dir = DMA_TO_DEVICE, - dma_dir = DMA_MODE_WRITE; - else - map_dir = DMA_FROM_DEVICE, - dma_dir = DMA_MODE_READ; - - dma_map_sg(dev, info->sg, bufs + 1, map_dir); - - disable_dma(dmach); - set_dma_sg(dmach, info->sg, bufs + 1); - set_dma_mode(dmach, dma_dir); - enable_dma(dmach); - return fasdma_real_all; - } - - /* - * If we're not doing DMA, - * we'll do slow PIO - */ - return fasdma_pio; -} - -/* Prototype: int powertecscsi_dma_stop(host, SCpnt) - * Purpose : stops DMA/PIO - * Params : host - host - * SCpnt - command - */ -static void -powertecscsi_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp) -{ - if (host->dma_channel != NO_DMA) - disable_dma(host->dma_channel); -} - -/* Prototype: const char *powertecscsi_info(struct Scsi_Host * host) - * Purpose : returns a descriptive string about this interface, - * Params : host - driver host structure to return info for. - * Returns : pointer to a static buffer containing null terminated string. - */ -const char *powertecscsi_info(struct Scsi_Host *host) -{ - struct powertec_info *info = (struct powertec_info *)host->hostdata; - static char string[150]; - - sprintf(string, "%s (%s) in slot %d v%s terminators o%s", - host->hostt->name, info->info.scsi.type, info->ec->slot_no, - VERSION, info->term_ctl ? "n" : "ff"); - - return string; -} - -/* Prototype: int powertecscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length) - * Purpose : Set a driver specific function - * Params : host - host to setup - * : buffer - buffer containing string describing operation - * : length - length of string - * Returns : -EINVAL, or 0 - */ -static int -powertecscsi_set_proc_info(struct Scsi_Host *host, char *buffer, int length) -{ - int ret = length; - - if (length >= 12 && strncmp(buffer, "POWERTECSCSI", 12) == 0) { - buffer += 12; - length -= 12; - - if (length >= 5 && strncmp(buffer, "term=", 5) == 0) { - if (buffer[5] == '1') - powertecscsi_terminator_ctl(host, 1); - else if (buffer[5] == '0') - powertecscsi_terminator_ctl(host, 0); - else - ret = -EINVAL; - } else - ret = -EINVAL; - } else - ret = -EINVAL; - - return ret; -} - -/* Prototype: int powertecscsi_proc_info(char *buffer, char **start, off_t offset, - * int length, int host_no, int inout) - * Purpose : Return information about the driver to a user process accessing - * the /proc filesystem. - * Params : buffer - a buffer to write information to - * start - a pointer into this buffer set by this routine to the start - * of the required information. - * offset - offset into information that we have read upto. - * length - length of buffer - * host_no - host number to return information for - * inout - 0 for reading, 1 for writing. - * Returns : length of data written to buffer. - */ -int powertecscsi_proc_info(char *buffer, char **start, off_t offset, - int length, int host_no, int inout) -{ - int pos, begin; - struct Scsi_Host *host; - struct powertec_info *info; - Scsi_Device *scd; - - host = scsi_host_hn_get(host_no); - if (!host) - return 0; - - if (inout == 1) - return powertecscsi_set_proc_info(host, buffer, length); - - info = (struct powertec_info *)host->hostdata; - - begin = 0; - pos = sprintf(buffer, "PowerTec SCSI driver v%s\n", VERSION); - pos += fas216_print_host(&info->info, buffer + pos); - pos += sprintf(buffer + pos, "Term : o%s\n", - info->term_ctl ? "n" : "ff"); - - pos += fas216_print_stats(&info->info, buffer + pos); - - pos += sprintf(buffer+pos, "\nAttached devices:\n"); - - list_for_each_entry(scd, &host->my_devices, siblings) { - pos += fas216_print_device(&info->info, scd, buffer + pos); - - if (pos + begin < offset) { - begin += pos; - pos = 0; - } - if (pos + begin > offset + length) - break; - } - - *start = buffer + (offset - begin); - pos -= offset - begin; - if (pos > length) - pos = length; - - return pos; -} - -static ssize_t powertecscsi_show_term(struct device *dev, char *buf) -{ - struct expansion_card *ec = ECARD_DEV(dev); - struct Scsi_Host *host = ecard_get_drvdata(ec); - struct powertec_info *info = (struct powertec_info *)host->hostdata; - - return sprintf(buf, "%d\n", info->term_ctl ? 1 : 0); -} - -static ssize_t -powertecscsi_store_term(struct device *dev, const char *buf, size_t len) -{ - struct expansion_card *ec = ECARD_DEV(dev); - struct Scsi_Host *host = ecard_get_drvdata(ec); - - if (len > 1) - powertecscsi_terminator_ctl(host, buf[0] != '0'); - - return len; -} - -static DEVICE_ATTR(bus_term, S_IRUGO | S_IWUSR, - powertecscsi_show_term, powertecscsi_store_term); - -static Scsi_Host_Template powertecscsi_template = { - .module = THIS_MODULE, - .proc_info = powertecscsi_proc_info, - .name = "PowerTec SCSI", - .info = powertecscsi_info, - .command = fas216_command, - .queuecommand = fas216_queue_command, - .eh_host_reset_handler = fas216_eh_host_reset, - .eh_bus_reset_handler = fas216_eh_bus_reset, - .eh_device_reset_handler = fas216_eh_device_reset, - .eh_abort_handler = fas216_eh_abort, - - .can_queue = 8, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 2, - .use_clustering = ENABLE_CLUSTERING, - .proc_name = "powertec", -}; - -static int __devinit -powertecscsi_probe(struct expansion_card *ec, const struct ecard_id *id) -{ - struct Scsi_Host *host; - struct powertec_info *info; - unsigned long resbase, reslen; - unsigned char *base; - int ret; - - resbase = ecard_resource_start(ec, ECARD_RES_IOCFAST); - reslen = ecard_resource_len(ec, ECARD_RES_IOCFAST); - - if (!request_mem_region(resbase, reslen, "powertecscsi")) { - ret = -EBUSY; - goto out; - } - - base = ioremap(resbase, reslen); - if (!base) { - ret = -ENOMEM; - goto out_region; - } - - host = scsi_register(&powertecscsi_template, - sizeof (struct powertec_info)); - if (!host) { - ret = -ENOMEM; - goto out_unmap; - } - - host->base = (unsigned long)base; - host->irq = ec->irq; - host->dma_channel = ec->dma; - - ec->irqaddr = base + POWERTEC_INTR_STATUS; - ec->irqmask = POWERTEC_INTR_BIT; - ec->irq_data = base + POWERTEC_INTR_CONTROL; - ec->ops = &powertecscsi_ops; - - ecard_set_drvdata(ec, host); - - info = (struct powertec_info *)host->hostdata; - info->term_port = base + POWERTEC_TERM_CONTROL; - powertecscsi_terminator_ctl(host, term[ec->slot_no]); - - device_create_file(&ec->dev, &dev_attr_bus_term); - - info->info.scsi.io_base = base + POWERTEC_FAS216_OFFSET; - info->info.scsi.io_shift = POWERTEC_FAS216_SHIFT; - info->info.scsi.irq = host->irq; - info->info.ifcfg.clockrate = 40; /* MHz */ - info->info.ifcfg.select_timeout = 255; - info->info.ifcfg.asyncperiod = 200; /* ns */ - info->info.ifcfg.sync_max_depth = 7; - info->info.ifcfg.cntl3 = CNTL3_BS8 | CNTL3_FASTSCSI | CNTL3_FASTCLK; - info->info.ifcfg.disconnect_ok = 1; - info->info.ifcfg.wide_max_size = 0; - info->info.ifcfg.capabilities = 0; - info->info.dma.setup = powertecscsi_dma_setup; - info->info.dma.pseudo = NULL; - info->info.dma.stop = powertecscsi_dma_stop; - - ret = fas216_init(host); - if (ret) - goto out_free; - - ret = request_irq(host->irq, powertecscsi_intr, - SA_INTERRUPT, "powertec", info); - if (ret) { - printk("scsi%d: IRQ%d not free: %d\n", - host->host_no, host->irq, ret); - goto out_release; - } - - if (host->dma_channel != NO_DMA) { - if (request_dma(host->dma_channel, "powertec")) { - printk("scsi%d: DMA%d not free, using PIO\n", - host->host_no, host->dma_channel); - host->dma_channel = NO_DMA; - } else { - set_dma_speed(host->dma_channel, 180); - info->info.ifcfg.capabilities |= FASCAP_DMA; - } - } - - ret = fas216_add(host, &ec->dev); - if (ret == 0) - goto out; - - if (host->dma_channel != NO_DMA) - free_dma(host->dma_channel); - free_irq(host->irq, host); - - out_release: - fas216_release(host); - - out_free: - device_remove_file(&ec->dev, &dev_attr_bus_term); - scsi_unregister(host); - - out_unmap: - iounmap(base); - - out_region: - release_mem_region(resbase, reslen); - - out: - return ret; -} - -static void __devexit powertecscsi_remove(struct expansion_card *ec) -{ - struct Scsi_Host *host = ecard_get_drvdata(ec); - struct powertecscsi_info *info = (struct powertecscsi_info *)host->hostdata; - unsigned long resbase, reslen; - - ecard_set_drvdata(ec, NULL); - fas216_remove(host); - - device_remove_file(&ec->dev, &dev_attr_bus_term); - - if (host->dma_channel != NO_DMA) - free_dma(host->dma_channel); - free_irq(host->irq, info); - - iounmap((void *)host->base); - - resbase = ecard_resource_start(ec, ECARD_RES_IOCFAST); - reslen = ecard_resource_len(ec, ECARD_RES_IOCFAST); - - release_mem_region(resbase, reslen); - - fas216_release(host); - scsi_unregister(host); -} - -static const struct ecard_id powertecscsi_cids[] = { - { MANU_ALSYSTEMS, PROD_ALSYS_SCSIATAPI }, - { 0xffff, 0xffff }, -}; - -static struct ecard_driver powertecscsi_driver = { - .probe = powertecscsi_probe, - .remove = __devexit_p(powertecscsi_remove), - .id_table = powertecscsi_cids, - .drv = { - .devclass = &shost_devclass, - .name = "powertecscsi", - }, -}; - -static int __init powertecscsi_init(void) -{ - return ecard_register_driver(&powertecscsi_driver); -} - -static void __exit powertecscsi_exit(void) -{ - ecard_remove_driver(&powertecscsi_driver); -} - -module_init(powertecscsi_init); -module_exit(powertecscsi_exit); - -MODULE_AUTHOR("Russell King"); -MODULE_DESCRIPTION("Powertec SCSI driver"); -MODULE_PARM(term, "1-8i"); -MODULE_PARM_DESC(term, "SCSI bus termination"); -MODULE_LICENSE("GPL"); diff -Nru a/drivers/acorn/scsi/queue.c b/drivers/acorn/scsi/queue.c --- a/drivers/acorn/scsi/queue.c Sat May 24 12:48:20 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,319 +0,0 @@ -/* - * linux/drivers/acorn/scsi/queue.c: queue handling primitives - * - * Copyright (C) 1997-2000 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Changelog: - * 15-Sep-1997 RMK Created. - * 11-Oct-1997 RMK Corrected problem with queue_remove_exclude - * not updating internal linked list properly - * (was causing commands to go missing). - * 30-Aug-2000 RMK Use Linux list handling and spinlocks - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../../scsi/scsi.h" - -#define DEBUG - -typedef struct queue_entry { - struct list_head list; - Scsi_Cmnd *SCpnt; -#ifdef DEBUG - unsigned long magic; -#endif -} QE_t; - -#ifdef DEBUG -#define QUEUE_MAGIC_FREE 0xf7e1c9a3 -#define QUEUE_MAGIC_USED 0xf7e1cc33 - -#define SET_MAGIC(q,m) ((q)->magic = (m)) -#define BAD_MAGIC(q,m) ((q)->magic != (m)) -#else -#define SET_MAGIC(q,m) do { } while (0) -#define BAD_MAGIC(q,m) (0) -#endif - -#include "queue.h" - -#define NR_QE 32 - -/* - * Function: void queue_initialise (Queue_t *queue) - * Purpose : initialise a queue - * Params : queue - queue to initialise - */ -int queue_initialise (Queue_t *queue) -{ - unsigned int nqueues = NR_QE; - QE_t *q; - - spin_lock_init(&queue->queue_lock); - INIT_LIST_HEAD(&queue->head); - INIT_LIST_HEAD(&queue->free); - - /* - * If life was easier, then SCpnt would have a - * host-available list head, and we wouldn't - * need to keep free lists or allocate this - * memory. - */ - queue->alloc = q = kmalloc(sizeof(QE_t) * nqueues, GFP_KERNEL); - if (q) { - for (; nqueues; q++, nqueues--) { - SET_MAGIC(q, QUEUE_MAGIC_FREE); - q->SCpnt = NULL; - list_add(&q->list, &queue->free); - } - } - - return queue->alloc != NULL; -} - -/* - * Function: void queue_free (Queue_t *queue) - * Purpose : free a queue - * Params : queue - queue to free - */ -void queue_free (Queue_t *queue) -{ - if (!list_empty(&queue->head)) - printk(KERN_WARNING "freeing non-empty queue %p\n", queue); - if (queue->alloc) - kfree(queue->alloc); -} - - -/* - * Function: int queue_add_cmd(Queue_t *queue, Scsi_Cmnd *SCpnt, int head) - * Purpose : Add a new command onto a queue, adding REQUEST_SENSE to head. - * Params : queue - destination queue - * SCpnt - command to add - * head - add command to head of queue - * Returns : 0 on error, !0 on success - */ -int __queue_add(Queue_t *queue, Scsi_Cmnd *SCpnt, int head) -{ - unsigned long flags; - struct list_head *l; - QE_t *q; - int ret = 0; - - spin_lock_irqsave(&queue->queue_lock, flags); - if (list_empty(&queue->free)) - goto empty; - - l = queue->free.next; - list_del(l); - - q = list_entry(l, QE_t, list); - if (BAD_MAGIC(q, QUEUE_MAGIC_FREE)) - BUG(); - - SET_MAGIC(q, QUEUE_MAGIC_USED); - q->SCpnt = SCpnt; - - if (head) - list_add(l, &queue->head); - else - list_add_tail(l, &queue->head); - - ret = 1; -empty: - spin_unlock_irqrestore(&queue->queue_lock, flags); - return ret; -} - -static Scsi_Cmnd *__queue_remove(Queue_t *queue, struct list_head *ent) -{ - QE_t *q; - - /* - * Move the entry from the "used" list onto the "free" list - */ - list_del(ent); - q = list_entry(ent, QE_t, list); - if (BAD_MAGIC(q, QUEUE_MAGIC_USED)) - BUG(); - - SET_MAGIC(q, QUEUE_MAGIC_FREE); - list_add(ent, &queue->free); - - return q->SCpnt; -} - -/* - * Function: Scsi_Cmnd *queue_remove_exclude (queue, exclude) - * Purpose : remove a SCSI command from a queue - * Params : queue - queue to remove command from - * exclude - bit array of target&lun which is busy - * Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available - */ -Scsi_Cmnd *queue_remove_exclude(Queue_t *queue, unsigned long *exclude) -{ - unsigned long flags; - struct list_head *l; - Scsi_Cmnd *SCpnt = NULL; - - spin_lock_irqsave(&queue->queue_lock, flags); - list_for_each(l, &queue->head) { - QE_t *q = list_entry(l, QE_t, list); - if (!test_bit(q->SCpnt->device->id * 8 + q->SCpnt->device->lun, exclude)) { - SCpnt = __queue_remove(queue, l); - break; - } - } - spin_unlock_irqrestore(&queue->queue_lock, flags); - - return SCpnt; -} - -/* - * Function: Scsi_Cmnd *queue_remove (queue) - * Purpose : removes first SCSI command from a queue - * Params : queue - queue to remove command from - * Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available - */ -Scsi_Cmnd *queue_remove(Queue_t *queue) -{ - unsigned long flags; - Scsi_Cmnd *SCpnt = NULL; - - spin_lock_irqsave(&queue->queue_lock, flags); - if (!list_empty(&queue->head)) - SCpnt = __queue_remove(queue, queue->head.next); - spin_unlock_irqrestore(&queue->queue_lock, flags); - - return SCpnt; -} - -/* - * Function: Scsi_Cmnd *queue_remove_tgtluntag (queue, target, lun, tag) - * Purpose : remove a SCSI command from the queue for a specified target/lun/tag - * Params : queue - queue to remove command from - * target - target that we want - * lun - lun on device - * tag - tag on device - * Returns : Scsi_Cmnd if successful, or NULL if no command satisfies requirements - */ -Scsi_Cmnd *queue_remove_tgtluntag (Queue_t *queue, int target, int lun, int tag) -{ - unsigned long flags; - struct list_head *l; - Scsi_Cmnd *SCpnt = NULL; - - spin_lock_irqsave(&queue->queue_lock, flags); - list_for_each(l, &queue->head) { - QE_t *q = list_entry(l, QE_t, list); - if (q->SCpnt->device->id == target && q->SCpnt->device->lun == lun && - q->SCpnt->tag == tag) { - SCpnt = __queue_remove(queue, l); - break; - } - } - spin_unlock_irqrestore(&queue->queue_lock, flags); - - return SCpnt; -} - -/* - * Function: queue_remove_all_target(queue, target) - * Purpose : remove all SCSI commands from the queue for a specified target - * Params : queue - queue to remove command from - * target - target device id - * Returns : nothing - */ -void queue_remove_all_target(Queue_t *queue, int target) -{ - unsigned long flags; - struct list_head *l; - - spin_lock_irqsave(&queue->queue_lock, flags); - list_for_each(l, &queue->head) { - QE_t *q = list_entry(l, QE_t, list); - if (q->SCpnt->device->id == target) - __queue_remove(queue, l); - } - spin_unlock_irqrestore(&queue->queue_lock, flags); -} - -/* - * Function: int queue_probetgtlun (queue, target, lun) - * Purpose : check to see if we have a command in the queue for the specified - * target/lun. - * Params : queue - queue to look in - * target - target we want to probe - * lun - lun on target - * Returns : 0 if not found, != 0 if found - */ -int queue_probetgtlun (Queue_t *queue, int target, int lun) -{ - unsigned long flags; - struct list_head *l; - int found = 0; - - spin_lock_irqsave(&queue->queue_lock, flags); - list_for_each(l, &queue->head) { - QE_t *q = list_entry(l, QE_t, list); - if (q->SCpnt->device->id == target && q->SCpnt->device->lun == lun) { - found = 1; - break; - } - } - spin_unlock_irqrestore(&queue->queue_lock, flags); - - return found; -} - -/* - * Function: int queue_remove_cmd(Queue_t *queue, Scsi_Cmnd *SCpnt) - * Purpose : remove a specific command from the queues - * Params : queue - queue to look in - * SCpnt - command to find - * Returns : 0 if not found - */ -int queue_remove_cmd(Queue_t *queue, Scsi_Cmnd *SCpnt) -{ - unsigned long flags; - struct list_head *l; - int found = 0; - - spin_lock_irqsave(&queue->queue_lock, flags); - list_for_each(l, &queue->head) { - QE_t *q = list_entry(l, QE_t, list); - if (q->SCpnt == SCpnt) { - __queue_remove(queue, l); - found = 1; - break; - } - } - spin_unlock_irqrestore(&queue->queue_lock, flags); - - return found; -} - -EXPORT_SYMBOL(queue_initialise); -EXPORT_SYMBOL(queue_free); -EXPORT_SYMBOL(__queue_add); -EXPORT_SYMBOL(queue_remove); -EXPORT_SYMBOL(queue_remove_exclude); -EXPORT_SYMBOL(queue_remove_tgtluntag); -EXPORT_SYMBOL(queue_remove_cmd); -EXPORT_SYMBOL(queue_remove_all_target); -EXPORT_SYMBOL(queue_probetgtlun); - -MODULE_AUTHOR("Russell King"); -MODULE_DESCRIPTION("SCSI command queueing"); -MODULE_LICENSE("GPL"); diff -Nru a/drivers/acorn/scsi/queue.h b/drivers/acorn/scsi/queue.h --- a/drivers/acorn/scsi/queue.h Sat May 24 12:48:25 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,105 +0,0 @@ -/* - * linux/drivers/acorn/scsi/queue.h: queue handling - * - * Copyright (C) 1997 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#ifndef QUEUE_H -#define QUEUE_H - -typedef struct { - struct list_head head; - struct list_head free; - spinlock_t queue_lock; - void *alloc; /* start of allocated mem */ -} Queue_t; - -/* - * Function: void queue_initialise (Queue_t *queue) - * Purpose : initialise a queue - * Params : queue - queue to initialise - */ -extern int queue_initialise (Queue_t *queue); - -/* - * Function: void queue_free (Queue_t *queue) - * Purpose : free a queue - * Params : queue - queue to free - */ -extern void queue_free (Queue_t *queue); - -/* - * Function: Scsi_Cmnd *queue_remove (queue) - * Purpose : removes first SCSI command from a queue - * Params : queue - queue to remove command from - * Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available - */ -extern Scsi_Cmnd *queue_remove (Queue_t *queue); - -/* - * Function: Scsi_Cmnd *queue_remove_exclude_ref (queue, exclude) - * Purpose : remove a SCSI command from a queue - * Params : queue - queue to remove command from - * exclude - array of busy LUNs - * Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available - */ -extern Scsi_Cmnd *queue_remove_exclude (Queue_t *queue, unsigned long *exclude); - -#define queue_add_cmd_ordered(queue,SCpnt) \ - __queue_add(queue,SCpnt,(SCpnt)->cmnd[0] == REQUEST_SENSE) -#define queue_add_cmd_tail(queue,SCpnt) \ - __queue_add(queue,SCpnt,0) -/* - * Function: int __queue_add(Queue_t *queue, Scsi_Cmnd *SCpnt, int head) - * Purpose : Add a new command onto a queue - * Params : queue - destination queue - * SCpnt - command to add - * head - add command to head of queue - * Returns : 0 on error, !0 on success - */ -extern int __queue_add(Queue_t *queue, Scsi_Cmnd *SCpnt, int head); - -/* - * Function: Scsi_Cmnd *queue_remove_tgtluntag (queue, target, lun, tag) - * Purpose : remove a SCSI command from the queue for a specified target/lun/tag - * Params : queue - queue to remove command from - * target - target that we want - * lun - lun on device - * tag - tag on device - * Returns : Scsi_Cmnd if successful, or NULL if no command satisfies requirements - */ -extern Scsi_Cmnd *queue_remove_tgtluntag (Queue_t *queue, int target, int lun, int tag); - -/* - * Function: queue_remove_all_target(queue, target) - * Purpose : remove all SCSI commands from the queue for a specified target - * Params : queue - queue to remove command from - * target - target device id - * Returns : nothing - */ -extern void queue_remove_all_target(Queue_t *queue, int target); - -/* - * Function: int queue_probetgtlun (queue, target, lun) - * Purpose : check to see if we have a command in the queue for the specified - * target/lun. - * Params : queue - queue to look in - * target - target we want to probe - * lun - lun on target - * Returns : 0 if not found, != 0 if found - */ -extern int queue_probetgtlun (Queue_t *queue, int target, int lun); - -/* - * Function: int queue_remove_cmd (Queue_t *queue, Scsi_Cmnd *SCpnt) - * Purpose : remove a specific command from the queues - * Params : queue - queue to look in - * SCpnt - command to find - * Returns : 0 if not found - */ -int queue_remove_cmd(Queue_t *queue, Scsi_Cmnd *SCpnt); - -#endif /* QUEUE_H */ diff -Nru a/drivers/acorn/scsi/scsi.h b/drivers/acorn/scsi/scsi.h --- a/drivers/acorn/scsi/scsi.h Sat May 24 12:48:21 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,115 +0,0 @@ -/* - * linux/drivers/acorn/scsi/scsi.h - * - * Copyright (C) 2002 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Commonly used scsi driver functions. - */ - -#define BELT_AND_BRACES - -/* - * The scatter-gather list handling. This contains all - * the yucky stuff that needs to be fixed properly. - */ -static inline int copy_SCp_to_sg(struct scatterlist *sg, Scsi_Pointer *SCp, int max) -{ - int bufs = SCp->buffers_residual; - - BUG_ON(bufs + 1 > max); - - sg->page = virt_to_page(SCp->ptr); - sg->offset = ((unsigned int)SCp->ptr) & ~PAGE_MASK; - sg->length = SCp->this_residual; - - if (bufs) - memcpy(sg + 1, SCp->buffer + 1, - sizeof(struct scatterlist) * bufs); - return bufs + 1; -} - -static inline int next_SCp(Scsi_Pointer *SCp) -{ - int ret = SCp->buffers_residual; - if (ret) { - SCp->buffer++; - SCp->buffers_residual--; - SCp->ptr = (char *) - (page_address(SCp->buffer->page) + - SCp->buffer->offset); - SCp->this_residual = SCp->buffer->length; - } else { - SCp->ptr = NULL; - SCp->this_residual = 0; - } - return ret; -} - -static inline unsigned char get_next_SCp_byte(Scsi_Pointer *SCp) -{ - char c = *SCp->ptr; - - SCp->ptr += 1; - SCp->this_residual -= 1; - - return c; -} - -static inline void put_next_SCp_byte(Scsi_Pointer *SCp, unsigned char c) -{ - *SCp->ptr = c; - SCp->ptr += 1; - SCp->this_residual -= 1; -} - -static inline void init_SCp(Scsi_Cmnd *SCpnt) -{ - memset(&SCpnt->SCp, 0, sizeof(struct scsi_pointer)); - - if (SCpnt->use_sg) { - unsigned long len = 0; - int buf; - - SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->buffer; - SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1; - SCpnt->SCp.ptr = (char *) - (page_address(SCpnt->SCp.buffer->page) + - SCpnt->SCp.buffer->offset); - SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; - -#ifdef BELT_AND_BRACES - /* - * Calculate correct buffer length. Some commands - * come in with the wrong request_bufflen. - */ - for (buf = 0; buf <= SCpnt->SCp.buffers_residual; buf++) - len += SCpnt->SCp.buffer[buf].length; - - if (SCpnt->request_bufflen != len) - printk(KERN_WARNING "scsi%d.%c: bad request buffer " - "length %d, should be %ld\n", SCpnt->device->host->host_no, - '0' + SCpnt->device->id, SCpnt->request_bufflen, len); - SCpnt->request_bufflen = len; -#endif - } else { - SCpnt->SCp.ptr = (unsigned char *)SCpnt->request_buffer; - SCpnt->SCp.this_residual = SCpnt->request_bufflen; - } - - /* - * If the upper SCSI layers pass a buffer, but zero length, - * we aren't interested in the buffer pointer. - */ - if (SCpnt->SCp.this_residual == 0 && SCpnt->SCp.ptr) { -#if 0 //def BELT_AND_BRACES - printk(KERN_WARNING "scsi%d.%c: zero length buffer passed for " - "command ", SCpnt->host->host_no, '0' + SCpnt->target); - print_command(SCpnt->cmnd); -#endif - SCpnt->SCp.ptr = NULL; - } -} diff -Nru a/drivers/acpi/acpi_ksyms.c b/drivers/acpi/acpi_ksyms.c --- a/drivers/acpi/acpi_ksyms.c Sat May 24 12:48:23 2003 +++ b/drivers/acpi/acpi_ksyms.c Sat May 24 12:48:23 2003 @@ -80,6 +80,7 @@ EXPORT_SYMBOL(acpi_get_possible_resources); EXPORT_SYMBOL(acpi_walk_resources); EXPORT_SYMBOL(acpi_set_current_resources); +EXPORT_SYMBOL(acpi_resource_to_address64); EXPORT_SYMBOL(acpi_enable_event); EXPORT_SYMBOL(acpi_disable_event); EXPORT_SYMBOL(acpi_clear_event); diff -Nru a/drivers/acpi/dispatcher/dsinit.c b/drivers/acpi/dispatcher/dsinit.c --- a/drivers/acpi/dispatcher/dsinit.c Sat May 24 12:48:32 2003 +++ b/drivers/acpi/dispatcher/dsinit.c Sat May 24 12:48:32 2003 @@ -222,8 +222,8 @@ } ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, - "\nTable [%4.4s] - %hd Objects with %hd Devices %hd Methods %hd Regions\n", - table_desc->pointer->signature, info.object_count, + "\nTable [%4.4s](id %4.4X) - %hd Objects with %hd Devices %hd Methods %hd Regions\n", + table_desc->pointer->signature, table_desc->table_id, info.object_count, info.device_count, info.method_count, info.op_region_count)); ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, diff -Nru a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c --- a/drivers/acpi/dispatcher/dsmethod.c Sat May 24 12:48:24 2003 +++ b/drivers/acpi/dispatcher/dsmethod.c Sat May 24 12:48:24 2003 @@ -290,6 +290,8 @@ return_ACPI_STATUS (AE_NULL_OBJECT); } + obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD); + /* Init for new method, wait on concurrency semaphore */ status = acpi_ds_begin_method_execution (method_node, obj_desc, diff -Nru a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c --- a/drivers/acpi/dispatcher/dsobject.c Sat May 24 12:48:19 2003 +++ b/drivers/acpi/dispatcher/dsobject.c Sat May 24 12:48:19 2003 @@ -204,7 +204,8 @@ if (obj_desc->buffer.length == 0) { obj_desc->buffer.pointer = NULL; - ACPI_REPORT_WARNING (("Buffer created with zero length in AML\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Buffer defined with zero length in AML, creating\n")); } else { obj_desc->buffer.pointer = ACPI_MEM_CALLOCATE ( diff -Nru a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c --- a/drivers/acpi/dispatcher/dsopcode.c Sat May 24 12:48:31 2003 +++ b/drivers/acpi/dispatcher/dsopcode.c Sat May 24 12:48:31 2003 @@ -82,7 +82,7 @@ union acpi_parse_object *arg; - ACPI_FUNCTION_TRACE ("acpi_ds_execute_arguments"); + ACPI_FUNCTION_TRACE ("ds_execute_arguments"); /* @@ -99,7 +99,7 @@ /* Create and initialize a new parser state */ - walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, NULL); + walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL); if (!walk_state) { return_ACPI_STATUS (AE_NO_MEMORY); } @@ -139,7 +139,7 @@ /* Create and initialize a new parser state */ - walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, NULL); + walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL); if (!walk_state) { return_ACPI_STATUS (AE_NO_MEMORY); } diff -Nru a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c --- a/drivers/acpi/dispatcher/dswexec.c Sat May 24 12:48:32 2003 +++ b/drivers/acpi/dispatcher/dswexec.c Sat May 24 12:48:32 2003 @@ -50,6 +50,7 @@ #include #include #include +#include #define _COMPONENT ACPI_DISPATCHER @@ -657,6 +658,16 @@ /* Always clear the object stack */ walk_state->num_operands = 0; + +#ifdef ACPI_DISASSEMBLER + + /* On error, display method locals/args */ + + if (ACPI_FAILURE (status)) { + acpi_dm_dump_method_info (status, walk_state, op); + } +#endif + return_ACPI_STATUS (status); } diff -Nru a/drivers/acpi/ec.c b/drivers/acpi/ec.c --- a/drivers/acpi/ec.c Sat May 24 12:48:25 2003 +++ b/drivers/acpi/ec.c Sat May 24 12:48:25 2003 @@ -113,7 +113,7 @@ switch (event) { case ACPI_EC_EVENT_OBF: do { - acpi_hw_low_level_read(8, &acpi_ec_status, &ec->status_addr, 0); + acpi_hw_low_level_read(8, &acpi_ec_status, &ec->status_addr); if (acpi_ec_status & ACPI_EC_FLAG_OBF) return 0; udelay(ACPI_EC_UDELAY); @@ -121,7 +121,7 @@ break; case ACPI_EC_EVENT_IBE: do { - acpi_hw_low_level_read(8, &acpi_ec_status, &ec->status_addr, 0); + acpi_hw_low_level_read(8, &acpi_ec_status, &ec->status_addr); if (!(acpi_ec_status & ACPI_EC_FLAG_IBF)) return 0; udelay(ACPI_EC_UDELAY); @@ -161,18 +161,18 @@ spin_lock_irqsave(&ec->lock, flags); - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->command_addr, 0); + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_READ, &ec->command_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (result) goto end; - acpi_hw_low_level_write(8, address, &ec->data_addr, 0); + acpi_hw_low_level_write(8, address, &ec->data_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); if (result) goto end; - acpi_hw_low_level_read(8, data, &ec->data_addr, 0); + acpi_hw_low_level_read(8, data, &ec->data_addr); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", *data, address)); @@ -211,17 +211,17 @@ spin_lock_irqsave(&ec->lock, flags); - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->command_addr, 0); + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->command_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (result) goto end; - acpi_hw_low_level_write(8, address, &ec->data_addr, 0); + acpi_hw_low_level_write(8, address, &ec->data_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (result) goto end; - acpi_hw_low_level_write(8, data, &ec->data_addr, 0); + acpi_hw_low_level_write(8, data, &ec->data_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (result) goto end; @@ -310,12 +310,12 @@ */ spin_lock_irqsave(&ec->lock, flags); - acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->command_addr, 0); + acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->command_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); if (result) goto end; - acpi_hw_low_level_read(8, data, &ec->data_addr, 0); + acpi_hw_low_level_read(8, data, &ec->data_addr); if (!*data) result = -ENODATA; @@ -355,7 +355,7 @@ goto end; spin_lock_irqsave(&ec->lock, flags); - acpi_hw_low_level_read(8, &value, &ec->command_addr, 0); + acpi_hw_low_level_read(8, &value, &ec->command_addr); spin_unlock_irqrestore(&ec->lock, flags); /* TBD: Implement asynch events! diff -Nru a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c --- a/drivers/acpi/events/evgpe.c Sat May 24 12:48:26 2003 +++ b/drivers/acpi/events/evgpe.c Sat May 24 12:48:26 2003 @@ -170,7 +170,7 @@ /* Read the Status Register */ status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value, - &gpe_register_info->status_address, 0); + &gpe_register_info->status_address); gpe_register_info->status = (u8) in_value; if (ACPI_FAILURE (status)) { goto unlock_and_exit; @@ -179,7 +179,7 @@ /* Read the Enable Register */ status = acpi_hw_low_level_read (ACPI_GPE_REGISTER_WIDTH, &in_value, - &gpe_register_info->enable_address, 0); + &gpe_register_info->enable_address); gpe_register_info->enable = (u8) in_value; if (ACPI_FAILURE (status)) { goto unlock_and_exit; diff -Nru a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c --- a/drivers/acpi/events/evgpeblk.c Sat May 24 12:48:25 2003 +++ b/drivers/acpi/events/evgpeblk.c Sat May 24 12:48:25 2003 @@ -634,13 +634,13 @@ * by writing a '0'. */ status = acpi_hw_low_level_write (ACPI_GPE_REGISTER_WIDTH, 0x00, - &this_register->enable_address, 0); + &this_register->enable_address); if (ACPI_FAILURE (status)) { goto error_exit; } status = acpi_hw_low_level_write (ACPI_GPE_REGISTER_WIDTH, 0xFF, - &this_register->status_address, 0); + &this_register->status_address); if (ACPI_FAILURE (status)) { goto error_exit; } @@ -732,17 +732,15 @@ /* Dump info about this GPE block */ - ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE Block: [%4.4s] %X registers at %8.8X%8.8X on interrupt %d\n", + ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE %02d to %02d [%4.4s] %d regs at %8.8X%8.8X on int %d\n", + gpe_block->block_base_number, + (u32) (gpe_block->block_base_number + + ((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)), gpe_device->name.ascii, gpe_block->register_count, ACPI_HIDWORD (gpe_block->block_address.address), ACPI_LODWORD (gpe_block->block_address.address), interrupt_level)); - - ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE Block defined as GPE 0x%.2X to GPE 0x%.2X\n", - gpe_block->block_base_number, - (u32) (gpe_block->block_base_number + - ((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)))); /* Find all GPE methods (_Lxx, _Exx) for this block */ diff -Nru a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c --- a/drivers/acpi/events/evmisc.c Sat May 24 12:48:26 2003 +++ b/drivers/acpi/events/evmisc.c Sat May 24 12:48:26 2003 @@ -156,10 +156,10 @@ case ACPI_TYPE_POWER: if (notify_value <= ACPI_MAX_SYS_NOTIFY) { - handler_obj = obj_desc->common_notify.sys_handler; + handler_obj = obj_desc->common_notify.system_notify; } else { - handler_obj = obj_desc->common_notify.drv_handler; + handler_obj = obj_desc->common_notify.device_notify; } break; @@ -171,8 +171,8 @@ /* If there is any handler to run, schedule the dispatcher */ - if ((acpi_gbl_sys_notify.handler && (notify_value <= ACPI_MAX_SYS_NOTIFY)) || - (acpi_gbl_drv_notify.handler && (notify_value > ACPI_MAX_SYS_NOTIFY)) || + if ((acpi_gbl_system_notify.handler && (notify_value <= ACPI_MAX_SYS_NOTIFY)) || + (acpi_gbl_device_notify.handler && (notify_value > ACPI_MAX_SYS_NOTIFY)) || handler_obj) { notify_info = acpi_ut_create_generic_state (); if (!notify_info) { @@ -235,17 +235,17 @@ if (notify_info->notify.value <= ACPI_MAX_SYS_NOTIFY) { /* Global system notification handler */ - if (acpi_gbl_sys_notify.handler) { - global_handler = acpi_gbl_sys_notify.handler; - global_context = acpi_gbl_sys_notify.context; + if (acpi_gbl_system_notify.handler) { + global_handler = acpi_gbl_system_notify.handler; + global_context = acpi_gbl_system_notify.context; } } else { /* Global driver notification handler */ - if (acpi_gbl_drv_notify.handler) { - global_handler = acpi_gbl_drv_notify.handler; - global_context = acpi_gbl_drv_notify.context; + if (acpi_gbl_device_notify.handler) { + global_handler = acpi_gbl_device_notify.handler; + global_context = acpi_gbl_device_notify.context; } } @@ -259,8 +259,8 @@ handler_obj = notify_info->notify.handler_obj; if (handler_obj) { - handler_obj->notify_handler.handler (notify_info->notify.node, notify_info->notify.value, - handler_obj->notify_handler.context); + handler_obj->notify.handler (notify_info->notify.node, notify_info->notify.value, + handler_obj->notify.context); } /* All done with the info object */ diff -Nru a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c --- a/drivers/acpi/events/evregion.c Sat May 24 12:48:28 2003 +++ b/drivers/acpi/events/evregion.c Sat May 24 12:48:28 2003 @@ -50,24 +50,32 @@ #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME ("evregion") +#define ACPI_NUM_DEFAULT_SPACES 4 + +u8 acpi_gbl_default_address_spaces[ACPI_NUM_DEFAULT_SPACES] = { + ACPI_ADR_SPACE_SYSTEM_MEMORY, + ACPI_ADR_SPACE_SYSTEM_IO, + ACPI_ADR_SPACE_PCI_CONFIG, + ACPI_ADR_SPACE_DATA_TABLE}; + /******************************************************************************* * * FUNCTION: acpi_ev_init_address_spaces * - * PARAMETERS: + * PARAMETERS: None * * RETURN: Status * - * DESCRIPTION: Installs the core subsystem address space handlers. + * DESCRIPTION: Installs the core subsystem default address space handlers. * ******************************************************************************/ acpi_status acpi_ev_init_address_spaces ( - void) -{ + void) { acpi_status status; + acpi_native_uint i; ACPI_FUNCTION_TRACE ("ev_init_address_spaces"); @@ -75,9 +83,11 @@ /* * All address spaces (PCI Config, EC, SMBus) are scope dependent - * and registration must occur for a specific device. In the case - * system memory and IO address spaces there is currently no device - * associated with the address space. For these we use the root. + * and registration must occur for a specific device. + * + * In the case of the system memory and IO address spaces there is currently + * no device associated with the address space. For these we use the root. + * * We install the default PCI config space handler at the root so * that this space is immediately available even though the we have * not enumerated all the PCI Root Buses yet. This is to conform @@ -86,39 +96,27 @@ * near ready to find the PCI root buses at this point. * * NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler - * has already been installed (via acpi_install_address_space_handler) + * has already been installed (via acpi_install_address_space_handler). + * Similar for AE_SAME_HANDLER. */ - status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node, - ACPI_ADR_SPACE_SYSTEM_MEMORY, - ACPI_DEFAULT_HANDLER, NULL, NULL); - if ((ACPI_FAILURE (status)) && - (status != AE_ALREADY_EXISTS)) { - return_ACPI_STATUS (status); - } - - status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node, - ACPI_ADR_SPACE_SYSTEM_IO, - ACPI_DEFAULT_HANDLER, NULL, NULL); - if ((ACPI_FAILURE (status)) && - (status != AE_ALREADY_EXISTS)) { - return_ACPI_STATUS (status); - } - - status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node, - ACPI_ADR_SPACE_PCI_CONFIG, - ACPI_DEFAULT_HANDLER, NULL, NULL); - if ((ACPI_FAILURE (status)) && - (status != AE_ALREADY_EXISTS)) { - return_ACPI_STATUS (status); - } - - status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node, - ACPI_ADR_SPACE_DATA_TABLE, - ACPI_DEFAULT_HANDLER, NULL, NULL); - if ((ACPI_FAILURE (status)) && - (status != AE_ALREADY_EXISTS)) { - return_ACPI_STATUS (status); + for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { + status = acpi_install_address_space_handler ((acpi_handle) acpi_gbl_root_node, + acpi_gbl_default_address_spaces[i], + ACPI_DEFAULT_HANDLER, NULL, NULL); + switch (status) { + case AE_OK: + case AE_SAME_HANDLER: + case AE_ALREADY_EXISTS: + + /* These exceptions are all OK */ + + break; + + default: + + return_ACPI_STATUS (status); + } } return_ACPI_STATUS (AE_OK); @@ -161,10 +159,10 @@ } /* - * _REG method has two arguments - * Arg0: Integer: Operation region space ID + * _REG method has two arguments + * Arg0: Integer: Operation region space ID * Same value as region_obj->Region.space_id - * Arg1: Integer: connection status + * Arg1: Integer: connection status * 1 for connecting the handler, * 0 for disconnecting the handler * Passed as a parameter @@ -180,16 +178,14 @@ goto cleanup; } - /* - * Set up the parameter objects - */ + /* Set up the parameter objects */ + params[0]->integer.value = region_obj->region.space_id; params[1]->integer.value = function; params[2] = NULL; - /* - * Execute the method, no return value - */ + /* Execute the method, no return value */ + ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_METHOD, region_obj2->extra.method_REG, NULL)); status = acpi_ns_evaluate_by_handle (region_obj2->extra.method_REG, params, NULL); @@ -245,10 +241,9 @@ return_ACPI_STATUS (AE_NOT_EXIST); } - /* - * Ensure that there is a handler associated with this region - */ - handler_desc = region_obj->region.addr_handler; + /* Ensure that there is a handler associated with this region */ + + handler_desc = region_obj->region.address_space; if (!handler_desc) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "no handler for region(%p) [%s]\n", region_obj, acpi_ut_get_region_name (region_obj->region.space_id))); @@ -264,24 +259,23 @@ /* * This region has not been initialized yet, do it */ - region_setup = handler_desc->addr_handler.setup; + region_setup = handler_desc->address_space.setup; if (!region_setup) { - /* - * Bad news, no init routine and not init'd - */ + /* No initialization routine, exit with error */ + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No init routine for region(%p) [%s]\n", region_obj, acpi_ut_get_region_name (region_obj->region.space_id))); - return_ACPI_STATUS (AE_UNKNOWN_STATUS); + return_ACPI_STATUS (AE_NOT_EXIST); } /* * We must exit the interpreter because the region setup will potentially - * execute control methods + * execute control methods (e.g., _REG method for this region) */ acpi_ex_exit_interpreter (); status = region_setup (region_obj, ACPI_REGION_ACTIVATE, - handler_desc->addr_handler.context, ®ion_context); + handler_desc->address_space.context, ®ion_context); /* Re-enter the interpreter */ @@ -290,9 +284,8 @@ return_ACPI_STATUS (status2); } - /* - * Init routine may fail - */ + /* Check for failure of the Region Setup */ + if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region Init: %s [%s]\n", acpi_format_exception (status), @@ -300,40 +293,50 @@ return_ACPI_STATUS (status); } - region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE; - /* - * Save the returned context for use in all accesses to - * this particular region. + * Region initialization may have been completed by region_setup */ - region_obj2->extra.region_context = region_context; + if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) { + region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE; + + if (region_obj2->extra.region_context) { + /* The handler for this region was already installed */ + + ACPI_MEM_FREE (region_context); + } + else { + /* + * Save the returned context for use in all accesses to + * this particular region + */ + region_obj2->extra.region_context = region_context; + } + } } - /* - * We have everything we need, begin the process - */ - handler = handler_desc->addr_handler.handler; + /* We have everything we need, we can invoke the address space handler */ + + handler = handler_desc->address_space.handler; ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", - ®ion_obj->region.addr_handler->addr_handler, handler, + ®ion_obj->region.address_space->address_space, handler, ACPI_HIDWORD (address), ACPI_LODWORD (address), acpi_ut_get_region_name (region_obj->region.space_id))); - if (!(handler_desc->addr_handler.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { + if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { /* - * For handlers other than the default (supplied) handlers, we must - * exit the interpreter because the handler *might* block -- we don't - * know what it will do, so we can't hold the lock on the intepreter. + * For handlers other than the default (supplied) handlers, we must + * exit the interpreter because the handler *might* block -- we don't + * know what it will do, so we can't hold the lock on the intepreter. */ acpi_ex_exit_interpreter(); } - /* - * Invoke the handler. - */ + /* Call the handler */ + status = handler (function, address, bit_width, value, - handler_desc->addr_handler.context, + handler_desc->address_space.context, region_obj2->extra.region_context); if (ACPI_FAILURE (status)) { @@ -342,7 +345,7 @@ acpi_format_exception (status))); } - if (!(handler_desc->addr_handler.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { + if (!(handler_desc->address_space.flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { /* * We just returned from a non-default handler, we must re-enter the * interpreter @@ -393,35 +396,30 @@ } region_context = region_obj2->extra.region_context; - /* - * Get the address handler from the region object - */ - handler_obj = region_obj->region.addr_handler; + /* Get the address handler from the region object */ + + handler_obj = region_obj->region.address_space; if (!handler_obj) { - /* - * This region has no handler, all done - */ + /* This region has no handler, all done */ + return_VOID; } + /* Find this region in the handler's list */ - /* - * Find this region in the handler's list - */ - obj_desc = handler_obj->addr_handler.region_list; - last_obj_ptr = &handler_obj->addr_handler.region_list; + obj_desc = handler_obj->address_space.region_list; + last_obj_ptr = &handler_obj->address_space.region_list; while (obj_desc) { - /* - * See if this is the one - */ + /* Is this the correct Region? */ + if (obj_desc == region_obj) { ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Removing Region %p from address handler %p\n", region_obj, handler_obj)); - /* - * This is it, remove it from the handler's list - */ + + /* This is it, remove it from the handler's list */ + *last_obj_ptr = obj_desc->region.next; obj_desc->region.next = NULL; /* Must clear field */ @@ -432,9 +430,8 @@ } } - /* - * Now stop region accesses by executing the _REG method - */ + /* Now stop region accesses by executing the _REG method */ + status = acpi_ev_execute_reg_method (region_obj, 0); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region _REG, [%s]\n", @@ -449,16 +446,14 @@ } } - /* - * Call the setup handler with the deactivate notification - */ - region_setup = handler_obj->addr_handler.setup; + /* Call the setup handler with the deactivate notification */ + + region_setup = handler_obj->address_space.setup; status = region_setup (region_obj, ACPI_REGION_DEACTIVATE, - handler_obj->addr_handler.context, ®ion_context); + handler_obj->address_space.context, ®ion_context); + + /* Init routine may fail, Just ignore errors */ - /* - * Init routine may fail, Just ignore errors - */ if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%s from region init, [%s]\n", acpi_format_exception (status), @@ -468,31 +463,29 @@ region_obj->region.flags &= ~(AOPOBJ_SETUP_COMPLETE); /* - * Remove handler reference in the region + * Remove handler reference in the region * - * NOTE: this doesn't mean that the region goes away - * The region is just inaccessible as indicated to - * the _REG method + * NOTE: this doesn't mean that the region goes away + * The region is just inaccessible as indicated to + * the _REG method * - * If the region is on the handler's list - * this better be the region's handler + * If the region is on the handler's list + * this better be the region's handler */ - region_obj->region.addr_handler = NULL; + region_obj->region.address_space = NULL; + acpi_ut_remove_reference (handler_obj); return_VOID; + } - } /* found the right handler */ + /* Walk the linked list of handlers */ - /* - * Move through the linked list of handlers - */ last_obj_ptr = &obj_desc->region.next; obj_desc = obj_desc->region.next; } - /* - * If we get here, the region was not in the handler's region list - */ + /* If we get here, the region was not in the handler's region list */ + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Cannot remove region %p from address handler %p\n", region_obj, handler_obj)); @@ -534,16 +527,19 @@ region_obj, handler_obj, acpi_ut_get_region_name (region_obj->region.space_id))); - /* - * Link this region to the front of the handler's list - */ - region_obj->region.next = handler_obj->addr_handler.region_list; - handler_obj->addr_handler.region_list = region_obj; + /* Link this region to the front of the handler's list */ - /* - * Set the region's handler - */ - region_obj->region.addr_handler = handler_obj; + region_obj->region.next = handler_obj->address_space.region_list; + handler_obj->address_space.region_list = region_obj; + + /* Install the region's handler */ + + if (region_obj->region.address_space) { + return_ACPI_STATUS (AE_ALREADY_EXISTS); + } + + region_obj->region.address_space = handler_obj; + acpi_ut_add_reference (handler_obj); /* * Tell all users that this region is usable by running the _REG @@ -571,14 +567,14 @@ /******************************************************************************* * - * FUNCTION: acpi_ev_addr_handler_helper + * FUNCTION: acpi_ev_install_handler * * PARAMETERS: Handle - Node to be dumped * Level - Nesting level of the handle * Context - Passed into acpi_ns_walk_namespace * * DESCRIPTION: This routine installs an address handler into objects that are - * of type Region. + * of type Region or Device. * * If the Object is a Device, and the device has a handler of * the same type then the search is terminated in that branch. @@ -589,20 +585,20 @@ ******************************************************************************/ acpi_status -acpi_ev_addr_handler_helper ( +acpi_ev_install_handler ( acpi_handle obj_handle, u32 level, void *context, void **return_value) { union acpi_operand_object *handler_obj; - union acpi_operand_object *tmp_obj; + union acpi_operand_object *next_handler_obj; union acpi_operand_object *obj_desc; struct acpi_namespace_node *node; acpi_status status; - ACPI_FUNCTION_NAME ("ev_addr_handler_helper"); + ACPI_FUNCTION_NAME ("ev_install_handler"); handler_obj = (union acpi_operand_object *) context; @@ -621,8 +617,8 @@ } /* - * We only care about regions.and objects - * that can have address handlers + * We only care about regions.and objects + * that are allowed to have address space handlers */ if ((node->type != ACPI_TYPE_DEVICE) && (node->type != ACPI_TYPE_REGION) && @@ -634,81 +630,70 @@ obj_desc = acpi_ns_get_attached_object (node); if (!obj_desc) { - /* - * The object DNE, we don't care about it - */ + /* No object, just exit */ + return (AE_OK); } - /* - * Devices are handled different than regions - */ + /* Devices are handled different than regions */ + if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_DEVICE) { - /* - * See if this guy has any handlers - */ - tmp_obj = obj_desc->device.addr_handler; - while (tmp_obj) { - /* - * Now let's see if it's for the same address space. - */ - if (tmp_obj->addr_handler.space_id == handler_obj->addr_handler.space_id) { - /* - * It's for the same address space - */ + /* Check if this Device already has a handler for this address space */ + + next_handler_obj = obj_desc->device.address_space; + while (next_handler_obj) { + /* Found a handler, is it for the same address space? */ + + if (next_handler_obj->address_space.space_id == handler_obj->address_space.space_id) { ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Found handler for region [%s] in device %p(%p) handler %p\n", - acpi_ut_get_region_name (handler_obj->addr_handler.space_id), - obj_desc, tmp_obj, handler_obj)); + acpi_ut_get_region_name (handler_obj->address_space.space_id), + obj_desc, next_handler_obj, handler_obj)); /* - * Since the object we found it on was a device, then it - * means that someone has already installed a handler for - * the branch of the namespace from this device on. Just - * bail out telling the walk routine to not traverse this - * branch. This preserves the scoping rule for handlers. + * Since the object we found it on was a device, then it + * means that someone has already installed a handler for + * the branch of the namespace from this device on. Just + * bail out telling the walk routine to not traverse this + * branch. This preserves the scoping rule for handlers. */ return (AE_CTRL_DEPTH); } - /* - * Move through the linked list of handlers - */ - tmp_obj = tmp_obj->addr_handler.next; + /* Walk the linked list of handlers attached to this device */ + + next_handler_obj = next_handler_obj->address_space.next; } /* - * As long as the device didn't have a handler for this - * space we don't care about it. We just ignore it and - * proceed. + * As long as the device didn't have a handler for this + * space we don't care about it. We just ignore it and + * proceed. */ return (AE_OK); } - /* - * Only here if it was a region - */ - if (obj_desc->region.space_id != handler_obj->addr_handler.space_id) { + /* Object is a Region */ + + if (obj_desc->region.space_id != handler_obj->address_space.space_id) { /* - * This region is for a different address space - * ignore it + * This region is for a different address space + * -- just ignore it */ return (AE_OK); } /* - * Now we have a region and it is for the handler's address - * space type. + * Now we have a region and it is for the handler's address + * space type. * - * First disconnect region for any previous handler (if any) + * First disconnect region for any previous handler (if any) */ acpi_ev_detach_region (obj_desc, FALSE); - /* - * Then connect the region to the new handler - */ - status = acpi_ev_attach_region (handler_obj, obj_desc, FALSE); + /* Connect the region to the new handler */ + status = acpi_ev_attach_region (handler_obj, obj_desc, FALSE); return (status); } diff -Nru a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c --- a/drivers/acpi/events/evrgnini.c Sat May 24 12:48:20 2003 +++ b/drivers/acpi/events/evrgnini.c Sat May 24 12:48:20 2003 @@ -165,10 +165,11 @@ void **region_context) { acpi_status status = AE_OK; - acpi_integer temp; + acpi_integer pci_value; struct acpi_pci_id *pci_id = *region_context; union acpi_operand_object *handler_obj; - struct acpi_namespace_node *node; + struct acpi_namespace_node *parent_node; + struct acpi_namespace_node *pci_root_node; union acpi_operand_object *region_obj = (union acpi_operand_object *) handle; struct acpi_device_id object_hID; @@ -176,7 +177,7 @@ ACPI_FUNCTION_TRACE ("ev_pci_config_region_setup"); - handler_obj = region_obj->region.addr_handler; + handler_obj = region_obj->region.address_space; if (!handler_obj) { /* * No installed handler. This shouldn't happen because the dispatch @@ -187,45 +188,15 @@ return_ACPI_STATUS (AE_NOT_EXIST); } + *region_context = NULL; if (function == ACPI_REGION_DEACTIVATE) { if (pci_id) { ACPI_MEM_FREE (pci_id); - *region_context = NULL; } - return_ACPI_STATUS (status); } - /* Create a new context */ - - pci_id = ACPI_MEM_CALLOCATE (sizeof (struct acpi_pci_id)); - if (!pci_id) { - return_ACPI_STATUS (AE_NO_MEMORY); - } - - /* - * For PCI Config space access, we have to pass the segment, bus, - * device and function numbers. This routine must acquire those. - */ - - /* - * First get device and function numbers from the _ADR object - * in the parent's scope. - */ - node = acpi_ns_get_parent_node (region_obj->region.node); - - /* Evaluate the _ADR object */ - - status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, node, &temp); - - /* - * The default is zero, and since the allocation above zeroed - * the data, just do nothing on failure. - */ - if (ACPI_SUCCESS (status)) { - pci_id->device = ACPI_HIWORD (ACPI_LODWORD (temp)); - pci_id->function = ACPI_LOWORD (ACPI_LODWORD (temp)); - } + parent_node = acpi_ns_get_parent_node (region_obj->region.node); /* * Get the _SEG and _BBN values from the device upon which the handler @@ -236,61 +207,106 @@ */ /* - * If the addr_handler.Node is still pointing to the root, we need + * If the address_space.Node is still pointing to the root, we need * to scan upward for a PCI Root bridge and re-associate the op_region * handlers with that device. */ - if (handler_obj->addr_handler.node == acpi_gbl_root_node) { - /* - * Node is currently the parent object - */ - while (node != acpi_gbl_root_node) { - status = acpi_ut_execute_HID (node, &object_hID); + if (handler_obj->address_space.node == acpi_gbl_root_node) { + /* Start search from the parent object */ + + pci_root_node = parent_node; + while (pci_root_node != acpi_gbl_root_node) { + status = acpi_ut_execute_HID (pci_root_node, &object_hID); if (ACPI_SUCCESS (status)) { /* Got a valid _HID, check if this is a PCI root */ - if (!(ACPI_STRNCMP (object_hID.buffer, PCI_ROOT_HID_STRING, + if (!(ACPI_STRNCMP (object_hID.value, PCI_ROOT_HID_STRING, sizeof (PCI_ROOT_HID_STRING)))) { /* Install a handler for this PCI root bridge */ - status = acpi_install_address_space_handler ((acpi_handle) node, + status = acpi_install_address_space_handler ((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); if (ACPI_FAILURE (status)) { - ACPI_REPORT_ERROR (("Could not install pci_config handler for %4.4s, %s\n", - node->name.ascii, acpi_format_exception (status))); + if (status == AE_SAME_HANDLER) { + /* + * It is OK if the handler is already installed on the root + * bridge. Still need to return a context object for the + * new PCI_Config operation region, however. + */ + status = AE_OK; + } + else { + ACPI_REPORT_ERROR (( + "Could not install pci_config handler for Root Bridge %4.4s, %s\n", + pci_root_node->name.ascii, acpi_format_exception (status))); + } } break; } } - node = acpi_ns_get_parent_node (node); + pci_root_node = acpi_ns_get_parent_node (pci_root_node); } + + /* PCI root bridge not found, use namespace root node */ } else { - node = handler_obj->addr_handler.node; + pci_root_node = handler_obj->address_space.node; } /* - * The PCI segment number comes from the _SEG method + * If this region is now initialized, we are done. + * (install_address_space_handler could have initialized it) */ - status = acpi_ut_evaluate_numeric_object (METHOD_NAME__SEG, node, &temp); - if (ACPI_SUCCESS (status)) { - pci_id->segment = ACPI_LOWORD (temp); + if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) { + return_ACPI_STATUS (AE_OK); + } + + /* Region is still not initialized. Create a new context */ + + pci_id = ACPI_MEM_CALLOCATE (sizeof (struct acpi_pci_id)); + if (!pci_id) { + return_ACPI_STATUS (AE_NO_MEMORY); } /* - * The PCI bus number comes from the _BBN method + * For PCI_Config space access, we need the segment, bus, + * device and function numbers. Acquire them here. */ - status = acpi_ut_evaluate_numeric_object (METHOD_NAME__BBN, node, &temp); - if (ACPI_SUCCESS (status)) { - pci_id->bus = ACPI_LOWORD (temp); - } /* - * Complete this device's pci_id + * Get the PCI device and function numbers from the _ADR object + * contained in the parent's scope. + */ + status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, parent_node, &pci_value); + + /* + * The default is zero, and since the allocation above zeroed + * the data, just do nothing on failure. */ - acpi_os_derive_pci_id (node, region_obj->region.node, &pci_id); + if (ACPI_SUCCESS (status)) { + pci_id->device = ACPI_HIWORD (ACPI_LODWORD (pci_value)); + pci_id->function = ACPI_LOWORD (ACPI_LODWORD (pci_value)); + } + + /* The PCI segment number comes from the _SEG method */ + + status = acpi_ut_evaluate_numeric_object (METHOD_NAME__SEG, pci_root_node, &pci_value); + if (ACPI_SUCCESS (status)) { + pci_id->segment = ACPI_LOWORD (pci_value); + } + + /* The PCI bus number comes from the _BBN method */ + + status = acpi_ut_evaluate_numeric_object (METHOD_NAME__BBN, pci_root_node, &pci_value); + if (ACPI_SUCCESS (status)) { + pci_id->bus = ACPI_LOWORD (pci_value); + } + + /* Complete this device's pci_id */ + + acpi_os_derive_pci_id (pci_root_node, region_obj->region.node, &pci_id); *region_context = pci_id; return_ACPI_STATUS (AE_OK); @@ -451,14 +467,15 @@ node = acpi_ns_get_parent_node (region_obj->region.node); space_id = region_obj->region.space_id; - region_obj->region.addr_handler = NULL; + /* Setup defaults */ + + region_obj->region.address_space = NULL; region_obj2->extra.method_REG = NULL; region_obj->common.flags &= ~(AOPOBJ_SETUP_COMPLETE); region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED; - /* - * Find any "_REG" method associated with this region definition - */ + /* Find any "_REG" method associated with this region definition */ + status = acpi_ns_search_node (*reg_name_ptr, node, ACPI_TYPE_METHOD, &method_node); if (ACPI_SUCCESS (status)) { @@ -475,29 +492,27 @@ * ie: acpi_gbl_root_node->parent_entry being set to NULL */ while (node) { - /* - * Check to see if a handler exists - */ + /* Check to see if a handler exists */ + handler_obj = NULL; obj_desc = acpi_ns_get_attached_object (node); if (obj_desc) { - /* - * Can only be a handler if the object exists - */ + /* Can only be a handler if the object exists */ + switch (node->type) { case ACPI_TYPE_DEVICE: - handler_obj = obj_desc->device.addr_handler; + handler_obj = obj_desc->device.address_space; break; case ACPI_TYPE_PROCESSOR: - handler_obj = obj_desc->processor.addr_handler; + handler_obj = obj_desc->processor.address_space; break; case ACPI_TYPE_THERMAL: - handler_obj = obj_desc->thermal_zone.addr_handler; + handler_obj = obj_desc->thermal_zone.address_space; break; default: @@ -508,7 +523,7 @@ while (handler_obj) { /* Is this handler of the correct type? */ - if (handler_obj->addr_handler.space_id == space_id) { + if (handler_obj->address_space.space_id == space_id) { /* Found correct handler */ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, @@ -523,7 +538,7 @@ /* Try next handler in the list */ - handler_obj = handler_obj->addr_handler.next; + handler_obj = handler_obj->address_space.next; } } @@ -534,9 +549,8 @@ node = acpi_ns_get_parent_node (node); } - /* - * If we get here, there is no handler for this region - */ + /* If we get here, there is no handler for this region */ + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "No handler for region_type %s(%X) (region_obj %p)\n", acpi_ut_get_region_name (space_id), space_id, region_obj)); diff -Nru a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c --- a/drivers/acpi/events/evxface.c Sat May 24 12:48:26 2003 +++ b/drivers/acpi/events/evxface.c Sat May 24 12:48:26 2003 @@ -244,22 +244,22 @@ /* Make sure the handler is not already installed */ if (((handler_type == ACPI_SYSTEM_NOTIFY) && - acpi_gbl_sys_notify.handler) || + acpi_gbl_system_notify.handler) || ((handler_type == ACPI_DEVICE_NOTIFY) && - acpi_gbl_drv_notify.handler)) { + acpi_gbl_device_notify.handler)) { status = AE_ALREADY_EXISTS; goto unlock_and_exit; } if (handler_type == ACPI_SYSTEM_NOTIFY) { - acpi_gbl_sys_notify.node = node; - acpi_gbl_sys_notify.handler = handler; - acpi_gbl_sys_notify.context = context; + acpi_gbl_system_notify.node = node; + acpi_gbl_system_notify.handler = handler; + acpi_gbl_system_notify.context = context; } else /* ACPI_DEVICE_NOTIFY */ { - acpi_gbl_drv_notify.node = node; - acpi_gbl_drv_notify.handler = handler; - acpi_gbl_drv_notify.context = context; + acpi_gbl_device_notify.node = node; + acpi_gbl_device_notify.handler = handler; + acpi_gbl_device_notify.context = context; } /* Global notify handler installed */ @@ -282,13 +282,12 @@ obj_desc = acpi_ns_get_attached_object (node); if (obj_desc) { - /* Object exists - make sure there's no handler */ if (((handler_type == ACPI_SYSTEM_NOTIFY) && - obj_desc->common_notify.sys_handler) || + obj_desc->common_notify.system_notify) || ((handler_type == ACPI_DEVICE_NOTIFY) && - obj_desc->common_notify.drv_handler)) { + obj_desc->common_notify.device_notify)) { status = AE_ALREADY_EXISTS; goto unlock_and_exit; } @@ -305,6 +304,11 @@ /* Attach new object to the Node */ status = acpi_ns_attach_object (device, obj_desc, node->type); + + /* Remove local reference to the object */ + + acpi_ut_remove_reference (obj_desc); + if (ACPI_FAILURE (status)) { goto unlock_and_exit; } @@ -318,15 +322,15 @@ goto unlock_and_exit; } - notify_obj->notify_handler.node = node; - notify_obj->notify_handler.handler = handler; - notify_obj->notify_handler.context = context; + notify_obj->notify.node = node; + notify_obj->notify.handler = handler; + notify_obj->notify.context = context; if (handler_type == ACPI_SYSTEM_NOTIFY) { - obj_desc->common_notify.sys_handler = notify_obj; + obj_desc->common_notify.system_notify = notify_obj; } else /* ACPI_DEVICE_NOTIFY */ { - obj_desc->common_notify.drv_handler = notify_obj; + obj_desc->common_notify.device_notify = notify_obj; } } @@ -395,22 +399,22 @@ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Removing notify handler for ROOT object.\n")); if (((handler_type == ACPI_SYSTEM_NOTIFY) && - !acpi_gbl_sys_notify.handler) || + !acpi_gbl_system_notify.handler) || ((handler_type == ACPI_DEVICE_NOTIFY) && - !acpi_gbl_drv_notify.handler)) { + !acpi_gbl_device_notify.handler)) { status = AE_NOT_EXIST; goto unlock_and_exit; } if (handler_type == ACPI_SYSTEM_NOTIFY) { - acpi_gbl_sys_notify.node = NULL; - acpi_gbl_sys_notify.handler = NULL; - acpi_gbl_sys_notify.context = NULL; + acpi_gbl_system_notify.node = NULL; + acpi_gbl_system_notify.handler = NULL; + acpi_gbl_system_notify.context = NULL; } else { - acpi_gbl_drv_notify.node = NULL; - acpi_gbl_drv_notify.handler = NULL; - acpi_gbl_drv_notify.context = NULL; + acpi_gbl_device_notify.node = NULL; + acpi_gbl_device_notify.handler = NULL; + acpi_gbl_device_notify.context = NULL; } } @@ -436,14 +440,14 @@ /* Object exists - make sure there's an existing handler */ if (handler_type == ACPI_SYSTEM_NOTIFY) { - notify_obj = obj_desc->common_notify.sys_handler; + notify_obj = obj_desc->common_notify.system_notify; } else { - notify_obj = obj_desc->common_notify.drv_handler; + notify_obj = obj_desc->common_notify.device_notify; } if ((!notify_obj) || - (notify_obj->notify_handler.handler != handler)) { + (notify_obj->notify.handler != handler)) { status = AE_BAD_PARAMETER; goto unlock_and_exit; } @@ -451,10 +455,10 @@ /* Remove the handler */ if (handler_type == ACPI_SYSTEM_NOTIFY) { - obj_desc->common_notify.sys_handler = NULL; + obj_desc->common_notify.system_notify = NULL; } else { - obj_desc->common_notify.drv_handler = NULL; + obj_desc->common_notify.device_notify = NULL; } acpi_ut_remove_reference (notify_obj); diff -Nru a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c --- a/drivers/acpi/events/evxfevnt.c Sat May 24 12:48:22 2003 +++ b/drivers/acpi/events/evxfevnt.c Sat May 24 12:48:22 2003 @@ -654,7 +654,11 @@ } status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_DEVICE); + + /* Remove local reference to the object */ + acpi_ut_remove_reference (obj_desc); + if (ACPI_FAILURE (status)) { goto unlock_and_exit; } diff -Nru a/drivers/acpi/events/evxfregn.c b/drivers/acpi/events/evxfregn.c --- a/drivers/acpi/events/evxfregn.c Sat May 24 12:48:21 2003 +++ b/drivers/acpi/events/evxfregn.c Sat May 24 12:48:21 2003 @@ -154,7 +154,7 @@ break; default: - status = AE_NOT_EXIST; + status = AE_BAD_PARAMETER; goto unlock_and_exit; } } @@ -170,26 +170,36 @@ obj_desc = acpi_ns_get_attached_object (node); if (obj_desc) { /* - * The object exists. + * The attached device object already exists. * Make sure the handler is not already installed. */ + handler_obj = obj_desc->device.address_space; - /* check the address handler the user requested */ + /* Walk the handler list for this device */ - handler_obj = obj_desc->device.addr_handler; while (handler_obj) { - /* - * Found an Address handler, see if user requested this - * address space. - */ - if(handler_obj->addr_handler.space_id == space_id) { - status = AE_ALREADY_EXISTS; + /* Same space_id indicates a handler already installed */ + + if(handler_obj->address_space.space_id == space_id) { + if (handler_obj->address_space.handler == handler) { + /* + * It is (relatively) OK to attempt to install the SAME + * handler twice. This can easily happen with PCI_Config space. + */ + status = AE_SAME_HANDLER; + goto unlock_and_exit; + } + else { + /* A handler is already installed */ + + status = AE_ALREADY_EXISTS; + } goto unlock_and_exit; } /* Walk the linked list of handlers */ - handler_obj = handler_obj->addr_handler.next; + handler_obj = handler_obj->address_space.next; } } else { @@ -218,8 +228,12 @@ /* Attach the new object to the Node */ status = acpi_ns_attach_object (node, obj_desc, type); + + /* Remove local reference to the object */ + + acpi_ut_remove_reference (obj_desc); + if (ACPI_FAILURE (status)) { - acpi_ut_remove_reference (obj_desc); goto unlock_and_exit; } } @@ -241,14 +255,25 @@ goto unlock_and_exit; } - handler_obj->addr_handler.space_id = (u8) space_id; - handler_obj->addr_handler.hflags = flags; - handler_obj->addr_handler.next = obj_desc->device.addr_handler; - handler_obj->addr_handler.region_list = NULL; - handler_obj->addr_handler.node = node; - handler_obj->addr_handler.handler = handler; - handler_obj->addr_handler.context = context; - handler_obj->addr_handler.setup = setup; + /* Init handler obj */ + + handler_obj->address_space.space_id = (u8) space_id; + handler_obj->address_space.hflags = flags; + handler_obj->address_space.region_list = NULL; + handler_obj->address_space.node = node; + handler_obj->address_space.handler = handler; + handler_obj->address_space.context = context; + handler_obj->address_space.setup = setup; + + /* Install at head of Device.address_space list */ + + handler_obj->address_space.next = obj_desc->device.address_space; + + /* + * The Device object is the first reference on the handler_obj. + * Each region that uses the handler adds a reference. + */ + obj_desc->device.address_space = handler_obj; /* * Walk the namespace finding all of the regions this @@ -262,18 +287,9 @@ * In either case, back up and search down the remainder * of the branch */ - status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, device, - ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, - acpi_ev_addr_handler_helper, - handler_obj, NULL); - - /* Place this handler 1st on the list */ - - handler_obj->common.reference_count = - (u16) (handler_obj->common.reference_count + - obj_desc->common.reference_count - 1); - obj_desc->device.addr_handler = handler_obj; - + status = acpi_ns_walk_namespace (ACPI_TYPE_ANY, device, ACPI_UINT32_MAX, + ACPI_NS_WALK_UNLOCK, acpi_ev_install_handler, + handler_obj, NULL); unlock_and_exit: (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); @@ -341,12 +357,12 @@ /* Find the address handler the user requested */ - handler_obj = obj_desc->device.addr_handler; - last_obj_ptr = &obj_desc->device.addr_handler; + handler_obj = obj_desc->device.address_space; + last_obj_ptr = &obj_desc->device.address_space; while (handler_obj) { /* We have a handler, see if user requested this one */ - if (handler_obj->addr_handler.space_id == space_id) { + if (handler_obj->address_space.space_id == space_id) { /* Matched space_id, first dereference this in the Regions */ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, @@ -354,7 +370,7 @@ handler_obj, handler, acpi_ut_get_region_name (space_id), node, obj_desc)); - region_obj = handler_obj->addr_handler.region_list; + region_obj = handler_obj->address_space.region_list; /* Walk the handler's region list */ @@ -372,13 +388,13 @@ * Walk the list: Just grab the head because the * detach_region removed the previous head. */ - region_obj = handler_obj->addr_handler.region_list; + region_obj = handler_obj->address_space.region_list; } /* Remove this Handler object from the list */ - *last_obj_ptr = handler_obj->addr_handler.next; + *last_obj_ptr = handler_obj->address_space.next; /* Now we can delete the handler object */ @@ -388,8 +404,8 @@ /* Walk the linked list of handlers */ - last_obj_ptr = &handler_obj->addr_handler.next; - handler_obj = handler_obj->addr_handler.next; + last_obj_ptr = &handler_obj->address_space.next; + handler_obj = handler_obj->address_space.next; } /* The handler does not exist */ diff -Nru a/drivers/acpi/executer/exconfig.c b/drivers/acpi/executer/exconfig.c --- a/drivers/acpi/executer/exconfig.c Sat May 24 12:48:26 2003 +++ b/drivers/acpi/executer/exconfig.c Sat May 24 12:48:26 2003 @@ -360,11 +360,11 @@ /* The table must be either an SSDT or a PSDT */ if ((!ACPI_STRNCMP (table_ptr->signature, - acpi_gbl_acpi_table_data[ACPI_TABLE_PSDT].signature, - acpi_gbl_acpi_table_data[ACPI_TABLE_PSDT].sig_length)) && + acpi_gbl_table_data[ACPI_TABLE_PSDT].signature, + acpi_gbl_table_data[ACPI_TABLE_PSDT].sig_length)) && (!ACPI_STRNCMP (table_ptr->signature, - acpi_gbl_acpi_table_data[ACPI_TABLE_SSDT].signature, - acpi_gbl_acpi_table_data[ACPI_TABLE_SSDT].sig_length))) { + acpi_gbl_table_data[ACPI_TABLE_SSDT].signature, + acpi_gbl_table_data[ACPI_TABLE_SSDT].sig_length))) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Table has invalid signature [%4.4s], must be SSDT or PSDT\n", table_ptr->signature)); diff -Nru a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c --- a/drivers/acpi/executer/exdump.c Sat May 24 12:48:20 2003 +++ b/drivers/acpi/executer/exdump.c Sat May 24 12:48:20 2003 @@ -635,9 +635,9 @@ case ACPI_TYPE_DEVICE: - acpi_ex_out_pointer ("addr_handler", obj_desc->device.addr_handler); - acpi_ex_out_pointer ("sys_handler", obj_desc->device.sys_handler); - acpi_ex_out_pointer ("drv_handler", obj_desc->device.drv_handler); + acpi_ex_out_pointer ("address_space", obj_desc->device.address_space); + acpi_ex_out_pointer ("system_notify", obj_desc->device.system_notify); + acpi_ex_out_pointer ("device_notify", obj_desc->device.device_notify); break; @@ -673,7 +673,7 @@ acpi_ex_out_integer ("Flags", obj_desc->region.flags); acpi_ex_out_address ("Address", obj_desc->region.address); acpi_ex_out_integer ("Length", obj_desc->region.length); - acpi_ex_out_pointer ("addr_handler", obj_desc->region.addr_handler); + acpi_ex_out_pointer ("address_space", obj_desc->region.address_space); acpi_ex_out_pointer ("Next", obj_desc->region.next); break; @@ -682,8 +682,8 @@ acpi_ex_out_integer ("system_level", obj_desc->power_resource.system_level); acpi_ex_out_integer ("resource_order", obj_desc->power_resource.resource_order); - acpi_ex_out_pointer ("sys_handler", obj_desc->power_resource.sys_handler); - acpi_ex_out_pointer ("drv_handler", obj_desc->power_resource.drv_handler); + acpi_ex_out_pointer ("system_notify", obj_desc->power_resource.system_notify); + acpi_ex_out_pointer ("device_notify", obj_desc->power_resource.device_notify); break; @@ -692,17 +692,17 @@ acpi_ex_out_integer ("Processor ID", obj_desc->processor.proc_id); acpi_ex_out_integer ("Length", obj_desc->processor.length); acpi_ex_out_address ("Address", (acpi_physical_address) obj_desc->processor.address); - acpi_ex_out_pointer ("sys_handler", obj_desc->processor.sys_handler); - acpi_ex_out_pointer ("drv_handler", obj_desc->processor.drv_handler); - acpi_ex_out_pointer ("addr_handler", obj_desc->processor.addr_handler); + acpi_ex_out_pointer ("system_notify", obj_desc->processor.system_notify); + acpi_ex_out_pointer ("device_notify", obj_desc->processor.device_notify); + acpi_ex_out_pointer ("address_space", obj_desc->processor.address_space); break; case ACPI_TYPE_THERMAL: - acpi_ex_out_pointer ("sys_handler", obj_desc->thermal_zone.sys_handler); - acpi_ex_out_pointer ("drv_handler", obj_desc->thermal_zone.drv_handler); - acpi_ex_out_pointer ("addr_handler", obj_desc->thermal_zone.addr_handler); + acpi_ex_out_pointer ("system_notify", obj_desc->thermal_zone.system_notify); + acpi_ex_out_pointer ("device_notify", obj_desc->thermal_zone.device_notify); + acpi_ex_out_pointer ("address_space", obj_desc->thermal_zone.address_space); break; @@ -762,18 +762,18 @@ case ACPI_TYPE_LOCAL_ADDRESS_HANDLER: - acpi_ex_out_integer ("space_id", obj_desc->addr_handler.space_id); - acpi_ex_out_pointer ("Next", obj_desc->addr_handler.next); - acpi_ex_out_pointer ("region_list", obj_desc->addr_handler.region_list); - acpi_ex_out_pointer ("Node", obj_desc->addr_handler.node); - acpi_ex_out_pointer ("Context", obj_desc->addr_handler.context); + acpi_ex_out_integer ("space_id", obj_desc->address_space.space_id); + acpi_ex_out_pointer ("Next", obj_desc->address_space.next); + acpi_ex_out_pointer ("region_list", obj_desc->address_space.region_list); + acpi_ex_out_pointer ("Node", obj_desc->address_space.node); + acpi_ex_out_pointer ("Context", obj_desc->address_space.context); break; case ACPI_TYPE_LOCAL_NOTIFY: - acpi_ex_out_pointer ("Node", obj_desc->notify_handler.node); - acpi_ex_out_pointer ("Context", obj_desc->notify_handler.context); + acpi_ex_out_pointer ("Node", obj_desc->notify.node); + acpi_ex_out_pointer ("Context", obj_desc->notify.context); break; diff -Nru a/drivers/acpi/hardware/hwgpe.c b/drivers/acpi/hardware/hwgpe.c --- a/drivers/acpi/hardware/hwgpe.c Sat May 24 12:48:19 2003 +++ b/drivers/acpi/hardware/hwgpe.c Sat May 24 12:48:19 2003 @@ -77,7 +77,7 @@ * to enable the GPE, and write out the new register. */ status = acpi_hw_low_level_read (8, &in_byte, - &gpe_event_info->register_info->enable_address, 0); + &gpe_event_info->register_info->enable_address); if (ACPI_FAILURE (status)) { return (status); } @@ -85,7 +85,7 @@ /* Write with the new GPE bit enabled */ status = acpi_hw_low_level_write (8, (in_byte | gpe_event_info->bit_mask), - &gpe_event_info->register_info->enable_address, 0); + &gpe_event_info->register_info->enable_address); return (status); } @@ -164,7 +164,7 @@ * and write out the new register value to disable the GPE. */ status = acpi_hw_low_level_read (8, &in_byte, - &gpe_register_info->enable_address, 0); + &gpe_register_info->enable_address); if (ACPI_FAILURE (status)) { return (status); } @@ -172,7 +172,7 @@ /* Write the byte with this GPE bit cleared */ status = acpi_hw_low_level_write (8, (in_byte & ~(gpe_event_info->bit_mask)), - &gpe_register_info->enable_address, 0); + &gpe_register_info->enable_address); if (ACPI_FAILURE (status)) { return (status); } @@ -246,7 +246,7 @@ * clear this GPE. */ status = acpi_hw_low_level_write (8, gpe_event_info->bit_mask, - &gpe_event_info->register_info->status_address, 0); + &gpe_event_info->register_info->status_address); return (status); } @@ -293,7 +293,7 @@ /* GPE Enabled? */ - status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->enable_address, 0); + status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->enable_address); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } @@ -310,7 +310,7 @@ /* GPE active (set)? */ - status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->status_address, 0); + status = acpi_hw_low_level_read (8, &in_byte, &gpe_register_info->status_address); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } @@ -360,7 +360,7 @@ for (i = 0; i < gpe_block->register_count; i++) { status = acpi_hw_low_level_write (8, 0x00, - &gpe_block->register_info[i].enable_address, (u32) i); + &gpe_block->register_info[i].enable_address); if (ACPI_FAILURE (status)) { return (status); } @@ -401,7 +401,7 @@ for (i = 0; i < gpe_block->register_count; i++) { status = acpi_hw_low_level_write (8, 0xFF, - &gpe_block->register_info[i].status_address, (u32) i); + &gpe_block->register_info[i].status_address); if (ACPI_FAILURE (status)) { return (status); } @@ -447,7 +447,7 @@ * will be using it to restore all the GPEs later. */ status = acpi_hw_low_level_read (8, &in_value, - &gpe_register_info->enable_address, 0); + &gpe_register_info->enable_address); if (ACPI_FAILURE (status)) { return (status); } @@ -458,7 +458,7 @@ * Disable all GPEs except wakeup GPEs. */ status = acpi_hw_low_level_write (8, gpe_register_info->wake_enable, - &gpe_register_info->enable_address, 0); + &gpe_register_info->enable_address); if (ACPI_FAILURE (status)) { return (status); } @@ -539,7 +539,7 @@ * Blast them back in. */ status = acpi_hw_low_level_write (8, gpe_register_info->enable, - &gpe_register_info->enable_address, 0); + &gpe_register_info->enable_address); if (ACPI_FAILURE (status)) { return (status); } diff -Nru a/drivers/acpi/hardware/hwregs.c b/drivers/acpi/hardware/hwregs.c --- a/drivers/acpi/hardware/hwregs.c Sat May 24 12:48:31 2003 +++ b/drivers/acpi/hardware/hwregs.c Sat May 24 12:48:31 2003 @@ -93,7 +93,7 @@ if (acpi_gbl_FADT->xpm1b_evt_blk.address) { status = acpi_hw_low_level_write (16, ACPI_BITMASK_ALL_FIXED_STATUS, - &acpi_gbl_FADT->xpm1b_evt_blk, 0); + &acpi_gbl_FADT->xpm1b_evt_blk); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } @@ -470,7 +470,6 @@ { u32 value1 = 0; u32 value2 = 0; - u32 bank_offset; acpi_status status; @@ -487,50 +486,53 @@ switch (register_id) { case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ - status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->xpm1a_evt_blk, 0); + status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->xpm1a_evt_blk); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } - status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->xpm1b_evt_blk, 0); + /* PM1B is optional */ + + status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->xpm1b_evt_blk); value1 |= value2; break; - case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access*/ + case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access */ - bank_offset = ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len); - status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->xpm1a_evt_blk, bank_offset); + status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_xpm1a_enable); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } - status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->xpm1b_evt_blk, bank_offset); + /* PM1B is optional */ + + status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_xpm1b_enable); value1 |= value2; break; case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ - status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->xpm1a_cnt_blk, 0); + status = acpi_hw_low_level_read (16, &value1, &acpi_gbl_FADT->xpm1a_cnt_blk); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } - status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->xpm1b_cnt_blk, 0); + status = acpi_hw_low_level_read (16, &value2, &acpi_gbl_FADT->xpm1b_cnt_blk); value1 |= value2; break; case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ - status = acpi_hw_low_level_read (8, &value1, &acpi_gbl_FADT->xpm2_cnt_blk, 0); + status = acpi_hw_low_level_read (8, &value1, &acpi_gbl_FADT->xpm2_cnt_blk); break; case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ - status = acpi_hw_low_level_read (32, &value1, &acpi_gbl_FADT->xpm_tmr_blk, 0); + status = acpi_hw_low_level_read (32, &value1, &acpi_gbl_FADT->xpm_tmr_blk); break; case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ @@ -577,7 +579,6 @@ u32 register_id, u32 value) { - u32 bank_offset; acpi_status status; @@ -594,59 +595,62 @@ switch (register_id) { case ACPI_REGISTER_PM1_STATUS: /* 16-bit access */ - status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_evt_blk, 0); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_evt_blk); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } - status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_evt_blk, 0); + /* PM1B is optional */ + + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_evt_blk); break; case ACPI_REGISTER_PM1_ENABLE: /* 16-bit access*/ - bank_offset = ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len); - status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_evt_blk, bank_offset); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_xpm1a_enable); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } - status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_evt_blk, bank_offset); + /* PM1B is optional */ + + status = acpi_hw_low_level_write (16, value, &acpi_gbl_xpm1b_enable); break; case ACPI_REGISTER_PM1_CONTROL: /* 16-bit access */ - status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_cnt_blk, 0); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_cnt_blk); if (ACPI_FAILURE (status)) { goto unlock_and_exit; } - status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_cnt_blk, 0); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_cnt_blk); break; case ACPI_REGISTER_PM1A_CONTROL: /* 16-bit access */ - status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_cnt_blk, 0); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1a_cnt_blk); break; case ACPI_REGISTER_PM1B_CONTROL: /* 16-bit access */ - status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_cnt_blk, 0); + status = acpi_hw_low_level_write (16, value, &acpi_gbl_FADT->xpm1b_cnt_blk); break; case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ - status = acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->xpm2_cnt_blk, 0); + status = acpi_hw_low_level_write (8, value, &acpi_gbl_FADT->xpm2_cnt_blk); break; case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ - status = acpi_hw_low_level_write (32, value, &acpi_gbl_FADT->xpm_tmr_blk, 0); + status = acpi_hw_low_level_write (32, value, &acpi_gbl_FADT->xpm_tmr_blk); break; @@ -676,11 +680,11 @@ * * FUNCTION: acpi_hw_low_level_read * - * PARAMETERS: Register - GAS register structure - * Offset - Offset from the base address in the GAS - * Width - 8, 16, or 32 + * PARAMETERS: Width - 8, 16, or 32 + * Value - Where the value is returned + * Register - GAS register structure * - * RETURN: Value read + * RETURN: Status * * DESCRIPTION: Read from either memory, IO, or PCI config space. * @@ -690,11 +694,8 @@ acpi_hw_low_level_read ( u32 width, u32 *value, - struct acpi_generic_address *reg, - u32 offset) + struct acpi_generic_address *reg) { - acpi_physical_address mem_address; - acpi_io_address io_address; struct acpi_pci_id pci_id; u16 pci_register; acpi_status status; @@ -721,19 +722,16 @@ switch (reg->address_space_id) { case ACPI_ADR_SPACE_SYSTEM_MEMORY: - mem_address = (reg->address - + (acpi_physical_address) offset); - - status = acpi_os_read_memory (mem_address, value, width); + status = acpi_os_read_memory ( + (acpi_physical_address) reg->address, + value, width); break; case ACPI_ADR_SPACE_SYSTEM_IO: - io_address = (acpi_io_address) (reg->address - + (acpi_physical_address) offset); - - status = acpi_os_read_port (io_address, value, width); + status = acpi_os_read_port ((acpi_io_address) reg->address, + value, width); break; @@ -743,15 +741,16 @@ pci_id.bus = 0; pci_id.device = ACPI_PCI_DEVICE (reg->address); pci_id.function = ACPI_PCI_FUNCTION (reg->address); - pci_register = (u16) (ACPI_PCI_REGISTER (reg->address) - + offset); + pci_register = (u16) ACPI_PCI_REGISTER (reg->address); - status = acpi_os_read_pci_configuration (&pci_id, pci_register, value, width); + status = acpi_os_read_pci_configuration (&pci_id, pci_register, + value, width); break; default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unsupported address space: %X\n", reg->address_space_id)); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Unsupported address space: %X\n", reg->address_space_id)); status = AE_BAD_PARAMETER; break; } @@ -767,12 +766,10 @@ * PARAMETERS: Width - 8, 16, or 32 * Value - To be written * Register - GAS register structure - * Offset - Offset from the base address in the GAS - * * - * RETURN: Value read + * RETURN: Status * - * DESCRIPTION: Read from either memory, IO, or PCI config space. + * DESCRIPTION: Write to either memory, IO, or PCI config space. * ******************************************************************************/ @@ -780,11 +777,8 @@ acpi_hw_low_level_write ( u32 width, u32 value, - struct acpi_generic_address *reg, - u32 offset) + struct acpi_generic_address *reg) { - acpi_physical_address mem_address; - acpi_io_address io_address; struct acpi_pci_id pci_id; u16 pci_register; acpi_status status; @@ -809,19 +803,16 @@ switch (reg->address_space_id) { case ACPI_ADR_SPACE_SYSTEM_MEMORY: - mem_address = (reg->address - + (acpi_physical_address) offset); - - status = acpi_os_write_memory (mem_address, value, width); + status = acpi_os_write_memory ( + (acpi_physical_address) reg->address, + value, width); break; case ACPI_ADR_SPACE_SYSTEM_IO: - io_address = (acpi_io_address) (reg->address - + (acpi_physical_address) offset); - - status = acpi_os_write_port (io_address, value, width); + status = acpi_os_write_port ((acpi_io_address) reg->address, + value, width); break; @@ -831,15 +822,16 @@ pci_id.bus = 0; pci_id.device = ACPI_PCI_DEVICE (reg->address); pci_id.function = ACPI_PCI_FUNCTION (reg->address); - pci_register = (u16) (ACPI_PCI_REGISTER (reg->address) - + offset); + pci_register = (u16) ACPI_PCI_REGISTER (reg->address); - status = acpi_os_write_pci_configuration (&pci_id, pci_register, (acpi_integer) value, width); + status = acpi_os_write_pci_configuration (&pci_id, pci_register, + (acpi_integer) value, width); break; default: - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unsupported address space: %X\n", reg->address_space_id)); + ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, + "Unsupported address space: %X\n", reg->address_space_id)); status = AE_BAD_PARAMETER; break; } diff -Nru a/drivers/acpi/hardware/hwtimer.c b/drivers/acpi/hardware/hwtimer.c --- a/drivers/acpi/hardware/hwtimer.c Sat May 24 12:48:20 2003 +++ b/drivers/acpi/hardware/hwtimer.c Sat May 24 12:48:20 2003 @@ -108,7 +108,7 @@ return_ACPI_STATUS (AE_BAD_PARAMETER); } - status = acpi_hw_low_level_read (32, ticks, &acpi_gbl_FADT->xpm_tmr_blk, 0); + status = acpi_hw_low_level_read (32, ticks, &acpi_gbl_FADT->xpm_tmr_blk); return_ACPI_STATUS (status); } diff -Nru a/drivers/acpi/namespace/nsalloc.c b/drivers/acpi/namespace/nsalloc.c --- a/drivers/acpi/namespace/nsalloc.c Sat May 24 12:48:25 2003 +++ b/drivers/acpi/namespace/nsalloc.c Sat May 24 12:48:25 2003 @@ -116,19 +116,33 @@ prev_node = NULL; next_node = parent_node->child; + /* Find the node that is the previous peer in the parent's child list */ + while (next_node != node) { prev_node = next_node; next_node = prev_node->peer; } if (prev_node) { + /* Node is not first child, unlink it */ + prev_node->peer = next_node->peer; if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { prev_node->flags |= ANOBJ_END_OF_PEER_LIST; } } else { - parent_node->child = next_node->peer; + /* Node is first child (has no previous peer) */ + + if (next_node->flags & ANOBJ_END_OF_PEER_LIST) { + /* No peers at all */ + + parent_node->child = NULL; + } + else { /* Link peer list to parent */ + + parent_node->child = next_node->peer; + } } @@ -222,7 +236,7 @@ struct acpi_namespace_node *node, /* New Child*/ acpi_object_type type) { - u16 owner_id = TABLE_ID_DSDT; + u16 owner_id = 0; struct acpi_namespace_node *child_node; #ifdef ACPI_ALPHABETIC_NAMESPACE @@ -355,6 +369,7 @@ { struct acpi_namespace_node *child_node; struct acpi_namespace_node *next_node; + struct acpi_namespace_node *node; u8 flags; @@ -399,6 +414,25 @@ * Detach an object if there is one, then free the child node */ acpi_ns_detach_object (child_node); + + /* + * Decrement the reference count(s) of all parents up to + * the root! (counts were incremented when the node was created) + */ + node = child_node; + while ((node = acpi_ns_get_parent_node (node)) != NULL) { + node->reference_count--; + } + + /* There should be only one reference remaining on this node */ + + if (child_node->reference_count != 1) { + ACPI_REPORT_WARNING (("Existing references (%d) on node being deleted (%p)\n", + child_node->reference_count, child_node)); + } + + /* Now we can delete the node */ + ACPI_MEM_FREE (child_node); /* And move on to the next child in the list */ @@ -512,7 +546,7 @@ * ******************************************************************************/ -static void +void acpi_ns_remove_reference ( struct acpi_namespace_node *node) { diff -Nru a/drivers/acpi/namespace/nsdumpdv.c b/drivers/acpi/namespace/nsdumpdv.c --- a/drivers/acpi/namespace/nsdumpdv.c Sat May 24 12:48:19 2003 +++ b/drivers/acpi/namespace/nsdumpdv.c Sat May 24 12:48:19 2003 @@ -72,7 +72,8 @@ void *context, void **return_value) { - struct acpi_device_info info; + struct acpi_buffer buffer; + struct acpi_device_info *info; acpi_status status; u32 i; @@ -82,16 +83,19 @@ status = acpi_ns_dump_one_object (obj_handle, level, context, return_value); - status = acpi_get_object_info (obj_handle, &info); + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_get_object_info (obj_handle, &buffer); if (ACPI_SUCCESS (status)) { + info = buffer.pointer; for (i = 0; i < level; i++) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " ")); } ACPI_DEBUG_PRINT_RAW ((ACPI_DB_TABLES, " HID: %s, ADR: %8.8X%8.8X, Status: %X\n", - info.hardware_id, - ACPI_HIDWORD (info.address), ACPI_LODWORD (info.address), - info.current_status)); + info->hardware_id.value, + ACPI_HIDWORD (info->address), ACPI_LODWORD (info->address), + info->current_status)); + ACPI_MEM_FREE (info); } return (status); diff -Nru a/drivers/acpi/namespace/nsload.c b/drivers/acpi/namespace/nsload.c --- a/drivers/acpi/namespace/nsload.c Sat May 24 12:48:32 2003 +++ b/drivers/acpi/namespace/nsload.c Sat May 24 12:48:32 2003 @@ -79,7 +79,7 @@ /* Check if table contains valid AML (must be DSDT, PSDT, SSDT, etc.) */ - if (!(acpi_gbl_acpi_table_data[table_desc->type].flags & ACPI_TABLE_EXECUTABLE)) { + if (!(acpi_gbl_table_data[table_desc->type].flags & ACPI_TABLE_EXECUTABLE)) { /* Just ignore this table */ return_ACPI_STATUS (AE_OK); @@ -182,7 +182,7 @@ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading DSDT\n")); - table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_DSDT]; + table_desc = acpi_gbl_table_lists[ACPI_TABLE_DSDT].next; /* If table already loaded into namespace, just return */ @@ -190,8 +190,6 @@ goto unlock_and_exit; } - table_desc->table_id = TABLE_ID_DSDT; - /* Now load the single DSDT */ status = acpi_ns_load_table (table_desc, acpi_gbl_root_node); @@ -205,13 +203,13 @@ case ACPI_TABLE_SSDT: ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d SSDTs\n", - acpi_gbl_acpi_tables[ACPI_TABLE_SSDT].count)); + acpi_gbl_table_lists[ACPI_TABLE_SSDT].count)); /* * Traverse list of SSDT tables */ - table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_SSDT]; - for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_SSDT].count; i++) { + table_desc = acpi_gbl_table_lists[ACPI_TABLE_SSDT].next; + for (i = 0; i < acpi_gbl_table_lists[ACPI_TABLE_SSDT].count; i++) { /* * Only attempt to load table if it is not * already loaded! @@ -233,14 +231,14 @@ case ACPI_TABLE_PSDT: ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d PSDTs\n", - acpi_gbl_acpi_tables[ACPI_TABLE_PSDT].count)); + acpi_gbl_table_lists[ACPI_TABLE_PSDT].count)); /* * Traverse list of PSDT tables */ - table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_PSDT]; + table_desc = acpi_gbl_table_lists[ACPI_TABLE_PSDT].next; - for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_PSDT].count; i++) { + for (i = 0; i < acpi_gbl_table_lists[ACPI_TABLE_PSDT].count; i++) { /* Only attempt to load table if it is not already loaded! */ if (!table_desc->loaded_into_namespace) { diff -Nru a/drivers/acpi/namespace/nsparse.c b/drivers/acpi/namespace/nsparse.c --- a/drivers/acpi/namespace/nsparse.c Sat May 24 12:48:20 2003 +++ b/drivers/acpi/namespace/nsparse.c Sat May 24 12:48:20 2003 @@ -85,10 +85,9 @@ return_ACPI_STATUS (AE_NO_MEMORY); } - /* Create and initialize a new walk state */ - walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, + walk_state = acpi_ds_create_walk_state (table_desc->table_id, NULL, NULL, NULL); if (!walk_state) { acpi_ps_free_op (parse_root); diff -Nru a/drivers/acpi/namespace/nssearch.c b/drivers/acpi/namespace/nssearch.c --- a/drivers/acpi/namespace/nssearch.c Sat May 24 12:48:32 2003 +++ b/drivers/acpi/namespace/nssearch.c Sat May 24 12:48:32 2003 @@ -117,8 +117,9 @@ * Found matching entry. */ ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, - "Name %4.4s Type [%s] found at %p\n", - (char *) &target_name, acpi_ut_get_type_name (next_node->type), next_node)); + "Name %4.4s Type [%s] found in scope [%4.4s] %p\n", + (char *) &target_name, acpi_ut_get_type_name (next_node->type), + next_node->name.ascii, next_node)); *return_node = next_node; return_ACPI_STATUS (AE_OK); @@ -141,8 +142,10 @@ /* Searched entire namespace level, not found */ - ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Name %4.4s Type [%s] not found at %p\n", - (char *) &target_name, acpi_ut_get_type_name (type), next_node)); + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Name %4.4s Type [%s] not found in search in scope [%4.4s] %p first child %p\n", + (char *) &target_name, acpi_ut_get_type_name (type), + node->name.ascii, node, node->child)); return_ACPI_STATUS (AE_NOT_FOUND); } diff -Nru a/drivers/acpi/namespace/nsutils.c b/drivers/acpi/namespace/nsutils.c --- a/drivers/acpi/namespace/nsutils.c Sat May 24 12:48:25 2003 +++ b/drivers/acpi/namespace/nsutils.c Sat May 24 12:48:25 2003 @@ -181,7 +181,11 @@ status = acpi_ns_handle_to_pathname (node, &buffer); if (ACPI_SUCCESS (status)) { - acpi_os_printf ("%s [%s] (Node %p)", msg, (char *) buffer.pointer, node); + if (msg) { + acpi_os_printf ("%s ", msg); + } + + acpi_os_printf ("[%s] (Node %p)", (char *) buffer.pointer, node); ACPI_MEM_FREE (buffer.pointer); } } @@ -799,38 +803,31 @@ acpi_ns_terminate (void) { union acpi_operand_object *obj_desc; - struct acpi_namespace_node *this_node; ACPI_FUNCTION_TRACE ("ns_terminate"); - this_node = acpi_gbl_root_node; - /* - * 1) Free the entire namespace -- all objects, tables, and stacks + * 1) Free the entire namespace -- all nodes and objects * - * Delete all objects linked to the root - * (additional table descriptors) + * Delete all object descriptors attached to namepsace nodes */ - acpi_ns_delete_namespace_subtree (this_node); + acpi_ns_delete_namespace_subtree (acpi_gbl_root_node); - /* Detach any object(s) attached to the root */ + /* Detach any objects attached to the root */ - obj_desc = acpi_ns_get_attached_object (this_node); + obj_desc = acpi_ns_get_attached_object (acpi_gbl_root_node); if (obj_desc) { - acpi_ns_detach_object (this_node); - acpi_ut_remove_reference (obj_desc); + acpi_ns_detach_object (acpi_gbl_root_node); } - acpi_ns_delete_children (this_node); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n")); - /* * 2) Now we can delete the ACPI tables */ - acpi_tb_delete_acpi_tables (); + acpi_tb_delete_all_tables (); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n")); return_VOID; diff -Nru a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c --- a/drivers/acpi/namespace/nsxfeval.c Sat May 24 12:48:33 2003 +++ b/drivers/acpi/namespace/nsxfeval.c Sat May 24 12:48:33 2003 @@ -437,16 +437,15 @@ void *context, void **return_value) { + struct acpi_get_devices_info *info = context; acpi_status status; struct acpi_namespace_node *node; u32 flags; struct acpi_device_id hid; - struct acpi_device_id cid; - struct acpi_get_devices_info *info; + struct acpi_compatible_id_list *cid; + acpi_native_uint i; - info = context; - status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { return (status); @@ -462,9 +461,8 @@ return (AE_BAD_PARAMETER); } - /* - * Run _STA to determine if device is present - */ + /* Run _STA to determine if device is present */ + status = acpi_ut_execute_STA (node, &flags); if (ACPI_FAILURE (status)) { return (AE_CTRL_DEPTH); @@ -472,12 +470,12 @@ if (!(flags & 0x01)) { /* Don't return at the device or children of the device if not there */ + return (AE_CTRL_DEPTH); } - /* - * Filter based on device HID & CID - */ + /* Filter based on device HID & CID */ + if (info->hid != NULL) { status = acpi_ut_execute_HID (node, &hid); if (status == AE_NOT_FOUND) { @@ -487,7 +485,9 @@ return (AE_CTRL_DEPTH); } - if (ACPI_STRNCMP (hid.buffer, info->hid, sizeof (hid.buffer)) != 0) { + if (ACPI_STRNCMP (hid.value, info->hid, sizeof (hid.value)) != 0) { + /* Get the list of Compatible IDs */ + status = acpi_ut_execute_CID (node, &cid); if (status == AE_NOT_FOUND) { return (AE_OK); @@ -496,11 +496,16 @@ return (AE_CTRL_DEPTH); } - /* TBD: Handle CID packages */ + /* Walk the CID list */ - if (ACPI_STRNCMP (cid.buffer, info->hid, sizeof (cid.buffer)) != 0) { - return (AE_OK); + for (i = 0; i < cid->count; i++) { + if (ACPI_STRNCMP (cid->id[i].value, info->hid, + sizeof (struct acpi_compatible_id)) != 0) { + ACPI_MEM_FREE (cid); + return (AE_OK); + } } + ACPI_MEM_FREE (cid); } } diff -Nru a/drivers/acpi/namespace/nsxfname.c b/drivers/acpi/namespace/nsxfname.c --- a/drivers/acpi/namespace/nsxfname.c Sat May 24 12:48:21 2003 +++ b/drivers/acpi/namespace/nsxfname.c Sat May 24 12:48:21 2003 @@ -51,7 +51,7 @@ ACPI_MODULE_NAME ("nsxfname") -/**************************************************************************** +/****************************************************************************** * * FUNCTION: acpi_get_handle * @@ -119,7 +119,8 @@ /* * Find the Node and convert to a handle */ - status = acpi_ns_get_node_by_path (pathname, prefix_node, ACPI_NS_NO_UPSEARCH, &node); + status = acpi_ns_get_node_by_path (pathname, prefix_node, ACPI_NS_NO_UPSEARCH, + &node); *ret_handle = NULL; if (ACPI_SUCCESS (status)) { @@ -130,7 +131,7 @@ } -/**************************************************************************** +/****************************************************************************** * * FUNCTION: acpi_get_name * @@ -211,7 +212,7 @@ } -/**************************************************************************** +/****************************************************************************** * * FUNCTION: acpi_get_object_info * @@ -229,22 +230,27 @@ acpi_status acpi_get_object_info ( acpi_handle handle, - struct acpi_device_info *info) + struct acpi_buffer *buffer) { - struct acpi_device_id hid; - struct acpi_device_id uid; acpi_status status; - u32 device_status = 0; - acpi_integer address = 0; struct acpi_namespace_node *node; + struct acpi_device_info info; + struct acpi_device_info *return_info; + struct acpi_compatible_id_list *cid_list = NULL; + acpi_size size; /* Parameter validation */ - if (!handle || !info) { + if (!handle || !buffer) { return (AE_BAD_PARAMETER); } + status = acpi_ut_validate_buffer (buffer); + if (ACPI_FAILURE (status)) { + return (status); + } + status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { return (status); @@ -256,69 +262,94 @@ return (AE_BAD_PARAMETER); } - info->type = node->type; - info->name = node->name.integer; + /* Init return structure */ + + size = sizeof (struct acpi_device_info); + ACPI_MEMSET (&info, 0, size); + + info.type = node->type; + info.name = node->name.integer; + info.valid = 0; status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (status)) { return (status); } - /* - * If not a device, we are all done. - */ - if (info->type != ACPI_TYPE_DEVICE) { - return (AE_OK); - } + /* If not a device, we are all done */ + if (info.type == ACPI_TYPE_DEVICE) { + /* + * Get extra info for ACPI Devices objects only: + * Run the Device _HID, _UID, _CID, _STA, and _ADR methods. + * + * Note: none of these methods are required, so they may or may + * not be present for this device. The Info.Valid bitfield is used + * to indicate which methods were found and ran successfully. + */ + + /* Execute the Device._HID method */ + + status = acpi_ut_execute_HID (node, &info.hardware_id); + if (ACPI_SUCCESS (status)) { + info.valid |= ACPI_VALID_HID; + } - /* - * Get extra info for ACPI devices only. Run the - * _HID, _UID, _STA, and _ADR methods. Note: none - * of these methods are required, so they may or may - * not be present. The Info->Valid bits are used - * to indicate which methods ran successfully. - */ - info->valid = 0; + /* Execute the Device._UID method */ - /* Execute the _HID method and save the result */ + status = acpi_ut_execute_UID (node, &info.unique_id); + if (ACPI_SUCCESS (status)) { + info.valid |= ACPI_VALID_UID; + } - status = acpi_ut_execute_HID (node, &hid); - if (ACPI_SUCCESS (status)) { - ACPI_STRNCPY (info->hardware_id, hid.buffer, sizeof(info->hardware_id)); - info->valid |= ACPI_VALID_HID; - } + /* Execute the Device._CID method */ - /* Execute the _UID method and save the result */ + status = acpi_ut_execute_CID (node, &cid_list); + if (ACPI_SUCCESS (status)) { + size += ((acpi_size) cid_list->count - 1) * + sizeof (struct acpi_compatible_id); + info.valid |= ACPI_VALID_CID; + } - status = acpi_ut_execute_UID (node, &uid); - if (ACPI_SUCCESS (status)) { - ACPI_STRCPY (info->unique_id, uid.buffer); - info->valid |= ACPI_VALID_UID; + /* Execute the Device._STA method */ + + status = acpi_ut_execute_STA (node, &info.current_status); + if (ACPI_SUCCESS (status)) { + info.valid |= ACPI_VALID_STA; + } + + /* Execute the Device._ADR method */ + + status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, node, + &info.address); + if (ACPI_SUCCESS (status)) { + info.valid |= ACPI_VALID_ADR; + } + + status = AE_OK; } - /* - * Execute the _STA method and save the result - * _STA is not always present - */ - status = acpi_ut_execute_STA (node, &device_status); - if (ACPI_SUCCESS (status)) { - info->current_status = device_status; - info->valid |= ACPI_VALID_STA; + /* Validate/Allocate/Clear caller buffer */ + + status = acpi_ut_initialize_buffer (buffer, size); + if (ACPI_FAILURE (status)) { + goto cleanup; } - /* - * Execute the _ADR method and save result if successful - * _ADR is not always present - */ - status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, - node, &address); + /* Populate the return buffer */ - if (ACPI_SUCCESS (status)) { - info->address = address; - info->valid |= ACPI_VALID_ADR; + return_info = buffer->pointer; + ACPI_MEMCPY (return_info, &info, sizeof (struct acpi_device_info)); + + if (cid_list) { + ACPI_MEMCPY (&return_info->compatibility_id, cid_list, cid_list->size); } - return (AE_OK); + +cleanup: + if (cid_list) { + ACPI_MEM_FREE (cid_list); + } + return (status); } diff -Nru a/drivers/acpi/osl.c b/drivers/acpi/osl.c --- a/drivers/acpi/osl.c Sat May 24 12:48:30 2003 +++ b/drivers/acpi/osl.c Sat May 24 12:48:30 2003 @@ -237,7 +237,7 @@ static irqreturn_t acpi_irq(int irq, void *dev_id, struct pt_regs *regs) { - return (*acpi_irq_handler)(acpi_irq_context); + return (*acpi_irq_handler)(acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE; } acpi_status @@ -1006,7 +1006,7 @@ return 0; for (; count-- && str && *str; str++) { - if (isalnum(*str) || *str == ' ') + if (isalnum(*str) || *str == ' ' || *str == ':') *p++ = *str; else if (*str == '\'' || *str == '"') continue; diff -Nru a/drivers/acpi/parser/psargs.c b/drivers/acpi/parser/psargs.c --- a/drivers/acpi/parser/psargs.c Sat May 24 12:48:22 2003 +++ b/drivers/acpi/parser/psargs.c Sat May 24 12:48:22 2003 @@ -350,6 +350,11 @@ (status != AE_NOT_FOUND)) { ACPI_REPORT_NSERROR (path, status); + + acpi_os_printf ("search_node %p start_node %p return_node %p\n", + scope_info.scope.node, parser_state->start_node, node); + + } else { /* diff -Nru a/drivers/acpi/parser/pswalk.c b/drivers/acpi/parser/pswalk.c --- a/drivers/acpi/parser/pswalk.c Sat May 24 12:48:29 2003 +++ b/drivers/acpi/parser/pswalk.c Sat May 24 12:48:29 2003 @@ -270,7 +270,7 @@ return_VOID; } - walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, thread); + walk_state = acpi_ds_create_walk_state (0, NULL, NULL, thread); if (!walk_state) { return_VOID; } diff -Nru a/drivers/acpi/parser/psxface.c b/drivers/acpi/parser/psxface.c --- a/drivers/acpi/parser/psxface.c Sat May 24 12:48:30 2003 +++ b/drivers/acpi/parser/psxface.c Sat May 24 12:48:30 2003 @@ -178,7 +178,7 @@ /* Create and initialize a new walk state */ - walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, NULL); + walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL); if (!walk_state) { return_ACPI_STATUS (AE_NO_MEMORY); } diff -Nru a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c --- a/drivers/acpi/resources/rsxface.c Sat May 24 12:48:28 2003 +++ b/drivers/acpi/resources/rsxface.c Sat May 24 12:48:28 2003 @@ -379,24 +379,30 @@ { struct acpi_resource_address16 *address16; struct acpi_resource_address32 *address32; - struct acpi_resource_address64 *address64; switch (resource->id) { case ACPI_RSTYPE_ADDRESS16: + address16 = (struct acpi_resource_address16 *) &resource->data; ACPI_COPY_ADDRESS(out, address16); break; + case ACPI_RSTYPE_ADDRESS32: + address32 = (struct acpi_resource_address32 *) &resource->data; ACPI_COPY_ADDRESS(out, address32); break; + case ACPI_RSTYPE_ADDRESS64: - address64 = (struct acpi_resource_address64 *) &resource->data; - ACPI_COPY_ADDRESS(out, address64); + + /* Simple copy for 64 bit source */ + + ACPI_MEMCPY (out, &resource->data, sizeof (struct acpi_resource_address64)); break; + default: return (AE_BAD_PARAMETER); diff -Nru a/drivers/acpi/scan.c b/drivers/acpi/scan.c --- a/drivers/acpi/scan.c Sat May 24 12:48:23 2003 +++ b/drivers/acpi/scan.c Sat May 24 12:48:23 2003 @@ -28,6 +28,8 @@ static void acpi_device_release(struct kobject * kobj) { struct acpi_device * dev = container_of(kobj,struct acpi_device,kobj); + if (dev->pnp.cid_list) + kfree(dev->pnp.cid_list); kfree(dev); } @@ -69,7 +71,7 @@ device->kobj.parent = &parent->kobj; device->kobj.ktype = &ktype_acpi_ns; device->kobj.kset = &acpi_namespace_kset; - kobject_register(&device->kobj); + kobject_add(&device->kobj); } static int @@ -201,32 +203,15 @@ goto Done; if (device->flags.compatible_ids) { - acpi_status status = AE_OK; - union acpi_object *object = NULL; - char cid[256] = {}; - - status = acpi_evaluate_object(device->handle, "_CID", NULL, - &buffer); - if (ACPI_FAILURE(status) || !buffer.pointer) - return -ENOENT; - - object = (union acpi_object *) buffer.pointer; - - switch (object->type) { - case ACPI_TYPE_INTEGER: - acpi_ex_eisa_id_to_string((u32) object->integer.value, - cid); - break; - case ACPI_TYPE_STRING: - strncpy(cid, object->string.pointer, sizeof(cid) - 1); - break; - case ACPI_TYPE_PACKAGE: - /* TBD: Support CID packages */ - break; - } + struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; + int i; - if (strlen(cid) && strstr(driver->ids,cid)) - goto Done; + /* compare multiple _CID entries against driver ids */ + for (i = 0; i < cid_list->count; i++) + { + if (strstr(driver->ids, cid_list->id[i].value)) + goto Done; + } } error = -ENOENT; @@ -523,27 +508,30 @@ static void acpi_device_set_id(struct acpi_device * device, struct acpi_device * parent, acpi_handle handle, int type) { - struct acpi_device_info info; + struct acpi_device_info *info; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; char *hid = NULL; char *uid = NULL; + struct acpi_compatible_id_list *cid_list = NULL; acpi_status status; switch (type) { case ACPI_BUS_TYPE_DEVICE: - status = acpi_get_object_info(handle, &info); + status = acpi_get_object_info(handle, &buffer); if (ACPI_FAILURE(status)) { printk("%s: Error reading device info\n",__FUNCTION__); return; } - /* Clean up info strings (not NULL terminated) */ - info.hardware_id[sizeof(info.hardware_id)-1] = '\0'; - info.unique_id[sizeof(info.unique_id)-1] = '\0'; - if (info.valid & ACPI_VALID_HID) - hid = info.hardware_id; - if (info.valid & ACPI_VALID_UID) - uid = info.unique_id; - if (info.valid & ACPI_VALID_ADR) { - device->pnp.bus_address = info.address; + + info = buffer.pointer; + if (info->valid & ACPI_VALID_HID) + hid = info->hardware_id.value; + if (info->valid & ACPI_VALID_UID) + uid = info->unique_id.value; + if (info->valid & ACPI_VALID_CID) + cid_list = &info->compatibility_id; + if (info->valid & ACPI_VALID_ADR) { + device->pnp.bus_address = info->address; device->flags.bus_address = 1; } break; @@ -586,6 +574,15 @@ sprintf(device->pnp.unique_id, "%s", uid); device->flags.unique_id = 1; } + if (cid_list) { + device->pnp.cid_list = kmalloc(cid_list->size, GFP_KERNEL); + if (device->pnp.cid_list) + memcpy(device->pnp.cid_list, cid_list, cid_list->size); + else + printk(KERN_ERR "Memory allocation error\n"); + } + + acpi_os_free(buffer.pointer); } int acpi_device_set_context(struct acpi_device * device, int type) @@ -781,8 +778,12 @@ end: if (!result) *child = device; - else + else { + if (device->pnp.cid_list) + kfree(device->pnp.cid_list); kfree(device); + } + return_VALUE(result); } diff -Nru a/drivers/acpi/tables/tbconvrt.c b/drivers/acpi/tables/tbconvrt.c --- a/drivers/acpi/tables/tbconvrt.c Sat May 24 12:48:23 2003 +++ b/drivers/acpi/tables/tbconvrt.c Sat May 24 12:48:23 2003 @@ -164,6 +164,36 @@ } +/****************************************************************************** + * + * FUNCTION: acpi_tb_init_generic_address + * + * PARAMETERS: new_gas_struct - GAS struct to be initialized + * register_bit_width - Width of this register + * Address - Address of the register + * + * RETURN: None + * + * DESCRIPTION: Initialize a GAS structure. + * + ******************************************************************************/ + +static void +acpi_tb_init_generic_address ( + struct acpi_generic_address *new_gas_struct, + u8 register_bit_width, + acpi_physical_address address) +{ + + ACPI_STORE_ADDRESS (new_gas_struct->address, address); + + new_gas_struct->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO; + new_gas_struct->register_bit_width = register_bit_width; + new_gas_struct->register_bit_offset = 0; + new_gas_struct->reserved = 0; +} + + /******************************************************************************* * * FUNCTION: acpi_tb_convert_fadt1 @@ -233,14 +263,34 @@ /* * Convert the V1.0 block addresses to V2.0 GAS structures */ - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm1a_evt_blk, local_fadt->pm1_evt_len, local_fadt->V1_pm1a_evt_blk); - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm1b_evt_blk, local_fadt->pm1_evt_len, local_fadt->V1_pm1b_evt_blk); - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm1a_cnt_blk, local_fadt->pm1_cnt_len, local_fadt->V1_pm1a_cnt_blk); - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm1b_cnt_blk, local_fadt->pm1_cnt_len, local_fadt->V1_pm1b_cnt_blk); - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm2_cnt_blk, local_fadt->pm2_cnt_len, local_fadt->V1_pm2_cnt_blk); - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm_tmr_blk, local_fadt->pm_tm_len, local_fadt->V1_pm_tmr_blk); - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xgpe0_blk, 0, local_fadt->V1_gpe0_blk); - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xgpe1_blk, 0, local_fadt->V1_gpe1_blk); + acpi_tb_init_generic_address (&local_fadt->xpm1a_evt_blk, local_fadt->pm1_evt_len, + (acpi_physical_address) local_fadt->V1_pm1a_evt_blk); + acpi_tb_init_generic_address (&local_fadt->xpm1b_evt_blk, local_fadt->pm1_evt_len, + (acpi_physical_address) local_fadt->V1_pm1b_evt_blk); + acpi_tb_init_generic_address (&local_fadt->xpm1a_cnt_blk, local_fadt->pm1_cnt_len, + (acpi_physical_address) local_fadt->V1_pm1a_cnt_blk); + acpi_tb_init_generic_address (&local_fadt->xpm1b_cnt_blk, local_fadt->pm1_cnt_len, + (acpi_physical_address) local_fadt->V1_pm1b_cnt_blk); + acpi_tb_init_generic_address (&local_fadt->xpm2_cnt_blk, local_fadt->pm2_cnt_len, + (acpi_physical_address) local_fadt->V1_pm2_cnt_blk); + acpi_tb_init_generic_address (&local_fadt->xpm_tmr_blk, local_fadt->pm_tm_len, + (acpi_physical_address) local_fadt->V1_pm_tmr_blk); + acpi_tb_init_generic_address (&local_fadt->xgpe0_blk, 0, + (acpi_physical_address) local_fadt->V1_gpe0_blk); + acpi_tb_init_generic_address (&local_fadt->xgpe1_blk, 0, + (acpi_physical_address) local_fadt->V1_gpe1_blk); + + /* Create separate GAS structs for the PM1 Enable registers */ + + acpi_tb_init_generic_address (&acpi_gbl_xpm1a_enable, + (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len), + (acpi_physical_address) (local_fadt->xpm1a_evt_blk.address + + ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len))); + + acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable, + (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len), + (acpi_physical_address) (local_fadt->xpm1b_evt_blk.address + + ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len))); } @@ -282,44 +332,58 @@ } if (!(local_fadt->xpm1a_evt_blk.address)) { - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm1a_evt_blk, - local_fadt->pm1_evt_len, local_fadt->V1_pm1a_evt_blk); + acpi_tb_init_generic_address (&local_fadt->xpm1a_evt_blk, + local_fadt->pm1_evt_len, (acpi_physical_address) local_fadt->V1_pm1a_evt_blk); } if (!(local_fadt->xpm1b_evt_blk.address)) { - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm1b_evt_blk, - local_fadt->pm1_evt_len, local_fadt->V1_pm1b_evt_blk); + acpi_tb_init_generic_address (&local_fadt->xpm1b_evt_blk, + local_fadt->pm1_evt_len, (acpi_physical_address) local_fadt->V1_pm1b_evt_blk); } if (!(local_fadt->xpm1a_cnt_blk.address)) { - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm1a_cnt_blk, - local_fadt->pm1_cnt_len, local_fadt->V1_pm1a_cnt_blk); + acpi_tb_init_generic_address (&local_fadt->xpm1a_cnt_blk, + local_fadt->pm1_cnt_len, (acpi_physical_address) local_fadt->V1_pm1a_cnt_blk); } if (!(local_fadt->xpm1b_cnt_blk.address)) { - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm1b_cnt_blk, - local_fadt->pm1_cnt_len, local_fadt->V1_pm1b_cnt_blk); + acpi_tb_init_generic_address (&local_fadt->xpm1b_cnt_blk, + local_fadt->pm1_cnt_len, (acpi_physical_address) local_fadt->V1_pm1b_cnt_blk); } if (!(local_fadt->xpm2_cnt_blk.address)) { - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm2_cnt_blk, - local_fadt->pm2_cnt_len, local_fadt->V1_pm2_cnt_blk); + acpi_tb_init_generic_address (&local_fadt->xpm2_cnt_blk, + local_fadt->pm2_cnt_len, (acpi_physical_address) local_fadt->V1_pm2_cnt_blk); } if (!(local_fadt->xpm_tmr_blk.address)) { - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xpm_tmr_blk, - local_fadt->pm_tm_len, local_fadt->V1_pm_tmr_blk); + acpi_tb_init_generic_address (&local_fadt->xpm_tmr_blk, + local_fadt->pm_tm_len, (acpi_physical_address) local_fadt->V1_pm_tmr_blk); } if (!(local_fadt->xgpe0_blk.address)) { - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xgpe0_blk, - 0, local_fadt->V1_gpe0_blk); + acpi_tb_init_generic_address (&local_fadt->xgpe0_blk, + 0, (acpi_physical_address) local_fadt->V1_gpe0_blk); } if (!(local_fadt->xgpe1_blk.address)) { - ASL_BUILD_GAS_FROM_V1_ENTRY (local_fadt->xgpe1_blk, - 0, local_fadt->V1_gpe1_blk); + acpi_tb_init_generic_address (&local_fadt->xgpe1_blk, + 0, (acpi_physical_address) local_fadt->V1_gpe1_blk); } + + /* Create separate GAS structs for the PM1 Enable registers */ + + acpi_tb_init_generic_address (&acpi_gbl_xpm1a_enable, + (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len), + (acpi_physical_address) (local_fadt->xpm1a_evt_blk.address + + ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len))); + acpi_gbl_xpm1a_enable.address_space_id = local_fadt->xpm1a_evt_blk.address_space_id; + + acpi_tb_init_generic_address (&acpi_gbl_xpm1b_enable, + (u8) ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len), + (acpi_physical_address) (local_fadt->xpm1b_evt_blk.address + + ACPI_DIV_2 (acpi_gbl_FADT->pm1_evt_len))); + acpi_gbl_xpm1b_enable.address_space_id = local_fadt->xpm1b_evt_blk.address_space_id; } @@ -396,7 +460,7 @@ /* Free the original table */ - table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_FADT]; + table_desc = acpi_gbl_table_lists[ACPI_TABLE_FADT].next; acpi_tb_delete_single_table (table_desc); /* Install the new table */ diff -Nru a/drivers/acpi/tables/tbget.c b/drivers/acpi/tables/tbget.c --- a/drivers/acpi/tables/tbget.c Sat May 24 12:48:27 2003 +++ b/drivers/acpi/tables/tbget.c Sat May 24 12:48:27 2003 @@ -456,18 +456,18 @@ * instance is always in the list head. */ if (instance == 1) { - /* - * Just pluck the pointer out of the global table! - * Will be null if no table is present - */ - *table_ptr_loc = acpi_gbl_acpi_tables[table_type].pointer; + /* Get the first */ + + if (acpi_gbl_table_lists[table_type].next) { + *table_ptr_loc = acpi_gbl_table_lists[table_type].next->pointer; + } return_ACPI_STATUS (AE_OK); } /* * Check for instance out of range */ - if (instance > acpi_gbl_acpi_tables[table_type].count) { + if (instance > acpi_gbl_table_lists[table_type].count) { return_ACPI_STATUS (AE_NOT_EXIST); } @@ -478,7 +478,7 @@ * need to walk from the 2nd table until we reach the Instance * that the user is looking for and return its table pointer. */ - table_desc = acpi_gbl_acpi_tables[table_type].next; + table_desc = acpi_gbl_table_lists[table_type].next; for (i = 2; i < instance; i++) { table_desc = table_desc->next; } diff -Nru a/drivers/acpi/tables/tbgetall.c b/drivers/acpi/tables/tbgetall.c --- a/drivers/acpi/tables/tbgetall.c Sat May 24 12:48:29 2003 +++ b/drivers/acpi/tables/tbgetall.c Sat May 24 12:48:29 2003 @@ -307,7 +307,7 @@ /* Always delete the RSDP mapping, we are done with it */ - acpi_tb_delete_acpi_table (ACPI_TABLE_RSDP); + acpi_tb_delete_tables_by_type (ACPI_TABLE_RSDP); return_ACPI_STATUS (status); } diff -Nru a/drivers/acpi/tables/tbinstal.c b/drivers/acpi/tables/tbinstal.c --- a/drivers/acpi/tables/tbinstal.c Sat May 24 12:48:21 2003 +++ b/drivers/acpi/tables/tbinstal.c Sat May 24 12:48:21 2003 @@ -79,13 +79,13 @@ /* * Search for a signature match among the known table types */ - for (i = 0; i < NUM_ACPI_TABLES; i++) { - if (!(acpi_gbl_acpi_table_data[i].flags & search_type)) { + for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) { + if (!(acpi_gbl_table_data[i].flags & search_type)) { continue; } - if (!ACPI_STRNCMP (signature, acpi_gbl_acpi_table_data[i].signature, - acpi_gbl_acpi_table_data[i].sig_length)) { + if (!ACPI_STRNCMP (signature, acpi_gbl_table_data[i].signature, + acpi_gbl_table_data[i].sig_length)) { /* Found a signature match, return index if requested */ if (table_info) { @@ -94,7 +94,7 @@ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Table [%4.4s] is an ACPI table consumed by the core subsystem\n", - (char *) acpi_gbl_acpi_table_data[i].signature)); + (char *) acpi_gbl_table_data[i].signature)); return_ACPI_STATUS (AE_OK); } @@ -149,7 +149,7 @@ } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "%s located at %p\n", - acpi_gbl_acpi_table_data[table_info->type].name, table_info->pointer)); + acpi_gbl_table_data[table_info->type].name, table_info->pointer)); (void) acpi_ut_release_mutex (ACPI_MTX_TABLES); return_ACPI_STATUS (status); @@ -239,70 +239,58 @@ acpi_table_type table_type, struct acpi_table_desc *table_info) { - struct acpi_table_desc *list_head; + struct acpi_table_list *list_head; struct acpi_table_desc *table_desc; ACPI_FUNCTION_TRACE_U32 ("tb_init_table_descriptor", table_type); + + /* Allocate a descriptor for this table */ + + table_desc = ACPI_MEM_CALLOCATE (sizeof (struct acpi_table_desc)); + if (!table_desc) { + return_ACPI_STATUS (AE_NO_MEMORY); + } + /* * Install the table into the global data structure */ - list_head = &acpi_gbl_acpi_tables[table_type]; - table_desc = list_head; + list_head = &acpi_gbl_table_lists[table_type]; /* * Two major types of tables: 1) Only one instance is allowed. This * includes most ACPI tables such as the DSDT. 2) Multiple instances of * the table are allowed. This includes SSDT and PSDTs. */ - if (ACPI_IS_SINGLE_TABLE (acpi_gbl_acpi_table_data[table_type].flags)) { + if (ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags)) { /* * Only one table allowed, and a table has alread been installed * at this location, so return an error. */ - if (list_head->pointer) { + if (list_head->next) { return_ACPI_STATUS (AE_ALREADY_EXISTS); } - - table_desc->count = 1; - table_desc->prev = NULL; - table_desc->next = NULL; } - else { - /* - * Multiple tables allowed for this table type, we must link - * the new table in to the list of tables of this type. - */ - if (list_head->pointer) { - table_desc = ACPI_MEM_CALLOCATE (sizeof (struct acpi_table_desc)); - if (!table_desc) { - return_ACPI_STATUS (AE_NO_MEMORY); - } - - list_head->count++; - - /* Update the original previous */ - - list_head->prev->next = table_desc; - - /* Update new entry */ - table_desc->prev = list_head->prev; - table_desc->next = list_head; - - /* Update list head */ + /* + * Link the new table in to the list of tables of this type. + * Just insert at the start of the list, order unimportant. + * + * table_desc->Prev is already NULL from calloc() + */ + table_desc->next = list_head->next; + list_head->next = table_desc; - list_head->prev = table_desc; - } - else { - table_desc->count = 1; - } + if (table_desc->next) { + table_desc->next->prev = table_desc; } - /* Common initialization of the table descriptor */ + list_head->count++; - table_desc->type = table_info->type; + /* Finish initialization of the table descriptor */ + + table_desc->type = (u8) table_type; table_desc->pointer = table_info->pointer; table_desc->length = table_info->length; table_desc->allocation = table_info->allocation; @@ -316,8 +304,8 @@ * Set the appropriate global pointer (if there is one) to point to the * newly installed table */ - if (acpi_gbl_acpi_table_data[table_type].global_ptr) { - *(acpi_gbl_acpi_table_data[table_type].global_ptr) = table_info->pointer; + if (acpi_gbl_table_data[table_type].global_ptr) { + *(acpi_gbl_table_data[table_type].global_ptr) = table_info->pointer; } /* Return Data */ @@ -331,7 +319,7 @@ /******************************************************************************* * - * FUNCTION: acpi_tb_delete_acpi_tables + * FUNCTION: acpi_tb_delete_all_tables * * PARAMETERS: None. * @@ -342,7 +330,7 @@ ******************************************************************************/ void -acpi_tb_delete_acpi_tables (void) +acpi_tb_delete_all_tables (void) { acpi_table_type type; @@ -351,15 +339,15 @@ * Free memory allocated for ACPI tables * Memory can either be mapped or allocated */ - for (type = 0; type < NUM_ACPI_TABLES; type++) { - acpi_tb_delete_acpi_table (type); + for (type = 0; type < NUM_ACPI_TABLE_TYPES; type++) { + acpi_tb_delete_tables_by_type (type); } } /******************************************************************************* * - * FUNCTION: acpi_tb_delete_acpi_table + * FUNCTION: acpi_tb_delete_tables_by_type * * PARAMETERS: Type - The table type to be deleted * @@ -371,11 +359,15 @@ ******************************************************************************/ void -acpi_tb_delete_acpi_table ( +acpi_tb_delete_tables_by_type ( acpi_table_type type) { + struct acpi_table_desc *table_desc; + u32 count; + u32 i; - ACPI_FUNCTION_TRACE_U32 ("tb_delete_acpi_table", type); + + ACPI_FUNCTION_TRACE_U32 ("tb_delete_tables_by_type", type); if (type > ACPI_TABLE_MAX) { @@ -416,43 +408,10 @@ } /* Free the table */ - - acpi_tb_free_acpi_tables_of_type (&acpi_gbl_acpi_tables[type]); - - (void) acpi_ut_release_mutex (ACPI_MTX_TABLES); - return_VOID; -} - - -/******************************************************************************* - * - * FUNCTION: acpi_tb_free_acpi_tables_of_type - * - * PARAMETERS: table_info - A table info struct - * - * RETURN: None. - * - * DESCRIPTION: Free the memory associated with an internal ACPI table - * Table mutex should be locked. - * - ******************************************************************************/ - -void -acpi_tb_free_acpi_tables_of_type ( - struct acpi_table_desc *list_head) -{ - struct acpi_table_desc *table_desc; - u32 count; - u32 i; - - - ACPI_FUNCTION_TRACE_PTR ("tb_free_acpi_tables_of_type", list_head); - - /* Get the head of the list */ - table_desc = list_head; - count = list_head->count; + table_desc = acpi_gbl_table_lists[type].next; + count = acpi_gbl_table_lists[type].count; /* * Walk the entire list, deleting both the allocated tables @@ -462,6 +421,7 @@ table_desc = acpi_tb_uninstall_table (table_desc); } + (void) acpi_ut_release_mutex (ACPI_MTX_TABLES); return_VOID; } @@ -484,30 +444,31 @@ struct acpi_table_desc *table_desc) { - if (!table_desc) { + /* Must have a valid table descriptor and pointer */ + + if ((!table_desc) || + (!table_desc->pointer)) { return; } - if (table_desc->pointer) { - /* Valid table, determine type of memory allocation */ + /* Valid table, determine type of memory allocation */ - switch (table_desc->allocation) { - case ACPI_MEM_NOT_ALLOCATED: - break; + switch (table_desc->allocation) { + case ACPI_MEM_NOT_ALLOCATED: + break; - case ACPI_MEM_ALLOCATED: + case ACPI_MEM_ALLOCATED: - ACPI_MEM_FREE (table_desc->pointer); - break; + ACPI_MEM_FREE (table_desc->pointer); + break; - case ACPI_MEM_MAPPED: + case ACPI_MEM_MAPPED: - acpi_os_unmap_memory (table_desc->pointer, table_desc->length); - break; + acpi_os_unmap_memory (table_desc->pointer, table_desc->length); + break; - default: - break; - } + default: + break; } } @@ -533,18 +494,23 @@ struct acpi_table_desc *next_desc; - ACPI_FUNCTION_TRACE_PTR ("acpi_tb_uninstall_table", table_desc); + ACPI_FUNCTION_TRACE_PTR ("tb_uninstall_table", table_desc); if (!table_desc) { return_PTR (NULL); } - /* Unlink the descriptor */ + /* Unlink the descriptor from the doubly linked list */ if (table_desc->prev) { table_desc->prev->next = table_desc->next; } + else { + /* Is first on list, update list head */ + + acpi_gbl_table_lists[table_desc->type].next = table_desc->next; + } if (table_desc->next) { table_desc->next->prev = table_desc->prev; @@ -554,23 +520,12 @@ acpi_tb_delete_single_table (table_desc); - /* Free the table descriptor (Don't delete the list head, tho) */ - - if ((table_desc->prev) == (table_desc->next)) { - next_desc = NULL; + /* Free the table descriptor */ - /* Clear the list head */ + next_desc = table_desc->next; + ACPI_MEM_FREE (table_desc); - table_desc->pointer = NULL; - table_desc->length = 0; - table_desc->count = 0; - } - else { - /* Free the table descriptor */ - - next_desc = table_desc->next; - ACPI_MEM_FREE (table_desc); - } + /* Return pointer to the next descriptor */ return_PTR (next_desc); } diff -Nru a/drivers/acpi/tables/tbutils.c b/drivers/acpi/tables/tbutils.c --- a/drivers/acpi/tables/tbutils.c Sat May 24 12:48:30 2003 +++ b/drivers/acpi/tables/tbutils.c Sat May 24 12:48:30 2003 @@ -66,26 +66,25 @@ acpi_status acpi_tb_handle_to_object ( u16 table_id, - struct acpi_table_desc **table_desc) + struct acpi_table_desc **return_table_desc) { u32 i; - struct acpi_table_desc *list_head; + struct acpi_table_desc *table_desc; ACPI_FUNCTION_NAME ("tb_handle_to_object"); for (i = 0; i < ACPI_TABLE_MAX; i++) { - list_head = &acpi_gbl_acpi_tables[i]; - do { - if (list_head->table_id == table_id) { - *table_desc = list_head; + table_desc = acpi_gbl_table_lists[i].next; + while (table_desc) { + if (table_desc->table_id == table_id) { + *return_table_desc = table_desc; return (AE_OK); } - list_head = list_head->next; - - } while (list_head != &acpi_gbl_acpi_tables[i]); + table_desc = table_desc->next; + } } ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "table_id=%X does not exist\n", table_id)); diff -Nru a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c --- a/drivers/acpi/tables/tbxface.c Sat May 24 12:48:31 2003 +++ b/drivers/acpi/tables/tbxface.c Sat May 24 12:48:31 2003 @@ -235,7 +235,7 @@ acpi_unload_table ( acpi_table_type table_type) { - struct acpi_table_desc *list_head; + struct acpi_table_desc *table_desc; ACPI_FUNCTION_TRACE ("acpi_unload_table"); @@ -250,22 +250,22 @@ /* Find all tables of the requested type */ - list_head = &acpi_gbl_acpi_tables[table_type]; - do { + table_desc = acpi_gbl_table_lists[table_type].next; + while (table_desc); { /* * Delete all namespace entries owned by this table. Note that these * entries can appear anywhere in the namespace by virtue of the AML * "Scope" operator. Thus, we need to track ownership by an ID, not * simply a position within the hierarchy */ - acpi_ns_delete_namespace_by_owner (list_head->table_id); + acpi_ns_delete_namespace_by_owner (table_desc->table_id); - /* Delete (or unmap) the actual table */ - - acpi_tb_delete_acpi_table (table_type); + table_desc = table_desc->next; + } - } while (list_head != &acpi_gbl_acpi_tables[table_type]); + /* Delete (or unmap) all tables of this type */ + acpi_tb_delete_tables_by_type (table_type); return_ACPI_STATUS (AE_OK); } @@ -313,7 +313,7 @@ /* Check the table type and instance */ if ((table_type > ACPI_TABLE_MAX) || - (ACPI_IS_SINGLE_TABLE (acpi_gbl_acpi_table_data[table_type].flags) && + (ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags) && instance > 1)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } @@ -394,7 +394,7 @@ /* Check the table type and instance */ if ((table_type > ACPI_TABLE_MAX) || - (ACPI_IS_SINGLE_TABLE (acpi_gbl_acpi_table_data[table_type].flags) && + (ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags) && instance > 1)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } diff -Nru a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c --- a/drivers/acpi/toshiba_acpi.c Sat May 24 12:48:20 2003 +++ b/drivers/acpi/toshiba_acpi.c Sat May 24 12:48:20 2003 @@ -33,7 +33,7 @@ * */ -#define TOSHIBA_ACPI_VERSION "0.14" +#define TOSHIBA_ACPI_VERSION "0.15" #define PROC_INTERFACE_VERSION 1 #include @@ -172,9 +172,7 @@ for (i = 0; i < HCI_WORDS; ++i) { in_objs[i].type = ACPI_TYPE_INTEGER; in_objs[i].integer.value = in[i]; - /*printk("%04x ", in[i]);*/ } - /*printk("\n");*/ results.length = sizeof(out_objs); results.pointer = out_objs; @@ -184,9 +182,7 @@ if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) { for (i = 0; i < out_objs->package.count; ++i) { out[i] = out_objs->package.elements[i].integer.value; - /*printk("%04x ", out[i]);*/ } - /*printk("\n");*/ } return status; @@ -226,7 +222,7 @@ typedef struct _ProcItem { - char* name; + const char* name; char* (*read_func)(char*); unsigned long (*write_func)(const char*, unsigned long); } ProcItem; @@ -284,10 +280,8 @@ write_lcd(const char* buffer, unsigned long count) { int value; - /*int byte_count;*/ u32 hci_result; - /* ISSUE: %i doesn't work with hex values as advertised */ if (snscanf(buffer, count, " brightness : %i", &value) == 1 && value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) { value = value << HCI_LCD_BRIGHTNESS_SHIFT; @@ -414,6 +408,11 @@ last_key_event = value; } else if (hci_result == HCI_EMPTY) { /* better luck next time */ + } else if (hci_result == HCI_NOT_SUPPORTED) { + /* This is a workaround for an unresolved issue on + * some machines where system events sporadically + * become disabled. */ + hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result); } else { p += sprintf(p, "ERROR\n"); goto end; diff -Nru a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c --- a/drivers/acpi/utilities/utcopy.c Sat May 24 12:48:24 2003 +++ b/drivers/acpi/utilities/utcopy.c Sat May 24 12:48:24 2003 @@ -651,13 +651,21 @@ */ if ((source_desc->buffer.pointer) && (!(source_desc->common.flags & AOPOBJ_STATIC_POINTER))) { - dest_desc->buffer.pointer = ACPI_MEM_ALLOCATE (source_desc->buffer.length); - if (!dest_desc->buffer.pointer) { - return (AE_NO_MEMORY); - } + dest_desc->buffer.pointer = NULL; + + /* Create an actual buffer only if length > 0 */ + + if (source_desc->buffer.length) { + dest_desc->buffer.pointer = ACPI_MEM_ALLOCATE (source_desc->buffer.length); + if (!dest_desc->buffer.pointer) { + return (AE_NO_MEMORY); + } - ACPI_MEMCPY (dest_desc->buffer.pointer, source_desc->buffer.pointer, - source_desc->buffer.length); + /* Copy the actual buffer data */ + + ACPI_MEMCPY (dest_desc->buffer.pointer, source_desc->buffer.pointer, + source_desc->buffer.length); + } } break; diff -Nru a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c --- a/drivers/acpi/utilities/utdelete.c Sat May 24 12:48:24 2003 +++ b/drivers/acpi/utilities/utdelete.c Sat May 24 12:48:24 2003 @@ -71,6 +71,7 @@ void *obj_pointer = NULL; union acpi_operand_object *handler_desc; union acpi_operand_object *second_desc; + union acpi_operand_object *next_desc; ACPI_FUNCTION_TRACE_PTR ("ut_delete_internal_obj", object); @@ -136,6 +137,15 @@ if (object->device.gpe_block) { (void) acpi_ev_delete_gpe_block (object->device.gpe_block); } + + /* Walk the handler list for this device */ + + handler_desc = object->device.address_space; + while (handler_desc) { + next_desc = handler_desc->address_space.next; + acpi_ut_remove_reference (handler_desc); + handler_desc = next_desc; + } break; @@ -183,10 +193,13 @@ * default handlers -- and therefore, we created the context object * locally, it was not created by an external caller. */ - handler_desc = object->region.addr_handler; - if ((handler_desc) && - (handler_desc->addr_handler.hflags == ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { - obj_pointer = second_desc->extra.region_context; + handler_desc = object->region.address_space; + if (handler_desc) { + if (handler_desc->address_space.hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) { + obj_pointer = second_desc->extra.region_context; + } + + acpi_ut_remove_reference (handler_desc); } /* Now we can free the Extra object */ @@ -211,7 +224,6 @@ break; } - /* Free any allocated memory (pointer within the object) found above */ if (obj_pointer) { @@ -299,7 +311,7 @@ new_count = count; /* - * Reference count action (increment, decrement, or force delete) + * Perform the reference count action (increment, decrement, or force delete) */ switch (action) { @@ -402,8 +414,6 @@ { acpi_status status; u32 i; - union acpi_operand_object *next; - union acpi_operand_object *new; union acpi_generic_state *state_list = NULL; union acpi_generic_state *state; @@ -417,9 +427,8 @@ return_ACPI_STATUS (AE_OK); } - /* - * Make sure that this isn't a namespace handle - */ + /* Make sure that this isn't a namespace handle */ + if (ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_NAMED) { ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Object %p is NS handle\n", object)); return_ACPI_STATUS (AE_OK); @@ -439,28 +448,8 @@ switch (ACPI_GET_OBJECT_TYPE (object)) { case ACPI_TYPE_DEVICE: - status = acpi_ut_create_update_state_and_push (object->device.addr_handler, - action, &state_list); - if (ACPI_FAILURE (status)) { - goto error_exit; - } - - acpi_ut_update_ref_count (object->device.sys_handler, action); - acpi_ut_update_ref_count (object->device.drv_handler, action); - break; - - - case ACPI_TYPE_LOCAL_ADDRESS_HANDLER: - - /* Must walk list of address handlers */ - - next = object->addr_handler.next; - while (next) { - new = next->addr_handler.next; - acpi_ut_update_ref_count (next, action); - - next = new; - } + acpi_ut_update_ref_count (object->device.system_notify, action); + acpi_ut_update_ref_count (object->device.device_notify, action); break; @@ -590,16 +579,14 @@ ACPI_FUNCTION_TRACE_PTR ("ut_add_reference", object); - /* - * Ensure that we have a valid object - */ + /* Ensure that we have a valid object */ + if (!acpi_ut_valid_internal_object (object)) { return_VOID; } - /* - * We have a valid ACPI internal object, now increment the reference count - */ + /* Increment the reference count */ + (void) acpi_ut_update_object_reference (object, REF_INCREMENT); return_VOID; } @@ -624,6 +611,7 @@ ACPI_FUNCTION_TRACE_PTR ("ut_remove_reference", object); + /* * Allow a NULL pointer to be passed in, just ignore it. This saves * each caller from having to check. Also, ignore NS nodes. @@ -634,9 +622,8 @@ return_VOID; } - /* - * Ensure that we have a valid object - */ + /* Ensure that we have a valid object */ + if (!acpi_ut_valid_internal_object (object)) { return_VOID; } diff -Nru a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c --- a/drivers/acpi/utilities/uteval.c Sat May 24 12:48:20 2003 +++ b/drivers/acpi/utilities/uteval.c Sat May 24 12:48:20 2003 @@ -210,6 +210,46 @@ /******************************************************************************* * + * FUNCTION: acpi_ut_copy_id_string + * + * PARAMETERS: Destination - Where to copy the string + * Source - Source string + * max_length - Length of the destination buffer + * + * RETURN: None + * + * DESCRIPTION: Copies an ID string for the _HID, _CID, and _UID methods. + * Performs removal of a leading asterisk if present -- workaround + * for a known issue on a bunch of machines. + * + ******************************************************************************/ + +static void +acpi_ut_copy_id_string ( + char *destination, + char *source, + acpi_size max_length) +{ + + + /* + * Workaround for ID strings that have a leading asterisk. This construct + * is not allowed by the ACPI specification (ID strings must be + * alphanumeric), but enough existing machines have this embedded in their + * ID strings that the following code is useful. + */ + if (*source == '*') { + source++; + } + + /* Do the actual copy */ + + ACPI_STRNCPY (destination, source, max_length); +} + + +/******************************************************************************* + * * FUNCTION: acpi_ut_execute_HID * * PARAMETERS: device_node - Node for the device @@ -245,12 +285,13 @@ if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) { /* Convert the Numeric HID to string */ - acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, hid->buffer); + acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, hid->value); } else { /* Copy the String HID from the returned object */ - ACPI_STRNCPY (hid->buffer, obj_desc->string.pointer, sizeof(hid->buffer)); + acpi_ut_copy_id_string (hid->value, obj_desc->string.pointer, + sizeof (hid->value)); } /* On exit, we must delete the return object */ @@ -262,6 +303,57 @@ /******************************************************************************* * + * FUNCTION: acpi_ut_translate_one_cid + * + * PARAMETERS: obj_desc - _CID object, must be integer or string + * one_cid - Where the CID string is returned + * + * RETURN: Status + * + * DESCRIPTION: Return a numeric or string _CID value as a string. + * (Compatible ID) + * + * NOTE: Assumes a maximum _CID string length of + * ACPI_MAX_CID_LENGTH. + * + ******************************************************************************/ + +static acpi_status +acpi_ut_translate_one_cid ( + union acpi_operand_object *obj_desc, + struct acpi_compatible_id *one_cid) +{ + + + switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { + case ACPI_TYPE_INTEGER: + + /* Convert the Numeric CID to string */ + + acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, one_cid->value); + return (AE_OK); + + case ACPI_TYPE_STRING: + + if (obj_desc->string.length > ACPI_MAX_CID_LENGTH) { + return (AE_AML_STRING_LIMIT); + } + + /* Copy the String CID from the returned object */ + + acpi_ut_copy_id_string (one_cid->value, obj_desc->string.pointer, + ACPI_MAX_CID_LENGTH); + return (AE_OK); + + default: + + return (AE_TYPE); + } +} + + +/******************************************************************************* + * * FUNCTION: acpi_ut_execute_CID * * PARAMETERS: device_node - Node for the device @@ -279,55 +371,86 @@ acpi_status acpi_ut_execute_CID ( struct acpi_namespace_node *device_node, - struct acpi_device_id *cid) + struct acpi_compatible_id_list **return_cid_list) { union acpi_operand_object *obj_desc; acpi_status status; + u32 count; + u32 size; + struct acpi_compatible_id_list *cid_list; + acpi_native_uint i; ACPI_FUNCTION_TRACE ("ut_execute_CID"); + /* Evaluate the _CID method for this device */ + status = acpi_ut_evaluate_object (device_node, METHOD_NAME__CID, - ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_PACKAGE, &obj_desc); + ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_PACKAGE, + &obj_desc); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } - /* - * A _CID can return either a single compatible ID or a package of compatible - * IDs. Each compatible ID can be a Number (32 bit compressed EISA ID) or - * string (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss"). - */ - switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { - case ACPI_TYPE_INTEGER: + /* Get the number of _CIDs returned */ - /* Convert the Numeric CID to string */ + count = 1; + if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_PACKAGE) { + count = obj_desc->package.count; + } - acpi_ex_eisa_id_to_string ((u32) obj_desc->integer.value, cid->buffer); - break; + /* Allocate a worst-case buffer for the _CIDs */ - case ACPI_TYPE_STRING: + size = (((count - 1) * sizeof (struct acpi_compatible_id)) + + sizeof (struct acpi_compatible_id_list)); - /* Copy the String CID from the returned object */ + cid_list = ACPI_MEM_CALLOCATE ((acpi_size) size); + if (!cid_list) { + return_ACPI_STATUS (AE_NO_MEMORY); + } - ACPI_STRNCPY (cid->buffer, obj_desc->string.pointer, sizeof (cid->buffer)); - break; + /* Init CID list */ - case ACPI_TYPE_PACKAGE: + cid_list->count = count; + cid_list->size = size; - /* TBD: Parse package elements; need different return struct, etc. */ + /* + * A _CID can return either a single compatible ID or a package of compatible + * IDs. Each compatible ID can be one of the following: + * -- Number (32 bit compressed EISA ID) or + * -- String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss"). + */ - status = AE_SUPPORT; - break; + /* The _CID object can be either a single CID or a package (list) of CIDs */ - default: + if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_PACKAGE) { + /* Translate each package element */ + + for (i = 0; i < count; i++) { + status = acpi_ut_translate_one_cid (obj_desc->package.elements[i], + &cid_list->id[i]); + if (ACPI_FAILURE (status)) { + break; + } + } + } + else { + /* Only one CID, translate to a string */ - status = AE_TYPE; - break; + status = acpi_ut_translate_one_cid (obj_desc, cid_list->id); } - /* On exit, we must delete the return object */ + /* Cleanup on error */ + + if (ACPI_FAILURE (status)) { + ACPI_MEM_FREE (cid_list); + } + else { + *return_cid_list = cid_list; + } + + /* On exit, we must delete the _CID return object */ acpi_ut_remove_reference (obj_desc); return_ACPI_STATUS (status); @@ -371,12 +494,13 @@ if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) { /* Convert the Numeric UID to string */ - acpi_ex_unsigned_integer_to_string (obj_desc->integer.value, uid->buffer); + acpi_ex_unsigned_integer_to_string (obj_desc->integer.value, uid->value); } else { /* Copy the String UID from the returned object */ - ACPI_STRNCPY (uid->buffer, obj_desc->string.pointer, sizeof (uid->buffer)); + acpi_ut_copy_id_string (uid->value, obj_desc->string.pointer, + sizeof (uid->value)); } /* On exit, we must delete the return object */ diff -Nru a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c --- a/drivers/acpi/utilities/utglobal.c Sat May 24 12:48:20 2003 +++ b/drivers/acpi/utilities/utglobal.c Sat May 24 12:48:20 2003 @@ -299,10 +299,10 @@ ******************************************************************************/ -struct acpi_table_desc acpi_gbl_acpi_tables[NUM_ACPI_TABLES]; +struct acpi_table_list acpi_gbl_table_lists[NUM_ACPI_TABLE_TYPES]; -struct acpi_table_support acpi_gbl_acpi_table_data[NUM_ACPI_TABLES] = +struct acpi_table_support acpi_gbl_table_data[NUM_ACPI_TABLE_TYPES] = { /*********** Name, Signature, Global typed pointer Signature size, Type How many allowed?, Contains valid AML? */ @@ -535,12 +535,10 @@ #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) - /* * Strings and procedures used for debug only */ - /***************************************************************************** * * FUNCTION: acpi_ut_get_mutex_name @@ -558,7 +556,7 @@ u32 mutex_id) { - if (mutex_id > MAX_MTX) + if (mutex_id > MAX_MUTEX) { return ("Invalid Mutex ID"); } @@ -566,7 +564,6 @@ return (acpi_gbl_mutex_names[mutex_id]); } - #endif @@ -630,9 +627,12 @@ owner_id = acpi_gbl_next_table_owner_id; acpi_gbl_next_table_owner_id++; + /* Check for wraparound */ + if (acpi_gbl_next_table_owner_id == ACPI_FIRST_METHOD_ID) { acpi_gbl_next_table_owner_id = ACPI_FIRST_TABLE_ID; + ACPI_REPORT_WARNING (("Table owner ID wraparound\n")); } break; @@ -644,6 +644,8 @@ if (acpi_gbl_next_method_owner_id == ACPI_FIRST_TABLE_ID) { + /* Check for wraparound */ + acpi_gbl_next_method_owner_id = ACPI_FIRST_METHOD_ID; } break; @@ -710,23 +712,19 @@ /* ACPI table structure */ - for (i = 0; i < NUM_ACPI_TABLES; i++) + for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) { - acpi_gbl_acpi_tables[i].prev = &acpi_gbl_acpi_tables[i]; - acpi_gbl_acpi_tables[i].next = &acpi_gbl_acpi_tables[i]; - acpi_gbl_acpi_tables[i].pointer = NULL; - acpi_gbl_acpi_tables[i].length = 0; - acpi_gbl_acpi_tables[i].allocation = ACPI_MEM_NOT_ALLOCATED; - acpi_gbl_acpi_tables[i].count = 0; + acpi_gbl_table_lists[i].next = NULL; + acpi_gbl_table_lists[i].count = 0; } /* Mutex locked flags */ - for (i = 0; i < NUM_MTX; i++) + for (i = 0; i < NUM_MUTEX; i++) { - acpi_gbl_acpi_mutex_info[i].mutex = NULL; - acpi_gbl_acpi_mutex_info[i].owner_id = ACPI_MUTEX_NOT_ACQUIRED; - acpi_gbl_acpi_mutex_info[i].use_count = 0; + acpi_gbl_mutex_info[i].mutex = NULL; + acpi_gbl_mutex_info[i].owner_id = ACPI_MUTEX_NOT_ACQUIRED; + acpi_gbl_mutex_info[i].use_count = 0; } /* GPE support */ @@ -737,8 +735,8 @@ /* Global notify handlers */ - acpi_gbl_sys_notify.handler = NULL; - acpi_gbl_drv_notify.handler = NULL; + acpi_gbl_system_notify.handler = NULL; + acpi_gbl_device_notify.handler = NULL; acpi_gbl_init_handler = NULL; /* Global "typed" ACPI table pointers */ diff -Nru a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c --- a/drivers/acpi/utilities/utmisc.c Sat May 24 12:48:20 2003 +++ b/drivers/acpi/utilities/utmisc.c Sat May 24 12:48:20 2003 @@ -549,7 +549,7 @@ /* * Create each of the predefined mutex objects */ - for (i = 0; i < NUM_MTX; i++) { + for (i = 0; i < NUM_MUTEX; i++) { status = acpi_ut_create_mutex (i); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); @@ -588,7 +588,7 @@ /* * Delete each predefined mutex object */ - for (i = 0; i < NUM_MTX; i++) { + for (i = 0; i < NUM_MUTEX; i++) { (void) acpi_ut_delete_mutex (i); } @@ -619,15 +619,15 @@ ACPI_FUNCTION_TRACE_U32 ("ut_create_mutex", mutex_id); - if (mutex_id > MAX_MTX) { + if (mutex_id > MAX_MUTEX) { return_ACPI_STATUS (AE_BAD_PARAMETER); } - if (!acpi_gbl_acpi_mutex_info[mutex_id].mutex) { + if (!acpi_gbl_mutex_info[mutex_id].mutex) { status = acpi_os_create_semaphore (1, 1, - &acpi_gbl_acpi_mutex_info[mutex_id].mutex); - acpi_gbl_acpi_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; - acpi_gbl_acpi_mutex_info[mutex_id].use_count = 0; + &acpi_gbl_mutex_info[mutex_id].mutex); + acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; + acpi_gbl_mutex_info[mutex_id].use_count = 0; } return_ACPI_STATUS (status); @@ -656,14 +656,14 @@ ACPI_FUNCTION_TRACE_U32 ("ut_delete_mutex", mutex_id); - if (mutex_id > MAX_MTX) { + if (mutex_id > MAX_MUTEX) { return_ACPI_STATUS (AE_BAD_PARAMETER); } - status = acpi_os_delete_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex); + status = acpi_os_delete_semaphore (acpi_gbl_mutex_info[mutex_id].mutex); - acpi_gbl_acpi_mutex_info[mutex_id].mutex = NULL; - acpi_gbl_acpi_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; + acpi_gbl_mutex_info[mutex_id].mutex = NULL; + acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; return_ACPI_STATUS (status); } @@ -693,7 +693,7 @@ ACPI_FUNCTION_NAME ("ut_acquire_mutex"); - if (mutex_id > MAX_MTX) { + if (mutex_id > MAX_MUTEX) { return (AE_BAD_PARAMETER); } @@ -705,8 +705,8 @@ * the mutex ordering rule. This indicates a coding error somewhere in * the ACPI subsystem code. */ - for (i = mutex_id; i < MAX_MTX; i++) { - if (acpi_gbl_acpi_mutex_info[i].owner_id == this_thread_id) { + for (i = mutex_id; i < MAX_MUTEX; i++) { + if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) { if (i == mutex_id) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Mutex [%s] already acquired by this thread [%X]\n", @@ -728,14 +728,14 @@ "Thread %X attempting to acquire Mutex [%s]\n", this_thread_id, acpi_ut_get_mutex_name (mutex_id))); - status = acpi_os_wait_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex, + status = acpi_os_wait_semaphore (acpi_gbl_mutex_info[mutex_id].mutex, 1, ACPI_WAIT_FOREVER); if (ACPI_SUCCESS (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X acquired Mutex [%s]\n", this_thread_id, acpi_ut_get_mutex_name (mutex_id))); - acpi_gbl_acpi_mutex_info[mutex_id].use_count++; - acpi_gbl_acpi_mutex_info[mutex_id].owner_id = this_thread_id; + acpi_gbl_mutex_info[mutex_id].use_count++; + acpi_gbl_mutex_info[mutex_id].owner_id = this_thread_id; } else { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Thread %X could not acquire Mutex [%s] %s\n", @@ -776,14 +776,14 @@ "Thread %X releasing Mutex [%s]\n", this_thread_id, acpi_ut_get_mutex_name (mutex_id))); - if (mutex_id > MAX_MTX) { + if (mutex_id > MAX_MUTEX) { return (AE_BAD_PARAMETER); } /* * Mutex must be acquired in order to release it! */ - if (acpi_gbl_acpi_mutex_info[mutex_id].owner_id == ACPI_MUTEX_NOT_ACQUIRED) { + if (acpi_gbl_mutex_info[mutex_id].owner_id == ACPI_MUTEX_NOT_ACQUIRED) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Mutex [%s] is not acquired, cannot release\n", acpi_ut_get_mutex_name (mutex_id))); @@ -797,8 +797,8 @@ * ordering rule. This indicates a coding error somewhere in * the ACPI subsystem code. */ - for (i = mutex_id; i < MAX_MTX; i++) { - if (acpi_gbl_acpi_mutex_info[i].owner_id == this_thread_id) { + for (i = mutex_id; i < MAX_MUTEX; i++) { + if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) { if (i == mutex_id) { continue; } @@ -813,9 +813,9 @@ /* Mark unlocked FIRST */ - acpi_gbl_acpi_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; + acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; - status = acpi_os_signal_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex, 1); + status = acpi_os_signal_semaphore (acpi_gbl_mutex_info[mutex_id].mutex, 1); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Thread %X could not release Mutex [%s] %s\n", diff -Nru a/drivers/acpi/utilities/utobject.c b/drivers/acpi/utilities/utobject.c --- a/drivers/acpi/utilities/utobject.c Sat May 24 12:48:27 2003 +++ b/drivers/acpi/utilities/utobject.c Sat May 24 12:48:27 2003 @@ -149,7 +149,7 @@ acpi_size buffer_size) { union acpi_operand_object *buffer_desc; - u8 *buffer; + u8 *buffer = NULL; ACPI_FUNCTION_TRACE_U32 ("ut_create_buffer_object", buffer_size); @@ -163,14 +163,18 @@ return_PTR (NULL); } - /* Allocate the actual buffer */ + /* Create an actual buffer only if size > 0 */ - buffer = ACPI_MEM_CALLOCATE (buffer_size); - if (!buffer) { - ACPI_REPORT_ERROR (("create_buffer: could not allocate size %X\n", - (u32) buffer_size)); - acpi_ut_remove_reference (buffer_desc); - return_PTR (NULL); + if (buffer_size > 0) { + /* Allocate the actual buffer */ + + buffer = ACPI_MEM_CALLOCATE (buffer_size); + if (!buffer) { + ACPI_REPORT_ERROR (("create_buffer: could not allocate size %X\n", + (u32) buffer_size)); + acpi_ut_remove_reference (buffer_desc); + return_PTR (NULL); + } } /* Complete buffer object initialization */ diff -Nru a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c --- a/drivers/acpi/utilities/utxface.c Sat May 24 12:48:20 2003 +++ b/drivers/acpi/utilities/utxface.c Sat May 24 12:48:20 2003 @@ -145,22 +145,8 @@ /* - * Install the default op_region handlers. These are installed unless - * other handlers have already been installed via the - * install_address_space_handler interface - */ - if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing default address space handlers\n")); - - status = acpi_ev_init_address_spaces (); - if (ACPI_FAILURE (status)) { - return_ACPI_STATUS (status); - } - } - - /* * We must initialize the hardware before we can enable ACPI. - * FADT values are validated here. + * The values from the FADT are validated here. */ if (!(flags & ACPI_NO_HARDWARE_INIT)) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI hardware\n")); @@ -172,7 +158,7 @@ } /* - * Enable ACPI on this platform + * Enable ACPI mode */ if (!(flags & ACPI_NO_ACPI_ENABLE)) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Going into ACPI mode\n")); @@ -187,8 +173,9 @@ } /* - * Note: - * We must have the hardware AND events initialized before we can execute + * Initialize ACPI Event handling + * + * NOTE: We must have the hardware AND events initialized before we can execute * ANY control methods SAFELY. Any control method can require ACPI hardware * support, so the hardware MUST be initialized before execution! */ @@ -201,7 +188,7 @@ } } - /* Install SCI handler, Global Lock handler, GPE handlers */ + /* Install the SCI handler, Global Lock handler, and GPE handlers */ if (!(flags & ACPI_NO_HANDLER_INIT)) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing SCI/GL/GPE handlers\n")); @@ -237,14 +224,20 @@ ACPI_FUNCTION_TRACE ("acpi_initialize_objects"); + /* - * Initialize all device objects in the namespace - * This runs the _STA and _INI methods. + * Install the default op_region handlers. These are installed unless + * other handlers have already been installed via the + * install_address_space_handler interface. + * + * NOTE: This will cause _REG methods to be run. Any objects accessed + * by the _REG methods will be automatically initialized, even if they + * contain executable AML (see call to acpi_ns_initialize_objects below). */ - if (!(flags & ACPI_NO_DEVICE_INIT)) { - ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI Devices\n")); + if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Installing default address space handlers\n")); - status = acpi_ns_initialize_devices (); + status = acpi_ev_init_address_spaces (); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } @@ -252,8 +245,8 @@ /* * Initialize the objects that remain uninitialized. This - * runs the executable AML that is part of the declaration of op_regions - * and Fields. + * runs the executable AML that may be part of the declaration of these + * objects: operation_regions, buffer_fields, Buffers, and Packages. */ if (!(flags & ACPI_NO_OBJECT_INIT)) { ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI Objects\n")); @@ -265,6 +258,19 @@ } /* + * Initialize all device objects in the namespace + * This runs the _STA and _INI methods. + */ + if (!(flags & ACPI_NO_DEVICE_INIT)) { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Initializing ACPI Devices\n")); + + status = acpi_ns_initialize_devices (); + if (ACPI_FAILURE (status)) { + return_ACPI_STATUS (status); + } + } + + /* * Empty the caches (delete the cached objects) on the assumption that * the table load filled them up more than they will be at runtime -- * thus wasting non-paged memory. @@ -431,9 +437,9 @@ /* Current status of the ACPI tables, per table type */ - info_ptr->num_table_types = NUM_ACPI_TABLES; - for (i = 0; i < NUM_ACPI_TABLES; i++) { - info_ptr->table_info[i].count = acpi_gbl_acpi_tables[i].count; + info_ptr->num_table_types = NUM_ACPI_TABLE_TYPES; + for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) { + info_ptr->table_info[i].count = acpi_gbl_table_lists[i].count; } return_ACPI_STATUS (AE_OK); diff -Nru a/drivers/atm/Kconfig b/drivers/atm/Kconfig --- a/drivers/atm/Kconfig Sat May 24 12:48:24 2003 +++ b/drivers/atm/Kconfig Sat May 24 12:48:24 2003 @@ -7,14 +7,14 @@ config ATM_TCP tristate "ATM over TCP" - depends on INET + depends on INET && ATM help ATM over TCP driver. Useful mainly for development and for experiments. If unsure, say N. config ATM_LANAI tristate "Efficient Networks Speedstream 3010" - depends on PCI + depends on PCI && ATM help Supports ATM cards based on the Efficient Networks "Lanai" chipset such as the Speedstream 3010 and the ENI-25p. The @@ -23,7 +23,7 @@ config ATM_ENI tristate "Efficient Networks ENI155P" - depends on PCI + depends on PCI && ATM ---help--- Driver for the Efficient Networks ENI155p series and SMC ATM Power155 155 Mbps ATM adapters. Both, the versions with 512KB and @@ -133,7 +133,7 @@ config ATM_FIRESTREAM tristate "Fujitsu FireStream (FS50/FS155) " - depends on PCI + depends on PCI && ATM help Driver for the Fujitsu FireStream 155 (MB86697) and FireStream 50 (MB86695) ATM PCI chips. @@ -145,7 +145,7 @@ config ATM_ZATM tristate "ZeitNet ZN1221/ZN1225" - depends on PCI + depends on PCI && ATM help Driver for the ZeitNet ZN1221 (MMF) and ZN1225 (UTP-5) 155 Mbps ATM adapters. @@ -182,7 +182,7 @@ # fi config ATM_NICSTAR tristate "IDT 77201 (NICStAR) (ForeRunnerLE)" - depends on PCI + depends on PCI && ATM help The NICStAR chipset family is used in a large number of ATM NICs for 25 and for 155 Mbps, including IDT cards and the Fore ForeRunnerLE @@ -217,7 +217,7 @@ config ATM_IDT77252 tristate "IDT 77252 (NICStAR II)" - depends on PCI + depends on PCI && ATM help Driver for the IDT 77252 ATM PCI chips. @@ -253,7 +253,7 @@ config ATM_AMBASSADOR tristate "Madge Ambassador (Collage PCI 155 Server)" - depends on PCI + 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) @@ -277,7 +277,7 @@ config ATM_HORIZON tristate "Madge Horizon [Ultra] (Collage PCI 25 and Collage PCI 155 Client)" - depends on PCI + depends on PCI && ATM help This is a driver for the Horizon chipset ATM adapter cards once produced by Madge Networks Ltd. Say Y (or M to compile as a module @@ -301,7 +301,7 @@ config ATM_IA tristate "Interphase ATM PCI x575/x525/x531" - depends on PCI + depends on PCI && ATM ---help--- This is a driver for the Interphase (i)ChipSAR adapter cards which include a variety of variants in term of the size of the @@ -334,7 +334,7 @@ config ATM_FORE200E_MAYBE tristate "FORE Systems 200E-series" - depends on PCI || SBUS + depends on (PCI || SBUS) && ATM ---help--- This is a driver for the FORE Systems 200E-series ATM adapter cards. It simultaneously supports PCA-200E and SBA-200E models @@ -439,6 +439,20 @@ depends on (PCI || SBUS) && (ATM_FORE200E_PCA || ATM_FORE200E_SBA) default m if ATM_FORE200E_MAYBE!=y default y if ATM_FORE200E_MAYBE=y + +config ATM_HE + tristate "ForeRunner HE Series" + depends on PCI && ATM + help + This is a driver for the Marconi ForeRunner HE-series ATM adapter + cards. It simultaneously supports the 155 and 622 versions. + +config ATM_HE_USE_SUNI + bool "Use S/UNI PHY driver" + depends on ATM_HE + help + Support for the S/UNI-Ultra and S/UNI-622 found in the ForeRunner + HE cards. This driver provides carrier detection some statistics. endmenu diff -Nru a/drivers/atm/Makefile b/drivers/atm/Makefile --- a/drivers/atm/Makefile Sat May 24 12:48:19 2003 +++ b/drivers/atm/Makefile Sat May 24 12:48:19 2003 @@ -49,6 +49,10 @@ CONFIG_ATM_FORE200E_SBA_FW := $(obj)/sba200e_ecd.bin2 endif endif +obj-$(CONFIG_ATM_HE) += he.o +ifeq ($(CONFIG_ATM_HE_USE_SUNI),y) + obj-$(CONFIG_ATM_HE) += suni.o +endif # FORE Systems 200E-series firmware magic $(obj)/fore200e_pca_fw.c: $(patsubst "%", %, $(CONFIG_ATM_FORE200E_PCA_FW)) \ diff -Nru a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c --- a/drivers/atm/ambassador.c Sat May 24 12:48:20 2003 +++ b/drivers/atm/ambassador.c Sat May 24 12:48:20 2003 @@ -290,12 +290,11 @@ /********** microcode **********/ #ifdef AMB_NEW_MICROCODE -#define UCODE(x) UCODE1(atmsar12.,x) +#define UCODE(x) UCODE2(atmsar12.x) #else -#define UCODE(x) UCODE1(atmsar11.,x) +#define UCODE(x) UCODE2(atmsar11.x) #endif #define UCODE2(x) #x -#define UCODE1(x,y) UCODE2(x ## y) static u32 __initdata ucode_start = #include UCODE(start) diff -Nru a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c --- a/drivers/atm/atmtcp.c Sat May 24 12:48:27 2003 +++ b/drivers/atm/atmtcp.c Sat May 24 12:48:27 2003 @@ -153,6 +153,7 @@ static int atmtcp_v_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg) { + unsigned long flags; struct atm_cirange ci; struct atm_vcc *vcc; @@ -162,9 +163,14 @@ if (ci.vci_bits == ATM_CI_MAX) ci.vci_bits = MAX_VCI_BITS; if (ci.vpi_bits > MAX_VPI_BITS || ci.vpi_bits < 0 || ci.vci_bits > MAX_VCI_BITS || ci.vci_bits < 0) return -EINVAL; + spin_lock_irqsave(&dev->lock, flags); for (vcc = dev->vccs; vcc; vcc = vcc->next) if ((vcc->vpi >> ci.vpi_bits) || - (vcc->vci >> ci.vci_bits)) return -EBUSY; + (vcc->vci >> ci.vci_bits)) { + spin_unlock_irqrestore(&dev->lock, flags); + return -EBUSY; + } + spin_unlock_irqrestore(&dev->lock, flags); dev->ci_range = ci; return 0; } @@ -227,6 +233,7 @@ static void atmtcp_c_close(struct atm_vcc *vcc) { + unsigned long flags; struct atm_dev *atmtcp_dev; struct atmtcp_dev_data *dev_data; struct atm_vcc *walk; @@ -239,13 +246,16 @@ kfree(dev_data); shutdown_atm_dev(atmtcp_dev); vcc->dev_data = NULL; + spin_lock_irqsave(&atmtcp_dev->lock, flags); for (walk = atmtcp_dev->vccs; walk; walk = walk->next) wake_up(&walk->sleep); + spin_unlock_irqrestore(&atmtcp_dev->lock, flags); } static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) { + unsigned long flags; struct atm_dev *dev; struct atmtcp_hdr *hdr; struct atm_vcc *out_vcc; @@ -260,11 +270,13 @@ (struct atmtcp_control *) skb->data); goto done; } + spin_lock_irqsave(&dev->lock, flags); for (out_vcc = dev->vccs; out_vcc; out_vcc = out_vcc->next) if (out_vcc->vpi == ntohs(hdr->vpi) && out_vcc->vci == ntohs(hdr->vci) && out_vcc->qos.rxtp.traffic_class != ATM_NONE) break; + spin_unlock_irqrestore(&dev->lock, flags); if (!out_vcc) { atomic_inc(&vcc->stats->tx_err); goto done; @@ -318,6 +330,7 @@ .ops = &atmtcp_c_dev_ops, .type = "atmtcp", .number = 999, + .lock = SPIN_LOCK_UNLOCKED }; @@ -350,9 +363,12 @@ struct atm_dev *dev; dev = NULL; - if (itf != -1) dev = atm_find_dev(itf); + if (itf != -1) dev = atm_dev_lookup(itf); if (dev) { - if (dev->ops != &atmtcp_v_dev_ops) return -EMEDIUMTYPE; + if (dev->ops != &atmtcp_v_dev_ops) { + atm_dev_release(dev); + return -EMEDIUMTYPE; + } if (PRIV(dev)->vcc) return -EBUSY; } else { @@ -383,14 +399,18 @@ struct atm_dev *dev; struct atmtcp_dev_data *dev_data; - dev = atm_find_dev(itf); + dev = atm_dev_lookup(itf); if (!dev) return -ENODEV; - if (dev->ops != &atmtcp_v_dev_ops) return -EMEDIUMTYPE; + if (dev->ops != &atmtcp_v_dev_ops) { + atm_dev_release(dev); + return -EMEDIUMTYPE; + } dev_data = PRIV(dev); if (!dev_data->persist) return 0; dev_data->persist = 0; if (PRIV(dev)->vcc) return 0; kfree(dev_data); + atm_dev_release(dev); shutdown_atm_dev(dev); return 0; } diff -Nru a/drivers/atm/eni.c b/drivers/atm/eni.c --- a/drivers/atm/eni.c Sat May 24 12:48:21 2003 +++ b/drivers/atm/eni.c Sat May 24 12:48:21 2003 @@ -1100,9 +1100,9 @@ dma_rd = eni_in(MID_DMA_RD_TX); dma_size = 3; /* JK for descriptor and final fill, plus final size mis-alignment fix */ -DPRINTK("iovcnt = %d\n",ATM_SKB(skb)->iovcnt); - if (!ATM_SKB(skb)->iovcnt) dma_size += 5; - else dma_size += 5*ATM_SKB(skb)->iovcnt; +DPRINTK("iovcnt = %d\n",skb_shinfo(skb)->nr_frags); + if (!skb_shinfo(skb)->nr_frags) dma_size += 5; + else dma_size += 5*(skb_shinfo(skb)->nr_frags+1); if (dma_size > TX_DMA_BUF) { printk(KERN_CRIT DEV_LABEL "(itf %d): needs %d DMA entries " "(got only %d)\n",vcc->dev->number,dma_size,TX_DMA_BUF); @@ -1123,15 +1123,20 @@ MID_DMA_COUNT_SHIFT) | (tx->index << MID_DMA_CHAN_SHIFT) | MID_DT_JK; j++; - if (!ATM_SKB(skb)->iovcnt) + if (!skb_shinfo(skb)->nr_frags) if (aal5) put_dma(tx->index,eni_dev->dma,&j,paddr,skb->len); else put_dma(tx->index,eni_dev->dma,&j,paddr+4,skb->len-4); else { DPRINTK("doing direct send\n"); /* @@@ well, this doesn't work anyway */ - for (i = 0; i < ATM_SKB(skb)->iovcnt; i++) - put_dma(tx->index,eni_dev->dma,&j,(unsigned long) - ((struct iovec *) skb->data)[i].iov_base, - ((struct iovec *) skb->data)[i].iov_len); + for (i = -1; i < skb_shinfo(skb)->nr_frags; i++) + if (i == -1) + put_dma(tx->index,eni_dev->dma,&j,(unsigned long) + skb->data, + skb->len - skb->data_len); + else + put_dma(tx->index,eni_dev->dma,&j,(unsigned long) + skb_shinfo(skb)->frags[i].page + skb_shinfo(skb)->frags[i].page_offset, + skb_shinfo(skb)->frags[i].size); } if (skb->len & 3) put_dma(tx->index,eni_dev->dma,&j,zeroes,4-(skb->len & 3)); @@ -1882,8 +1887,10 @@ static int get_ci(struct atm_vcc *vcc,short *vpi,int *vci) { + unsigned long flags; struct atm_vcc *walk; + spin_lock_irqsave(&vcc->dev->lock, flags); if (*vpi == ATM_VPI_ANY) *vpi = 0; if (*vci == ATM_VCI_ANY) { for (*vci = ATM_NOT_RSV_VCI; *vci < NR_VCI; (*vci)++) { @@ -1902,17 +1909,29 @@ } break; } + spin_unlock_irqrestore(&vcc->dev->lock, flags); return *vci == NR_VCI ? -EADDRINUSE : 0; } - if (*vci == ATM_VCI_UNSPEC) return 0; + if (*vci == ATM_VCI_UNSPEC) { + spin_unlock_irqrestore(&vcc->dev->lock, flags); + return 0; + } if (vcc->qos.rxtp.traffic_class != ATM_NONE && - ENI_DEV(vcc->dev)->rx_map[*vci]) + ENI_DEV(vcc->dev)->rx_map[*vci]) { + spin_unlock_irqrestore(&vcc->dev->lock, flags); return -EADDRINUSE; - if (vcc->qos.txtp.traffic_class == ATM_NONE) return 0; + } + if (vcc->qos.txtp.traffic_class == ATM_NONE) { + spin_unlock_irqrestore(&vcc->dev->lock, flags); + return 0; + } for (walk = vcc->dev->vccs; walk; walk = walk->next) if (test_bit(ATM_VF_ADDR,&walk->flags) && walk->vci == *vci && - walk->qos.txtp.traffic_class != ATM_NONE) + walk->qos.txtp.traffic_class != ATM_NONE) { + spin_unlock_irqrestore(&vcc->dev->lock, flags); return -EADDRINUSE; + } + spin_unlock_irqrestore(&vcc->dev->lock, flags); return 0; } @@ -2120,6 +2139,7 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page) { + unsigned long flags; static const char *signal[] = { "LOST","unknown","okay" }; struct eni_dev *eni_dev = ENI_DEV(dev); struct atm_vcc *vcc; @@ -2192,6 +2212,7 @@ return sprintf(page,"%10sbacklog %u packets\n","", skb_queue_len(&tx->backlog)); } + spin_lock_irqsave(&dev->lock, flags); for (vcc = dev->vccs; vcc; vcc = vcc->next) { struct eni_vcc *eni_vcc = ENI_VCC(vcc); int length; @@ -2210,8 +2231,10 @@ length += sprintf(page+length,"tx[%d], txing %d bytes", eni_vcc->tx->index,eni_vcc->txing); page[length] = '\n'; + spin_unlock_irqrestore(&dev->lock, flags); return length+1; } + spin_unlock_irqrestore(&dev->lock, flags); for (i = 0; i < eni_dev->free_len; i++) { struct eni_free *fe = eni_dev->free_list+i; unsigned long offset; diff -Nru a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c --- a/drivers/atm/fore200e.c Sat May 24 12:48:33 2003 +++ b/drivers/atm/fore200e.c Sat May 24 12:48:33 2003 @@ -1074,13 +1074,16 @@ static struct atm_vcc* fore200e_find_vcc(struct fore200e* fore200e, struct rpd* rpd) { + unsigned long flags; struct atm_vcc* vcc; + spin_lock_irqsave(&fore200e->atm_dev->lock, flags); for (vcc = fore200e->atm_dev->vccs; vcc; vcc = vcc->next) { if (vcc->vpi == rpd->atm_header.vpi && vcc->vci == rpd->atm_header.vci) break; } + spin_unlock_irqrestore(&fore200e->atm_dev->lock, flags); return vcc; } @@ -1352,9 +1355,13 @@ static int fore200e_walk_vccs(struct atm_vcc *vcc, short *vpi, int *vci) { + unsigned long flags; struct atm_vcc* walk; /* find a free VPI */ + + spin_lock_irqsave(&vcc->dev->lock, flags); + if (*vpi == ATM_VPI_ANY) { for (*vpi = 0, walk = vcc->dev->vccs; walk; walk = walk->next) { @@ -1378,6 +1385,8 @@ } } + spin_unlock_irqrestore(&vcc->dev->lock, flags); + return 0; } @@ -2638,6 +2647,7 @@ static int fore200e_proc_read(struct atm_dev *dev,loff_t* pos,char* page) { + unsigned long flags; struct fore200e* fore200e = FORE200E_DEV(dev); int len, left = *pos; @@ -2884,6 +2894,7 @@ len = sprintf(page,"\n" " VCCs:\n address\tVPI.VCI:AAL\t(min/max tx PDU size) (min/max rx PDU size)\n"); + spin_lock_irqsave(&fore200e->atm_dev->lock, flags); for (vcc = fore200e->atm_dev->vccs; vcc; vcc = vcc->next) { fore200e_vcc = FORE200E_VCC(vcc); @@ -2898,6 +2909,7 @@ fore200e_vcc->rx_max_pdu ); } + spin_unlock_irqrestore(&fore200e->atm_dev->lock, flags); return len; } diff -Nru a/drivers/atm/he.c b/drivers/atm/he.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/atm/he.c Sat May 24 12:48:34 2003 @@ -0,0 +1,3266 @@ +/* $Id: he.c,v 1.18 2003/05/06 22:57:15 chas Exp $ */ + +/* + + he.c + + ForeRunnerHE ATM Adapter driver for ATM on Linux + Copyright (C) 1999-2001 Naval Research Laboratory + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/* + + he.c + + ForeRunnerHE ATM Adapter driver for ATM on Linux + Copyright (C) 1999-2001 Naval Research Laboratory + + Permission to use, copy, modify and distribute this software and its + documentation is hereby granted, provided that both the copyright + notice and this permission notice appear in all copies of the software, + derivative works or modified versions, and any portions thereof, and + that both notices appear in supporting documentation. + + NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND + DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER + RESULTING FROM THE USE OF THIS SOFTWARE. + + This driver was written using the "Programmer's Reference Manual for + ForeRunnerHE(tm)", MANU0361-01 - Rev. A, 08/21/98. + + AUTHORS: + chas williams + eric kinzie + + NOTES: + 4096 supported 'connections' + group 0 is used for all traffic + interrupt queue 0 is used for all interrupts + aal0 support (based on work from ulrich.u.muller@nokia.com) + + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#ifndef ATM_OC12_PCR +#define ATM_OC12_PCR (622080000/1080*1040/8/53) +#endif + +#ifdef BUS_INT_WAR +void sn_add_polled_interrupt(int irq, int interval); +void sn_delete_polled_interrupt(int irq); +#endif + +#define USE_TASKLET +#define USE_HE_FIND_VCC +#undef USE_SCATTERGATHER +#undef USE_CHECKSUM_HW /* still confused about this */ +#define USE_RBPS +#undef USE_RBPS_POOL /* if memory is tight try this */ +#undef USE_RBPL_POOL /* if memory is tight try this */ +#define USE_TPD_POOL +/* #undef CONFIG_ATM_HE_USE_SUNI */ + +/* compatibility */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,69) +typedef void irqreturn_t; +#define IRQ_NONE +#define IRQ_HANDLED +#define IRQ_RETVAL(x) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,9) +#define __devexit_p(func) func +#endif + +#ifndef MODULE_LICENSE +#define MODULE_LICENSE(x) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,3) +#define pci_set_drvdata(pci_dev, data) (pci_dev)->driver_data = (data) +#define pci_get_drvdata(pci_dev) (pci_dev)->driver_data +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,44) +#define pci_pool_create(a, b, c, d, e) pci_pool_create(a, b, c, d, e, SLAB_KERNEL) +#endif + +#include "he.h" + +#include "suni.h" + +#include + +#define hprintk(fmt,args...) printk(KERN_ERR DEV_LABEL "%d: " fmt, he_dev->number , ##args) + +#undef DEBUG +#ifdef DEBUG +#define HPRINTK(fmt,args...) hprintk(fmt,args) +#else +#define HPRINTK(fmt,args...) do { } while(0) +#endif /* DEBUG */ + + +/* version definition */ + +static char *version = "$Id: he.c,v 1.18 2003/05/06 22:57:15 chas Exp $"; + +/* declarations */ + +static int he_open(struct atm_vcc *vcc, short vpi, int vci); +static void he_close(struct atm_vcc *vcc); +static int he_send(struct atm_vcc *vcc, struct sk_buff *skb); +static int he_sg_send(struct atm_vcc *vcc, unsigned long start, unsigned long size); +static int he_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg); +static irqreturn_t he_irq_handler(int irq, void *dev_id, struct pt_regs *regs); +static void he_tasklet(unsigned long data); +static int he_proc_read(struct atm_dev *dev,loff_t *pos,char *page); +static int he_start(struct atm_dev *dev); +static void he_stop(struct he_dev *dev); +static void he_phy_put(struct atm_dev *, unsigned char, unsigned long); +static unsigned char he_phy_get(struct atm_dev *, unsigned long); + +static u8 read_prom_byte(struct he_dev *he_dev, int addr); + +/* globals */ + +struct he_dev *he_devs = NULL; +static short disable64 = -1; +static short nvpibits = -1; +static short nvcibits = -1; +static short rx_skb_reserve = 16; +static short irq_coalesce = 1; +static short sdh = 1; + +static struct atmdev_ops he_ops = +{ + open: he_open, + close: he_close, + ioctl: he_ioctl, + send: he_send, + sg_send: he_sg_send, + phy_put: he_phy_put, + phy_get: he_phy_get, + proc_read: he_proc_read, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,1) + owner: THIS_MODULE +#endif +}; + +/* see the comments in he.h about global_lock */ + +#define HE_SPIN_LOCK(dev, flags) spin_lock_irqsave(&(dev)->global_lock, flags) +#define HE_SPIN_UNLOCK(dev, flags) spin_unlock_irqrestore(&(dev)->global_lock, flags) + +#define he_writel(dev, val, reg) do { writel(val, (dev)->membase + (reg)); wmb(); } while(0) +#define he_readl(dev, reg) readl((dev)->membase + (reg)) + +/* section 2.12 connection memory access */ + +static __inline__ void +he_writel_internal(struct he_dev *he_dev, unsigned val, unsigned addr, + unsigned flags) +{ + he_writel(he_dev, val, CON_DAT); +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl(he_dev, CON_DAT); +#endif + he_writel(he_dev, flags | CON_CTL_WRITE | CON_CTL_ADDR(addr), CON_CTL); + while(he_readl(he_dev, CON_CTL) & CON_CTL_BUSY); +} + +#define he_writel_rcm(dev, val, reg) \ + he_writel_internal(dev, val, reg, CON_CTL_RCM) + +#define he_writel_tcm(dev, val, reg) \ + he_writel_internal(dev, val, reg, CON_CTL_TCM) + +#define he_writel_mbox(dev, val, reg) \ + he_writel_internal(dev, val, reg, CON_CTL_MBOX) + +static unsigned +he_readl_internal(struct he_dev *he_dev, unsigned addr, unsigned flags) +{ + he_writel(he_dev, flags | CON_CTL_READ | CON_CTL_ADDR(addr), CON_CTL); + while(he_readl(he_dev, CON_CTL) & CON_CTL_BUSY); + return he_readl(he_dev, CON_DAT); +} + +#define he_readl_rcm(dev, reg) \ + he_readl_internal(dev, reg, CON_CTL_RCM) + +#define he_readl_tcm(dev, reg) \ + he_readl_internal(dev, reg, CON_CTL_TCM) + +#define he_readl_mbox(dev, reg) \ + he_readl_internal(dev, reg, CON_CTL_MBOX) + + +/* figure 2.2 connection id */ + +#define he_mkcid(dev, vpi, vci) (((vpi<<(dev)->vcibits) | vci) & 0x1fff) + +/* 2.5.1 per connection transmit state registers */ + +#define he_writel_tsr0(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 0) +#define he_readl_tsr0(dev, cid) \ + he_readl_tcm(dev, CONFIG_TSRA | (cid<<3) | 0) + +#define he_writel_tsr1(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 1) + +#define he_writel_tsr2(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 2) + +#define he_writel_tsr3(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 3) + +#define he_writel_tsr4(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 4) + + /* from page 2-20 + * + * NOTE While the transmit connection is active, bits 23 through 0 + * of this register must not be written by the host. Byte + * enables should be used during normal operation when writing + * the most significant byte. + */ + +#define he_writel_tsr4_upper(dev, val, cid) \ + he_writel_internal(dev, val, CONFIG_TSRA | (cid<<3) | 4, \ + CON_CTL_TCM \ + | CON_BYTE_DISABLE_2 \ + | CON_BYTE_DISABLE_1 \ + | CON_BYTE_DISABLE_0) + +#define he_readl_tsr4(dev, cid) \ + he_readl_tcm(dev, CONFIG_TSRA | (cid<<3) | 4) + +#define he_writel_tsr5(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 5) + +#define he_writel_tsr6(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 6) + +#define he_writel_tsr7(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRA | (cid<<3) | 7) + + +#define he_writel_tsr8(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<2) | 0) + +#define he_writel_tsr9(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<2) | 1) + +#define he_writel_tsr10(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<2) | 2) + +#define he_writel_tsr11(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRB | (cid<<2) | 3) + + +#define he_writel_tsr12(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRC | (cid<<1) | 0) + +#define he_writel_tsr13(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRC | (cid<<1) | 1) + + +#define he_writel_tsr14(dev, val, cid) \ + he_writel_tcm(dev, val, CONFIG_TSRD | cid) + +#define he_writel_tsr14_upper(dev, val, cid) \ + he_writel_internal(dev, val, CONFIG_TSRD | cid, \ + CON_CTL_TCM \ + | CON_BYTE_DISABLE_2 \ + | CON_BYTE_DISABLE_1 \ + | CON_BYTE_DISABLE_0) + +/* 2.7.1 per connection receive state registers */ + +#define he_writel_rsr0(dev, val, cid) \ + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 0) +#define he_readl_rsr0(dev, cid) \ + he_readl_rcm(dev, 0x00000 | (cid<<3) | 0) + +#define he_writel_rsr1(dev, val, cid) \ + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 1) + +#define he_writel_rsr2(dev, val, cid) \ + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 2) + +#define he_writel_rsr3(dev, val, cid) \ + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 3) + +#define he_writel_rsr4(dev, val, cid) \ + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 4) + +#define he_writel_rsr5(dev, val, cid) \ + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 5) + +#define he_writel_rsr6(dev, val, cid) \ + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 6) + +#define he_writel_rsr7(dev, val, cid) \ + he_writel_rcm(dev, val, 0x00000 | (cid<<3) | 7) + +static __inline__ struct atm_vcc* +he_find_vcc(struct he_dev *he_dev, unsigned cid) +{ + unsigned long flags; + struct atm_vcc *vcc; + short vpi; + int vci; + + vpi = cid >> he_dev->vcibits; + vci = cid & ((1<vcibits)-1); + + spin_lock_irqsave(&he_dev->atm_dev->lock, flags); + for (vcc = he_dev->atm_dev->vccs; vcc; vcc = vcc->next) + if (vcc->vci == vci && vcc->vpi == vpi + && vcc->qos.rxtp.traffic_class != ATM_NONE) { + spin_unlock_irqrestore(&he_dev->atm_dev->lock, flags); + return vcc; + } + + spin_unlock_irqrestore(&he_dev->atm_dev->lock, flags); + return NULL; +} + +static int __devinit +he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) +{ + struct atm_dev *atm_dev = NULL; + struct he_dev *he_dev = NULL; + int err = 0; + + printk(KERN_INFO "he: %s\n", version); + + if (pci_enable_device(pci_dev)) return -EIO; + if (pci_set_dma_mask(pci_dev, HE_DMA_MASK) != 0) { + printk(KERN_WARNING "he: no suitable dma available\n"); + err = -EIO; + goto init_one_failure; + } + + atm_dev = atm_dev_register(DEV_LABEL, &he_ops, -1, 0); + if (!atm_dev) { + err = -ENODEV; + goto init_one_failure; + } + pci_set_drvdata(pci_dev, atm_dev); + + he_dev = (struct he_dev *) kmalloc(sizeof(struct he_dev), + GFP_KERNEL); + if (!he_dev) { + err = -ENOMEM; + goto init_one_failure; + } + memset(he_dev, 0, sizeof(struct he_dev)); + + he_dev->pci_dev = pci_dev; + he_dev->atm_dev = atm_dev; + he_dev->atm_dev->dev_data = he_dev; + HE_DEV(atm_dev) = he_dev; + he_dev->number = atm_dev->number; + if (he_start(atm_dev)) { + he_stop(he_dev); + err = -ENODEV; + goto init_one_failure; + } + he_dev->next = NULL; + if (he_devs) he_dev->next = he_devs; + he_devs = he_dev; + return 0; + +init_one_failure: + if (atm_dev) + atm_dev_deregister(atm_dev); + if (he_dev) + kfree(he_dev); + pci_disable_device(pci_dev); + return err; +} + +static void __devexit +he_remove_one (struct pci_dev *pci_dev) +{ + struct atm_dev *atm_dev; + struct he_dev *he_dev; + + atm_dev = pci_get_drvdata(pci_dev); + he_dev = HE_DEV(atm_dev); + + /* need to remove from he_devs */ + + he_stop(he_dev); + atm_dev_deregister(atm_dev); + kfree(he_dev); + + pci_set_drvdata(pci_dev, NULL); + pci_disable_device(pci_dev); +} + + +static unsigned +rate_to_atmf(unsigned rate) /* cps to atm forum format */ +{ +#define NONZERO (1<<14) + + unsigned exp = 0; + + if (rate == 0) return(0); + + rate <<= 9; + while (rate > 0x3ff) + { + ++exp; + rate >>= 1; + } + + return (NONZERO | (exp << 9) | (rate & 0x1ff)); +} + +static void __init +he_init_rx_lbfp0(struct he_dev *he_dev) +{ + unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count; + unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf; + unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD; + unsigned row_offset = he_dev->r0_startrow * he_dev->bytes_per_row; + + lbufd_index = 0; + lbm_offset = he_readl(he_dev, RCMLBM_BA); + + he_writel(he_dev, lbufd_index, RLBF0_H); + + for (i = 0, lbuf_count = 0; i < he_dev->r0_numbuffs; ++i) + { + lbufd_index += 2; + lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32; + + he_writel_rcm(he_dev, lbuf_addr, lbm_offset); + he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1); + + if (++lbuf_count == lbufs_per_row) + { + lbuf_count = 0; + row_offset += he_dev->bytes_per_row; + } + lbm_offset += 4; + } + + he_writel(he_dev, lbufd_index - 2, RLBF0_T); + he_writel(he_dev, he_dev->r0_numbuffs, RLBF0_C); +} + +static void __init +he_init_rx_lbfp1(struct he_dev *he_dev) +{ + unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count; + unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf; + unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD; + unsigned row_offset = he_dev->r1_startrow * he_dev->bytes_per_row; + + lbufd_index = 1; + lbm_offset = he_readl(he_dev, RCMLBM_BA) + (2 * lbufd_index); + + he_writel(he_dev, lbufd_index, RLBF1_H); + + for (i = 0, lbuf_count = 0; i < he_dev->r1_numbuffs; ++i) + { + lbufd_index += 2; + lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32; + + he_writel_rcm(he_dev, lbuf_addr, lbm_offset); + he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1); + + if (++lbuf_count == lbufs_per_row) + { + lbuf_count = 0; + row_offset += he_dev->bytes_per_row; + } + lbm_offset += 4; + } + + he_writel(he_dev, lbufd_index - 2, RLBF1_T); + he_writel(he_dev, he_dev->r1_numbuffs, RLBF1_C); +} + +static void __init +he_init_tx_lbfp(struct he_dev *he_dev) +{ + unsigned i, lbm_offset, lbufd_index, lbuf_addr, lbuf_count; + unsigned lbufs_per_row = he_dev->cells_per_row / he_dev->cells_per_lbuf; + unsigned lbuf_bufsize = he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD; + unsigned row_offset = he_dev->tx_startrow * he_dev->bytes_per_row; + + lbufd_index = he_dev->r0_numbuffs + he_dev->r1_numbuffs; + lbm_offset = he_readl(he_dev, RCMLBM_BA) + (2 * lbufd_index); + + he_writel(he_dev, lbufd_index, TLBF_H); + + for (i = 0, lbuf_count = 0; i < he_dev->tx_numbuffs; ++i) + { + lbufd_index += 1; + lbuf_addr = (row_offset + (lbuf_count * lbuf_bufsize)) / 32; + + he_writel_rcm(he_dev, lbuf_addr, lbm_offset); + he_writel_rcm(he_dev, lbufd_index, lbm_offset + 1); + + if (++lbuf_count == lbufs_per_row) + { + lbuf_count = 0; + row_offset += he_dev->bytes_per_row; + } + lbm_offset += 2; + } + + he_writel(he_dev, lbufd_index - 1, TLBF_T); +} + +static int __init +he_init_tpdrq(struct he_dev *he_dev) +{ + he_dev->tpdrq_base = pci_alloc_consistent(he_dev->pci_dev, + CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq), &he_dev->tpdrq_phys); + if (he_dev->tpdrq_base == NULL) + { + hprintk("failed to alloc tpdrq\n"); + return -ENOMEM; + } + memset(he_dev->tpdrq_base, 0, + CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq)); + + he_dev->tpdrq_tail = he_dev->tpdrq_base; + he_dev->tpdrq_head = he_dev->tpdrq_base; + + he_writel(he_dev, he_dev->tpdrq_phys, TPDRQ_B_H); + he_writel(he_dev, 0, TPDRQ_T); + he_writel(he_dev, CONFIG_TPDRQ_SIZE - 1, TPDRQ_S); + + return 0; +} + +static void __init +he_init_cs_block(struct he_dev *he_dev) +{ + unsigned clock, rate, delta; + int reg; + + /* 5.1.7 cs block initialization */ + + for(reg = 0; reg < 0x20; ++reg) + he_writel_mbox(he_dev, 0x0, CS_STTIM0 + reg); + + /* rate grid timer reload values */ + + clock = he_is622(he_dev) ? 66667000 : 50000000; + rate = he_dev->atm_dev->link_rate; + delta = rate / 16 / 2; + + for(reg = 0; reg < 0x10; ++reg) + { + /* 2.4 internal transmit function + * + * we initialize the first row in the rate grid. + * values are period (in clock cycles) of timer + */ + unsigned period = clock / rate; + + he_writel_mbox(he_dev, period, CS_TGRLD0 + reg); + rate -= delta; + } + + if (he_is622(he_dev)) + { + /* table 5.2 (4 cells per lbuf) */ + he_writel_mbox(he_dev, 0x000800fa, CS_ERTHR0); + he_writel_mbox(he_dev, 0x000c33cb, CS_ERTHR1); + he_writel_mbox(he_dev, 0x0010101b, CS_ERTHR2); + he_writel_mbox(he_dev, 0x00181dac, CS_ERTHR3); + he_writel_mbox(he_dev, 0x00280600, CS_ERTHR4); + + /* table 5.3, 5.4, 5.5, 5.6, 5.7 */ + he_writel_mbox(he_dev, 0x023de8b3, CS_ERCTL0); + he_writel_mbox(he_dev, 0x1801, CS_ERCTL1); + he_writel_mbox(he_dev, 0x68b3, CS_ERCTL2); + he_writel_mbox(he_dev, 0x1280, CS_ERSTAT0); + he_writel_mbox(he_dev, 0x68b3, CS_ERSTAT1); + he_writel_mbox(he_dev, 0x14585, CS_RTFWR); + + he_writel_mbox(he_dev, 0x4680, CS_RTATR); + + /* table 5.8 */ + he_writel_mbox(he_dev, 0x00159ece, CS_TFBSET); + he_writel_mbox(he_dev, 0x68b3, CS_WCRMAX); + he_writel_mbox(he_dev, 0x5eb3, CS_WCRMIN); + he_writel_mbox(he_dev, 0xe8b3, CS_WCRINC); + he_writel_mbox(he_dev, 0xdeb3, CS_WCRDEC); + he_writel_mbox(he_dev, 0x68b3, CS_WCRCEIL); + + /* table 5.9 */ + he_writel_mbox(he_dev, 0x5, CS_OTPPER); + he_writel_mbox(he_dev, 0x14, CS_OTWPER); + } + else + { + /* table 5.1 (4 cells per lbuf) */ + he_writel_mbox(he_dev, 0x000400ea, CS_ERTHR0); + he_writel_mbox(he_dev, 0x00063388, CS_ERTHR1); + he_writel_mbox(he_dev, 0x00081018, CS_ERTHR2); + he_writel_mbox(he_dev, 0x000c1dac, CS_ERTHR3); + he_writel_mbox(he_dev, 0x0014051a, CS_ERTHR4); + + /* table 5.3, 5.4, 5.5, 5.6, 5.7 */ + he_writel_mbox(he_dev, 0x0235e4b1, CS_ERCTL0); + he_writel_mbox(he_dev, 0x4701, CS_ERCTL1); + he_writel_mbox(he_dev, 0x64b1, CS_ERCTL2); + he_writel_mbox(he_dev, 0x1280, CS_ERSTAT0); + he_writel_mbox(he_dev, 0x64b1, CS_ERSTAT1); + he_writel_mbox(he_dev, 0xf424, CS_RTFWR); + + he_writel_mbox(he_dev, 0x4680, CS_RTATR); + + /* table 5.8 */ + he_writel_mbox(he_dev, 0x000563b7, CS_TFBSET); + he_writel_mbox(he_dev, 0x64b1, CS_WCRMAX); + he_writel_mbox(he_dev, 0x5ab1, CS_WCRMIN); + he_writel_mbox(he_dev, 0xe4b1, CS_WCRINC); + he_writel_mbox(he_dev, 0xdab1, CS_WCRDEC); + he_writel_mbox(he_dev, 0x64b1, CS_WCRCEIL); + + /* table 5.9 */ + he_writel_mbox(he_dev, 0x6, CS_OTPPER); + he_writel_mbox(he_dev, 0x1e, CS_OTWPER); + + } + + he_writel_mbox(he_dev, 0x8, CS_OTTLIM); + + for(reg = 0; reg < 0x8; ++reg) + he_writel_mbox(he_dev, 0x0, CS_HGRRT0 + reg); + +} + +static void __init +he_init_cs_block_rcm(struct he_dev *he_dev) +{ + unsigned rategrid[16][16]; + unsigned rate, delta; + int i, j, reg; + + unsigned rate_atmf, exp, man; + unsigned long long rate_cps; + int mult, buf, buf_limit = 4; + + /* initialize rate grid group table */ + + for (reg = 0x0; reg < 0xff; ++reg) + he_writel_rcm(he_dev, 0x0, CONFIG_RCMABR + reg); + + /* initialize rate controller groups */ + + for (reg = 0x100; reg < 0x1ff; ++reg) + he_writel_rcm(he_dev, 0x0, CONFIG_RCMABR + reg); + + /* initialize tNrm lookup table */ + + /* the manual makes reference to a routine in a sample driver + for proper configuration; fortunately, we only need this + in order to support abr connection */ + + /* initialize rate to group table */ + + rate = he_dev->atm_dev->link_rate; + delta = rate / 32; + + /* + * 2.4 transmit internal functions + * + * we construct a copy of the rate grid used by the scheduler + * in order to construct the rate to group table below + */ + + for (j = 0; j < 16; j++) + { + rategrid[0][j] = rate; + rate -= delta; + } + + for (i = 1; i < 16; i++) + for (j = 0; j < 16; j++) + if (i > 14) + rategrid[i][j] = rategrid[i - 1][j] / 4; + else + rategrid[i][j] = rategrid[i - 1][j] / 2; + + /* + * 2.4 transmit internal function + * + * this table maps the upper 5 bits of exponent and mantissa + * of the atm forum representation of the rate into an index + * on rate grid + */ + + rate_atmf = 0; + while (rate_atmf < 0x400) + { + man = (rate_atmf & 0x1f) << 4; + exp = rate_atmf >> 5; + + /* + instead of '/ 512', use '>> 9' to prevent a call + to divdu3 on x86 platforms + */ + rate_cps = (unsigned long long) (1 << exp) * (man + 512) >> 9; + + if (rate_cps < 10) rate_cps = 10; + /* 2.2.1 minimum payload rate is 10 cps */ + + for (i = 255; i > 0; i--) + if (rategrid[i/16][i%16] >= rate_cps) break; + /* pick nearest rate instead? */ + + /* + * each table entry is 16 bits: (rate grid index (8 bits) + * and a buffer limit (8 bits) + * there are two table entries in each 32-bit register + */ + +#ifdef notdef + buf = rate_cps * he_dev->tx_numbuffs / + (he_dev->atm_dev->link_rate * 2); +#else + /* this is pretty, but avoids _divdu3 and is mostly correct */ + buf = 0; + mult = he_dev->atm_dev->link_rate / ATM_OC3_PCR; + if (rate_cps > (68 * mult)) buf = 1; + if (rate_cps > (136 * mult)) buf = 2; + if (rate_cps > (204 * mult)) buf = 3; + if (rate_cps > (272 * mult)) buf = 4; +#endif + if (buf > buf_limit) buf = buf_limit; + reg = (reg<<16) | ((i<<8) | buf); + +#define RTGTBL_OFFSET 0x400 + + if (rate_atmf & 0x1) + he_writel_rcm(he_dev, reg, + CONFIG_RCMABR + RTGTBL_OFFSET + (rate_atmf>>1)); + + ++rate_atmf; + } +} + +static int __init +he_init_group(struct he_dev *he_dev, int group) +{ + int i; + +#ifdef USE_RBPS + /* small buffer pool */ +#ifdef USE_RBPS_POOL + he_dev->rbps_pool = pci_pool_create("rbps", he_dev->pci_dev, + CONFIG_RBPS_BUFSIZE, 8, 0); + if (he_dev->rbps_pool == NULL) + { + hprintk("unable to create rbps pages\n"); + return -ENOMEM; + } +#else /* !USE_RBPS_POOL */ + he_dev->rbps_pages = pci_alloc_consistent(he_dev->pci_dev, + CONFIG_RBPS_SIZE * CONFIG_RBPS_BUFSIZE, &he_dev->rbps_pages_phys); + if (he_dev->rbps_pages == NULL) { + hprintk("unable to create rbps page pool\n"); + return -ENOMEM; + } +#endif /* USE_RBPS_POOL */ + + he_dev->rbps_base = pci_alloc_consistent(he_dev->pci_dev, + CONFIG_RBPS_SIZE * sizeof(struct he_rbp), &he_dev->rbps_phys); + if (he_dev->rbps_base == NULL) + { + hprintk("failed to alloc rbps\n"); + return -ENOMEM; + } + memset(he_dev->rbps_base, 0, CONFIG_RBPS_SIZE * sizeof(struct he_rbp)); + he_dev->rbps_virt = kmalloc(CONFIG_RBPS_SIZE * sizeof(struct he_virt), GFP_KERNEL); + + for (i = 0; i < CONFIG_RBPS_SIZE; ++i) + { + dma_addr_t dma_handle; + void *cpuaddr; + +#ifdef USE_RBPS_POOL + cpuaddr = pci_pool_alloc(he_dev->rbps_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle); + if (cpuaddr == NULL) + return -ENOMEM; +#else + cpuaddr = he_dev->rbps_pages + (i * CONFIG_RBPS_BUFSIZE); + dma_handle = he_dev->rbps_pages_phys + (i * CONFIG_RBPS_BUFSIZE); +#endif + + he_dev->rbps_virt[i].virt = cpuaddr; + he_dev->rbps_base[i].status = RBP_LOANED | RBP_SMALLBUF | (i << RBP_INDEX_OFF); + he_dev->rbps_base[i].phys = dma_handle; + + } + he_dev->rbps_tail = &he_dev->rbps_base[CONFIG_RBPS_SIZE-1]; + + he_writel(he_dev, he_dev->rbps_phys, G0_RBPS_S + (group * 32)); + he_writel(he_dev, RBPS_MASK(he_dev->rbps_tail), + G0_RBPS_T + (group * 32)); + he_writel(he_dev, CONFIG_RBPS_BUFSIZE/4, + G0_RBPS_BS + (group * 32)); + he_writel(he_dev, + RBP_THRESH(CONFIG_RBPS_THRESH) | + RBP_QSIZE(CONFIG_RBPS_SIZE-1) | + RBP_INT_ENB, + G0_RBPS_QI + (group * 32)); +#else /* !USE_RBPS */ + he_writel(he_dev, 0x0, G0_RBPS_S + (group * 32)); + he_writel(he_dev, 0x0, G0_RBPS_T + (group * 32)); + he_writel(he_dev, 0x0, G0_RBPS_QI + (group * 32)); + he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0), + G0_RBPS_BS + (group * 32)); +#endif /* USE_RBPS */ + + /* large buffer pool */ +#ifdef USE_RBPL_POOL + he_dev->rbpl_pool = pci_pool_create("rbpl", he_dev->pci_dev, + CONFIG_RBPL_BUFSIZE, 8, 0); + if (he_dev->rbpl_pool == NULL) + { + hprintk("unable to create rbpl pool\n"); + return -ENOMEM; + } +#else /* !USE_RBPL_POOL */ + he_dev->rbpl_pages = (void *) pci_alloc_consistent(he_dev->pci_dev, + CONFIG_RBPL_SIZE * CONFIG_RBPL_BUFSIZE, &he_dev->rbpl_pages_phys); + if (he_dev->rbpl_pages == NULL) + { + hprintk("unable to create rbpl pages\n"); + return -ENOMEM; + } +#endif /* USE_RBPL_POOL */ + + he_dev->rbpl_base = pci_alloc_consistent(he_dev->pci_dev, + CONFIG_RBPL_SIZE * sizeof(struct he_rbp), &he_dev->rbpl_phys); + if (he_dev->rbpl_base == NULL) + { + hprintk("failed to alloc rbpl\n"); + return -ENOMEM; + } + memset(he_dev->rbpl_base, 0, CONFIG_RBPL_SIZE * sizeof(struct he_rbp)); + he_dev->rbpl_virt = kmalloc(CONFIG_RBPL_SIZE * sizeof(struct he_virt), GFP_KERNEL); + + for (i = 0; i < CONFIG_RBPL_SIZE; ++i) + { + dma_addr_t dma_handle; + void *cpuaddr; + +#ifdef USE_RBPL_POOL + cpuaddr = pci_pool_alloc(he_dev->rbpl_pool, SLAB_KERNEL|SLAB_DMA, &dma_handle); + if (cpuaddr == NULL) + return -ENOMEM; +#else + cpuaddr = he_dev->rbpl_pages + (i * CONFIG_RBPL_BUFSIZE); + dma_handle = he_dev->rbpl_pages_phys + (i * CONFIG_RBPL_BUFSIZE); +#endif + + he_dev->rbpl_virt[i].virt = cpuaddr; + he_dev->rbpl_base[i].status = RBP_LOANED | (i << RBP_INDEX_OFF); + he_dev->rbpl_base[i].phys = dma_handle; + + } + he_dev->rbpl_tail = &he_dev->rbpl_base[CONFIG_RBPL_SIZE-1]; + + he_writel(he_dev, he_dev->rbpl_phys, G0_RBPL_S + (group * 32)); + he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail), + G0_RBPL_T + (group * 32)); + he_writel(he_dev, CONFIG_RBPL_BUFSIZE/4, + G0_RBPL_BS + (group * 32)); + he_writel(he_dev, + RBP_THRESH(CONFIG_RBPL_THRESH) | + RBP_QSIZE(CONFIG_RBPL_SIZE-1) | + RBP_INT_ENB, + G0_RBPL_QI + (group * 32)); + + /* rx buffer ready queue */ + + he_dev->rbrq_base = pci_alloc_consistent(he_dev->pci_dev, + CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), &he_dev->rbrq_phys); + if (he_dev->rbrq_base == NULL) + { + hprintk("failed to allocate rbrq\n"); + return -ENOMEM; + } + memset(he_dev->rbrq_base, 0, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq)); + + he_dev->rbrq_head = he_dev->rbrq_base; + he_writel(he_dev, he_dev->rbrq_phys, G0_RBRQ_ST + (group * 16)); + he_writel(he_dev, 0, G0_RBRQ_H + (group * 16)); + he_writel(he_dev, + RBRQ_THRESH(CONFIG_RBRQ_THRESH) | RBRQ_SIZE(CONFIG_RBRQ_SIZE-1), + G0_RBRQ_Q + (group * 16)); + if (irq_coalesce) + { + hprintk("coalescing interrupts\n"); + he_writel(he_dev, RBRQ_TIME(768) | RBRQ_COUNT(7), + G0_RBRQ_I + (group * 16)); + } + else + he_writel(he_dev, RBRQ_TIME(0) | RBRQ_COUNT(1), + G0_RBRQ_I + (group * 16)); + + /* tx buffer ready queue */ + + he_dev->tbrq_base = pci_alloc_consistent(he_dev->pci_dev, + CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), &he_dev->tbrq_phys); + if (he_dev->tbrq_base == NULL) + { + hprintk("failed to allocate tbrq\n"); + return -ENOMEM; + } + memset(he_dev->tbrq_base, 0, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq)); + + he_dev->tbrq_head = he_dev->tbrq_base; + + he_writel(he_dev, he_dev->tbrq_phys, G0_TBRQ_B_T + (group * 16)); + he_writel(he_dev, 0, G0_TBRQ_H + (group * 16)); + he_writel(he_dev, CONFIG_TBRQ_SIZE - 1, G0_TBRQ_S + (group * 16)); + he_writel(he_dev, CONFIG_TBRQ_THRESH, G0_TBRQ_THRESH + (group * 16)); + + return 0; +} + +static int __init +he_init_irq(struct he_dev *he_dev) +{ + int i; + + /* 2.9.3.5 tail offset for each interrupt queue is located after the + end of the interrupt queue */ + + he_dev->irq_base = pci_alloc_consistent(he_dev->pci_dev, + (CONFIG_IRQ_SIZE+1) * sizeof(struct he_irq), &he_dev->irq_phys); + if (he_dev->irq_base == NULL) + { + hprintk("failed to allocate irq\n"); + return -ENOMEM; + } + he_dev->irq_tailoffset = (unsigned *) + &he_dev->irq_base[CONFIG_IRQ_SIZE]; + *he_dev->irq_tailoffset = 0; + he_dev->irq_head = he_dev->irq_base; + he_dev->irq_tail = he_dev->irq_base; + + for(i=0; i < CONFIG_IRQ_SIZE; ++i) + he_dev->irq_base[i].isw = ITYPE_INVALID; + + he_writel(he_dev, he_dev->irq_phys, IRQ0_BASE); + he_writel(he_dev, + IRQ_SIZE(CONFIG_IRQ_SIZE) | IRQ_THRESH(CONFIG_IRQ_THRESH), + IRQ0_HEAD); + he_writel(he_dev, IRQ_INT_A | IRQ_TYPE_LINE, IRQ0_CNTL); + he_writel(he_dev, 0x0, IRQ0_DATA); + + he_writel(he_dev, 0x0, IRQ1_BASE); + he_writel(he_dev, 0x0, IRQ1_HEAD); + he_writel(he_dev, 0x0, IRQ1_CNTL); + he_writel(he_dev, 0x0, IRQ1_DATA); + + he_writel(he_dev, 0x0, IRQ2_BASE); + he_writel(he_dev, 0x0, IRQ2_HEAD); + he_writel(he_dev, 0x0, IRQ2_CNTL); + he_writel(he_dev, 0x0, IRQ2_DATA); + + he_writel(he_dev, 0x0, IRQ3_BASE); + he_writel(he_dev, 0x0, IRQ3_HEAD); + he_writel(he_dev, 0x0, IRQ3_CNTL); + he_writel(he_dev, 0x0, IRQ3_DATA); + + /* 2.9.3.2 interrupt queue mapping registers */ + + he_writel(he_dev, 0x0, GRP_10_MAP); + he_writel(he_dev, 0x0, GRP_32_MAP); + he_writel(he_dev, 0x0, GRP_54_MAP); + he_writel(he_dev, 0x0, GRP_76_MAP); + + if (request_irq(he_dev->pci_dev->irq, he_irq_handler, SA_INTERRUPT|SA_SHIRQ, DEV_LABEL, he_dev)) + { + hprintk("irq %d already in use\n", he_dev->pci_dev->irq); + return -EINVAL; + } + + he_dev->irq = he_dev->pci_dev->irq; + +#ifdef BUS_INT_WAR + HPRINTK("sn_add_polled_interrupt(irq %d, 1)\n", he_dev->irq); + sn_add_polled_interrupt(he_dev->irq, 1); +#endif + + return 0; +} + +static int __init +he_start(struct atm_dev *dev) +{ + struct he_dev *he_dev; + struct pci_dev *pci_dev; + + u16 command; + u32 gen_cntl_0, host_cntl, lb_swap; + u8 cache_size, timer; + + unsigned err; + unsigned int status, reg; + int i, group; + + he_dev = HE_DEV(dev); + pci_dev = he_dev->pci_dev; + + he_dev->membase = pci_dev->resource[0].start; + HPRINTK("membase = 0x%lx irq = %d.\n", he_dev->membase, pci_dev->irq); + + /* + * pci bus controller initialization + */ + + /* 4.3 pci bus controller-specific initialization */ + if (pci_read_config_dword(pci_dev, GEN_CNTL_0, &gen_cntl_0) != 0) + { + hprintk("can't read GEN_CNTL_0\n"); + return -EINVAL; + } + gen_cntl_0 |= (MRL_ENB | MRM_ENB | IGNORE_TIMEOUT); + if (pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0) != 0) + { + hprintk("can't write GEN_CNTL_0.\n"); + return -EINVAL; + } + + if (pci_read_config_word(pci_dev, PCI_COMMAND, &command) != 0) + { + hprintk("can't read PCI_COMMAND.\n"); + return -EINVAL; + } + + command |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE); + if (pci_write_config_word(pci_dev, PCI_COMMAND, command) != 0) + { + hprintk("can't enable memory.\n"); + return -EINVAL; + } + + if (pci_read_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, &cache_size)) + { + hprintk("can't read cache line size?\n"); + return -EINVAL; + } + + if (cache_size < 16) + { + cache_size = 16; + if (pci_write_config_byte(pci_dev, PCI_CACHE_LINE_SIZE, cache_size)) + hprintk("can't set cache line size to %d\n", cache_size); + } + + if (pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &timer)) + { + hprintk("can't read latency timer?\n"); + return -EINVAL; + } + + /* from table 3.9 + * + * LAT_TIMER = 1 + AVG_LAT + BURST_SIZE/BUS_SIZE + * + * AVG_LAT: The average first data read/write latency [maximum 16 clock cycles] + * BURST_SIZE: 1536 bytes (read) for 622, 768 bytes (read) for 155 [192 clock cycles] + * + */ +#define LAT_TIMER 209 + if (timer < LAT_TIMER) + { + HPRINTK("latency timer was %d, setting to %d\n", timer, LAT_TIMER); + timer = LAT_TIMER; + if (pci_write_config_byte(pci_dev, PCI_LATENCY_TIMER, timer)) + hprintk("can't set latency timer to %d\n", timer); + } + + if (!(he_dev->membase = (unsigned long) ioremap(he_dev->membase, HE_REGMAP_SIZE))) { + hprintk("can't set up page mapping\n"); + return -EINVAL; + } + + /* 4.4 card reset */ + he_writel(he_dev, 0x0, RESET_CNTL); + he_writel(he_dev, 0xff, RESET_CNTL); + + udelay(16*1000); /* 16 ms */ + status = he_readl(he_dev, RESET_CNTL); + if ((status & BOARD_RST_STATUS) == 0) + { + hprintk("reset failed\n"); + return -EINVAL; + } + + /* 4.5 set bus width */ + host_cntl = he_readl(he_dev, HOST_CNTL); + if (host_cntl & PCI_BUS_SIZE64) + gen_cntl_0 |= ENBL_64; + else + gen_cntl_0 &= ~ENBL_64; + + if (disable64 == 1) + { + hprintk("disabling 64-bit pci bus transfers\n"); + gen_cntl_0 &= ~ENBL_64; + } + + if (gen_cntl_0 & ENBL_64) hprintk("64-bit transfers enabled\n"); + + pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0); + + /* 4.7 read prom contents */ + for(i=0; iprod_id[i] = read_prom_byte(he_dev, PROD_ID + i); + + he_dev->media = read_prom_byte(he_dev, MEDIA); + + for(i=0; i<6; ++i) + dev->esi[i] = read_prom_byte(he_dev, MAC_ADDR + i); + + hprintk("%s%s, %x:%x:%x:%x:%x:%x\n", + he_dev->prod_id, + he_dev->media & 0x40 ? "SM" : "MM", + dev->esi[0], + dev->esi[1], + dev->esi[2], + dev->esi[3], + dev->esi[4], + dev->esi[5]); + he_dev->atm_dev->link_rate = he_is622(he_dev) ? + ATM_OC12_PCR : ATM_OC3_PCR; + + /* 4.6 set host endianess */ + lb_swap = he_readl(he_dev, LB_SWAP); + if (he_is622(he_dev)) + lb_swap &= ~XFER_SIZE; /* 4 cells */ + else + lb_swap |= XFER_SIZE; /* 8 cells */ +#ifdef __BIG_ENDIAN + lb_swap |= DESC_WR_SWAP | INTR_SWAP | BIG_ENDIAN_HOST; +#else + lb_swap &= ~(DESC_WR_SWAP | INTR_SWAP | BIG_ENDIAN_HOST | + DATA_WR_SWAP | DATA_RD_SWAP | DESC_RD_SWAP); +#endif /* __BIG_ENDIAN */ + he_writel(he_dev, lb_swap, LB_SWAP); + + /* 4.8 sdram controller initialization */ + he_writel(he_dev, he_is622(he_dev) ? LB_64_ENB : 0x0, SDRAM_CTL); + + /* 4.9 initialize rnum value */ + lb_swap |= SWAP_RNUM_MAX(0xf); + he_writel(he_dev, lb_swap, LB_SWAP); + + /* 4.10 initialize the interrupt queues */ + if ((err = he_init_irq(he_dev)) != 0) return err; + +#ifdef USE_TASKLET + tasklet_init(&he_dev->tasklet, he_tasklet, (unsigned long) he_dev); +#endif + spin_lock_init(&he_dev->global_lock); + + /* 4.11 enable pci bus controller state machines */ + host_cntl |= (OUTFF_ENB | CMDFF_ENB | + QUICK_RD_RETRY | QUICK_WR_RETRY | PERR_INT_ENB); + he_writel(he_dev, host_cntl, HOST_CNTL); + + gen_cntl_0 |= INT_PROC_ENBL|INIT_ENB; + pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0); + + /* + * atm network controller initialization + */ + + /* 5.1.1 generic configuration state */ + + /* + * local (cell) buffer memory map + * + * HE155 HE622 + * + * 0 ____________1023 bytes 0 _______________________2047 bytes + * | | | | | + * | utility | | rx0 | | + * 5|____________| 255|___________________| u | + * 6| | 256| | t | + * | | | | i | + * | rx0 | row | tx | l | + * | | | | i | + * | | 767|___________________| t | + * 517|____________| 768| | y | + * row 518| | | rx1 | | + * | | 1023|___________________|___| + * | | + * | tx | + * | | + * | | + * 1535|____________| + * 1536| | + * | rx1 | + * 2047|____________| + * + */ + + /* total 4096 connections */ + he_dev->vcibits = CONFIG_DEFAULT_VCIBITS; + he_dev->vpibits = CONFIG_DEFAULT_VPIBITS; + + if (nvpibits != -1 && nvcibits != -1 && nvpibits+nvcibits != HE_MAXCIDBITS) + { + hprintk("nvpibits + nvcibits != %d\n", HE_MAXCIDBITS); + return -ENODEV; + } + + if (nvpibits != -1) + { + he_dev->vpibits = nvpibits; + he_dev->vcibits = HE_MAXCIDBITS - nvpibits; + } + + if (nvcibits != -1) + { + he_dev->vcibits = nvcibits; + he_dev->vpibits = HE_MAXCIDBITS - nvcibits; + } + + + if (he_is622(he_dev)) + { + he_dev->cells_per_row = 40; + he_dev->bytes_per_row = 2048; + he_dev->r0_numrows = 256; + he_dev->tx_numrows = 512; + he_dev->r1_numrows = 256; + he_dev->r0_startrow = 0; + he_dev->tx_startrow = 256; + he_dev->r1_startrow = 768; + } + else + { + he_dev->cells_per_row = 20; + he_dev->bytes_per_row = 1024; + he_dev->r0_numrows = 512; + he_dev->tx_numrows = 1018; + he_dev->r1_numrows = 512; + he_dev->r0_startrow = 6; + he_dev->tx_startrow = 518; + he_dev->r1_startrow = 1536; + } + + he_dev->cells_per_lbuf = 4; + he_dev->buffer_limit = 4; + he_dev->r0_numbuffs = he_dev->r0_numrows * + he_dev->cells_per_row / he_dev->cells_per_lbuf; + if (he_dev->r0_numbuffs > 2560) he_dev->r0_numbuffs = 2560; + + he_dev->r1_numbuffs = he_dev->r1_numrows * + he_dev->cells_per_row / he_dev->cells_per_lbuf; + if (he_dev->r1_numbuffs > 2560) he_dev->r1_numbuffs = 2560; + + he_dev->tx_numbuffs = he_dev->tx_numrows * + he_dev->cells_per_row / he_dev->cells_per_lbuf; + if (he_dev->tx_numbuffs > 5120) he_dev->tx_numbuffs = 5120; + + /* 5.1.2 configure hardware dependent registers */ + + he_writel(he_dev, + SLICE_X(0x2) | ARB_RNUM_MAX(0xf) | TH_PRTY(0x3) | + RH_PRTY(0x3) | TL_PRTY(0x2) | RL_PRTY(0x1) | + (he_is622(he_dev) ? BUS_MULTI(0x28) : BUS_MULTI(0x46)) | + (he_is622(he_dev) ? NET_PREF(0x50) : NET_PREF(0x8c)), + LBARB); + + he_writel(he_dev, BANK_ON | + (he_is622(he_dev) ? (REF_RATE(0x384) | WIDE_DATA) : REF_RATE(0x150)), + SDRAMCON); + + he_writel(he_dev, + (he_is622(he_dev) ? RM_BANK_WAIT(1) : RM_BANK_WAIT(0)) | + RM_RW_WAIT(1), RCMCONFIG); + he_writel(he_dev, + (he_is622(he_dev) ? TM_BANK_WAIT(2) : TM_BANK_WAIT(1)) | + TM_RW_WAIT(1), TCMCONFIG); + + he_writel(he_dev, he_dev->cells_per_lbuf * ATM_CELL_PAYLOAD, LB_CONFIG); + + he_writel(he_dev, + (he_is622(he_dev) ? UT_RD_DELAY(8) : UT_RD_DELAY(0)) | + (he_is622(he_dev) ? RC_UT_MODE(0) : RC_UT_MODE(1)) | + RX_VALVP(he_dev->vpibits) | + RX_VALVC(he_dev->vcibits), RC_CONFIG); + + he_writel(he_dev, DRF_THRESH(0x20) | + (he_is622(he_dev) ? TX_UT_MODE(0) : TX_UT_MODE(1)) | + TX_VCI_MASK(he_dev->vcibits) | + LBFREE_CNT(he_dev->tx_numbuffs), TX_CONFIG); + + he_writel(he_dev, 0x0, TXAAL5_PROTO); + + he_writel(he_dev, PHY_INT_ENB | + (he_is622(he_dev) ? PTMR_PRE(67-1) : PTMR_PRE(50-1)), + RH_CONFIG); + + /* 5.1.3 initialize connection memory */ + + for(i=0; i < TCM_MEM_SIZE; ++i) + he_writel_tcm(he_dev, 0, i); + + for(i=0; i < RCM_MEM_SIZE; ++i) + he_writel_rcm(he_dev, 0, i); + + /* + * transmit connection memory map + * + * tx memory + * 0x0 ___________________ + * | | + * | | + * | TSRa | + * | | + * | | + * 0x8000|___________________| + * | | + * | TSRb | + * 0xc000|___________________| + * | | + * | TSRc | + * 0xe000|___________________| + * | TSRd | + * 0xf000|___________________| + * | tmABR | + * 0x10000|___________________| + * | | + * | tmTPD | + * |___________________| + * | | + * .... + * 0x1ffff|___________________| + * + * + */ + + he_writel(he_dev, CONFIG_TSRB, TSRB_BA); + he_writel(he_dev, CONFIG_TSRC, TSRC_BA); + he_writel(he_dev, CONFIG_TSRD, TSRD_BA); + he_writel(he_dev, CONFIG_TMABR, TMABR_BA); + he_writel(he_dev, CONFIG_TPDBA, TPD_BA); + + + /* + * receive connection memory map + * + * 0x0 ___________________ + * | | + * | | + * | RSRa | + * | | + * | | + * 0x8000|___________________| + * | | + * | rx0/1 | + * | LBM | link lists of local + * | tx | buffer memory + * | | + * 0xd000|___________________| + * | | + * | rmABR | + * 0xe000|___________________| + * | | + * | RSRb | + * |___________________| + * | | + * .... + * 0xffff|___________________| + */ + + he_writel(he_dev, 0x08000, RCMLBM_BA); + he_writel(he_dev, 0x0e000, RCMRSRB_BA); + he_writel(he_dev, 0x0d800, RCMABR_BA); + + /* 5.1.4 initialize local buffer free pools linked lists */ + + he_init_rx_lbfp0(he_dev); + he_init_rx_lbfp1(he_dev); + + he_writel(he_dev, 0x0, RLBC_H); + he_writel(he_dev, 0x0, RLBC_T); + he_writel(he_dev, 0x0, RLBC_H2); + + he_writel(he_dev, 512, RXTHRSH); /* 10% of r0+r1 buffers */ + he_writel(he_dev, 256, LITHRSH); /* 5% of r0+r1 buffers */ + + he_init_tx_lbfp(he_dev); + + he_writel(he_dev, he_is622(he_dev) ? 0x104780 : 0x800, UBUFF_BA); + + /* 5.1.5 initialize intermediate receive queues */ + + if (he_is622(he_dev)) + { + he_writel(he_dev, 0x000f, G0_INMQ_S); + he_writel(he_dev, 0x200f, G0_INMQ_L); + + he_writel(he_dev, 0x001f, G1_INMQ_S); + he_writel(he_dev, 0x201f, G1_INMQ_L); + + he_writel(he_dev, 0x002f, G2_INMQ_S); + he_writel(he_dev, 0x202f, G2_INMQ_L); + + he_writel(he_dev, 0x003f, G3_INMQ_S); + he_writel(he_dev, 0x203f, G3_INMQ_L); + + he_writel(he_dev, 0x004f, G4_INMQ_S); + he_writel(he_dev, 0x204f, G4_INMQ_L); + + he_writel(he_dev, 0x005f, G5_INMQ_S); + he_writel(he_dev, 0x205f, G5_INMQ_L); + + he_writel(he_dev, 0x006f, G6_INMQ_S); + he_writel(he_dev, 0x206f, G6_INMQ_L); + + he_writel(he_dev, 0x007f, G7_INMQ_S); + he_writel(he_dev, 0x207f, G7_INMQ_L); + } + else + { + he_writel(he_dev, 0x0000, G0_INMQ_S); + he_writel(he_dev, 0x0008, G0_INMQ_L); + + he_writel(he_dev, 0x0001, G1_INMQ_S); + he_writel(he_dev, 0x0009, G1_INMQ_L); + + he_writel(he_dev, 0x0002, G2_INMQ_S); + he_writel(he_dev, 0x000a, G2_INMQ_L); + + he_writel(he_dev, 0x0003, G3_INMQ_S); + he_writel(he_dev, 0x000b, G3_INMQ_L); + + he_writel(he_dev, 0x0004, G4_INMQ_S); + he_writel(he_dev, 0x000c, G4_INMQ_L); + + he_writel(he_dev, 0x0005, G5_INMQ_S); + he_writel(he_dev, 0x000d, G5_INMQ_L); + + he_writel(he_dev, 0x0006, G6_INMQ_S); + he_writel(he_dev, 0x000e, G6_INMQ_L); + + he_writel(he_dev, 0x0007, G7_INMQ_S); + he_writel(he_dev, 0x000f, G7_INMQ_L); + } + + /* 5.1.6 application tunable parameters */ + + he_writel(he_dev, 0x0, MCC); + he_writel(he_dev, 0x0, OEC); + he_writel(he_dev, 0x0, DCC); + he_writel(he_dev, 0x0, CEC); + + /* 5.1.7 cs block initialization */ + + he_init_cs_block(he_dev); + + /* 5.1.8 cs block connection memory initialization */ + + he_init_cs_block_rcm(he_dev); + + /* 5.1.10 initialize host structures */ + + he_init_tpdrq(he_dev); + +#ifdef USE_TPD_POOL + he_dev->tpd_pool = pci_pool_create("tpd", he_dev->pci_dev, + sizeof(struct he_tpd), TPD_ALIGNMENT, 0); + if (he_dev->tpd_pool == NULL) + { + hprintk("unable to create tpd pci_pool\n"); + return -ENOMEM; + } + + INIT_LIST_HEAD(&he_dev->outstanding_tpds); +#else + he_dev->tpd_base = (void *) pci_alloc_consistent(he_dev->pci_dev, + CONFIG_NUMTPDS * sizeof(struct he_tpd), &he_dev->tpd_base_phys); + if (!he_dev->tpd_base) + return -ENOMEM; + + for(i = 0; i < CONFIG_NUMTPDS; ++i) + { + he_dev->tpd_base[i].status = (i << TPD_ADDR_SHIFT); + he_dev->tpd_base[i].inuse = 0; + } + + he_dev->tpd_head = he_dev->tpd_base; + he_dev->tpd_end = &he_dev->tpd_base[CONFIG_NUMTPDS-1]; +#endif + + if (he_init_group(he_dev, 0) != 0) + return -ENOMEM; + + for (group = 1; group < HE_NUM_GROUPS; ++group) + { + he_writel(he_dev, 0x0, G0_RBPS_S + (group * 32)); + he_writel(he_dev, 0x0, G0_RBPS_T + (group * 32)); + he_writel(he_dev, 0x0, G0_RBPS_QI + (group * 32)); + he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0), + G0_RBPS_BS + (group * 32)); + + he_writel(he_dev, 0x0, G0_RBPL_S + (group * 32)); + he_writel(he_dev, 0x0, G0_RBPL_T + (group * 32)); + he_writel(he_dev, RBP_THRESH(0x1) | RBP_QSIZE(0x0), + G0_RBPL_QI + (group * 32)); + he_writel(he_dev, 0x0, G0_RBPL_BS + (group * 32)); + + he_writel(he_dev, 0x0, G0_RBRQ_ST + (group * 16)); + he_writel(he_dev, 0x0, G0_RBRQ_H + (group * 16)); + he_writel(he_dev, RBRQ_THRESH(0x1) | RBRQ_SIZE(0x0), + G0_RBRQ_Q + (group * 16)); + he_writel(he_dev, 0x0, G0_RBRQ_I + (group * 16)); + + he_writel(he_dev, 0x0, G0_TBRQ_B_T + (group * 16)); + he_writel(he_dev, 0x0, G0_TBRQ_H + (group * 16)); + he_writel(he_dev, TBRQ_THRESH(0x1), + G0_TBRQ_THRESH + (group * 16)); + he_writel(he_dev, 0x0, G0_TBRQ_S + (group * 16)); + } + + /* host status page */ + + he_dev->hsp = pci_alloc_consistent(he_dev->pci_dev, + sizeof(struct he_hsp), &he_dev->hsp_phys); + if (he_dev->hsp == NULL) + { + hprintk("failed to allocate host status page\n"); + return -ENOMEM; + } + memset(he_dev->hsp, 0, sizeof(struct he_hsp)); + he_writel(he_dev, he_dev->hsp_phys, HSP_BA); + + /* initialize framer */ + +#ifdef CONFIG_ATM_HE_USE_SUNI + suni_init(he_dev->atm_dev); + if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->start) + he_dev->atm_dev->phy->start(he_dev->atm_dev); +#endif /* CONFIG_ATM_HE_USE_SUNI */ + + if (sdh) + { + /* this really should be in suni.c but for now... */ + + int val; + + val = he_phy_get(he_dev->atm_dev, SUNI_TPOP_APM); + val = (val & ~SUNI_TPOP_APM_S) | ( 0x2 << SUNI_TPOP_APM_S_SHIFT); + he_phy_put(he_dev->atm_dev, val, SUNI_TPOP_APM); + } + + /* 5.1.12 enable transmit and receive */ + + reg = he_readl_mbox(he_dev, CS_ERCTL0); + reg |= TX_ENABLE|ER_ENABLE; + he_writel_mbox(he_dev, reg, CS_ERCTL0); + + reg = he_readl(he_dev, RC_CONFIG); + reg |= RX_ENABLE; + he_writel(he_dev, reg, RC_CONFIG); + +#ifndef USE_HE_FIND_VCC + he_dev->he_vcc_table = kmalloc(sizeof(struct he_vcc_table) * + (1 << (he_dev->vcibits + he_dev->vpibits)), GFP_KERNEL); + if (he_dev->he_vcc_table == NULL) + { + hprintk("failed to alloc he_vcc_table\n"); + return -ENOMEM; + } + memset(he_dev->he_vcc_table, 0, sizeof(struct he_vcc_table) * + (1 << (he_dev->vcibits + he_dev->vpibits))); +#endif + + for (i = 0; i < HE_NUM_CS_STPER; ++i) + { + he_dev->cs_stper[i].inuse = 0; + he_dev->cs_stper[i].pcr = -1; + } + he_dev->total_bw = 0; + + + /* atm linux initialization */ + + he_dev->atm_dev->ci_range.vpi_bits = he_dev->vpibits; + he_dev->atm_dev->ci_range.vci_bits = he_dev->vcibits; + + he_dev->irq_peak = 0; + he_dev->rbrq_peak = 0; + he_dev->rbpl_peak = 0; + he_dev->tbrq_peak = 0; + + HPRINTK("hell bent for leather!\n"); + + return 0; +} + +static void +he_stop(struct he_dev *he_dev) +{ + u16 command; + u32 gen_cntl_0, reg; + struct pci_dev *pci_dev; + + pci_dev = he_dev->pci_dev; + + /* disable interrupts */ + + if (he_dev->membase) + { + pci_read_config_dword(pci_dev, GEN_CNTL_0, &gen_cntl_0); + gen_cntl_0 &= ~(INT_PROC_ENBL | INIT_ENB); + pci_write_config_dword(pci_dev, GEN_CNTL_0, gen_cntl_0); + +#ifdef USE_TASKLET + tasklet_disable(&he_dev->tasklet); +#endif + + /* disable recv and transmit */ + + reg = he_readl_mbox(he_dev, CS_ERCTL0); + reg &= ~(TX_ENABLE|ER_ENABLE); + he_writel_mbox(he_dev, reg, CS_ERCTL0); + + reg = he_readl(he_dev, RC_CONFIG); + reg &= ~(RX_ENABLE); + he_writel(he_dev, reg, RC_CONFIG); + } + +#ifdef CONFIG_ATM_HE_USE_SUNI + if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->stop) + he_dev->atm_dev->phy->stop(he_dev->atm_dev); +#endif /* CONFIG_ATM_HE_USE_SUNI */ + + if (he_dev->irq) + { +#ifdef BUS_INT_WAR + sn_delete_polled_interrupt(he_dev->irq); +#endif + free_irq(he_dev->irq, he_dev); + } + + if (he_dev->irq_base) + pci_free_consistent(he_dev->pci_dev, (CONFIG_IRQ_SIZE+1) + * sizeof(struct he_irq), he_dev->irq_base, he_dev->irq_phys); + + if (he_dev->hsp) + pci_free_consistent(he_dev->pci_dev, sizeof(struct he_hsp), + he_dev->hsp, he_dev->hsp_phys); + + if (he_dev->rbpl_base) + { +#ifdef USE_RBPL_POOL + for (i=0; irbpl_virt[i].virt; + dma_addr_t dma_handle = he_dev->rbpl_base[i].phys; + + pci_pool_free(he_dev->rbpl_pool, cpuaddr, dma_handle); + } +#else + pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE + * CONFIG_RBPL_BUFSIZE, he_dev->rbpl_pages, he_dev->rbpl_pages_phys); +#endif + pci_free_consistent(he_dev->pci_dev, CONFIG_RBPL_SIZE + * sizeof(struct he_rbp), he_dev->rbpl_base, he_dev->rbpl_phys); + } + +#ifdef USE_RBPL_POOL + if (he_dev->rbpl_pool) + pci_pool_destroy(he_dev->rbpl_pool); +#endif + +#ifdef USE_RBPS + if (he_dev->rbps_base) + { +#ifdef USE_RBPS_POOL + for (i=0; irbps_virt[i].virt; + dma_addr_t dma_handle = he_dev->rbps_base[i].phys; + + pci_pool_free(he_dev->rbps_pool, cpuaddr, dma_handle); + } +#else + pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE + * CONFIG_RBPS_BUFSIZE, he_dev->rbps_pages, he_dev->rbps_pages_phys); +#endif + pci_free_consistent(he_dev->pci_dev, CONFIG_RBPS_SIZE + * sizeof(struct he_rbp), he_dev->rbps_base, he_dev->rbps_phys); + } + +#ifdef USE_RBPS_POOL + if (he_dev->rbps_pool) + pci_pool_destroy(he_dev->rbps_pool); +#endif + +#endif /* USE_RBPS */ + + if (he_dev->rbrq_base) + pci_free_consistent(he_dev->pci_dev, CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq), + he_dev->rbrq_base, he_dev->rbrq_phys); + + if (he_dev->tbrq_base) + pci_free_consistent(he_dev->pci_dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), + he_dev->tbrq_base, he_dev->tbrq_phys); + + if (he_dev->tpdrq_base) + pci_free_consistent(he_dev->pci_dev, CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq), + he_dev->tpdrq_base, he_dev->tpdrq_phys); + +#ifdef USE_TPD_POOL + if (he_dev->tpd_pool) + pci_pool_destroy(he_dev->tpd_pool); +#else + if (he_dev->tpd_base) + pci_free_consistent(he_dev->pci_dev, CONFIG_NUMTPDS * sizeof(struct he_tpd), + he_dev->tpd_base, he_dev->tpd_base_phys); +#endif + +#ifndef USE_HE_FIND_VCC + if (he_dev->he_vcc_table) + kfree(he_dev->he_vcc_table); +#endif + + if (he_dev->pci_dev) + { + pci_read_config_word(he_dev->pci_dev, PCI_COMMAND, &command); + command &= ~(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + pci_write_config_word(he_dev->pci_dev, PCI_COMMAND, command); + } + + if (he_dev->membase) iounmap((void *) he_dev->membase); +} + +static struct he_tpd * +__alloc_tpd(struct he_dev *he_dev) +{ +#ifdef USE_TPD_POOL + struct he_tpd *tpd; + dma_addr_t dma_handle; + + tpd = pci_pool_alloc(he_dev->tpd_pool, SLAB_ATOMIC|SLAB_DMA, &dma_handle); + if (tpd == NULL) + return NULL; + + tpd->status = TPD_ADDR(dma_handle); + tpd->reserved = 0; + tpd->iovec[0].addr = 0; tpd->iovec[0].len = 0; + tpd->iovec[1].addr = 0; tpd->iovec[1].len = 0; + tpd->iovec[2].addr = 0; tpd->iovec[2].len = 0; + + return tpd; +#else + int i; + + for(i = 0; i < CONFIG_NUMTPDS; ++i) + { + ++he_dev->tpd_head; + if (he_dev->tpd_head > he_dev->tpd_end) { + he_dev->tpd_head = he_dev->tpd_base; + } + + if (!he_dev->tpd_head->inuse) { + he_dev->tpd_head->inuse = 1; + he_dev->tpd_head->status &= TPD_MASK; + he_dev->tpd_head->iovec[0].addr = 0; he_dev->tpd_head->iovec[0].len = 0; + he_dev->tpd_head->iovec[1].addr = 0; he_dev->tpd_head->iovec[1].len = 0; + he_dev->tpd_head->iovec[2].addr = 0; he_dev->tpd_head->iovec[2].len = 0; + return he_dev->tpd_head; + } + } + hprintk("out of tpds -- increase CONFIG_NUMTPDS (%d)\n", CONFIG_NUMTPDS); + return NULL; +#endif +} + +#define AAL5_LEN(buf,len) \ + ((((unsigned char *)(buf))[(len)-6]<<8) | \ + (((unsigned char *)(buf))[(len)-5])) + +/* 2.10.1.2 receive + * + * aal5 packets can optionally return the tcp checksum in the lower + * 16 bits of the crc (RSR0_TCP_CKSUM) + */ + +#define TCP_CKSUM(buf,len) \ + ((((unsigned char *)(buf))[(len)-2]<<8) | \ + (((unsigned char *)(buf))[(len-1)])) + +static int +he_service_rbrq(struct he_dev *he_dev, int group) +{ + struct he_rbrq *rbrq_tail = (struct he_rbrq *) + ((unsigned long)he_dev->rbrq_base | + he_dev->hsp->group[group].rbrq_tail); + struct he_rbp *rbp = NULL; + unsigned cid, lastcid = -1; + unsigned buf_len = 0; + struct sk_buff *skb; + struct atm_vcc *vcc = NULL; + struct he_vcc *he_vcc; + struct he_iovec *iov; + int pdus_assembled = 0; + int updated = 0; + + while (he_dev->rbrq_head != rbrq_tail) + { + ++updated; + + HPRINTK("%p rbrq%d 0x%x len=%d cid=0x%x %s%s%s%s%s%s\n", + he_dev->rbrq_head, group, + RBRQ_ADDR(he_dev->rbrq_head), + RBRQ_BUFLEN(he_dev->rbrq_head), + RBRQ_CID(he_dev->rbrq_head), + RBRQ_CRC_ERR(he_dev->rbrq_head) ? " CRC_ERR" : "", + RBRQ_LEN_ERR(he_dev->rbrq_head) ? " LEN_ERR" : "", + RBRQ_END_PDU(he_dev->rbrq_head) ? " END_PDU" : "", + RBRQ_AAL5_PROT(he_dev->rbrq_head) ? " AAL5_PROT" : "", + RBRQ_CON_CLOSED(he_dev->rbrq_head) ? " CON_CLOSED" : "", + RBRQ_HBUF_ERR(he_dev->rbrq_head) ? " HBUF_ERR" : ""); + +#ifdef USE_RBPS + if (RBRQ_ADDR(he_dev->rbrq_head) & RBP_SMALLBUF) + rbp = &he_dev->rbps_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))]; + else +#endif + rbp = &he_dev->rbpl_base[RBP_INDEX(RBRQ_ADDR(he_dev->rbrq_head))]; + + buf_len = RBRQ_BUFLEN(he_dev->rbrq_head) * 4; + cid = RBRQ_CID(he_dev->rbrq_head); + +#ifdef USE_HE_FIND_VCC + if (cid != lastcid) + vcc = he_find_vcc(he_dev, cid); + lastcid = cid; +#else + vcc = HE_LOOKUP_VCC(he_dev, cid); +#endif + if (vcc == NULL) + { + hprintk("vcc == NULL (cid 0x%x)\n", cid); + if (!RBRQ_HBUF_ERR(he_dev->rbrq_head)) + rbp->status &= ~RBP_LOANED; + + goto next_rbrq_entry; + } + + he_vcc = HE_VCC(vcc); + if (he_vcc == NULL) + { + hprintk("he_vcc == NULL (cid 0x%x)\n", cid); + if (!RBRQ_HBUF_ERR(he_dev->rbrq_head)) + rbp->status &= ~RBP_LOANED; + goto next_rbrq_entry; + } + + if (RBRQ_HBUF_ERR(he_dev->rbrq_head)) + { + hprintk("HBUF_ERR! (cid 0x%x)\n", cid); + atomic_inc(&vcc->stats->rx_drop); + goto return_host_buffers; + } + + he_vcc->iov_tail->iov_base = RBRQ_ADDR(he_dev->rbrq_head); + he_vcc->iov_tail->iov_len = buf_len; + he_vcc->pdu_len += buf_len; + ++he_vcc->iov_tail; + + if (RBRQ_CON_CLOSED(he_dev->rbrq_head)) + { + lastcid = -1; + HPRINTK("wake_up rx_waitq (cid 0x%x)\n", cid); + wake_up(&he_vcc->rx_waitq); + goto return_host_buffers; + } + +#ifdef notdef + if ((he_vcc->iov_tail - he_vcc->iov_head) > HE_MAXIOV) + { + hprintk("iovec full! cid 0x%x\n", cid); + goto return_host_buffers; + } +#endif + if (!RBRQ_END_PDU(he_dev->rbrq_head)) goto next_rbrq_entry; + + if (RBRQ_LEN_ERR(he_dev->rbrq_head) + || RBRQ_CRC_ERR(he_dev->rbrq_head)) + { + HPRINTK("%s%s (%d.%d)\n", + RBRQ_CRC_ERR(he_dev->rbrq_head) + ? "CRC_ERR " : "", + RBRQ_LEN_ERR(he_dev->rbrq_head) + ? "LEN_ERR" : "", + vcc->vpi, vcc->vci); + atomic_inc(&vcc->stats->rx_err); + goto return_host_buffers; + } + + skb = atm_alloc_charge(vcc, he_vcc->pdu_len + rx_skb_reserve, + GFP_ATOMIC); + if (!skb) + { + HPRINTK("charge failed (%d.%d)\n", vcc->vpi, vcc->vci); + goto return_host_buffers; + } + + if (rx_skb_reserve > 0) skb_reserve(skb, rx_skb_reserve); + + do_gettimeofday(&skb->stamp); + + for(iov = he_vcc->iov_head; + iov < he_vcc->iov_tail; ++iov) + { +#ifdef USE_RBPS + if (iov->iov_base & RBP_SMALLBUF) + memcpy(skb_put(skb, iov->iov_len), + he_dev->rbps_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len); + else +#endif + memcpy(skb_put(skb, iov->iov_len), + he_dev->rbpl_virt[RBP_INDEX(iov->iov_base)].virt, iov->iov_len); + } + + switch(vcc->qos.aal) + { + case ATM_AAL0: + /* 2.10.1.5 raw cell receive */ + skb->len = ATM_AAL0_SDU; + skb->tail = skb->data + skb->len; + break; + case ATM_AAL5: + /* 2.10.1.2 aal5 receive */ + + skb->len = AAL5_LEN(skb->data, he_vcc->pdu_len); + skb->tail = skb->data + skb->len; +#ifdef USE_CHECKSUM_HW + if (vcc->vpi == 0 && vcc->vci >= ATM_NOT_RSV_VCI) + { + skb->ip_summed = CHECKSUM_HW; + skb->csum = TCP_CKSUM(skb->data, + he_vcc->pdu_len); + } +#endif + break; + } + +#ifdef should_never_happen + if (skb->len > vcc->qos.rxtp.max_sdu) + hprintk("pdu_len (%d) > vcc->qos.rxtp.max_sdu (%d)! cid 0x%x\n", skb->len, vcc->qos.rxtp.max_sdu, cid); +#endif + +#ifdef notdef + ATM_SKB(skb)->vcc = vcc; +#endif + vcc->push(vcc, skb); + + atomic_inc(&vcc->stats->rx); + +return_host_buffers: + ++pdus_assembled; + + for(iov = he_vcc->iov_head; + iov < he_vcc->iov_tail; ++iov) + { +#ifdef USE_RBPS + if (iov->iov_base & RBP_SMALLBUF) + rbp = &he_dev->rbps_base[RBP_INDEX(iov->iov_base)]; + else +#endif + rbp = &he_dev->rbpl_base[RBP_INDEX(iov->iov_base)]; + + rbp->status &= ~RBP_LOANED; + } + + he_vcc->iov_tail = he_vcc->iov_head; + he_vcc->pdu_len = 0; + +next_rbrq_entry: + he_dev->rbrq_head = (struct he_rbrq *) + ((unsigned long) he_dev->rbrq_base | + RBRQ_MASK(++he_dev->rbrq_head)); + + } + + if (updated) + { + if (updated > he_dev->rbrq_peak) he_dev->rbrq_peak = updated; + + he_writel(he_dev, RBRQ_MASK(he_dev->rbrq_head), + G0_RBRQ_H + (group * 16)); +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl(he_dev, G0_RBRQ_H + (group * 16)); +#endif + } + + return pdus_assembled; +} + +static void +he_service_tbrq(struct he_dev *he_dev, int group) +{ + struct he_tbrq *tbrq_tail = (struct he_tbrq *) + ((unsigned long)he_dev->tbrq_base | + he_dev->hsp->group[group].tbrq_tail); + struct he_tpd *tpd; + int slot, updated = 0; +#ifdef USE_TPD_POOL + struct list_head *p; +#endif + + /* 2.1.6 transmit buffer return queue */ + + while (he_dev->tbrq_head != tbrq_tail) + { + ++updated; + + HPRINTK("tbrq%d 0x%x%s%s\n", + group, + TBRQ_TPD(he_dev->tbrq_head), + TBRQ_EOS(he_dev->tbrq_head) ? " EOS" : "", + TBRQ_MULTIPLE(he_dev->tbrq_head) ? " MULTIPLE" : ""); +#ifdef USE_TPD_POOL + tpd = NULL; + p = &he_dev->outstanding_tpds; + while ((p = p->next) != &he_dev->outstanding_tpds) + { + struct he_tpd *__tpd = list_entry(p, struct he_tpd, entry); + if (TPD_ADDR(__tpd->status) == TBRQ_TPD(he_dev->tbrq_head)) + { + tpd = __tpd; + list_del(&__tpd->entry); + break; + } + } + + if (tpd == NULL) + { + hprintk("unable to locate tpd for dma buffer %x\n", + TBRQ_TPD(he_dev->tbrq_head)); + goto next_tbrq_entry; + } +#else + tpd = &he_dev->tpd_base[ TPD_INDEX(TBRQ_TPD(he_dev->tbrq_head)) ]; +#endif + + if (TBRQ_EOS(he_dev->tbrq_head)) + { + HPRINTK("wake_up(tx_waitq) cid 0x%x\n", + he_mkcid(he_dev, tpd->vcc->vpi, tpd->vcc->vci)); + if (tpd->vcc) + wake_up(&HE_VCC(tpd->vcc)->tx_waitq); + + goto next_tbrq_entry; + } + + for(slot = 0; slot < TPD_MAXIOV; ++slot) + { + if (tpd->iovec[slot].addr) + pci_unmap_single(he_dev->pci_dev, + tpd->iovec[slot].addr, + tpd->iovec[slot].len & TPD_LEN_MASK, + PCI_DMA_TODEVICE); + if (tpd->iovec[slot].len & TPD_LST) break; + + } + + if (tpd->skb) /* && !TBRQ_MULTIPLE(he_dev->tbrq_head) */ + { + if (tpd->vcc && tpd->vcc->pop) + tpd->vcc->pop(tpd->vcc, tpd->skb); + else + dev_kfree_skb_any(tpd->skb); + } + +next_tbrq_entry: +#ifdef USE_TPD_POOL + if (tpd) pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status)); +#else + tpd->inuse = 0; +#endif + he_dev->tbrq_head = (struct he_tbrq *) + ((unsigned long) he_dev->tbrq_base | + TBRQ_MASK(++he_dev->tbrq_head)); + } + + if (updated) + { + if (updated > he_dev->tbrq_peak) he_dev->tbrq_peak = updated; + + he_writel(he_dev, TBRQ_MASK(he_dev->tbrq_head), + G0_TBRQ_H + (group * 16)); +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl(he_dev, G0_TBRQ_H + (group * 16)); +#endif + } +} + + +static void +he_service_rbpl(struct he_dev *he_dev, int group) +{ + struct he_rbp *newtail; + struct he_rbp *rbpl_head; + int moved = 0; + + rbpl_head = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base | + RBPL_MASK(he_readl(he_dev, G0_RBPL_S))); + + for(;;) + { + newtail = (struct he_rbp *) ((unsigned long)he_dev->rbpl_base | + RBPL_MASK(he_dev->rbpl_tail+1)); + + /* table 3.42 -- rbpl_tail should never be set to rbpl_head */ + if ((newtail == rbpl_head) || (newtail->status & RBP_LOANED)) + break; + + newtail->status |= RBP_LOANED; + he_dev->rbpl_tail = newtail; + ++moved; + + } + + if (moved) { + he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail), G0_RBPL_T); +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl(he_dev, G0_RBPL_T); +#endif + } +} + +#ifdef USE_RBPS +static void +he_service_rbps(struct he_dev *he_dev, int group) +{ + struct he_rbp *newtail; + struct he_rbp *rbps_head; + int moved = 0; + + rbps_head = (struct he_rbp *) ((unsigned long)he_dev->rbps_base | + RBPS_MASK(he_readl(he_dev, G0_RBPS_S))); + + for(;;) + { + newtail = (struct he_rbp *) ((unsigned long)he_dev->rbps_base | + RBPS_MASK(he_dev->rbps_tail+1)); + + /* table 3.42 -- rbps_tail should never be set to rbps_head */ + if ((newtail == rbps_head) || (newtail->status & RBP_LOANED)) + break; + + newtail->status |= RBP_LOANED; + he_dev->rbps_tail = newtail; + ++moved; + + } + + if (moved) { + he_writel(he_dev, RBPS_MASK(he_dev->rbps_tail), G0_RBPS_T); +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl(he_dev, G0_RBPS_T); +#endif + } +} +#endif /* USE_RBPS */ + +static void +he_tasklet(unsigned long data) +{ + unsigned long flags; + struct he_dev *he_dev = (struct he_dev *) data; + int group, type; + int updated = 0; + + HPRINTK("tasklet (0x%lx)\n", data); +#ifdef USE_TASKLET + HE_SPIN_LOCK(he_dev, flags); +#endif + + while(he_dev->irq_head != he_dev->irq_tail) + { + ++updated; + + type = ITYPE_TYPE(he_dev->irq_head->isw); + group = ITYPE_GROUP(he_dev->irq_head->isw); + + switch (type) + { + case ITYPE_RBRQ_THRESH: + hprintk("rbrq%d threshold\n", group); + case ITYPE_RBRQ_TIMER: + if (he_service_rbrq(he_dev, group)) + { + he_service_rbpl(he_dev, group); +#ifdef USE_RBPS + he_service_rbps(he_dev, group); +#endif /* USE_RBPS */ + } + break; + case ITYPE_TBRQ_THRESH: + hprintk("tbrq%d threshold\n", group); + case ITYPE_TPD_COMPLETE: + he_service_tbrq(he_dev, group); + break; + case ITYPE_RBPL_THRESH: + he_service_rbpl(he_dev, group); + break; + case ITYPE_RBPS_THRESH: +#ifdef USE_RBPS + he_service_rbps(he_dev, group); +#endif /* USE_RBPS */ + break; + case ITYPE_PHY: +#ifdef CONFIG_ATM_HE_USE_SUNI + HE_SPIN_UNLOCK(he_dev, flags); + if (he_dev->atm_dev->phy && he_dev->atm_dev->phy->interrupt) + he_dev->atm_dev->phy->interrupt(he_dev->atm_dev); + HE_SPIN_LOCK(he_dev, flags); +#endif + HPRINTK("phy interrupt\n"); + break; + case ITYPE_OTHER: + switch (type|group) + { + case ITYPE_PARITY: + hprintk("parity error\n"); + break; + case ITYPE_ABORT: + hprintk("abort 0x%x\n", he_readl(he_dev, ABORT_ADDR)); + break; + } + break; + default: + if (he_dev->irq_head->isw == ITYPE_INVALID) + { + /* see 8.1.1 -- check all queues */ + + HPRINTK("isw not updated 0x%x\n", + he_dev->irq_head->isw); + + he_service_rbrq(he_dev, 0); + he_service_rbpl(he_dev, 0); +#ifdef USE_RBPS + he_service_rbps(he_dev, 0); +#endif /* USE_RBPS */ + he_service_tbrq(he_dev, 0); + } + else + hprintk("bad isw = 0x%x?\n", + he_dev->irq_head->isw); + } + + he_dev->irq_head->isw = ITYPE_INVALID; + + he_dev->irq_head = (struct he_irq *) NEXT_ENTRY(he_dev->irq_base, he_dev->irq_head, IRQ_MASK); + } + + if (updated) + { + if (updated > he_dev->irq_peak) he_dev->irq_peak = updated; + + he_writel(he_dev, + IRQ_SIZE(CONFIG_IRQ_SIZE) | + IRQ_THRESH(CONFIG_IRQ_THRESH) | + IRQ_TAIL(he_dev->irq_tail), IRQ0_HEAD); + (void) he_readl(he_dev, INT_FIFO); /* 8.1.2 controller errata */ + } +#ifdef USE_TASKLET + HE_SPIN_UNLOCK(he_dev, flags); +#endif +} + +static irqreturn_t +he_irq_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long flags; + struct he_dev *he_dev = (struct he_dev * )dev_id; + int handled = 0; + + if (he_dev == NULL) + return IRQ_NONE; + + HE_SPIN_LOCK(he_dev, flags); + + he_dev->irq_tail = (struct he_irq *) (((unsigned long)he_dev->irq_base) | + (*he_dev->irq_tailoffset << 2)); + + if (he_dev->irq_tail == he_dev->irq_head) + { + HPRINTK("tailoffset not updated?\n"); + he_dev->irq_tail = (struct he_irq *) ((unsigned long)he_dev->irq_base | + ((he_readl(he_dev, IRQ0_BASE) & IRQ_MASK) << 2)); + (void) he_readl(he_dev, INT_FIFO); /* 8.1.2 controller errata */ + } + +#ifdef DEBUG + if (he_dev->irq_head == he_dev->irq_tail /* && !IRQ_PENDING */) + hprintk("spurious (or shared) interrupt?\n"); +#endif + + if (he_dev->irq_head != he_dev->irq_tail) + { + handled = 1; +#ifdef USE_TASKLET + tasklet_schedule(&he_dev->tasklet); +#else + he_tasklet((unsigned long) he_dev); +#endif + he_writel(he_dev, INT_CLEAR_A, INT_FIFO); + /* clear interrupt */ +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl(he_dev, INT_FIFO); +#endif + } + HE_SPIN_UNLOCK(he_dev, flags); + return IRQ_RETVAL(handled); + +} + +static __inline__ void +__enqueue_tpd(struct he_dev *he_dev, struct he_tpd *tpd, unsigned cid) +{ + struct he_tpdrq *new_tail; + + HPRINTK("tpdrq %p cid 0x%x -> tpdrq_tail %p\n", + tpd, cid, he_dev->tpdrq_tail); + + /* new_tail = he_dev->tpdrq_tail; */ + new_tail = (struct he_tpdrq *) ((unsigned long) he_dev->tpdrq_base | + TPDRQ_MASK(he_dev->tpdrq_tail+1)); + + /* + * check to see if we are about to set the tail == head + * if true, update the head pointer from the adapter + * to see if this is really the case (reading the queue + * head for every enqueue would be unnecessarily slow) + */ + + if (new_tail == he_dev->tpdrq_head) + { + he_dev->tpdrq_head = (struct he_tpdrq *) + (((unsigned long)he_dev->tpdrq_base) | + TPDRQ_MASK(he_readl(he_dev, TPDRQ_B_H))); + + if (new_tail == he_dev->tpdrq_head) + { + hprintk("tpdrq full (cid 0x%x)\n", cid); + /* + * FIXME + * push tpd onto a transmit backlog queue + * after service_tbrq, service the backlog + * for now, we just drop the pdu + */ + if (tpd->skb) + { + if (tpd->vcc->pop) + tpd->vcc->pop(tpd->vcc, tpd->skb); + else + dev_kfree_skb_any(tpd->skb); + atomic_inc(&tpd->vcc->stats->tx_err); + } +#ifdef USE_TPD_POOL + pci_pool_free(he_dev->tpd_pool, tpd, TPD_ADDR(tpd->status)); +#else + tpd->inuse = 0; +#endif + return; + } + } + + /* 2.1.5 transmit packet descriptor ready queue */ +#ifdef USE_TPD_POOL + list_add_tail(&tpd->entry, &he_dev->outstanding_tpds); + he_dev->tpdrq_tail->tpd = TPD_ADDR(tpd->status); +#else + he_dev->tpdrq_tail->tpd = he_dev->tpd_base_phys + + (TPD_INDEX(tpd->status) * sizeof(struct he_tpd)); +#endif + he_dev->tpdrq_tail->cid = cid; + wmb(); + + he_dev->tpdrq_tail = new_tail; + + he_writel(he_dev, TPDRQ_MASK(he_dev->tpdrq_tail), TPDRQ_T); +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl(he_dev, TPDRQ_T); +#endif +} + +static int +he_open(struct atm_vcc *vcc, short vpi, int vci) +{ + unsigned long flags; + struct he_dev *he_dev = HE_DEV(vcc->dev); + struct he_vcc *he_vcc; + int err = 0; + unsigned cid, rsr0, rsr1, rsr4, tsr0, tsr0_aal, tsr4, period, reg, clock; + + + if ((err = atm_find_ci(vcc, &vpi, &vci))) + { + HPRINTK("atm_find_ci err = %d\n", err); + return err; + } + if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC) return 0; + vcc->vpi = vpi; + vcc->vci = vci; + + HPRINTK("open vcc %p %d.%d\n", vcc, vpi, vci); + + set_bit(ATM_VF_ADDR, &vcc->flags); + + cid = he_mkcid(he_dev, vpi, vci); + + he_vcc = (struct he_vcc *) kmalloc(sizeof(struct he_vcc), GFP_ATOMIC); + if (he_vcc == NULL) + { + hprintk("unable to allocate he_vcc during open\n"); + return -ENOMEM; + } + + he_vcc->iov_tail = he_vcc->iov_head; + he_vcc->pdu_len = 0; + he_vcc->rc_index = -1; + + init_waitqueue_head(&he_vcc->rx_waitq); + init_waitqueue_head(&he_vcc->tx_waitq); + + HE_VCC(vcc) = he_vcc; + + if (vcc->qos.txtp.traffic_class != ATM_NONE) + { + int pcr_goal; + + pcr_goal = atm_pcr_goal(&vcc->qos.txtp); + if (pcr_goal == 0) + pcr_goal = he_dev->atm_dev->link_rate; + if (pcr_goal < 0) /* means round down, technically */ + pcr_goal = -pcr_goal; + + HPRINTK("open tx cid 0x%x pcr_goal %d\n", cid, pcr_goal); + + switch (vcc->qos.aal) + { + case ATM_AAL5: + tsr0_aal = TSR0_AAL5; + tsr4 = TSR4_AAL5; + break; + case ATM_AAL0: + tsr0_aal = TSR0_AAL0_SDU; + tsr4 = TSR4_AAL0_SDU; + break; + default: + err = -EINVAL; + goto open_failed; + } + + HE_SPIN_LOCK(he_dev, flags); + tsr0 = he_readl_tsr0(he_dev, cid); + HE_SPIN_UNLOCK(he_dev, flags); + + if (TSR0_CONN_STATE(tsr0) != 0) + { + hprintk("cid 0x%x not idle (tsr0 = 0x%x)\n", cid, tsr0); + err = -EBUSY; + goto open_failed; + } + + switch(vcc->qos.txtp.traffic_class) + { + case ATM_UBR: + /* 2.3.3.1 open connection ubr */ + + tsr0 = TSR0_UBR | TSR0_GROUP(0) | tsr0_aal | + TSR0_USE_WMIN | TSR0_UPDATE_GER; + break; + + case ATM_CBR: + /* 2.3.3.2 open connection cbr */ + + /* 8.2.3 cbr scheduler wrap problem -- limit to 90% total link rate */ + if ((he_dev->total_bw + pcr_goal) + > (he_dev->atm_dev->link_rate * 9 / 10)) + { + err = -EBUSY; + goto open_failed; + } + + HE_SPIN_LOCK(he_dev, flags); /* also protects he_dev->cs_stper[] */ + + /* find an unused cs_stper register */ + for(reg = 0; reg < HE_NUM_CS_STPER; ++reg) + if (he_dev->cs_stper[reg].inuse == 0 || + he_dev->cs_stper[reg].pcr == pcr_goal) + break; + + if (reg == HE_NUM_CS_STPER) + { + err = -EBUSY; + HE_SPIN_UNLOCK(he_dev, flags); + goto open_failed; + } + + he_dev->total_bw += pcr_goal; + + he_vcc->rc_index = reg; + ++he_dev->cs_stper[reg].inuse; + he_dev->cs_stper[reg].pcr = pcr_goal; + + clock = he_is622(he_dev) ? 66667000 : 50000000; + period = clock / pcr_goal; + + HPRINTK("rc_index = %d period = %d\n", + reg, period); + + he_writel_mbox(he_dev, rate_to_atmf(period/2), + CS_STPER0 + reg); + HE_SPIN_UNLOCK(he_dev, flags); + + tsr0 = TSR0_CBR | TSR0_GROUP(0) | tsr0_aal | + TSR0_RC_INDEX(reg); + + break; + default: + err = -EINVAL; + goto open_failed; + } + + HE_SPIN_LOCK(he_dev, flags); + + he_writel_tsr0(he_dev, tsr0, cid); + he_writel_tsr4(he_dev, tsr4 | 1, cid); + he_writel_tsr1(he_dev, TSR1_MCR(rate_to_atmf(0)) | + TSR1_PCR(rate_to_atmf(pcr_goal)), cid); + he_writel_tsr2(he_dev, TSR2_ACR(rate_to_atmf(pcr_goal)), cid); + he_writel_tsr9(he_dev, TSR9_OPEN_CONN, cid); + + he_writel_tsr3(he_dev, 0x0, cid); + he_writel_tsr5(he_dev, 0x0, cid); + he_writel_tsr6(he_dev, 0x0, cid); + he_writel_tsr7(he_dev, 0x0, cid); + he_writel_tsr8(he_dev, 0x0, cid); + he_writel_tsr10(he_dev, 0x0, cid); + he_writel_tsr11(he_dev, 0x0, cid); + he_writel_tsr12(he_dev, 0x0, cid); + he_writel_tsr13(he_dev, 0x0, cid); + he_writel_tsr14(he_dev, 0x0, cid); +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl_tsr0(he_dev, cid); +#endif + HE_SPIN_UNLOCK(he_dev, flags); + } + + if (vcc->qos.rxtp.traffic_class != ATM_NONE) + { + unsigned aal; + + HPRINTK("open rx cid 0x%x (rx_waitq %p)\n", cid, + &HE_VCC(vcc)->rx_waitq); + + switch (vcc->qos.aal) + { + case ATM_AAL5: + aal = RSR0_AAL5; + break; + case ATM_AAL0: + aal = RSR0_RAWCELL; + break; + default: + err = -EINVAL; + goto open_failed; + } + + HE_SPIN_LOCK(he_dev, flags); + + rsr0 = he_readl_rsr0(he_dev, cid); + if (rsr0 & RSR0_OPEN_CONN) + { + HE_SPIN_UNLOCK(he_dev, flags); + + hprintk("cid 0x%x not idle (rsr0 = 0x%x)\n", cid, rsr0); + err = -EBUSY; + goto open_failed; + } + +#ifdef USE_RBPS + rsr1 = RSR1_GROUP(0); + rsr4 = RSR4_GROUP(0); +#else /* !USE_RBPS */ + rsr1 = RSR1_GROUP(0)|RSR1_RBPL_ONLY; + rsr4 = RSR4_GROUP(0)|RSR4_RBPL_ONLY; +#endif /* USE_RBPS */ + rsr0 = vcc->qos.rxtp.traffic_class == ATM_UBR ? + (RSR0_EPD_ENABLE|RSR0_PPD_ENABLE) : 0; + +#ifdef USE_CHECKSUM_HW + if (vpi == 0 && vci >= ATM_NOT_RSV_VCI) rsr0 |= RSR0_TCP_CKSUM; +#endif + + he_writel_rsr4(he_dev, rsr4, cid); + he_writel_rsr1(he_dev, rsr1, cid); + /* 5.1.11 last parameter initialized should be + the open/closed indication in rsr0 */ + he_writel_rsr0(he_dev, + rsr0 | RSR0_START_PDU | RSR0_OPEN_CONN | aal, cid); +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl_rsr0(he_dev, cid); +#endif + + HE_SPIN_UNLOCK(he_dev, flags); + +#ifndef USE_HE_FIND_VCC + HE_LOOKUP_VCC(he_dev, cid) = vcc; +#endif + } + +open_failed: + + if (err) + { + if (he_vcc) kfree(he_vcc); + clear_bit(ATM_VF_ADDR, &vcc->flags); + } + else + set_bit(ATM_VF_READY, &vcc->flags); + + return err; +} + +static void +he_close(struct atm_vcc *vcc) +{ + unsigned long flags; + DECLARE_WAITQUEUE(wait, current); + struct he_dev *he_dev = HE_DEV(vcc->dev); + struct he_tpd *tpd; + unsigned cid; + struct he_vcc *he_vcc = HE_VCC(vcc); +#define MAX_RETRY 30 + int retry = 0, sleep = 1, tx_inuse; + + HPRINTK("close vcc %p %d.%d\n", vcc, vcc->vpi, vcc->vci); + + clear_bit(ATM_VF_READY, &vcc->flags); + cid = he_mkcid(he_dev, vcc->vpi, vcc->vci); + + if (vcc->qos.rxtp.traffic_class != ATM_NONE) + { + int timeout; + + HPRINTK("close rx cid 0x%x\n", cid); + + /* 2.7.2.2 close receive operation */ + + /* wait for previous close (if any) to finish */ + + HE_SPIN_LOCK(he_dev, flags); + while(he_readl(he_dev, RCC_STAT) & RCC_BUSY) + { + HPRINTK("close cid 0x%x RCC_BUSY\n", cid); + udelay(250); + } + + add_wait_queue(&he_vcc->rx_waitq, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); + + he_writel_rsr0(he_dev, RSR0_CLOSE_CONN, cid); +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl_rsr0(he_dev, cid); +#endif + he_writel_mbox(he_dev, cid, RXCON_CLOSE); + HE_SPIN_UNLOCK(he_dev, flags); + + timeout = schedule_timeout(30*HZ); + + remove_wait_queue(&he_vcc->rx_waitq, &wait); + set_current_state(TASK_RUNNING); + + if (timeout == 0) + hprintk("close rx timeout cid 0x%x\n", cid); + +#ifndef USE_HE_FIND_VCC + HE_LOOKUP_VCC(he_dev, cid) = NULL; +#endif + HPRINTK("close rx cid 0x%x complete\n", cid); + + } + + if (vcc->qos.txtp.traffic_class != ATM_NONE) + { + volatile unsigned tsr4, tsr0; + int timeout; + + HPRINTK("close tx cid 0x%x\n", cid); + + /* 2.1.2 + * + * ... the host must first stop queueing packets to the TPDRQ + * on the connection to be closed, then wait for all outstanding + * packets to be transmitted and their buffers returned to the + * TBRQ. When the last packet on the connection arrives in the + * TBRQ, the host issues the close command to the adapter. + */ + + while (((tx_inuse = atomic_read(&vcc->sk->wmem_alloc)) > 0) + && (retry < MAX_RETRY)) + { + set_current_state(TASK_UNINTERRUPTIBLE); + (void) schedule_timeout(sleep); + set_current_state(TASK_RUNNING); + if (sleep < HZ) sleep = sleep * 2; + + ++retry; + } + + if (tx_inuse) hprintk("close tx cid 0x%x tx_inuse = %d\n", + cid, tx_inuse); + + /* 2.3.1.1 generic close operations with flush */ + + HE_SPIN_LOCK(he_dev, flags); + he_writel_tsr4_upper(he_dev, TSR4_FLUSH_CONN, cid); + /* also clears TSR4_SESSION_ENDED */ +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl_tsr4(he_dev, cid); +#endif + + switch(vcc->qos.txtp.traffic_class) + { + case ATM_UBR: + he_writel_tsr1(he_dev, + TSR1_MCR(rate_to_atmf(200000)) + | TSR1_PCR(0), cid); + break; + case ATM_CBR: + he_writel_tsr14_upper(he_dev, TSR14_DELETE, cid); + break; + } + + + tpd = __alloc_tpd(he_dev); + if (tpd == NULL) + { + hprintk("close tx he_alloc_tpd failed cid 0x%x\n", cid); + goto close_tx_incomplete; + } + tpd->status |= TPD_EOS | TPD_INT; + tpd->skb = NULL; + tpd->vcc = vcc; + wmb(); + + add_wait_queue(&he_vcc->tx_waitq, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); + __enqueue_tpd(he_dev, tpd, cid); + HE_SPIN_UNLOCK(he_dev, flags); + + timeout = schedule_timeout(30*HZ); + + remove_wait_queue(&he_vcc->tx_waitq, &wait); + set_current_state(TASK_RUNNING); + + if (timeout == 0) + { + hprintk("close tx timeout cid 0x%x\n", cid); + goto close_tx_incomplete; + } + + HE_SPIN_LOCK(he_dev, flags); + while (!((tsr4 = he_readl_tsr4(he_dev, cid)) + & TSR4_SESSION_ENDED)) + { + HPRINTK("close tx cid 0x%x !TSR4_SESSION_ENDED (tsr4 = 0x%x)\n", cid, tsr4); + udelay(250); + } + + while (TSR0_CONN_STATE(tsr0 = he_readl_tsr0(he_dev, cid)) != 0) + { + HPRINTK("close tx cid 0x%x TSR0_CONN_STATE != 0 (tsr0 = 0x%x)\n", cid, tsr0); + udelay(250); + } + +close_tx_incomplete: + + if (vcc->qos.txtp.traffic_class == ATM_CBR) + { + int reg = he_vcc->rc_index; + + HPRINTK("cs_stper reg = %d\n", reg); + + if (he_dev->cs_stper[reg].inuse == 0) + hprintk("cs_stper[%d].inuse = 0!\n", reg); + else + --he_dev->cs_stper[reg].inuse; + + he_dev->total_bw -= he_dev->cs_stper[reg].pcr; + } + HE_SPIN_UNLOCK(he_dev, flags); + + HPRINTK("close tx cid 0x%x complete\n", cid); + } + + kfree(he_vcc); + + clear_bit(ATM_VF_ADDR, &vcc->flags); +} + +static int +he_sg_send(struct atm_vcc *vcc, unsigned long start, unsigned long size) +{ +#ifdef USE_SCATTERGATHER + return 1; +#else + return 0; +#endif +} + +static int +he_send(struct atm_vcc *vcc, struct sk_buff *skb) +{ + unsigned long flags; + struct he_dev *he_dev = HE_DEV(vcc->dev); + unsigned cid = he_mkcid(he_dev, vcc->vpi, vcc->vci); + struct he_tpd *tpd; +#ifdef USE_SCATTERGATHER + int i, slot = 0; +#endif + +#define HE_TPD_BUFSIZE 0xffff + + HPRINTK("send %d.%d\n", vcc->vpi, vcc->vci); + + if ((skb->len > HE_TPD_BUFSIZE) || + ((vcc->qos.aal == ATM_AAL0) && (skb->len != ATM_AAL0_SDU))) + { + hprintk("buffer too large (or small) -- %d bytes\n", skb->len ); + if (vcc->pop) + vcc->pop(vcc, skb); + else + dev_kfree_skb_any(skb); + atomic_inc(&vcc->stats->tx_err); + return -EINVAL; + } + +#ifndef USE_SCATTERGATHER + if (skb_shinfo(skb)->nr_frags) + { + hprintk("no scatter/gather support\n"); + if (vcc->pop) + vcc->pop(vcc, skb); + else + dev_kfree_skb_any(skb); + atomic_inc(&vcc->stats->tx_err); + return -EINVAL; + } +#endif + HE_SPIN_LOCK(he_dev, flags); + + tpd = __alloc_tpd(he_dev); + if (tpd == NULL) + { + if (vcc->pop) + vcc->pop(vcc, skb); + else + dev_kfree_skb_any(skb); + atomic_inc(&vcc->stats->tx_err); + HE_SPIN_UNLOCK(he_dev, flags); + return -ENOMEM; + } + + if (vcc->qos.aal == ATM_AAL5) + tpd->status |= TPD_CELLTYPE(TPD_USERCELL); + else + { + char *pti_clp = (void *) (skb->data + 3); + int clp, pti; + + pti = (*pti_clp & ATM_HDR_PTI_MASK) >> ATM_HDR_PTI_SHIFT; + clp = (*pti_clp & ATM_HDR_CLP); + tpd->status |= TPD_CELLTYPE(pti); + if (clp) tpd->status |= TPD_CLP; + + skb_pull(skb, ATM_AAL0_SDU - ATM_CELL_PAYLOAD); + } + +#ifdef USE_SCATTERGATHER + tpd->iovec[slot].addr = pci_map_single(he_dev->pci_dev, skb->data, + skb->len - skb->data_len, PCI_DMA_TODEVICE); + tpd->iovec[slot].len = skb->len - skb->data_len; + ++slot; + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) + { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + + if (slot == TPD_MAXIOV) /* send tpd; start new tpd */ + { + tpd->vcc = vcc; + tpd->skb = NULL; /* not the last fragment + so dont ->push() yet */ + wmb(); + + __enqueue_tpd(he_dev, tpd, cid); + tpd = __alloc_tpd(he_dev); + if (tpd == NULL) + { + if (vcc->pop) + vcc->pop(vcc, skb); + else + dev_kfree_skb_any(skb); + atomic_inc(&vcc->stats->tx_err); + HE_SPIN_UNLOCK(he_dev, flags); + return -ENOMEM; + } + tpd->status |= TPD_USERCELL; + slot = 0; + } + + tpd->iovec[slot].addr = pci_map_single(he_dev->pci_dev, + (void *) page_address(frag->page) + frag->page_offset, + frag->size, PCI_DMA_TODEVICE); + tpd->iovec[slot].len = frag->size; + ++slot; + + } + + tpd->iovec[slot-1].len |= TPD_LST; +#else + tpd->address0 = pci_map_single(he_dev->pci_dev, skb->data, skb->len, PCI_DMA_TODEVICE); + tpd->length0 = skb->len | TPD_LST; +#endif + tpd->status |= TPD_INT; + + tpd->vcc = vcc; + tpd->skb = skb; + wmb(); + ATM_SKB(skb)->vcc = vcc; + + __enqueue_tpd(he_dev, tpd, cid); + HE_SPIN_UNLOCK(he_dev, flags); + + atomic_inc(&vcc->stats->tx); + + return 0; +} + +static int +he_ioctl(struct atm_dev *atm_dev, unsigned int cmd, void *arg) +{ + unsigned long flags; + struct he_dev *he_dev = HE_DEV(atm_dev); + struct he_ioctl_reg reg; + int err = 0; + + switch (cmd) + { + case HE_GET_REG: + if (!capable(CAP_NET_ADMIN)) return -EPERM; + + copy_from_user(®, (struct he_ioctl_reg *) arg, + sizeof(struct he_ioctl_reg)); + HE_SPIN_LOCK(he_dev, flags); + switch (reg.type) + { + case HE_REGTYPE_PCI: + reg.val = he_readl(he_dev, reg.addr); + break; + case HE_REGTYPE_RCM: + reg.val = + he_readl_rcm(he_dev, reg.addr); + break; + case HE_REGTYPE_TCM: + reg.val = + he_readl_tcm(he_dev, reg.addr); + break; + case HE_REGTYPE_MBOX: + reg.val = + he_readl_mbox(he_dev, reg.addr); + break; + default: + err = -EINVAL; + break; + } + HE_SPIN_UNLOCK(he_dev, flags); + if (err == 0) copy_to_user((struct he_ioctl_reg *) arg, ®, + sizeof(struct he_ioctl_reg)); + break; + default: +#ifdef CONFIG_ATM_HE_USE_SUNI + if (atm_dev->phy && atm_dev->phy->ioctl) + err = atm_dev->phy->ioctl(atm_dev, cmd, arg); +#else /* CONFIG_ATM_HE_USE_SUNI */ + return -EINVAL; +#endif /* CONFIG_ATM_HE_USE_SUNI */ + break; + } + + return err; +} + +static void +he_phy_put(struct atm_dev *atm_dev, unsigned char val, unsigned long addr) +{ + unsigned long flags; + struct he_dev *he_dev = HE_DEV(atm_dev); + + HPRINTK("phy_put(val 0x%x, addr 0x%lx)\n", val, addr); + + HE_SPIN_LOCK(he_dev, flags); + he_writel(he_dev, val, FRAMER + (addr*4)); +#ifdef CONFIG_IA64_SGI_SN2 + (void) he_readl(he_dev, FRAMER + (addr*4)); +#endif + HE_SPIN_UNLOCK(he_dev, flags); +} + + +static unsigned char +he_phy_get(struct atm_dev *atm_dev, unsigned long addr) +{ + unsigned long flags; + struct he_dev *he_dev = HE_DEV(atm_dev); + unsigned reg; + + HE_SPIN_LOCK(he_dev, flags); + reg = he_readl(he_dev, FRAMER + (addr*4)); + HE_SPIN_UNLOCK(he_dev, flags); + + HPRINTK("phy_get(addr 0x%lx) =0x%x\n", addr, reg); + return reg; +} + +static int +he_proc_read(struct atm_dev *dev, loff_t *pos, char *page) +{ + unsigned long flags; + struct he_dev *he_dev = HE_DEV(dev); + int left, i; +#ifdef notdef + struct he_rbrq *rbrq_tail; + struct he_tpdrq *tpdrq_head; + int rbpl_head, rbpl_tail; +#endif + static long mcc = 0, oec = 0, dcc = 0, cec = 0; + + + left = *pos; + if (!left--) + return sprintf(page, "%s\n", version); + + if (!left--) + return sprintf(page, "%s%s\n\n", + he_dev->prod_id, he_dev->media & 0x40 ? "SM" : "MM"); + + if (!left--) + return sprintf(page, "Mismatched Cells VPI/VCI Not Open Dropped Cells RCM Dropped Cells\n"); + + HE_SPIN_LOCK(he_dev, flags); + mcc += he_readl(he_dev, MCC); + oec += he_readl(he_dev, OEC); + dcc += he_readl(he_dev, DCC); + cec += he_readl(he_dev, CEC); + HE_SPIN_UNLOCK(he_dev, flags); + + if (!left--) + return sprintf(page, "%16ld %16ld %13ld %17ld\n\n", + mcc, oec, dcc, cec); + + if (!left--) + return sprintf(page, "irq_size = %d inuse = ? peak = %d\n", + CONFIG_IRQ_SIZE, he_dev->irq_peak); + + if (!left--) + return sprintf(page, "tpdrq_size = %d inuse = ?\n", + CONFIG_TPDRQ_SIZE); + + if (!left--) + return sprintf(page, "rbrq_size = %d inuse = ? peak = %d\n", + CONFIG_RBRQ_SIZE, he_dev->rbrq_peak); + + if (!left--) + return sprintf(page, "tbrq_size = %d peak = %d\n", + CONFIG_TBRQ_SIZE, he_dev->tbrq_peak); + + +#ifdef notdef + rbpl_head = RBPL_MASK(he_readl(he_dev, G0_RBPL_S)); + rbpl_tail = RBPL_MASK(he_readl(he_dev, G0_RBPL_T)); + + inuse = rbpl_head - rbpl_tail; + if (inuse < 0) inuse += CONFIG_RBPL_SIZE * sizeof(struct he_rbp); + inuse /= sizeof(struct he_rbp); + + if (!left--) + return sprintf(page, "rbpl_size = %d inuse = %d\n\n", + CONFIG_RBPL_SIZE, inuse); +#endif + + if (!left--) + return sprintf(page, "rate controller periods (cbr)\n pcr #vc\n"); + + for (i = 0; i < HE_NUM_CS_STPER; ++i) + if (!left--) + return sprintf(page, "cs_stper%-2d %8ld %3d\n", i, + he_dev->cs_stper[i].pcr, + he_dev->cs_stper[i].inuse); + + if (!left--) + return sprintf(page, "total bw (cbr): %d (limit %d)\n", + he_dev->total_bw, he_dev->atm_dev->link_rate * 10 / 9); + + return 0; +} + +/* eeprom routines -- see 4.7 */ + +u8 +read_prom_byte(struct he_dev *he_dev, int addr) +{ + u32 val = 0, tmp_read = 0; + int i, j = 0; + u8 byte_read = 0; + + val = readl(he_dev->membase + HOST_CNTL); + val &= 0xFFFFE0FF; + + /* Turn on write enable */ + val |= 0x800; + he_writel(he_dev, val, HOST_CNTL); + + /* Send READ instruction */ + for (i=0; i=0; i--) { + he_writel(he_dev, val | clocktab[j++] | (((addr >> i) & 1) << 9), HOST_CNTL); + udelay(EEPROM_DELAY); + he_writel(he_dev, val | clocktab[j++] | (((addr >> i) & 1) << 9), HOST_CNTL); + udelay(EEPROM_DELAY); + } + + j=0; + + val &= 0xFFFFF7FF; /* Turn off write enable */ + he_writel(he_dev, val, HOST_CNTL); + + /* Now, we can read data from the EEPROM by clocking it in */ + for (i=7; i>=0; i--) { + he_writel(he_dev, val | clocktab[j++], HOST_CNTL); + udelay(EEPROM_DELAY); + tmp_read = he_readl(he_dev, HOST_CNTL); + byte_read |= (unsigned char) + ((tmp_read & ID_DOUT) + >> ID_DOFFSET << i); + he_writel(he_dev, val | clocktab[j++], HOST_CNTL); + udelay(EEPROM_DELAY); + } + + he_writel(he_dev, val | ID_CS, HOST_CNTL); + udelay(EEPROM_DELAY); + + return (byte_read); +} + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("chas williams "); +MODULE_DESCRIPTION("ForeRunnerHE ATM Adapter driver"); +MODULE_PARM(disable64, "h"); +MODULE_PARM_DESC(disable64, "disable 64-bit pci bus transfers"); +MODULE_PARM(nvpibits, "i"); +MODULE_PARM_DESC(nvpibits, "numbers of bits for vpi (default 0)"); +MODULE_PARM(nvcibits, "i"); +MODULE_PARM_DESC(nvcibits, "numbers of bits for vci (default 12)"); +MODULE_PARM(rx_skb_reserve, "i"); +MODULE_PARM_DESC(rx_skb_reserve, "padding for receive skb (default 16)"); +MODULE_PARM(irq_coalesce, "i"); +MODULE_PARM_DESC(irq_coalesce, "use interrupt coalescing (default 1)"); +MODULE_PARM(sdh, "i"); +MODULE_PARM_DESC(sdh, "use SDH framing (default 0)"); + +static struct pci_device_id he_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_HE, PCI_ANY_ID, PCI_ANY_ID, + 0, 0, 0 }, + { 0, } +}; + +static struct pci_driver he_driver = { + .name = "he", + .probe = he_init_one, + .remove = __devexit_p(he_remove_one), + .id_table = he_pci_tbl, +}; + +static int __init he_init(void) +{ + return pci_module_init(&he_driver); +} + +static void __exit he_cleanup(void) +{ + pci_unregister_driver(&he_driver); +} + +module_init(he_init); +module_exit(he_cleanup); diff -Nru a/drivers/atm/he.h b/drivers/atm/he.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/atm/he.h Sat May 24 12:48:34 2003 @@ -0,0 +1,938 @@ +/* $Id: he.h,v 1.4 2003/05/06 22:48:00 chas Exp $ */ + +/* + + he.h + + ForeRunnerHE ATM Adapter driver for ATM on Linux + Copyright (C) 1999-2001 Naval Research Laboratory + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/* + + he.h + + ForeRunnerHE ATM Adapter driver for ATM on Linux + Copyright (C) 1999-2000 Naval Research Laboratory + + Permission to use, copy, modify and distribute this software and its + documentation is hereby granted, provided that both the copyright + notice and this permission notice appear in all copies of the software, + derivative works or modified versions, and any portions thereof, and + that both notices appear in supporting documentation. + + NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND + DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER + RESULTING FROM THE USE OF THIS SOFTWARE. + + */ + +#ifndef _HE_H_ +#define _HE_H_ + +#define DEV_LABEL "he" + +#define CONFIG_DEFAULT_VCIBITS 12 +#define CONFIG_DEFAULT_VPIBITS 0 + +#define CONFIG_IRQ_SIZE 128 +#define CONFIG_IRQ_THRESH (CONFIG_IRQ_SIZE/2) + +#define CONFIG_NUMTPDS 256 + +#define CONFIG_TPDRQ_SIZE 512 +#define TPDRQ_MASK(x) (((unsigned long)(x))&((CONFIG_TPDRQ_SIZE<<3)-1)) + +#define CONFIG_RBRQ_SIZE 512 +#define CONFIG_RBRQ_THRESH 400 +#define RBRQ_MASK(x) (((unsigned long)(x))&((CONFIG_RBRQ_SIZE<<3)-1)) + +#define CONFIG_TBRQ_SIZE 512 +#define CONFIG_TBRQ_THRESH 400 +#define TBRQ_MASK(x) (((unsigned long)(x))&((CONFIG_TBRQ_SIZE<<2)-1)) + +#define CONFIG_RBPL_SIZE 512 +#define CONFIG_RBPL_THRESH 64 +#define CONFIG_RBPL_BUFSIZE 4096 +#define RBPL_MASK(x) (((unsigned long)(x))&((CONFIG_RBPL_SIZE<<3)-1)) + +#define CONFIG_RBPS_SIZE 1024 +#define CONFIG_RBPS_THRESH 64 +#define CONFIG_RBPS_BUFSIZE 128 +#define RBPS_MASK(x) (((unsigned long)(x))&((CONFIG_RBPS_SIZE<<3)-1)) + +/* 5.1.3 initialize connection memory */ + +#define CONFIG_RSRA 0x00000 +#define CONFIG_RCMLBM 0x08000 +#define CONFIG_RCMABR 0x0d800 +#define CONFIG_RSRB 0x0e000 + +#define CONFIG_TSRA 0x00000 +#define CONFIG_TSRB 0x08000 +#define CONFIG_TSRC 0x0c000 +#define CONFIG_TSRD 0x0e000 +#define CONFIG_TMABR 0x0f000 +#define CONFIG_TPDBA 0x10000 + +#define HE_MAXCIDBITS 12 + +/* 2.9.3.3 interrupt encodings */ + +struct he_irq { + volatile u32 isw; +}; + +#define IRQ_ALIGNMENT 0x1000 + +#define NEXT_ENTRY(base, tail, mask) \ + (((unsigned long)base)|(((unsigned long)(tail+1))&mask)) + +#define ITYPE_INVALID 0xffffffff +#define ITYPE_TBRQ_THRESH (0<<3) +#define ITYPE_TPD_COMPLETE (1<<3) +#define ITYPE_RBPS_THRESH (2<<3) +#define ITYPE_RBPL_THRESH (3<<3) +#define ITYPE_RBRQ_THRESH (4<<3) +#define ITYPE_RBRQ_TIMER (5<<3) +#define ITYPE_PHY (6<<3) +#define ITYPE_OTHER 0x80 +#define ITYPE_PARITY 0x81 +#define ITYPE_ABORT 0x82 + +#define ITYPE_GROUP(x) (x & 0x7) +#define ITYPE_TYPE(x) (x & 0xf8) + +#define HE_NUM_GROUPS 8 + +/* 2.1.4 transmit packet descriptor */ + +struct he_tpd { + + /* read by the adapter */ + + volatile u32 status; + volatile u32 reserved; + +#define TPD_MAXIOV 3 + struct { + u32 addr, len; + } iovec[TPD_MAXIOV]; + +#define address0 iovec[0].addr +#define length0 iovec[0].len + + /* linux-atm extensions */ + + struct sk_buff *skb; + struct atm_vcc *vcc; + +#ifdef USE_TPD_POOL + struct list_head entry; +#else + u32 inuse; + char padding[32 - sizeof(u32) - (2*sizeof(void*))]; +#endif +}; + +#define TPD_ALIGNMENT 64 +#define TPD_LEN_MASK 0xffff + +#define TPD_ADDR_SHIFT 6 +#define TPD_MASK 0xffffffc0 +#define TPD_ADDR(x) ((x) & TPD_MASK) +#define TPD_INDEX(x) (TPD_ADDR(x) >> TPD_ADDR_SHIFT) + + +/* table 2.3 transmit buffer return elements */ + +struct he_tbrq { + volatile u32 tbre; +}; + +#define TBRQ_ALIGNMENT CONFIG_TBRQ_SIZE + +#define TBRQ_TPD(tbrq) ((tbrq)->tbre & 0xffffffc0) +#define TBRQ_EOS(tbrq) ((tbrq)->tbre & (1<<3)) +#define TBRQ_MULTIPLE(tbrq) ((tbrq)->tbre & (1)) + +/* table 2.21 receive buffer return queue element field organization */ + +struct he_rbrq { + volatile u32 addr; + volatile u32 cidlen; +}; + +#define RBRQ_ALIGNMENT CONFIG_RBRQ_SIZE + +#define RBRQ_ADDR(rbrq) ((rbrq)->addr & 0xffffffc0) +#define RBRQ_CRC_ERR(rbrq) ((rbrq)->addr & (1<<5)) +#define RBRQ_LEN_ERR(rbrq) ((rbrq)->addr & (1<<4)) +#define RBRQ_END_PDU(rbrq) ((rbrq)->addr & (1<<3)) +#define RBRQ_AAL5_PROT(rbrq) ((rbrq)->addr & (1<<2)) +#define RBRQ_CON_CLOSED(rbrq) ((rbrq)->addr & (1<<1)) +#define RBRQ_HBUF_ERR(rbrq) ((rbrq)->addr & 1) +#define RBRQ_CID(rbrq) (((rbrq)->cidlen >> 16) & 0x1fff) +#define RBRQ_BUFLEN(rbrq) ((rbrq)->cidlen & 0xffff) + +/* figure 2.3 transmit packet descriptor ready queue */ + +struct he_tpdrq { + volatile u32 tpd; + volatile u32 cid; +}; + +#define TPDRQ_ALIGNMENT CONFIG_TPDRQ_SIZE + +/* table 2.30 host status page detail */ + +#define HSP_ALIGNMENT 0x400 /* must align on 1k boundary */ + +struct he_hsp { + struct he_hsp_entry { + volatile u32 tbrq_tail; + volatile u32 reserved1[15]; + volatile u32 rbrq_tail; + volatile u32 reserved2[15]; + } group[HE_NUM_GROUPS]; +}; + +/* figure 2.9 receive buffer pools */ + +struct he_rbp { + volatile u32 phys; + volatile u32 status; +}; + +/* NOTE: it is suggested that virt be the virtual address of the host + buffer. on a 64-bit machine, this would not work. Instead, we + store the real virtual address in another list, and store an index + (and buffer status) in the virt member. +*/ + +#define RBP_INDEX_OFF 6 +#define RBP_INDEX(x) (((long)(x) >> RBP_INDEX_OFF) & 0xffff) +#define RBP_LOANED 0x80000000 +#define RBP_SMALLBUF 0x40000000 + +struct he_virt { + void *virt; +}; + +#define RBPL_ALIGNMENT CONFIG_RBPL_SIZE +#define RBPS_ALIGNMENT CONFIG_RBPS_SIZE + +#ifdef notyet +struct he_group { + u32 rpbs_size, rpbs_qsize; + struct he_rbp rbps_ba; + + u32 rpbl_size, rpbl_qsize; + struct he_rpb_entry *rbpl_ba; +}; +#endif + +#define HE_LOOKUP_VCC(dev, cid) ((dev)->he_vcc_table[(cid)].vcc) + +struct he_vcc_table +{ + struct atm_vcc *vcc; +}; + +struct he_cs_stper +{ + long pcr; + int inuse; +}; + +#define HE_NUM_CS_STPER 16 + +struct he_dev { + unsigned int number; + unsigned int irq; + unsigned long membase; + + char prod_id[30]; + char mac_addr[6]; + int media; /* + * 0x26 = HE155 MM + * 0x27 = HE622 MM + * 0x46 = HE155 SM + * 0x47 = HE622 SM + */ + + + unsigned int vcibits, vpibits; + unsigned int cells_per_row; + unsigned int bytes_per_row; + unsigned int cells_per_lbuf; + unsigned int r0_numrows, r0_startrow, r0_numbuffs; + unsigned int r1_numrows, r1_startrow, r1_numbuffs; + unsigned int tx_numrows, tx_startrow, tx_numbuffs; + unsigned int buffer_limit; + + struct he_vcc_table *he_vcc_table; + +#ifdef notyet + struct he_group group[HE_NUM_GROUPS]; +#endif + struct he_cs_stper cs_stper[HE_NUM_CS_STPER]; + unsigned total_bw; + + dma_addr_t irq_phys; + struct he_irq *irq_base, *irq_head, *irq_tail; + volatile unsigned *irq_tailoffset; + int irq_peak; + +#ifdef USE_TASKLET + struct tasklet_struct tasklet; +#endif +#ifdef USE_TPD_POOL + struct pci_pool *tpd_pool; + struct list_head outstanding_tpds; +#else + struct he_tpd *tpd_head, *tpd_base, *tpd_end; + dma_addr_t tpd_base_phys; +#endif + + dma_addr_t tpdrq_phys; + struct he_tpdrq *tpdrq_base, *tpdrq_tail, *tpdrq_head; + + spinlock_t global_lock; /* 8.1.5 pci transaction ordering + error problem */ + dma_addr_t rbrq_phys; + struct he_rbrq *rbrq_base, *rbrq_head; + int rbrq_peak; + +#ifdef USE_RBPL_POOL + struct pci_pool *rbpl_pool; +#else + void *rbpl_pages; + dma_addr_t rbpl_pages_phys; +#endif + dma_addr_t rbpl_phys; + struct he_rbp *rbpl_base, *rbpl_tail; + struct he_virt *rbpl_virt; + int rbpl_peak; + +#ifdef USE_RBPS +#ifdef USE_RBPS_POOL + struct pci_pool *rbps_pool; +#else + void *rbps_pages; + dma_addr_t rbps_pages_phys; +#endif +#endif + dma_addr_t rbps_phys; + struct he_rbp *rbps_base, *rbps_tail; + struct he_virt *rbps_virt; + int rbps_peak; + + dma_addr_t tbrq_phys; + struct he_tbrq *tbrq_base, *tbrq_head; + int tbrq_peak; + + dma_addr_t hsp_phys; + struct he_hsp *hsp; + + struct pci_dev *pci_dev; + struct atm_dev *atm_dev; + struct he_dev *next; +}; + +struct he_iovec +{ + u32 iov_base; + u32 iov_len; +}; + +#define HE_MAXIOV 20 + +struct he_vcc +{ + struct he_iovec iov_head[HE_MAXIOV]; + struct he_iovec *iov_tail; + int pdu_len; + + int rc_index; + + wait_queue_head_t rx_waitq; + wait_queue_head_t tx_waitq; +}; + +#define HE_VCC(vcc) ((struct he_vcc *)(vcc->dev_data)) + +#define PCI_VENDOR_ID_FORE 0x1127 +#define PCI_DEVICE_ID_FORE_HE 0x400 + +#define HE_DMA_MASK 0xffffffff + +#define GEN_CNTL_0 0x40 +#define INT_PROC_ENBL (1<<25) +#define SLAVE_ENDIAN_MODE (1<<16) +#define MRL_ENB (1<<5) +#define MRM_ENB (1<<4) +#define INIT_ENB (1<<2) +#define IGNORE_TIMEOUT (1<<1) +#define ENBL_64 (1<<0) + +#define MIN_PCI_LATENCY 32 /* errata 8.1.3 */ + +#define HE_DEV(dev) ((struct he_dev *) (dev)->dev_data) + +#define he_is622(dev) ((dev)->media & 0x1) + +#define HE_REGMAP_SIZE 0x100000 + +#define RESET_CNTL 0x80000 +#define BOARD_RST_STATUS (1<<6) + +#define HOST_CNTL 0x80004 +#define PCI_BUS_SIZE64 (1<<27) +#define DESC_RD_STATIC_64 (1<<26) +#define DATA_RD_STATIC_64 (1<<25) +#define DATA_WR_STATIC_64 (1<<24) +#define ID_CS (1<<12) +#define ID_WREN (1<<11) +#define ID_DOUT (1<<10) +#define ID_DOFFSET 10 +#define ID_DIN (1<<9) +#define ID_CLOCK (1<<8) +#define QUICK_RD_RETRY (1<<7) +#define QUICK_WR_RETRY (1<<6) +#define OUTFF_ENB (1<<5) +#define CMDFF_ENB (1<<4) +#define PERR_INT_ENB (1<<2) +#define IGNORE_INTR (1<<0) + +#define LB_SWAP 0x80008 +#define SWAP_RNUM_MAX(x) (x<<27) +#define DATA_WR_SWAP (1<<20) +#define DESC_RD_SWAP (1<<19) +#define DATA_RD_SWAP (1<<18) +#define INTR_SWAP (1<<17) +#define DESC_WR_SWAP (1<<16) +#define SDRAM_INIT (1<<15) +#define BIG_ENDIAN_HOST (1<<14) +#define XFER_SIZE (1<<7) + +#define LB_MEM_ADDR 0x8000c +#define LB_MEM_DATA 0x80010 + +#define LB_MEM_ACCESS 0x80014 +#define LB_MEM_HNDSHK (1<<30) +#define LM_MEM_WRITE (0x7) +#define LM_MEM_READ (0x3) + +#define SDRAM_CTL 0x80018 +#define LB_64_ENB (1<<3) +#define LB_TWR (1<<2) +#define LB_TRP (1<<1) +#define LB_TRAS (1<<0) + +#define INT_FIFO 0x8001c +#define INT_MASK_D (1<<15) +#define INT_MASK_C (1<<14) +#define INT_MASK_B (1<<13) +#define INT_MASK_A (1<<12) +#define INT_CLEAR_D (1<<11) +#define INT_CLEAR_C (1<<10) +#define INT_CLEAR_B (1<<9) +#define INT_CLEAR_A (1<<8) + +#define ABORT_ADDR 0x80020 + +#define IRQ0_BASE 0x80080 +#define IRQ_BASE(x) (x<<12) +#define IRQ_MASK ((CONFIG_IRQ_SIZE<<2)-1) /* was 0x3ff */ +#define IRQ_TAIL(x) (((unsigned long)(x)) & IRQ_MASK) +#define IRQ0_HEAD 0x80084 +#define IRQ_SIZE(x) (x<<22) +#define IRQ_THRESH(x) (x<<12) +#define IRQ_HEAD(x) (x<<2) +/* #define IRQ_PENDING (1) conflict with linux/irq.h */ +#define IRQ0_CNTL 0x80088 +#define IRQ_ADDRSEL(x) (x<<2) +#define IRQ_INT_A (0<<2) +#define IRQ_INT_B (1<<2) +#define IRQ_INT_C (2<<2) +#define IRQ_INT_D (3<<2) +#define IRQ_TYPE_ADDR 0x1 +#define IRQ_TYPE_LINE 0x0 +#define IRQ0_DATA 0x8008c + +#define IRQ1_BASE 0x80090 +#define IRQ1_HEAD 0x80094 +#define IRQ1_CNTL 0x80098 +#define IRQ1_DATA 0x8009c + +#define IRQ2_BASE 0x800a0 +#define IRQ2_HEAD 0x800a4 +#define IRQ2_CNTL 0x800a8 +#define IRQ2_DATA 0x800ac + +#define IRQ3_BASE 0x800b0 +#define IRQ3_HEAD 0x800b4 +#define IRQ3_CNTL 0x800b8 +#define IRQ3_DATA 0x800bc + +#define GRP_10_MAP 0x800c0 +#define GRP_32_MAP 0x800c4 +#define GRP_54_MAP 0x800c8 +#define GRP_76_MAP 0x800cc + +#define G0_RBPS_S 0x80400 +#define G0_RBPS_T 0x80404 +#define RBP_TAIL(x) ((x)<<3) +#define RBP_MASK(x) ((x)|0x1fff) +#define G0_RBPS_QI 0x80408 +#define RBP_QSIZE(x) ((x)<<14) +#define RBP_INT_ENB (1<<13) +#define RBP_THRESH(x) (x) +#define G0_RBPS_BS 0x8040c +#define G0_RBPL_S 0x80410 +#define G0_RBPL_T 0x80414 +#define G0_RBPL_QI 0x80418 +#define G0_RBPL_BS 0x8041c + +#define G1_RBPS_S 0x80420 +#define G1_RBPS_T 0x80424 +#define G1_RBPS_QI 0x80428 +#define G1_RBPS_BS 0x8042c +#define G1_RBPL_S 0x80430 +#define G1_RBPL_T 0x80434 +#define G1_RBPL_QI 0x80438 +#define G1_RBPL_BS 0x8043c + +#define G2_RBPS_S 0x80440 +#define G2_RBPS_T 0x80444 +#define G2_RBPS_QI 0x80448 +#define G2_RBPS_BS 0x8044c +#define G2_RBPL_S 0x80450 +#define G2_RBPL_T 0x80454 +#define G2_RBPL_QI 0x80458 +#define G2_RBPL_BS 0x8045c + +#define G3_RBPS_S 0x80460 +#define G3_RBPS_T 0x80464 +#define G3_RBPS_QI 0x80468 +#define G3_RBPS_BS 0x8046c +#define G3_RBPL_S 0x80470 +#define G3_RBPL_T 0x80474 +#define G3_RBPL_QI 0x80478 +#define G3_RBPL_BS 0x8047c + +#define G4_RBPS_S 0x80480 +#define G4_RBPS_T 0x80484 +#define G4_RBPS_QI 0x80488 +#define G4_RBPS_BS 0x8048c +#define G4_RBPL_S 0x80490 +#define G4_RBPL_T 0x80494 +#define G4_RBPL_QI 0x80498 +#define G4_RBPL_BS 0x8049c + +#define G5_RBPS_S 0x804a0 +#define G5_RBPS_T 0x804a4 +#define G5_RBPS_QI 0x804a8 +#define G5_RBPS_BS 0x804ac +#define G5_RBPL_S 0x804b0 +#define G5_RBPL_T 0x804b4 +#define G5_RBPL_QI 0x804b8 +#define G5_RBPL_BS 0x804bc + +#define G6_RBPS_S 0x804c0 +#define G6_RBPS_T 0x804c4 +#define G6_RBPS_QI 0x804c8 +#define G6_RBPS_BS 0x804cc +#define G6_RBPL_S 0x804d0 +#define G6_RBPL_T 0x804d4 +#define G6_RBPL_QI 0x804d8 +#define G6_RBPL_BS 0x804dc + +#define G7_RBPS_S 0x804e0 +#define G7_RBPS_T 0x804e4 +#define G7_RBPS_QI 0x804e8 +#define G7_RBPS_BS 0x804ec + +#define G7_RBPL_S 0x804f0 +#define G7_RBPL_T 0x804f4 +#define G7_RBPL_QI 0x804f8 +#define G7_RBPL_BS 0x804fc + +#define G0_RBRQ_ST 0x80500 +#define G0_RBRQ_H 0x80504 +#define G0_RBRQ_Q 0x80508 +#define RBRQ_THRESH(x) ((x)<<13) +#define RBRQ_SIZE(x) (x) +#define G0_RBRQ_I 0x8050c +#define RBRQ_TIME(x) ((x)<<8) +#define RBRQ_COUNT(x) (x) + +/* fill in 1 ... 7 later */ + +#define G0_TBRQ_B_T 0x80600 +#define G0_TBRQ_H 0x80604 +#define G0_TBRQ_S 0x80608 +#define G0_TBRQ_THRESH 0x8060c +#define TBRQ_THRESH(x) (x) + +/* fill in 1 ... 7 later */ + +#define RH_CONFIG 0x805c0 +#define PHY_INT_ENB (1<<10) +#define OAM_GID(x) (x<<7) +#define PTMR_PRE(x) (x) + +#define G0_INMQ_S 0x80580 +#define G0_INMQ_L 0x80584 +#define G1_INMQ_S 0x80588 +#define G1_INMQ_L 0x8058c +#define G2_INMQ_S 0x80590 +#define G2_INMQ_L 0x80594 +#define G3_INMQ_S 0x80598 +#define G3_INMQ_L 0x8059c +#define G4_INMQ_S 0x805a0 +#define G4_INMQ_L 0x805a4 +#define G5_INMQ_S 0x805a8 +#define G5_INMQ_L 0x805ac +#define G6_INMQ_S 0x805b0 +#define G6_INMQ_L 0x805b4 +#define G7_INMQ_S 0x805b8 +#define G7_INMQ_L 0x805bc + +#define TPDRQ_B_H 0x80680 +#define TPDRQ_T 0x80684 +#define TPDRQ_S 0x80688 + +#define UBUFF_BA 0x8068c + +#define RLBF0_H 0x806c0 +#define RLBF0_T 0x806c4 +#define RLBF1_H 0x806c8 +#define RLBF1_T 0x806cc +#define RLBC_H 0x806d0 +#define RLBC_T 0x806d4 +#define RLBC_H2 0x806d8 +#define TLBF_H 0x806e0 +#define TLBF_T 0x806e4 +#define RLBF0_C 0x806e8 +#define RLBF1_C 0x806ec +#define RXTHRSH 0x806f0 +#define LITHRSH 0x806f4 + +#define LBARB 0x80700 +#define SLICE_X(x) (x<<28) +#define ARB_RNUM_MAX(x) (x<<23) +#define TH_PRTY(x) (x<<21) +#define RH_PRTY(x) (x<<19) +#define TL_PRTY(x) (x<<17) +#define RL_PRTY(x) (x<<15) +#define BUS_MULTI(x) (x<<8) +#define NET_PREF(x) (x) + +#define SDRAMCON 0x80704 +#define BANK_ON (1<<14) +#define WIDE_DATA (1<<13) +#define TWR_WAIT (1<<12) +#define TRP_WAIT (1<<11) +#define TRAS_WAIT (1<<10) +#define REF_RATE(x) (x) + +#define LBSTAT 0x80708 + +#define RCC_STAT 0x8070c +#define RCC_BUSY (1) + +#define TCMCONFIG 0x80740 +#define TM_DESL2 (1<<10) +#define TM_BANK_WAIT(x) (x<<6) +#define TM_ADD_BANK4(x) (x<<4) +#define TM_PAR_CHECK(x) (x<<3) +#define TM_RW_WAIT(x) (x<<2) +#define TM_SRAM_TYPE(x) (x) + +#define TSRB_BA 0x80744 +#define TSRC_BA 0x80748 +#define TMABR_BA 0x8074c +#define TPD_BA 0x80750 +#define TSRD_BA 0x80758 + +#define TX_CONFIG 0x80760 +#define DRF_THRESH(x) (x<<22) +#define TX_UT_MODE(x) (x<<21) +#define TX_VCI_MASK(x) (x<<17) +#define LBFREE_CNT(x) (x) + +#define TXAAL5_PROTO 0x80764 +#define CPCS_UU(x) (x<<8) +#define CPI(x) (x) + +#define RCMCONFIG 0x80780 +#define RM_DESL2(x) (x<<10) +#define RM_BANK_WAIT(x) (x<<6) +#define RM_ADD_BANK(x) (x<<4) +#define RM_PAR_CHECK(x) (x<<3) +#define RM_RW_WAIT(x) (x<<2) +#define RM_SRAM_TYPE(x) (x) + +#define RCMRSRB_BA 0x80784 +#define RCMLBM_BA 0x80788 +#define RCMABR_BA 0x8078c + +#define RC_CONFIG 0x807c0 +#define UT_RD_DELAY(x) (x<<11) +#define WRAP_MODE(x) (x<<10) +#define RC_UT_MODE(x) (x<<9) +#define RX_ENABLE (1<<8) +#define RX_VALVP(x) (x<<4) +#define RX_VALVC(x) (x) + +#define MCC 0x807c4 +#define OEC 0x807c8 +#define DCC 0x807cc +#define CEC 0x807d0 + +#define HSP_BA 0x807f0 + +#define LB_CONFIG 0x807f4 +#define LB_SIZE(x) (x) + +#define CON_DAT 0x807f8 +#define CON_CTL 0x807fc +#define CON_CTL_MBOX (2<<30) +#define CON_CTL_TCM (1<<30) +#define CON_CTL_RCM (0<<30) +#define CON_CTL_WRITE (1<<29) +#define CON_CTL_READ (0<<29) +#define CON_CTL_BUSY (1<<28) +#define CON_BYTE_DISABLE_3 (1<<22) /* 24..31 */ +#define CON_BYTE_DISABLE_2 (1<<21) /* 16..23 */ +#define CON_BYTE_DISABLE_1 (1<<20) /* 8..15 */ +#define CON_BYTE_DISABLE_0 (1<<19) /* 0..7 */ +#define CON_CTL_ADDR(x) (x) + +#define FRAMER 0x80800 /* to 0x80bfc */ + +/* 3.3 network controller (internal) mailbox registers */ + +#define CS_STPER0 0x0 + /* ... */ +#define CS_STPER31 0x01f + +#define CS_STTIM0 0x020 + /* ... */ +#define CS_STTIM31 0x03f + +#define CS_TGRLD0 0x040 + /* ... */ +#define CS_TGRLD15 0x04f + +#define CS_ERTHR0 0x050 +#define CS_ERTHR1 0x051 +#define CS_ERTHR2 0x052 +#define CS_ERTHR3 0x053 +#define CS_ERTHR4 0x054 +#define CS_ERCTL0 0x055 +#define TX_ENABLE (1<<28) +#define ER_ENABLE (1<<27) +#define CS_ERCTL1 0x056 +#define CS_ERCTL2 0x057 +#define CS_ERSTAT0 0x058 +#define CS_ERSTAT1 0x059 + +#define CS_RTCCT 0x060 +#define CS_RTFWC 0x061 +#define CS_RTFWR 0x062 +#define CS_RTFTC 0x063 +#define CS_RTATR 0x064 + +#define CS_TFBSET 0x070 +#define CS_TFBADD 0x071 +#define CS_TFBSUB 0x072 +#define CS_WCRMAX 0x073 +#define CS_WCRMIN 0x074 +#define CS_WCRINC 0x075 +#define CS_WCRDEC 0x076 +#define CS_WCRCEIL 0x077 +#define CS_BWDCNT 0x078 + +#define CS_OTPPER 0x080 +#define CS_OTWPER 0x081 +#define CS_OTTLIM 0x082 +#define CS_OTTCNT 0x083 + +#define CS_HGRRT0 0x090 + /* ... */ +#define CS_HGRRT7 0x097 + +#define CS_ORPTRS 0x0a0 + +#define RXCON_CLOSE 0x100 + + +#define RCM_MEM_SIZE 0x10000 /* 1M of 32-bit registers */ +#define TCM_MEM_SIZE 0x20000 /* 2M of 32-bit registers */ + +/* 2.5 transmit connection memory registers */ + +#define TSR0_CONN_STATE(x) ((x>>28) & 0x7) +#define TSR0_USE_WMIN (1<<23) +#define TSR0_GROUP(x) ((x & 0x7)<<18) +#define TSR0_ABR (2<<16) +#define TSR0_UBR (1<<16) +#define TSR0_CBR (0<<16) +#define TSR0_PROT (1<<15) +#define TSR0_AAL0_SDU (2<<12) +#define TSR0_AAL0 (1<<12) +#define TSR0_AAL5 (0<<12) +#define TSR0_HALT_ER (1<<11) +#define TSR0_MARK_CI (1<<10) +#define TSR0_MARK_ER (1<<9) +#define TSR0_UPDATE_GER (1<<8) +#define TSR0_RC_INDEX(x) (x & 0x1F) + +#define TSR1_PCR(x) ((x & 0x7FFF)<<16) +#define TSR1_MCR(x) (x & 0x7FFF) + +#define TSR2_ACR(x) ((x & 0x7FFF)<<16) + +#define TSR3_NRM_CNT(x) ((x & 0xFF)<<24) +#define TSR3_CRM_CNT(x) (x & 0xFFFF) + +#define TSR4_FLUSH_CONN (1<<31) +#define TSR4_SESSION_ENDED (1<<30) +#define TSR4_CRC10 (1<<28) +#define TSR4_NULL_CRC10 (1<<27) +#define TSR4_PROT (1<<26) +#define TSR4_AAL0_SDU (2<<23) +#define TSR4_AAL0 (1<<23) +#define TSR4_AAL5 (0<<23) + +#define TSR9_OPEN_CONN (1<<20) + +#define TSR11_ICR(x) ((x & 0x7FFF)<<16) +#define TSR11_TRM(x) ((x & 0x7)<<13) +#define TSR11_NRM(x) ((x & 0x7)<<10) +#define TSR11_ADTF(x) (x & 0x3FF) + +#define TSR13_RDF(x) ((x & 0xF)<<23) +#define TSR13_RIF(x) ((x & 0xF)<<19) +#define TSR13_CDF(x) ((x & 0x7)<<16) +#define TSR13_CRM(x) (x & 0xFFFF) + +#define TSR14_DELETE (1<<31) +#define TSR14_ABR_CLOSE (1<<16) + +/* 2.7.1 per connection receieve state registers */ + +#define RSR0_START_PDU (1<<10) +#define RSR0_OPEN_CONN (1<<6) +#define RSR0_CLOSE_CONN (0<<6) +#define RSR0_PPD_ENABLE (1<<5) +#define RSR0_EPD_ENABLE (1<<4) +#define RSR0_TCP_CKSUM (1<<3) +#define RSR0_AAL5 (0) +#define RSR0_AAL0 (1) +#define RSR0_AAL0_SDU (2) +#define RSR0_RAWCELL (3) +#define RSR0_RAWCELL_CRC10 (4) + +#define RSR1_AQI_ENABLE (1<<20) +#define RSR1_RBPL_ONLY (1<<19) +#define RSR1_GROUP(x) ((x)<<16) + +#define RSR4_AQI_ENABLE (1<<30) +#define RSR4_GROUP(x) ((x)<<27) +#define RSR4_RBPL_ONLY (1<<26) + +/* 2.1.4 transmit packet descriptor */ + +#define TPD_USERCELL 0x0 +#define TPD_SEGMENT_OAMF5 0x4 +#define TPD_END2END_OAMF5 0x5 +#define TPD_RMCELL 0x6 +#define TPD_CELLTYPE(x) (x<<3) +#define TPD_EOS (1<<2) +#define TPD_CLP (1<<1) +#define TPD_INT (1<<0) +#define TPD_LST (1<<31) + +/* table 4.3 serial eeprom information */ + +#define PROD_ID 0x08 /* char[] */ +#define PROD_ID_LEN 30 +#define HW_REV 0x26 /* char[] */ +#define M_SN 0x3a /* integer */ +#define MEDIA 0x3e /* integer */ +#define HE155MM 0x26 +#define HE155SM 0x27 +#define HE622MM 0x46 +#define HE622SM 0x47 +#define MAC_ADDR 0x42 /* char[] */ + +#define CS_LOW 0x0 +#define CS_HIGH ID_CS /* HOST_CNTL_ID_PROM_SEL */ +#define CLK_LOW 0x0 +#define CLK_HIGH ID_CLOCK /* HOST_CNTL_ID_PROM_CLOCK */ +#define SI_HIGH ID_DIN /* HOST_CNTL_ID_PROM_DATA_IN */ +#define EEPROM_DELAY 400 /* microseconds */ + +/* Read from EEPROM = 0000 0011b */ +unsigned int readtab[] = { + CS_HIGH | CLK_HIGH, + CS_LOW | CLK_LOW, + CLK_HIGH, /* 0 */ + CLK_LOW, + CLK_HIGH, /* 0 */ + CLK_LOW, + CLK_HIGH, /* 0 */ + CLK_LOW, + CLK_HIGH, /* 0 */ + CLK_LOW, + CLK_HIGH, /* 0 */ + CLK_LOW, + CLK_HIGH, /* 0 */ + CLK_LOW | SI_HIGH, + CLK_HIGH | SI_HIGH, /* 1 */ + CLK_LOW | SI_HIGH, + CLK_HIGH | SI_HIGH /* 1 */ +}; + +/* Clock to read from/write to the EEPROM */ +unsigned int clocktab[] = { + CLK_LOW, + CLK_HIGH, + CLK_LOW, + CLK_HIGH, + CLK_LOW, + CLK_HIGH, + CLK_LOW, + CLK_HIGH, + CLK_LOW, + CLK_HIGH, + CLK_LOW, + CLK_HIGH, + CLK_LOW, + CLK_HIGH, + CLK_LOW, + CLK_HIGH, + CLK_LOW +}; + + +#endif /* _HE_H_ */ diff -Nru a/drivers/atm/horizon.c b/drivers/atm/horizon.c --- a/drivers/atm/horizon.c Sat May 24 12:48:19 2003 +++ b/drivers/atm/horizon.c Sat May 24 12:48:19 2003 @@ -1768,17 +1768,20 @@ { unsigned int tx_len = skb->len; - unsigned int tx_iovcnt = ATM_SKB(skb)->iovcnt; + unsigned int tx_iovcnt = skb_shinfo(skb)->nr_frags; // remember this so we can free it later dev->tx_skb = skb; if (tx_iovcnt) { // scatter gather transfer dev->tx_regions = tx_iovcnt; - dev->tx_iovec = (struct iovec *) skb->data; + dev->tx_iovec = 0; /* @@@ needs rewritten */ dev->tx_bytes = 0; PRINTD (DBG_TX|DBG_BUS, "TX start scatter-gather transfer (iovec %p, len %d)", skb->data, tx_len); + tx_release (dev); + hrz_kfree_skb (skb); + return -EIO; } else { // simple transfer dev->tx_regions = 0; diff -Nru a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c --- a/drivers/atm/idt77252.c Sat May 24 12:48:24 2003 +++ b/drivers/atm/idt77252.c Sat May 24 12:48:24 2003 @@ -1986,7 +1986,7 @@ return -EINVAL; } - if (ATM_SKB(skb)->iovcnt != 0) { + if (skb_shinfo(skb)->nr_frags != 0) { printk("%s: No scatter-gather yet.\n", card->name); atomic_inc(&vcc->stats->tx_err); dev_kfree_skb(skb); @@ -2023,8 +2023,7 @@ atomic_inc(&vcc->stats->tx_err); return -ENOMEM; } - atomic_add(skb->truesize + ATM_PDU_OVHD, &vcc->sk->wmem_alloc); - ATM_SKB(skb)->iovcnt = 0; + atomic_add(skb->truesize, &vcc->sk->wmem_alloc); memcpy(skb_put(skb, 52), cell, 52); @@ -2403,8 +2402,10 @@ static int idt77252_find_vcc(struct atm_vcc *vcc, short *vpi, int *vci) { + unsigned long flags; struct atm_vcc *walk; + spin_lock_irqsave(&vcc->dev->lock, flags); if (*vpi == ATM_VPI_ANY) { *vpi = 0; walk = vcc->dev->vccs; @@ -2431,6 +2432,7 @@ } } + spin_unlock_irqrestore(&vcc->dev->lock, flags); return 0; } diff -Nru a/drivers/atm/iphase.c b/drivers/atm/iphase.c --- a/drivers/atm/iphase.c Sat May 24 12:48:32 2003 +++ b/drivers/atm/iphase.c Sat May 24 12:48:32 2003 @@ -1167,7 +1167,6 @@ skb_put(skb,len); // pwang_test ATM_SKB(skb)->vcc = vcc; - ATM_SKB(skb)->iovcnt = 0; ATM_DESC(skb) = desc; skb_queue_tail(&iadev->rx_dma_q, skb); @@ -2778,7 +2777,7 @@ if (!capable(CAP_NET_ADMIN)) return -EPERM; tmps = (u16 *)ia_cmds.buf; for(i=0; i<0x80; i+=2, tmps++) - if(put_user(*(u16*)(iadev->seg_reg+i), tmps)) return -EFAULT; + if(put_user((u16)(readl(iadev->seg_reg+i) & 0xffff), tmps)) return -EFAULT; ia_cmds.status = 0; ia_cmds.len = 0x80; break; @@ -2786,26 +2785,33 @@ if (!capable(CAP_NET_ADMIN)) return -EPERM; tmps = (u16 *)ia_cmds.buf; for(i=0; i<0x80; i+=2, tmps++) - if(put_user(*(u16*)(iadev->reass_reg+i), tmps)) return -EFAULT; + if(put_user((u16)(readl(iadev->reass_reg+i) & 0xffff), tmps)) return -EFAULT; ia_cmds.status = 0; ia_cmds.len = 0x80; break; case MEMDUMP_FFL: { - ia_regs_t regs_local; - ffredn_t *ffL = ®s_local.ffredn; - rfredn_t *rfL = ®s_local.rfredn; + ia_regs_t *regs_local; + ffredn_t *ffL; + rfredn_t *rfL; if (!capable(CAP_NET_ADMIN)) return -EPERM; + regs_local = kmalloc(sizeof(*regs_local), GFP_KERNEL); + if (!regs_local) return -ENOMEM; + ffL = ®s_local->ffredn; + rfL = ®s_local->rfredn; /* Copy real rfred registers into the local copy */ for (i=0; i<(sizeof (rfredn_t))/4; i++) - ((u_int *)rfL)[i] = ((u_int *)iadev->reass_reg)[i] & 0xffff; + ((u_int *)rfL)[i] = readl(iadev->reass_reg + i) & 0xffff; /* Copy real ffred registers into the local copy */ for (i=0; i<(sizeof (ffredn_t))/4; i++) - ((u_int *)ffL)[i] = ((u_int *)iadev->seg_reg)[i] & 0xffff; + ((u_int *)ffL)[i] = readl(iadev->seg_reg + i) & 0xffff; - if (copy_to_user(ia_cmds.buf, ®s_local,sizeof(ia_regs_t))) + if (copy_to_user(ia_cmds.buf, regs_local,sizeof(ia_regs_t))) { + kfree(regs_local); return -EFAULT; + } + kfree(regs_local); printk("Board %d registers dumped\n", board); ia_cmds.status = 0; } diff -Nru a/drivers/atm/lanai.c b/drivers/atm/lanai.c --- a/drivers/atm/lanai.c Sat May 24 12:48:22 2003 +++ b/drivers/atm/lanai.c Sat May 24 12:48:22 2003 @@ -2846,7 +2846,6 @@ .phy_get = NULL, .feedback = NULL, .change_qos = lanai_change_qos, - .free_rx_skb = NULL, .proc_read = lanai_proc_read }; diff -Nru a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c --- a/drivers/atm/nicstar.c Sat May 24 12:48:21 2003 +++ b/drivers/atm/nicstar.c Sat May 24 12:48:21 2003 @@ -882,9 +882,14 @@ return error; } - if (ns_parse_mac(mac[i], card->atmdev->esi)) + if (ns_parse_mac(mac[i], card->atmdev->esi)) { nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET, card->atmdev->esi, 6); + if (memcmp(card->atmdev->esi, "\x00\x00\x00\x00\x00\x00", 6) == 0) { + nicstar_read_eprom(card->membase, NICSTAR_EPROM_MAC_ADDR_OFFSET_ALT, + card->atmdev->esi, 6); + } + } printk("nicstar%d: MAC address %02X:%02X:%02X:%02X:%02X:%02X\n", i, card->atmdev->esi[0], card->atmdev->esi[1], card->atmdev->esi[2], @@ -1601,9 +1606,9 @@ card->index); iovb = vc->rx_iov; recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, - ATM_SKB(iovb)->iovcnt); - ATM_SKB(iovb)->iovcnt = 0; - ATM_SKB(iovb)->vcc = NULL; + NS_SKB(iovb)->iovcnt); + NS_SKB(iovb)->iovcnt = 0; + NS_SKB(iovb)->vcc = NULL; ns_grab_int_lock(card, flags); recycle_iov_buf(card, iovb); spin_unlock_irqrestore(&card->int_lock, flags); @@ -1801,7 +1806,7 @@ return -EINVAL; } - if (ATM_SKB(skb)->iovcnt != 0) + if (skb_shinfo(skb)->nr_frags != 0) { printk("nicstar%d: No scatter-gather yet.\n", card->index); atomic_inc(&vcc->stats->tx_err); @@ -2226,30 +2231,30 @@ } } vc->rx_iov = iovb; - ATM_SKB(iovb)->iovcnt = 0; + NS_SKB(iovb)->iovcnt = 0; iovb->len = 0; iovb->tail = iovb->data = iovb->head; - ATM_SKB(iovb)->vcc = vcc; + NS_SKB(iovb)->vcc = vcc; /* IMPORTANT: a pointer to the sk_buff containing the small or large buffer is stored as iovec base, NOT a pointer to the small or large buffer itself. */ } - else if (ATM_SKB(iovb)->iovcnt >= NS_MAX_IOVECS) + else if (NS_SKB(iovb)->iovcnt >= NS_MAX_IOVECS) { printk("nicstar%d: received too big AAL5 SDU.\n", card->index); atomic_inc(&vcc->stats->rx_err); recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, NS_MAX_IOVECS); - ATM_SKB(iovb)->iovcnt = 0; + NS_SKB(iovb)->iovcnt = 0; iovb->len = 0; iovb->tail = iovb->data = iovb->head; - ATM_SKB(iovb)->vcc = vcc; + NS_SKB(iovb)->vcc = vcc; } - iov = &((struct iovec *) iovb->data)[ATM_SKB(iovb)->iovcnt++]; + iov = &((struct iovec *) iovb->data)[NS_SKB(iovb)->iovcnt++]; iov->iov_base = (void *) skb; iov->iov_len = ns_rsqe_cellcount(rsqe) * 48; iovb->len += iov->iov_len; - if (ATM_SKB(iovb)->iovcnt == 1) + if (NS_SKB(iovb)->iovcnt == 1) { if (skb->list != &card->sbpool.queue) { @@ -2263,7 +2268,7 @@ return; } } - else /* ATM_SKB(iovb)->iovcnt >= 2 */ + else /* NS_SKB(iovb)->iovcnt >= 2 */ { if (skb->list != &card->lbpool.queue) { @@ -2272,7 +2277,7 @@ which_list(card, skb); atomic_inc(&vcc->stats->rx_err); recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, - ATM_SKB(iovb)->iovcnt); + NS_SKB(iovb)->iovcnt); vc->rx_iov = NULL; recycle_iov_buf(card, iovb); return; @@ -2296,7 +2301,7 @@ printk(".\n"); atomic_inc(&vcc->stats->rx_err); recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, - ATM_SKB(iovb)->iovcnt); + NS_SKB(iovb)->iovcnt); vc->rx_iov = NULL; recycle_iov_buf(card, iovb); return; @@ -2304,7 +2309,7 @@ /* By this point we (hopefully) have a complete SDU without errors. */ - if (ATM_SKB(iovb)->iovcnt == 1) /* Just a small buffer */ + if (NS_SKB(iovb)->iovcnt == 1) /* Just a small buffer */ { /* skb points to a small buffer */ if (!atm_charge(vcc, skb->truesize)) @@ -2326,7 +2331,7 @@ atomic_inc(&vcc->stats->rx); } } - else if (ATM_SKB(iovb)->iovcnt == 2) /* One small plus one large buffer */ + else if (NS_SKB(iovb)->iovcnt == 2) /* One small plus one large buffer */ { struct sk_buff *sb; @@ -2403,7 +2408,7 @@ printk("nicstar%d: Out of huge buffers.\n", card->index); atomic_inc(&vcc->stats->rx_drop); recycle_iovec_rx_bufs(card, (struct iovec *) iovb->data, - ATM_SKB(iovb)->iovcnt); + NS_SKB(iovb)->iovcnt); vc->rx_iov = NULL; recycle_iov_buf(card, iovb); return; @@ -2441,7 +2446,7 @@ if (!atm_charge(vcc, hb->truesize)) { - recycle_iovec_rx_bufs(card, iov, ATM_SKB(iovb)->iovcnt); + recycle_iovec_rx_bufs(card, iov, NS_SKB(iovb)->iovcnt); if (card->hbpool.count < card->hbnr.max) { skb_queue_tail(&card->hbpool.queue, hb); @@ -2464,7 +2469,7 @@ 0, 0); /* Copy all large buffers to the huge buffer and free them */ - for (j = 1; j < ATM_SKB(iovb)->iovcnt; j++) + for (j = 1; j < NS_SKB(iovb)->iovcnt; j++) { lb = (struct sk_buff *) iov->iov_base; tocopy = MIN(remaining, iov->iov_len); diff -Nru a/drivers/atm/nicstar.h b/drivers/atm/nicstar.h --- a/drivers/atm/nicstar.h Sat May 24 12:48:22 2003 +++ b/drivers/atm/nicstar.h Sat May 24 12:48:22 2003 @@ -96,6 +96,7 @@ /* ESI stuff ******************************************************************/ #define NICSTAR_EPROM_MAC_ADDR_OFFSET 0x6C +#define NICSTAR_EPROM_MAC_ADDR_OFFSET_ALT 0xF6 /* #defines *******************************************************************/ @@ -747,6 +748,15 @@ SCD. 0x00000000 for UBR/VBR/ABR */ int tbd_count; } vc_map; + + +struct ns_skb_data +{ + struct atm_vcc *vcc; + int iovcnt; +}; + +#define NS_SKB(skb) (((struct ns_skb_data *) (skb)->cb)) typedef struct ns_dev diff -Nru a/drivers/atm/zatm.c b/drivers/atm/zatm.c --- a/drivers/atm/zatm.c Sat May 24 12:48:21 2003 +++ b/drivers/atm/zatm.c Sat May 24 12:48:21 2003 @@ -827,10 +827,10 @@ vcc = ATM_SKB(skb)->vcc; zatm_dev = ZATM_DEV(vcc->dev); zatm_vcc = ZATM_VCC(vcc); - EVENT("iovcnt=%d\n",ATM_SKB(skb)->iovcnt,0); + EVENT("iovcnt=%d\n",skb_shinfo(skb)->nr_frags,0); save_flags(flags); cli(); - if (!ATM_SKB(skb)->iovcnt) { + if (!skb_shinfo(skb)->nr_frags) { if (zatm_vcc->txing == RING_ENTRIES-1) { restore_flags(flags); return RING_BUSY; diff -Nru a/drivers/base/base.h b/drivers/base/base.h --- a/drivers/base/base.h Sat May 24 12:48:23 2003 +++ b/drivers/base/base.h Sat May 24 12:48:23 2003 @@ -1,5 +1,3 @@ -extern struct semaphore device_sem; - extern int bus_add_device(struct device * dev); extern void bus_remove_device(struct device * dev); diff -Nru a/drivers/base/bus.c b/drivers/base/bus.c --- a/drivers/base/bus.c Sat May 24 12:48:21 2003 +++ b/drivers/base/bus.c Sat May 24 12:48:21 2003 @@ -316,7 +316,7 @@ * Note that we ignore the error from bus_match(), since it's perfectly * valid for a driver not to bind to any devices. */ -static void driver_attach(struct device_driver * drv) +void driver_attach(struct device_driver * drv) { struct bus_type * bus = drv->bus; struct list_head * entry; diff -Nru a/drivers/base/class.c b/drivers/base/class.c --- a/drivers/base/class.c Sat May 24 12:48:33 2003 +++ b/drivers/base/class.c Sat May 24 12:48:33 2003 @@ -133,6 +133,21 @@ sysfs_remove_link(&class_dev->kobj, "device"); } +static int class_device_driver_link(struct class_device * class_dev) +{ + if ((class_dev->dev) && (class_dev->dev->driver)) + return sysfs_create_link(&class_dev->kobj, + &class_dev->dev->driver->kobj, "driver"); + return 0; +} + +static void class_device_driver_unlink(struct class_device * class_dev) +{ + if ((class_dev->dev) && (class_dev->dev->driver)) + sysfs_remove_link(&class_dev->kobj, "driver"); +} + + #define to_class_dev(obj) container_of(obj,struct class_device,kobj) #define to_class_dev_attr(_attr) container_of(_attr,struct class_device_attribute,attr) @@ -244,7 +259,6 @@ /* first, register with generic layer. */ strncpy(class_dev->kobj.name, class_dev->class_id, KOBJ_NAME_LEN); - kobj_set_kset_s(class_dev, class_subsys); kobj_set_kset_s(class_dev, class_obj_subsys); if (parent) class_dev->kobj.parent = &parent->subsys.kset.kobj; @@ -265,6 +279,7 @@ } class_device_dev_link(class_dev); + class_device_driver_link(class_dev); register_done: if (error && parent) @@ -298,6 +313,7 @@ if (class_dev->dev) { class_device_dev_unlink(class_dev); + class_device_driver_unlink(class_dev); put_device(class_dev->dev); } diff -Nru a/drivers/base/core.c b/drivers/base/core.c --- a/drivers/base/core.c Sat May 24 12:48:20 2003 +++ b/drivers/base/core.c Sat May 24 12:48:20 2003 @@ -21,9 +21,6 @@ int (*platform_notify)(struct device * dev) = NULL; int (*platform_notify_remove)(struct device * dev) = NULL; -DECLARE_MUTEX(device_sem); - - /* * sysfs bindings for devices. */ @@ -180,6 +177,7 @@ void device_initialize(struct device *dev) { + kobj_set_kset_s(dev,devices_subsys); kobject_init(&dev->kobj); INIT_LIST_HEAD(&dev->node); INIT_LIST_HEAD(&dev->children); @@ -214,7 +212,6 @@ /* first, register with generic layer. */ strncpy(dev->kobj.name,dev->bus_id,KOBJ_NAME_LEN); - kobj_set_kset_s(dev,devices_subsys); if (parent) dev->kobj.parent = &parent->kobj; @@ -222,11 +219,11 @@ goto register_done; /* now take care of our own registration */ - if (parent) { - down(&device_sem); + + down_write(&devices_subsys.rwsem); + if (parent) list_add_tail(&dev->node,&parent->children); - up(&device_sem); - } + up_write(&devices_subsys.rwsem); bus_add_device(dev); @@ -304,11 +301,10 @@ { struct device * parent = dev->parent; - if (parent) { - down(&device_sem); + down_write(&devices_subsys.rwsem); + if (parent) list_del_init(&dev->node); - up(&device_sem); - } + up_write(&devices_subsys.rwsem); /* Notify the platform of the removal, in case they * need to do anything... diff -Nru a/drivers/block/DAC960.c b/drivers/block/DAC960.c --- a/drivers/block/DAC960.c Sat May 24 12:48:30 2003 +++ b/drivers/block/DAC960.c Sat May 24 12:48:30 2003 @@ -48,8 +48,7 @@ static DAC960_Controller_T *DAC960_Controllers[DAC960_MaxControllers]; static int DAC960_ControllerCount; -static PROC_DirectoryEntry_T *DAC960_ProcDirectoryEntry; - +static struct proc_dir_entry *DAC960_ProcDirectoryEntry; static long disk_size(DAC960_Controller_T *p, int drive_nr) { @@ -103,7 +102,7 @@ int drive_nr = (int)disk->private_data; struct hd_geometry g, *loc = (struct hd_geometry *)arg; - if (file->f_flags & O_NONBLOCK) + if (file && (file->f_flags & O_NONBLOCK)) return DAC960_UserIOCTL(inode, file, cmd, arg); if (cmd != HDIO_GETGEO || !loc) @@ -759,12 +758,15 @@ { DAC960_Controller_T *Controller = Command->Controller; DECLARE_COMPLETION(Completion); - unsigned long ProcessorFlags; + unsigned long flags; Command->Completion = &Completion; - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + + spin_lock_irqsave(&Controller->queue_lock, flags); DAC960_QueueCommand(Command); - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - if (in_interrupt()) return; + spin_unlock_irqrestore(&Controller->queue_lock, flags); + + if (in_interrupt()) + return; wait_for_completion(&Completion); } @@ -1132,7 +1134,7 @@ { void *ControllerBaseAddress = Controller->BaseAddress; DAC960_HardwareType_T hw_type = Controller->HardwareType; - PCI_Device_T *PCI_Device = Controller->PCIDevice; + struct pci_dev *PCI_Device = Controller->PCIDevice; struct dma_loaf *DmaPages = &Controller->DmaPages; size_t DmaPagesSize; size_t CommandMailboxesSize; @@ -1337,7 +1339,7 @@ *Controller) { void *ControllerBaseAddress = Controller->BaseAddress; - PCI_Device_T *PCI_Device = Controller->PCIDevice; + struct pci_dev *PCI_Device = Controller->PCIDevice; struct dma_loaf *DmaPages = &Controller->DmaPages; size_t DmaPagesSize; size_t CommandMailboxesSize; @@ -1915,8 +1917,8 @@ dma_addr_t SCSI_NewInquiryUnitSerialNumberDMA[DAC960_V1_MaxChannels]; DAC960_SCSI_Inquiry_UnitSerialNumber_T *SCSI_NewInquiryUnitSerialNumberCPU[DAC960_V1_MaxChannels]; - Completion_T Completions[DAC960_V1_MaxChannels]; - unsigned long ProcessorFlags; + struct completion Completions[DAC960_V1_MaxChannels]; + unsigned long flags; int Channel, TargetID; if (!init_dma_loaf(Controller->PCIDevice, &local_dma, @@ -1951,7 +1953,7 @@ DAC960_V1_DCDB_T *DCDB = DCDBs_cpu[Channel]; dma_addr_t DCDB_dma = DCDBs_dma[Channel]; DAC960_Command_T *Command = Controller->Commands[Channel]; - Completion_T *Completion = &Completions[Channel]; + struct completion *Completion = &Completions[Channel]; init_completion(Completion); DAC960_V1_ClearCommand(Command); @@ -1977,9 +1979,10 @@ DCDB->CDB[3] = 0; /* Reserved */ DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_T); DCDB->CDB[5] = 0; /* Control */ - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + + spin_lock_irqsave(&Controller->queue_lock, flags); DAC960_QueueCommand(Command); - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + spin_unlock_irqrestore(&Controller->queue_lock, flags); } /* * Wait for the problems submitted in the previous loop @@ -1999,7 +2002,7 @@ &Controller->V1.InquiryUnitSerialNumber[Channel][TargetID]; DAC960_Command_T *Command = Controller->Commands[Channel]; DAC960_V1_DCDB_T *DCDB = DCDBs_cpu[Channel]; - Completion_T *Completion = &Completions[Channel]; + struct completion *Completion = &Completions[Channel]; wait_for_completion(Completion); @@ -2021,9 +2024,10 @@ DCDB->CDB[3] = 0; /* Reserved */ DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); DCDB->CDB[5] = 0; /* Control */ - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + + spin_lock_irqsave(&Controller->queue_lock, flags); DAC960_QueueCommand(Command); - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + spin_unlock_irqrestore(&Controller->queue_lock, flags); wait_for_completion(Completion); if (Command->V1.CommandStatus != DAC960_V1_NormalCompletion) { @@ -2457,7 +2461,7 @@ static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller) { int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber; - RequestQueue_T *RequestQueue; + struct request_queue *RequestQueue; int n; /* @@ -2642,11 +2646,13 @@ */ static DAC960_Controller_T * -DAC960_DetectController(PCI_Device_T *PCI_Device, - const struct pci_device_id *entry) +DAC960_DetectController(struct pci_dev *PCI_Device, + const struct pci_device_id *entry) { - struct DAC960_privdata *privdata = (struct DAC960_privdata *)entry->driver_data; - irqreturn_t (*InterruptHandler)(int, void *, Registers_T *) = privdata->InterruptHandler; + struct DAC960_privdata *privdata = + (struct DAC960_privdata *)entry->driver_data; + irqreturn_t (*InterruptHandler)(int, void *, struct pt_regs *) = + privdata->InterruptHandler; unsigned int MemoryWindowSize = privdata->MemoryWindowSize; DAC960_Controller_T *Controller = NULL; unsigned char DeviceFunction = PCI_Device->devfn; @@ -3001,7 +3007,7 @@ { if (Controller->ControllerInitialized) { - unsigned long ProcessorFlags; + unsigned long flags; /* * Acquiring and releasing lock here eliminates @@ -3019,9 +3025,11 @@ * commands that complete from this time on will NOT return * their command structure to the free list. */ - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + + spin_lock_irqsave(&Controller->queue_lock, flags); Controller->ShutdownMonitoringTimer = 1; - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + spin_unlock_irqrestore(&Controller->queue_lock, flags); + del_timer_sync(&Controller->MonitoringTimer); if (Controller->FirmwareType == DAC960_V1_Controller) { @@ -3088,7 +3096,7 @@ DAC960_Finalize finalizes the DAC960 Driver. */ -static void DAC960_Remove(PCI_Device_T *PCI_Device) +static void DAC960_Remove(struct pci_dev *PCI_Device) { int Controller_Number = (int)pci_get_drvdata(PCI_Device); DAC960_Controller_T *Controller = DAC960_Controllers[Controller_Number]; @@ -3236,8 +3244,8 @@ static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller, boolean WaitForCommand) { - RequestQueue_T *RequestQueue = &Controller->RequestQueue; - IO_Request_T *Request; + struct request_queue *RequestQueue = &Controller->RequestQueue; + struct request *Request; DAC960_Command_T *Command; if (!Controller->ControllerInitialized) @@ -3293,7 +3301,7 @@ static void DAC960_queue_partial_rw(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; - IO_Request_T *Request = Command->Request; + struct request *Request = Command->Request; if (Command->DmaDirection == PCI_DMA_FROMDEVICE) Command->CommandType = DAC960_ReadRetryCommand; @@ -3324,43 +3332,17 @@ return; } - -/* - DAC960_ProcessRequests attempts to remove as many I/O Requests as possible - from Controller's I/O Request Queue and queue them to the Controller. -*/ - -static inline void DAC960_ProcessRequests(DAC960_Controller_T *Controller) -{ - int Counter = 0; - while (DAC960_ProcessRequest(Controller, Counter++ == 0)) ; -} - - /* DAC960_RequestFunction is the I/O Request Function for DAC960 Controllers. */ -static void DAC960_RequestFunction(RequestQueue_T *RequestQueue) +static void DAC960_RequestFunction(struct request_queue *RequestQueue) { - DAC960_Controller_T *Controller = - (DAC960_Controller_T *) RequestQueue->queuedata; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); + int i = 0; + while (DAC960_ProcessRequest(RequestQueue->queuedata, (i++ == 0))) + ; } - /* DAC960_ProcessCompletedBuffer performs completion processing for an individual Buffer. @@ -3369,7 +3351,7 @@ static inline boolean DAC960_ProcessCompletedRequest(DAC960_Command_T *Command, boolean SuccessfulIO) { - IO_Request_T *Request = Command->Request; + struct request *Request = Command->Request; int UpToDate; UpToDate = 0; @@ -5174,20 +5156,14 @@ static irqreturn_t DAC960_BA_InterruptHandler(int IRQ_Channel, void *DeviceIdentifier, - Registers_T *InterruptRegisters) + struct pt_regs *InterruptRegisters) { DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; void *ControllerBaseAddress = Controller->BaseAddress; DAC960_V2_StatusMailbox_T *NextStatusMailbox; - ProcessorFlags_T ProcessorFlags; + unsigned long flags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags); - /* - Process Hardware Interrupts for Controller. - */ + spin_lock_irqsave(&Controller->queue_lock, flags); DAC960_BA_AcknowledgeInterrupt(ControllerBaseAddress); NextStatusMailbox = Controller->V2.NextStatusMailbox; while (NextStatusMailbox->Fields.CommandIdentifier > 0) @@ -5210,11 +5186,9 @@ Attempt to remove additional I/O Requests from the Controller's I/O Request Queue and queue them to the Controller. */ - while (DAC960_ProcessRequest(Controller, false)) ; - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags); + while (DAC960_ProcessRequest(Controller, false)) + ; + spin_unlock_irqrestore(&Controller->queue_lock, flags); return IRQ_HANDLED; } @@ -5226,19 +5200,14 @@ static irqreturn_t DAC960_LP_InterruptHandler(int IRQ_Channel, void *DeviceIdentifier, - Registers_T *InterruptRegisters) + struct pt_regs *InterruptRegisters) { DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; void *ControllerBaseAddress = Controller->BaseAddress; DAC960_V2_StatusMailbox_T *NextStatusMailbox; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags); - /* - Process Hardware Interrupts for Controller. - */ + unsigned long flags; + + spin_lock_irqsave(&Controller->queue_lock, flags); DAC960_LP_AcknowledgeInterrupt(ControllerBaseAddress); NextStatusMailbox = Controller->V2.NextStatusMailbox; while (NextStatusMailbox->Fields.CommandIdentifier > 0) @@ -5261,11 +5230,9 @@ Attempt to remove additional I/O Requests from the Controller's I/O Request Queue and queue them to the Controller. */ - while (DAC960_ProcessRequest(Controller, false)) ; - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags); + while (DAC960_ProcessRequest(Controller, false)) + ; + spin_unlock_irqrestore(&Controller->queue_lock, flags); return IRQ_HANDLED; } @@ -5277,19 +5244,14 @@ static irqreturn_t DAC960_LA_InterruptHandler(int IRQ_Channel, void *DeviceIdentifier, - Registers_T *InterruptRegisters) + struct pt_regs *InterruptRegisters) { DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; void *ControllerBaseAddress = Controller->BaseAddress; DAC960_V1_StatusMailbox_T *NextStatusMailbox; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags); - /* - Process Hardware Interrupts for Controller. - */ + unsigned long flags; + + spin_lock_irqsave(&Controller->queue_lock, flags); DAC960_LA_AcknowledgeInterrupt(ControllerBaseAddress); NextStatusMailbox = Controller->V1.NextStatusMailbox; while (NextStatusMailbox->Fields.Valid) @@ -5308,11 +5270,9 @@ Attempt to remove additional I/O Requests from the Controller's I/O Request Queue and queue them to the Controller. */ - while (DAC960_ProcessRequest(Controller, false)) ; - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags); + while (DAC960_ProcessRequest(Controller, false)) + ; + spin_unlock_irqrestore(&Controller->queue_lock, flags); return IRQ_HANDLED; } @@ -5324,19 +5284,14 @@ static irqreturn_t DAC960_PG_InterruptHandler(int IRQ_Channel, void *DeviceIdentifier, - Registers_T *InterruptRegisters) + struct pt_regs *InterruptRegisters) { DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; void *ControllerBaseAddress = Controller->BaseAddress; DAC960_V1_StatusMailbox_T *NextStatusMailbox; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags); - /* - Process Hardware Interrupts for Controller. - */ + unsigned long flags; + + spin_lock_irqsave(&Controller->queue_lock, flags); DAC960_PG_AcknowledgeInterrupt(ControllerBaseAddress); NextStatusMailbox = Controller->V1.NextStatusMailbox; while (NextStatusMailbox->Fields.Valid) @@ -5355,11 +5310,9 @@ Attempt to remove additional I/O Requests from the Controller's I/O Request Queue and queue them to the Controller. */ - while (DAC960_ProcessRequest(Controller, false)) ; - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags); + while (DAC960_ProcessRequest(Controller, false)) + ; + spin_unlock_irqrestore(&Controller->queue_lock, flags); return IRQ_HANDLED; } @@ -5371,18 +5324,13 @@ static irqreturn_t DAC960_PD_InterruptHandler(int IRQ_Channel, void *DeviceIdentifier, - Registers_T *InterruptRegisters) + struct pt_regs *InterruptRegisters) { DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; void *ControllerBaseAddress = Controller->BaseAddress; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags); - /* - Process Hardware Interrupts for Controller. - */ + unsigned long flags; + + spin_lock_irqsave(&Controller->queue_lock, flags); while (DAC960_PD_StatusAvailableP(ControllerBaseAddress)) { DAC960_V1_CommandIdentifier_T CommandIdentifier = @@ -5398,11 +5346,9 @@ Attempt to remove additional I/O Requests from the Controller's I/O Request Queue and queue them to the Controller. */ - while (DAC960_ProcessRequest(Controller, false)) ; - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags); + while (DAC960_ProcessRequest(Controller, false)) + ; + spin_unlock_irqrestore(&Controller->queue_lock, flags); return IRQ_HANDLED; } @@ -5418,18 +5364,13 @@ static irqreturn_t DAC960_P_InterruptHandler(int IRQ_Channel, void *DeviceIdentifier, - Registers_T *InterruptRegisters) + struct pt_regs *InterruptRegisters) { DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; void *ControllerBaseAddress = Controller->BaseAddress; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags); - /* - Process Hardware Interrupts for Controller. - */ + unsigned long flags; + + spin_lock_irqsave(&Controller->queue_lock, flags); while (DAC960_PD_StatusAvailableP(ControllerBaseAddress)) { DAC960_V1_CommandIdentifier_T CommandIdentifier = @@ -5480,11 +5421,9 @@ Attempt to remove additional I/O Requests from the Controller's I/O Request Queue and queue them to the Controller. */ - while (DAC960_ProcessRequest(Controller, false)) ; - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags); + while (DAC960_ProcessRequest(Controller, false)) + ; + spin_unlock_irqrestore(&Controller->queue_lock, flags); return IRQ_HANDLED; } @@ -5547,13 +5486,11 @@ { DAC960_Controller_T *Controller = (DAC960_Controller_T *) TimerData; DAC960_Command_T *Command; - ProcessorFlags_T ProcessorFlags; + unsigned long flags; + if (Controller->FirmwareType == DAC960_V1_Controller) { - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + spin_lock_irqsave(&Controller->queue_lock, flags); /* Queue a Status Monitoring Command to Controller. */ @@ -5561,10 +5498,7 @@ if (Command != NULL) DAC960_V1_QueueMonitoringCommand(Command); else Controller->MonitoringCommandDeferred = true; - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + spin_unlock_irqrestore(&Controller->queue_lock, flags); } else { @@ -5613,10 +5547,8 @@ } Controller->V2.StatusChangeCounter = StatusChangeCounter; Controller->PrimaryMonitoringTime = jiffies; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + + spin_lock_irqsave(&Controller->queue_lock, flags); /* Queue a Status Monitoring Command to Controller. */ @@ -5624,10 +5556,7 @@ if (Command != NULL) DAC960_V2_QueueMonitoringCommand(Command); else Controller->MonitoringCommandDeferred = true; - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + spin_unlock_irqrestore(&Controller->queue_lock, flags); /* Wake up any processes waiting on a Health Status Buffer change. */ @@ -5639,7 +5568,7 @@ DAC960_UserIOCTL is the User IOCTL Function for the DAC960 Driver. */ -static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File, +static int DAC960_UserIOCTL(struct inode *inode, struct file *file, unsigned int Request, unsigned long Argument) { int ErrorCode = 0; @@ -5691,7 +5620,7 @@ DAC960_V1_DCDB_T DCDB; DAC960_V1_DCDB_T *DCDB_IOBUF = NULL; dma_addr_t DCDB_IOBUFDMA; - ProcessorFlags_T ProcessorFlags; + unsigned long flags; int ControllerNumber, DataTransferLength; unsigned char *DataTransferBuffer = NULL; dma_addr_t DataTransferBufferDMA; @@ -5764,7 +5693,7 @@ } if (CommandOpcode == DAC960_V1_DCDB) { - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + spin_lock_irqsave(&Controller->queue_lock, flags); while ((Command = DAC960_AllocateCommand(Controller)) == NULL) DAC960_WaitForCommand(Controller); while (Controller->V1.DirectCommandActive[DCDB.Channel] @@ -5778,7 +5707,7 @@ } Controller->V1.DirectCommandActive[DCDB.Channel] [DCDB.TargetID] = true; - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + spin_unlock_irqrestore(&Controller->queue_lock, flags); DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; memcpy(&Command->V1.CommandMailbox, &UserCommand.CommandMailbox, @@ -5789,10 +5718,10 @@ } else { - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + spin_lock_irqsave(&Controller->queue_lock, flags); while ((Command = DAC960_AllocateCommand(Controller)) == NULL) DAC960_WaitForCommand(Controller); - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + spin_unlock_irqrestore(&Controller->queue_lock, flags); DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; memcpy(&Command->V1.CommandMailbox, &UserCommand.CommandMailbox, @@ -5803,9 +5732,9 @@ } DAC960_ExecuteCommand(Command); CommandStatus = Command->V1.CommandStatus; - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + spin_lock_irqsave(&Controller->queue_lock, flags); DAC960_DeallocateCommand(Command); - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + spin_unlock_irqrestore(&Controller->queue_lock, flags); if (DataTransferLength > 0) { if (copy_to_user(UserCommand.DataTransferBuffer, @@ -5848,7 +5777,7 @@ DAC960_Command_T *Command = NULL; DAC960_V2_CommandMailbox_T *CommandMailbox; DAC960_V2_CommandStatus_T CommandStatus; - ProcessorFlags_T ProcessorFlags; + unsigned long flags; int ControllerNumber, DataTransferLength; int DataTransferResidue, RequestSenseLength; unsigned char *DataTransferBuffer = NULL; @@ -5900,10 +5829,10 @@ } memset(RequestSenseBuffer, 0, RequestSenseLength); } - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + spin_lock_irqsave(&Controller->queue_lock, flags); while ((Command = DAC960_AllocateCommand(Controller)) == NULL) DAC960_WaitForCommand(Controller); - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + spin_unlock_irqrestore(&Controller->queue_lock, flags); DAC960_V2_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; CommandMailbox = &Command->V2.CommandMailbox; @@ -5951,9 +5880,9 @@ CommandStatus = Command->V2.CommandStatus; RequestSenseLength = Command->V2.RequestSenseLength; DataTransferResidue = Command->V2.DataTransferResidue; - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + spin_lock_irqsave(&Controller->queue_lock, flags); DAC960_DeallocateCommand(Command); - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + spin_unlock_irqrestore(&Controller->queue_lock, flags); if (RequestSenseLength > UserCommand.RequestSenseLength) RequestSenseLength = UserCommand.RequestSenseLength; if (copy_to_user(&UserSpaceUserCommand->DataTransferLength, @@ -6302,12 +6231,13 @@ { DAC960_Command_T *Command; DAC960_V1_CommandMailbox_T *CommandMailbox; - ProcessorFlags_T ProcessorFlags; + unsigned long flags; unsigned char Channel, TargetID, LogicalDriveNumber; - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + + spin_lock_irqsave(&Controller->queue_lock, flags); while ((Command = DAC960_AllocateCommand(Controller)) == NULL) DAC960_WaitForCommand(Controller); - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + spin_unlock_irqrestore(&Controller->queue_lock, flags); Controller->UserStatusLength = 0; DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; @@ -6497,9 +6427,10 @@ } else DAC960_UserCritical("Illegal User Command: '%s'\n", Controller, UserCommand); - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + + spin_lock_irqsave(&Controller->queue_lock, flags); DAC960_DeallocateCommand(Command); - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + spin_unlock_irqrestore(&Controller->queue_lock, flags); return true; } @@ -6562,13 +6493,14 @@ { DAC960_Command_T *Command; DAC960_V2_CommandMailbox_T *CommandMailbox; - ProcessorFlags_T ProcessorFlags; + unsigned long flags; unsigned char Channel, TargetID, LogicalDriveNumber; unsigned short LogicalDeviceNumber; - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + + spin_lock_irqsave(&Controller->queue_lock, flags); while ((Command = DAC960_AllocateCommand(Controller)) == NULL) DAC960_WaitForCommand(Controller); - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + spin_unlock_irqrestore(&Controller->queue_lock, flags); Controller->UserStatusLength = 0; DAC960_V2_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; @@ -6758,9 +6690,10 @@ Controller->SuppressEnclosureMessages = true; else DAC960_UserCritical("Illegal User Command: '%s'\n", Controller, UserCommand); - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + + spin_lock_irqsave(&Controller->queue_lock, flags); DAC960_DeallocateCommand(Command); - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + spin_unlock_irqrestore(&Controller->queue_lock, flags); return true; } @@ -6893,7 +6826,7 @@ DAC960_ProcWriteUserCommand implements writing /proc/rd/cN/user_command. */ -static int DAC960_ProcWriteUserCommand(File_T *File, const char *Buffer, +static int DAC960_ProcWriteUserCommand(struct file *file, const char *Buffer, unsigned long Count, void *Data) { DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data; @@ -6921,9 +6854,9 @@ static void DAC960_CreateProcEntries(DAC960_Controller_T *Controller) { - PROC_DirectoryEntry_T *StatusProcEntry; - PROC_DirectoryEntry_T *ControllerProcEntry; - PROC_DirectoryEntry_T *UserCommandProcEntry; + struct proc_dir_entry *StatusProcEntry; + struct proc_dir_entry *ControllerProcEntry; + struct proc_dir_entry *UserCommandProcEntry; if (DAC960_ProcDirectoryEntry == NULL) { DAC960_ProcDirectoryEntry = proc_mkdir("rd", NULL); diff -Nru a/drivers/block/DAC960.h b/drivers/block/DAC960.h --- a/drivers/block/DAC960.h Sat May 24 12:48:30 2003 +++ b/drivers/block/DAC960.h Sat May 24 12:48:30 2003 @@ -2203,33 +2203,10 @@ DAC960_Message(DAC960_UserCriticalLevel, Format, ##Arguments) -/* - Define types for some of the structures that interface with the rest - of the Linux Kernel and I/O Subsystem. -*/ - -typedef struct file File_T; -typedef struct block_device_operations BlockDeviceOperations_T; -typedef struct completion Completion_T; -typedef struct hd_geometry DiskGeometry_T; -typedef struct inode Inode_T; -typedef struct inode_operations InodeOperations_T; -typedef kdev_t KernelDevice_T; -typedef struct list_head ListHead_T; -typedef struct pci_dev PCI_Device_T; -typedef struct proc_dir_entry PROC_DirectoryEntry_T; -typedef unsigned long ProcessorFlags_T; -typedef struct pt_regs Registers_T; -typedef struct request IO_Request_T; -typedef request_queue_t RequestQueue_T; -typedef struct super_block SuperBlock_T; -typedef struct timer_list Timer_T; -typedef wait_queue_head_t WaitQueue_T; - struct DAC960_privdata { DAC960_HardwareType_T HardwareType; DAC960_FirmwareType_T FirmwareType; - irqreturn_t (*InterruptHandler)(int, void *, Registers_T *); + irqreturn_t (*InterruptHandler)(int, void *, struct pt_regs *); unsigned int MemoryWindowSize; }; @@ -2295,14 +2272,14 @@ DAC960_CommandType_T CommandType; struct DAC960_Controller *Controller; struct DAC960_Command *Next; - Completion_T *Completion; + struct completion *Completion; unsigned int LogicalDriveNumber; unsigned int BlockNumber; unsigned int BlockCount; unsigned int SegmentCount; int DmaDirection; struct scatterlist *cmd_sglist; - IO_Request_T *Request; + struct request *Request; struct pci_dev *PciDevice; union { struct { @@ -2344,7 +2321,7 @@ DAC960_HardwareType_T HardwareType; DAC960_IO_Address_T IO_Address; DAC960_PCI_Address_T PCI_Address; - PCI_Device_T *PCIDevice; + struct pci_dev *PCIDevice; unsigned char ControllerNumber; unsigned char ControllerName[4]; unsigned char ModelName[20]; @@ -2383,19 +2360,19 @@ boolean DriveSpinUpMessageDisplayed; boolean MonitoringAlertMode; boolean SuppressEnclosureMessages; - Timer_T MonitoringTimer; + struct timer_list MonitoringTimer; struct gendisk *disks[DAC960_MaxLogicalDrives]; struct pci_pool *ScatterGatherPool; DAC960_Command_T *FreeCommands; unsigned char *CombinedStatusBuffer; unsigned char *CurrentStatusBuffer; - RequestQueue_T RequestQueue; + struct request_queue RequestQueue; spinlock_t queue_lock; - WaitQueue_T CommandWaitQueue; - WaitQueue_T HealthStatusWaitQueue; + wait_queue_head_t CommandWaitQueue; + wait_queue_head_t HealthStatusWaitQueue; DAC960_Command_T InitialCommand; DAC960_Command_T *Commands[DAC960_MaxDriverQueueDepth]; - PROC_DirectoryEntry_T *ControllerProcEntry; + struct proc_dir_entry *ControllerProcEntry; boolean LogicalDriveInitiallyAccessible[DAC960_MaxLogicalDrives]; void (*QueueCommand)(DAC960_Command_T *Command); boolean (*ReadControllerConfiguration)(struct DAC960_Controller *); @@ -2596,85 +2573,6 @@ } /* - DAC960_AcquireControllerLock acquires exclusive access to Controller. - Reference the queue_lock through the controller structure, - rather than through the request queue. These macros are - used to mutex on the controller structure during initialization, - BEFORE the request queue is allocated and initialized in - DAC960_RegisterBlockDevice(). -*/ - -static inline -void DAC960_AcquireControllerLock(DAC960_Controller_T *Controller, - ProcessorFlags_T *ProcessorFlags) -{ - spin_lock_irqsave(&Controller->queue_lock, *ProcessorFlags); -} - - -/* - DAC960_ReleaseControllerLock releases exclusive access to Controller. -*/ - -static inline -void DAC960_ReleaseControllerLock(DAC960_Controller_T *Controller, - ProcessorFlags_T *ProcessorFlags) -{ - spin_unlock_irqrestore(&Controller->queue_lock, *ProcessorFlags); -} - - -/* - DAC960_AcquireControllerLockRF acquires exclusive access to Controller, - but is only called from the request function with the queue lock held. -*/ - -static inline -void DAC960_AcquireControllerLockRF(DAC960_Controller_T *Controller, - ProcessorFlags_T *ProcessorFlags) -{ -} - - -/* - DAC960_ReleaseControllerLockRF releases exclusive access to Controller, - but is only called from the request function with the queue lock held. -*/ - -static inline -void DAC960_ReleaseControllerLockRF(DAC960_Controller_T *Controller, - ProcessorFlags_T *ProcessorFlags) -{ -} - - -/* - DAC960_AcquireControllerLockIH acquires exclusive access to Controller, - but is only called from the interrupt handler. -*/ - -static inline -void DAC960_AcquireControllerLockIH(DAC960_Controller_T *Controller, - ProcessorFlags_T *ProcessorFlags) -{ - spin_lock_irqsave(&Controller->queue_lock, *ProcessorFlags); -} - - -/* - DAC960_ReleaseControllerLockIH releases exclusive access to Controller, - but is only called from the interrupt handler. -*/ - -static inline -void DAC960_ReleaseControllerLockIH(DAC960_Controller_T *Controller, - ProcessorFlags_T *ProcessorFlags) -{ - spin_unlock_irqrestore(&Controller->queue_lock, *ProcessorFlags); -} - - -/* Define the DAC960 BA Series Controller Interface Register Offsets. */ @@ -4230,17 +4128,18 @@ static void DAC960_FinalizeController(DAC960_Controller_T *); static void DAC960_V1_QueueReadWriteCommand(DAC960_Command_T *); static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *); -static void DAC960_RequestFunction(RequestQueue_T *); -static irqreturn_t DAC960_BA_InterruptHandler(int, void *, Registers_T *); -static irqreturn_t DAC960_LP_InterruptHandler(int, void *, Registers_T *); -static irqreturn_t DAC960_LA_InterruptHandler(int, void *, Registers_T *); -static irqreturn_t DAC960_PG_InterruptHandler(int, void *, Registers_T *); -static irqreturn_t DAC960_PD_InterruptHandler(int, void *, Registers_T *); -static irqreturn_t DAC960_P_InterruptHandler(int, void *, Registers_T *); +static void DAC960_RequestFunction(struct request_queue *); +static irqreturn_t DAC960_BA_InterruptHandler(int, void *, struct pt_regs *); +static irqreturn_t DAC960_LP_InterruptHandler(int, void *, struct pt_regs *); +static irqreturn_t DAC960_LA_InterruptHandler(int, void *, struct pt_regs *); +static irqreturn_t DAC960_PG_InterruptHandler(int, void *, struct pt_regs *); +static irqreturn_t DAC960_PD_InterruptHandler(int, void *, struct pt_regs *); +static irqreturn_t DAC960_P_InterruptHandler(int, void *, struct pt_regs *); static void DAC960_V1_QueueMonitoringCommand(DAC960_Command_T *); static void DAC960_V2_QueueMonitoringCommand(DAC960_Command_T *); static void DAC960_MonitoringTimerFunction(unsigned long); -static int DAC960_UserIOCTL(Inode_T *, File_T *, unsigned int, unsigned long); +static int DAC960_UserIOCTL(struct inode *, struct file *, + unsigned int, unsigned long); static void DAC960_Message(DAC960_MessageLevel_T, unsigned char *, DAC960_Controller_T *, ...); static void DAC960_CreateProcEntries(DAC960_Controller_T *); diff -Nru a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c --- a/drivers/block/acsi_slm.c Sat May 24 12:48:19 2003 +++ b/drivers/block/acsi_slm.c Sat May 24 12:48:19 2003 @@ -1008,11 +1008,8 @@ devfs_mk_dir("slm"); for (i = 0; i < MAX_SLM; i++) { - char name[16]; - sprintf(name, "slm/%d", i); - devfs_register(NULL, name, DEVFS_FL_DEFAULT, - ACSI_MAJOR, i, S_IFCHR | S_IRUSR | S_IWUSR, - &slm_fops, NULL); + devfs_mk_cdev(MKDEV(ACSI_MAJOR, i), + S_IFCHR|S_IRUSR|S_IWUSR, "slm/%d", i); } return 0; } diff -Nru a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c --- a/drivers/block/cciss_scsi.c Sat May 24 12:48:21 2003 +++ b/drivers/block/cciss_scsi.c Sat May 24 12:48:21 2003 @@ -51,8 +51,6 @@ int cmd_type); -int __init cciss_scsi_detect(Scsi_Host_Template *tpnt); -int cciss_scsi_release(struct Scsi_Host *sh); const char *cciss_scsi_info(struct Scsi_Host *sa); int cciss_scsi_proc_info( @@ -84,22 +82,17 @@ { .name = "cciss7", .ndevices = 0 }, }; -/* We need one Scsi_Host_Template *per controller* instead of - the usual one Scsi_Host_Template per controller *type*. This - is so PCI hot plug could have a remote possibility of still - working even with the SCSI system. It's so - scsi_unregister_host will differentiate the controllers. - When register_scsi_module is called, each host template is - customized (name change) in cciss_register_scsi() (that's - called from cciss_engage_scsi, called from - cciss.c:cciss_proc_write(), on "engage scsi" being received - from user space.) */ - -static -Scsi_Host_Template driver_template[MAX_CTLR] = -{ - CCISS_SCSI, CCISS_SCSI, CCISS_SCSI, CCISS_SCSI, - CCISS_SCSI, CCISS_SCSI, CCISS_SCSI, CCISS_SCSI, +static Scsi_Host_Template cciss_driver_template = { + .module = THIS_MODULE, + .name = "cciss", + .proc_name = "cciss", + .proc_info = cciss_scsi_proc_info, + .queuecommand = cciss_scsi_queue_command, + .can_queue = SCSI_CCISS_CAN_QUEUE, + .this_id = 7, + .sg_tablesize = MAXSGENTRIES, + .cmd_per_lun = 1, + .use_clustering = DISABLE_CLUSTERING, }; #pragma pack(1) @@ -700,60 +693,31 @@ scsi_cmd_free(ctlr, cp); } -/* cciss_scsi_detect is called from the scsi mid layer. - The scsi mid layer (scsi_register_host) is - called from cciss.c:cciss_init_one(). */ - -int __init -cciss_scsi_detect(Scsi_Host_Template *tpnt) +static int __init +cciss_scsi_detect(int ctlr) { - int i; struct Scsi_Host *sh; - /* Tell the kernel we want to be a SCSI driver... */ - sh = scsi_register(tpnt, sizeof(struct ctlr_info *)); - if (sh == NULL) return 0; + sh = scsi_register(&cciss_driver_template, sizeof(struct ctlr_info *)); + if (sh == NULL) + return 0; sh->io_port = 0; // good enough? FIXME, sh->n_io_port = 0; // I don't think we use these two... sh->this_id = SELF_SCSI_ID; - /* This is a bit kludgey, using the adapter name to figure out */ - /* which scsi host template we've got, won't scale beyond 9 ctlrs. */ - i = tpnt->name[5] - '0'; - -# if MAX_CTLR > 9 -# error "cciss_scsi.c: MAX_CTLR > 9, code maintenance needed." -# endif - - if (i<0 || i>=MAX_CTLR || hba[i] == NULL) { - /* we didn't find ourself... we shouldn't get here. */ - printk("cciss_scsi_detect: could not find ourself in hba[]\n"); - return 0; - } - ((struct cciss_scsi_adapter_data_t *) - hba[i]->scsi_ctlr)->scsi_host = (void *) sh; - sh->hostdata[0] = (unsigned long) hba[i]; - sh->irq = hba[i]->intr; + hba[ctlr]->scsi_ctlr)->scsi_host = (void *) sh; + sh->hostdata[0] = (unsigned long) hba[ctlr]; + sh->irq = hba[ctlr]->intr; sh->unique_id = sh->irq; - scsi_set_device(sh, &hba[i]->pdev->dev); + scsi_add_host(sh, &hba[ctlr]->pdev->dev); - return 1; /* Say we have 1 scsi adapter, this will be */ - /* called multiple times, once for each adapter */ - /* from cciss.c:cciss_init_one(). We do it this */ - /* way for PCI-hot plug reasons. (we don't know how */ - /* many adapters we have total, so we say we have */ - /* 1, each of a unique type.) */ + return 1; } static void __exit cleanup_cciss_module(void); -int -cciss_scsi_release(struct Scsi_Host *sh) -{ - return 0; -} static void cciss_unmap_one(struct pci_dev *pdev, @@ -1082,7 +1046,7 @@ } else { printk(KERN_ERR "cciss: Report physical LUNs failed.\n"); - return; + goto out; } @@ -1127,7 +1091,7 @@ } adjust_cciss_scsi_table(cntl_num, hostno, currentsd, ncurrent); - +out: kfree(inq_buff); kfree(ld_buff); return; @@ -1382,33 +1346,6 @@ } static void -init_driver_template(int ctlr) -{ - memset(&driver_template[ctlr], 0, sizeof(driver_template[ctlr])); - driver_template[ctlr].name = ccissscsi[ctlr].name; - driver_template[ctlr].proc_name = ccissscsi[ctlr].name; - driver_template[ctlr].detect = cciss_scsi_detect; - driver_template[ctlr].release = cciss_scsi_release; - driver_template[ctlr].proc_info = cciss_scsi_proc_info; - driver_template[ctlr].queuecommand = cciss_scsi_queue_command; - driver_template[ctlr].eh_abort_handler = NULL; - driver_template[ctlr].eh_device_reset_handler = NULL; - driver_template[ctlr].can_queue = SCSI_CCISS_CAN_QUEUE; - driver_template[ctlr].this_id = 7; - driver_template[ctlr].sg_tablesize = MAXSGENTRIES; - driver_template[ctlr].cmd_per_lun = 1; - driver_template[ctlr].use_clustering = DISABLE_CLUSTERING; - driver_template[ctlr].module = THIS_MODULE; - - /* set scsi_host to NULL so our detect routine will - find us on register */ - - ((struct cciss_scsi_adapter_data_t *) - hba[ctlr]->scsi_ctlr)->scsi_host = NULL; - -} - -static void cciss_unregister_scsi(int ctlr) { struct cciss_scsi_adapter_data_t *sa; @@ -1422,15 +1359,18 @@ stk = &sa->cmd_stack; /* if we weren't ever actually registered, don't unregister */ - if (((struct cciss_scsi_adapter_data_t *) - hba[ctlr]->scsi_ctlr)->registered) { + if (sa->registered) { spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); - scsi_unregister_host(&driver_template[ctlr]); + scsi_remove_host(sa->scsi_host); + scsi_unregister(sa->scsi_host); spin_lock_irqsave(CCISS_LOCK(ctlr), flags); } - init_driver_template(ctlr); + + /* set scsi_host to NULL so our detect routine will + find us on register */ + sa->scsi_host = NULL; scsi_cmd_stack_free(ctlr); - kfree(hba[ctlr]->scsi_ctlr); + kfree(sa); spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); } @@ -1440,9 +1380,6 @@ unsigned long flags; CPQ_TAPE_LOCK(ctlr, flags); - driver_template[ctlr].name = ccissscsi[ctlr].name; - driver_template[ctlr].proc_name = ccissscsi[ctlr].name; - driver_template[ctlr].module = THIS_MODULE;; /* Since this is really a block driver, the SCSI core may not be initialized at init time, in which case, calling scsi_register_host @@ -1454,7 +1391,7 @@ ((struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr)->registered = 1; CPQ_TAPE_UNLOCK(ctlr, flags); - return scsi_register_host(&driver_template[ctlr]); + return cciss_scsi_detect(ctlr); } CPQ_TAPE_UNLOCK(ctlr, flags); printk(KERN_INFO @@ -1489,8 +1426,8 @@ static void cciss_proc_tape_report(int ctlr, unsigned char *buffer, off_t *pos, off_t *len) { + unsigned long flags; int size; - unsigned int flags; *pos = *pos -1; *len = *len - 1; // cut off the last trailing newline diff -Nru a/drivers/block/cciss_scsi.h b/drivers/block/cciss_scsi.h --- a/drivers/block/cciss_scsi.h Sat May 24 12:48:25 2003 +++ b/drivers/block/cciss_scsi.h Sat May 24 12:48:25 2003 @@ -38,23 +38,6 @@ #define SCSI_CCISS_CAN_QUEUE 2 -/* this notation works fine for static initializations (as is the usual - case for linux scsi drivers), but not so well for dynamic settings, - so, if you change this, you also have to change cciss_unregister_scsi() - in cciss_scsi.c */ -#define CCISS_SCSI { \ - name: "", \ - detect: cciss_scsi_detect, \ - release: cciss_scsi_release, \ - proc_info: cciss_scsi_proc_info, \ - queuecommand: cciss_scsi_queue_command, \ - can_queue: SCSI_CCISS_CAN_QUEUE, \ - this_id: 7, \ - sg_tablesize: MAXSGENTRIES, \ - cmd_per_lun: 1, \ - use_clustering: DISABLE_CLUSTERING,\ -} - /* info: cciss_scsi_info, \ diff -Nru a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c --- a/drivers/block/deadline-iosched.c Sat May 24 12:48:30 2003 +++ b/drivers/block/deadline-iosched.c Sat May 24 12:48:30 2003 @@ -28,7 +28,7 @@ static int fifo_batch = 16; /* # of sequential requests treated as one by the above parameters. For throughput. */ -static const int deadline_hash_shift = 10; +static const int deadline_hash_shift = 5; #define DL_HASH_BLOCK(sec) ((sec) >> 3) #define DL_HASH_FN(sec) (hash_long(DL_HASH_BLOCK((sec)), deadline_hash_shift)) #define DL_HASH_ENTRIES (1 << deadline_hash_shift) @@ -71,6 +71,8 @@ int fifo_batch; int writes_starved; int front_merges; + + mempool_t *drq_pool; }; /* @@ -130,6 +132,21 @@ list_add(&drq->hash, &dd->hash[DL_HASH_FN(rq_hash_key(rq))]); } +/* + * move hot entry to front of chain + */ +static inline void +deadline_hot_drq_hash(struct deadline_data *dd, struct deadline_rq *drq) +{ + struct request *rq = drq->request; + struct list_head *head = &dd->hash[DL_HASH_FN(rq_hash_key(rq))]; + + if (ON_HASH(drq) && drq->hash.prev != head) { + list_del(&drq->hash); + list_add(&drq->hash, head); + } +} + static struct request * deadline_find_drq_hash(struct deadline_data *dd, sector_t offset) { @@ -296,11 +313,6 @@ deadline_del_drq_hash(drq); deadline_del_drq_rb(dd, drq); } - - if (q->last_merge == &rq->queuelist) - q->last_merge = NULL; - - list_del_init(&rq->queuelist); } static int @@ -353,6 +365,8 @@ out: q->last_merge = &__rq->queuelist; out_insert: + if (ret) + deadline_hot_drq_hash(dd, RQ_DATA(__rq)); *insert = &__rq->queuelist; return ret; } @@ -673,28 +687,11 @@ static void deadline_exit(request_queue_t *q, elevator_t *e) { struct deadline_data *dd = e->elevator_data; - struct deadline_rq *drq; - struct request *rq; - int i; BUG_ON(!list_empty(&dd->fifo_list[READ])); BUG_ON(!list_empty(&dd->fifo_list[WRITE])); - for (i = READ; i <= WRITE; i++) { - struct request_list *rl = &q->rq[i]; - struct list_head *entry; - - list_for_each(entry, &rl->free) { - rq = list_entry_rq(entry); - - if ((drq = RQ_DATA(rq)) == NULL) - continue; - - rq->elevator_private = NULL; - kmem_cache_free(drq_pool, drq); - } - } - + mempool_destroy(dd->drq_pool); kfree(dd->hash); kfree(dd); } @@ -706,9 +703,7 @@ static int deadline_init(request_queue_t *q, elevator_t *e) { struct deadline_data *dd; - struct deadline_rq *drq; - struct request *rq; - int i, ret = 0; + int i; if (!drq_pool) return -ENOMEM; @@ -724,6 +719,13 @@ return -ENOMEM; } + dd->drq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, drq_pool); + if (!dd->drq_pool) { + kfree(dd->hash); + kfree(dd); + return -ENOMEM; + } + for (i = 0; i < DL_HASH_ENTRIES; i++) INIT_LIST_HEAD(&dd->hash[i]); @@ -739,33 +741,41 @@ dd->front_merges = 1; dd->fifo_batch = fifo_batch; e->elevator_data = dd; + return 0; +} - for (i = READ; i <= WRITE; i++) { - struct request_list *rl = &q->rq[i]; - struct list_head *entry; - - list_for_each(entry, &rl->free) { - rq = list_entry_rq(entry); - - drq = kmem_cache_alloc(drq_pool, GFP_KERNEL); - if (!drq) { - ret = -ENOMEM; - break; - } +static void deadline_put_request(request_queue_t *q, struct request *rq) +{ + struct deadline_data *dd = q->elevator.elevator_data; + struct deadline_rq *drq = RQ_DATA(rq); - memset(drq, 0, sizeof(*drq)); - INIT_LIST_HEAD(&drq->fifo); - INIT_LIST_HEAD(&drq->hash); - RB_CLEAR(&drq->rb_node); - drq->request = rq; - rq->elevator_private = drq; - } + if (drq) { + mempool_free(drq, dd->drq_pool); + rq->elevator_private = NULL; } +} - if (ret) - deadline_exit(q, e); +static int +deadline_set_request(request_queue_t *q, struct request *rq, int gfp_mask) +{ + struct deadline_data *dd = q->elevator.elevator_data; + struct deadline_rq *drq; - return ret; + drq = mempool_alloc(dd->drq_pool, gfp_mask); + if (drq) { + RB_CLEAR(&drq->rb_node); + drq->request = rq; + + INIT_LIST_HEAD(&drq->hash); + drq->hash_valid_count = 0; + + INIT_LIST_HEAD(&drq->fifo); + + rq->elevator_private = drq; + return 0; + } + + return 1; } /* @@ -916,6 +926,8 @@ .elevator_queue_empty_fn = deadline_queue_empty, .elevator_former_req_fn = deadline_former_request, .elevator_latter_req_fn = deadline_latter_request, + .elevator_set_req_fn = deadline_set_request, + .elevator_put_req_fn = deadline_put_request, .elevator_init_fn = deadline_init, .elevator_exit_fn = deadline_exit, diff -Nru a/drivers/block/elevator.c b/drivers/block/elevator.c --- a/drivers/block/elevator.c Sat May 24 12:48:30 2003 +++ b/drivers/block/elevator.c Sat May 24 12:48:30 2003 @@ -39,63 +39,6 @@ #include /* - * This is a bit tricky. It's given that bio and rq are for the same - * device, but the next request might of course not be. Run through - * the tests below to check if we want to insert here if we can't merge - * bio into an existing request - */ -inline int bio_rq_in_between(struct bio *bio, struct request *rq, - struct list_head *head) -{ - struct list_head *next; - struct request *next_rq; - - /* - * if .next is a valid request - */ - next = rq->queuelist.next; - if (unlikely(next == head)) - return 0; - - next_rq = list_entry(next, struct request, queuelist); - - /* - * not a sector based request - */ - if (!(next_rq->flags & REQ_CMD)) - return 0; - - /* - * if the device is different (not a normal case) just check if - * bio is after rq - */ - if (next_rq->rq_disk != rq->rq_disk) - return bio->bi_sector > rq->sector; - - /* - * ok, rq, next_rq and bio are on the same device. if bio is in between - * the two, this is the sweet spot - */ - if (bio->bi_sector < next_rq->sector && bio->bi_sector > rq->sector) - return 1; - - /* - * next_rq is ordered wrt rq, but bio is not in between the two - */ - if (next_rq->sector > rq->sector) - return 0; - - /* - * next_rq and rq not ordered, if we happen to be either before - * next_rq or after rq insert here anyway - */ - if (bio->bi_sector > rq->sector || bio->bi_sector < next_rq->sector) - return 1; - - return 0; -} - -/* * can we safely merge with this request? */ inline int elv_rq_merge_ok(struct request *rq, struct bio *bio) @@ -138,22 +81,10 @@ inline int elv_try_last_merge(request_queue_t *q, struct bio *bio) { - int ret = ELEVATOR_NO_MERGE; - - /* - * give a one-shot try to merging with the last touched - * request - */ - if (q->last_merge) { - struct request *__rq = list_entry_rq(q->last_merge); + if (q->last_merge) + return elv_try_merge(list_entry_rq(q->last_merge), bio); - if (!rq_mergeable(__rq)) - q->last_merge = NULL; - else - ret = elv_try_merge(__rq, bio); - } - - return ret; + return ELEVATOR_NO_MERGE; } /* @@ -181,7 +112,7 @@ else if (__rq->flags & REQ_STARTED) break; - if (!(__rq->flags & REQ_CMD)) + if (!blk_fs_request(__rq)) continue; if ((ret = elv_try_merge(__rq, bio))) { @@ -276,6 +207,9 @@ { elevator_t *e = &q->elevator; + if (q->last_merge == &next->queuelist) + q->last_merge = NULL; + if (e->elevator_merge_req_fn) e->elevator_merge_req_fn(q, rq, next); } @@ -406,6 +340,25 @@ return list_entry_rq(prev); return NULL; +} + +int elv_set_request(request_queue_t *q, struct request *rq, int gfp_mask) +{ + elevator_t *e = &q->elevator; + + if (e->elevator_set_req_fn) + return e->elevator_set_req_fn(q, rq, gfp_mask); + + rq->elevator_private = NULL; + return 0; +} + +void elv_put_request(request_queue_t *q, struct request *rq) +{ + elevator_t *e = &q->elevator; + + if (e->elevator_put_req_fn) + e->elevator_put_req_fn(q, rq); } int elv_register_queue(struct gendisk *disk) diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c --- a/drivers/block/genhd.c Sat May 24 12:48:24 2003 +++ b/drivers/block/genhd.c Sat May 24 12:48:24 2003 @@ -367,9 +367,7 @@ static struct gendisk *base_probe(dev_t dev, int *part, void *data) { - char name[30]; - sprintf(name, "block-major-%d", MAJOR(dev)); - request_module(name); + request_module("block-major-%d", MAJOR(dev)); return NULL; } diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c --- a/drivers/block/ll_rw_blk.c Sat May 24 12:48:20 2003 +++ b/drivers/block/ll_rw_blk.c Sat May 24 12:48:20 2003 @@ -48,12 +48,6 @@ */ static int queue_nr_requests; -/* - * How many free requests must be available before we wake a process which - * is waiting for a request? - */ -static int batch_requests; - unsigned long blk_max_low_pfn, blk_max_pfn; int blk_nohighio = 0; @@ -419,7 +413,7 @@ { struct blk_queue_tag *bqt = q->queue_tags; - if(unlikely(bqt == NULL || bqt->max_depth < tag)) + if (unlikely(bqt == NULL || bqt->max_depth < tag)) return NULL; return bqt->tag_index[tag]; @@ -1122,26 +1116,6 @@ spin_unlock_irq(&blk_plug_lock); } -static int __blk_cleanup_queue(struct request_list *list) -{ - struct list_head *head = &list->free; - struct request *rq; - int i = 0; - - while (!list_empty(head)) { - rq = list_entry(head->next, struct request, queuelist); - list_del_init(&rq->queuelist); - kmem_cache_free(request_cachep, rq); - i++; - } - - if (i != list->count) - printk("request list leak!\n"); - - list->count = 0; - return i; -} - /** * blk_cleanup_queue: - release a &request_queue_t when it is no longer needed * @q: the request queue to be released @@ -1158,18 +1132,14 @@ **/ void blk_cleanup_queue(request_queue_t * q) { - int count = (queue_nr_requests*2); + struct request_list *rl = &q->rq; elevator_exit(q); - count -= __blk_cleanup_queue(&q->rq[READ]); - count -= __blk_cleanup_queue(&q->rq[WRITE]); - del_timer_sync(&q->unplug_timer); flush_scheduled_work(); - if (count) - printk("blk_cleanup_queue: leaked requests (%d)\n", count); + mempool_destroy(rl->rq_pool); if (blk_queue_tagged(q)) blk_queue_free_tags(q); @@ -1179,42 +1149,16 @@ static int blk_init_free_list(request_queue_t *q) { - struct request_list *rl; - struct request *rq; - int i; + struct request_list *rl = &q->rq; - INIT_LIST_HEAD(&q->rq[READ].free); - INIT_LIST_HEAD(&q->rq[WRITE].free); - q->rq[READ].count = 0; - q->rq[WRITE].count = 0; + rl->count[READ] = rl->count[WRITE] = 0; - /* - * Divide requests in half between read and write - */ - rl = &q->rq[READ]; - for (i = 0; i < (queue_nr_requests*2); i++) { - rq = kmem_cache_alloc(request_cachep, SLAB_KERNEL); - if (!rq) - goto nomem; - - /* - * half way through, switch to WRITE list - */ - if (i == queue_nr_requests) - rl = &q->rq[WRITE]; + rl->rq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, request_cachep); - memset(rq, 0, sizeof(struct request)); - rq->rq_status = RQ_INACTIVE; - list_add(&rq->queuelist, &rl->free); - rl->count++; - } + if (!rl->rq_pool) + return -ENOMEM; - init_waitqueue_head(&q->rq[READ].wait); - init_waitqueue_head(&q->rq[WRITE].wait); return 0; -nomem: - blk_cleanup_queue(q); - return 1; } static int __make_request(request_queue_t *, struct bio *); @@ -1276,41 +1220,79 @@ blk_queue_max_hw_segments(q, MAX_HW_SEGMENTS); blk_queue_max_phys_segments(q, MAX_PHYS_SEGMENTS); - INIT_LIST_HEAD(&q->plug_list); - return 0; } +static inline void blk_free_request(request_queue_t *q, struct request *rq) +{ + elv_put_request(q, rq); + mempool_free(rq, q->rq.rq_pool); +} + +static inline struct request *blk_alloc_request(request_queue_t *q,int gfp_mask) +{ + struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask); + + if (!rq) + return NULL; + + if (!elv_set_request(q, rq, gfp_mask)) + return rq; + + mempool_free(rq, q->rq.rq_pool); + return NULL; +} + #define blkdev_free_rq(list) list_entry((list)->next, struct request, queuelist) /* - * Get a free request. queue lock must be held and interrupts - * disabled on the way in. + * Get a free request, queue_lock must not be held */ -static struct request *get_request(request_queue_t *q, int rw) +static struct request *get_request(request_queue_t *q, int rw, int gfp_mask) { struct request *rq = NULL; - struct request_list *rl = q->rq + rw; + struct request_list *rl = &q->rq; - if (!list_empty(&rl->free)) { - rq = blkdev_free_rq(&rl->free); - list_del_init(&rq->queuelist); - rq->ref_count = 1; - rl->count--; - if (rl->count < queue_congestion_on_threshold()) - set_queue_congested(q, rw); - rq->flags = 0; - rq->rq_status = RQ_ACTIVE; - rq->errors = 0; - rq->special = NULL; - rq->buffer = NULL; - rq->data = NULL; - rq->sense = NULL; - rq->waiting = NULL; - rq->bio = rq->biotail = NULL; - rq->q = q; - rq->rl = rl; + spin_lock_irq(q->queue_lock); + if (rl->count[rw] == BLKDEV_MAX_RQ) { + spin_unlock_irq(q->queue_lock); + goto out; } + rl->count[rw]++; + if ((BLKDEV_MAX_RQ - rl->count[rw]) < queue_congestion_on_threshold()) + set_queue_congested(q, rw); + spin_unlock_irq(q->queue_lock); + + rq = blk_alloc_request(q, gfp_mask); + if (!rq) { + spin_lock_irq(q->queue_lock); + rl->count[rw]--; + if ((BLKDEV_MAX_RQ - rl->count[rw]) >= queue_congestion_off_threshold()) + clear_queue_congested(q, rw); + spin_unlock_irq(q->queue_lock); + goto out; + } + + INIT_LIST_HEAD(&rq->queuelist); + /* + * first three bits are identical in rq->flags and bio->bi_rw, + * see bio.h and blkdev.h + */ + rq->flags = rw; + + rq->errors = 0; + rq->rq_status = RQ_ACTIVE; + rq->bio = rq->biotail = NULL; + rq->buffer = NULL; + rq->ref_count = 1; + rq->q = q; + rq->rl = rl; + rq->waiting = NULL; + rq->special = NULL; + rq->data = NULL; + rq->sense = NULL; + +out: return rq; } @@ -1319,31 +1301,16 @@ */ static struct request *get_request_wait(request_queue_t *q, int rw) { - DEFINE_WAIT(wait); - struct request_list *rl = &q->rq[rw]; struct request *rq; - spin_lock_prefetch(q->queue_lock); - generic_unplug_device(q); do { - int block = 0; + rq = get_request(q, rw, GFP_NOIO); - prepare_to_wait_exclusive(&rl->wait, &wait, - TASK_UNINTERRUPTIBLE); - spin_lock_irq(q->queue_lock); - if (!rl->count) - block = 1; - spin_unlock_irq(q->queue_lock); - - if (block) - io_schedule(); - finish_wait(&rl->wait, &wait); + if (!rq) + blk_congestion_wait(rw, HZ / 50); + } while (!rq); - spin_lock_irq(q->queue_lock); - rq = get_request(q, rw); - spin_unlock_irq(q->queue_lock); - } while (rq == NULL); return rq; } @@ -1353,39 +1320,11 @@ BUG_ON(rw != READ && rw != WRITE); - spin_lock_irq(q->queue_lock); - rq = get_request(q, rw); - spin_unlock_irq(q->queue_lock); + rq = get_request(q, rw, gfp_mask); if (!rq && (gfp_mask & __GFP_WAIT)) rq = get_request_wait(q, rw); - if (rq) { - rq->flags = 0; - rq->buffer = NULL; - rq->bio = rq->biotail = NULL; - rq->waiting = NULL; - } - return rq; -} - -/* - * Non-locking blk_get_request variant, for special requests from drivers. - */ -struct request *__blk_get_request(request_queue_t *q, int rw) -{ - struct request *rq; - - BUG_ON(rw != READ && rw != WRITE); - - rq = get_request(q, rw); - - if (rq) { - rq->flags = 0; - rq->buffer = NULL; - rq->bio = rq->biotail = NULL; - rq->waiting = NULL; - } return rq; } @@ -1503,14 +1442,17 @@ disk->stamp_idle = now; } +/* + * queue lock must be held + */ void __blk_put_request(request_queue_t *q, struct request *req) { struct request_list *rl = req->rl; - if (unlikely(--req->ref_count)) - return; if (unlikely(!q)) return; + if (unlikely(--req->ref_count)) + return; req->rq_status = RQ_INACTIVE; req->q = NULL; @@ -1521,24 +1463,15 @@ * it didn't come out of our reserved rq pools */ if (rl) { - int rw = 0; + int rw = rq_data_dir(req); BUG_ON(!list_empty(&req->queuelist)); - list_add(&req->queuelist, &rl->free); + blk_free_request(q, req); - if (rl == &q->rq[WRITE]) - rw = WRITE; - else if (rl == &q->rq[READ]) - rw = READ; - else - BUG(); - - rl->count++; - if (rl->count >= queue_congestion_off_threshold()) + rl->count[rw]--; + if ((BLKDEV_MAX_RQ - rl->count[rw]) >= queue_congestion_off_threshold()) clear_queue_congested(q, rw); - if (rl->count >= batch_requests && waitqueue_active(&rl->wait)) - wake_up(&rl->wait); } } @@ -1605,24 +1538,23 @@ * will have updated segment counts, update sector * counts here. */ - if (q->merge_requests_fn(q, req, next)) { - req->biotail->bi_next = next->bio; - req->biotail = next->biotail; + if (!q->merge_requests_fn(q, req, next)) + return 0; - req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors; + req->biotail->bi_next = next->bio; + req->biotail = next->biotail; - elv_merge_requests(q, req, next); + req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors; - if (req->rq_disk) { - disk_round_stats(req->rq_disk); - disk_stat_dec(req->rq_disk, in_flight); - } + elv_merge_requests(q, req, next); - __blk_put_request(q, next); - return 1; + if (req->rq_disk) { + disk_round_stats(req->rq_disk); + disk_stat_dec(req->rq_disk, in_flight); } - return 0; + __blk_put_request(q, next); + return 1; } static inline int attempt_back_merge(request_queue_t *q, struct request *rq) @@ -1684,7 +1616,8 @@ sector = bio->bi_sector; nr_sectors = bio_sectors(bio); - cur_nr_sectors = bio_iovec(bio)->bv_len >> 9; + cur_nr_sectors = bio_cur_sectors(bio); + rw = bio_data_dir(bio); /* @@ -1698,9 +1631,9 @@ barrier = test_bit(BIO_RW_BARRIER, &bio->bi_rw); - spin_lock_irq(q->queue_lock); again: insert_here = NULL; + spin_lock_irq(q->queue_lock); if (elv_queue_empty(q)) { blk_plug_device(q); @@ -1740,7 +1673,10 @@ } bio->bi_next = req->bio; - req->bio = bio; + req->cbio = req->bio = bio; + req->nr_cbio_segments = bio_segments(bio); + req->nr_cbio_sectors = bio_sectors(bio); + /* * may not be valid. if the low level driver said * it didn't need a bounce buffer then it better @@ -1776,17 +1712,17 @@ if (freereq) { req = freereq; freereq = NULL; - } else if ((req = get_request(q, rw)) == NULL) { + } else { spin_unlock_irq(q->queue_lock); - - /* - * READA bit set - */ - if (bio_flagged(bio, BIO_RW_AHEAD)) - goto end_io; - - freereq = get_request_wait(q, rw); - spin_lock_irq(q->queue_lock); + if ((freereq = get_request(q, rw, GFP_ATOMIC)) == NULL) { + /* + * READA bit set + */ + if (bio_flagged(bio, BIO_RW_AHEAD)) + goto end_io; + + freereq = get_request_wait(q, rw); + } goto again; } @@ -1808,19 +1744,22 @@ req->current_nr_sectors = req->hard_cur_sectors = cur_nr_sectors; req->nr_phys_segments = bio_phys_segments(q, bio); req->nr_hw_segments = bio_hw_segments(q, bio); + req->nr_cbio_segments = bio_segments(bio); + req->nr_cbio_sectors = bio_sectors(bio); req->buffer = bio_data(bio); /* see ->buffer comment above */ req->waiting = NULL; - req->bio = req->biotail = bio; + req->cbio = req->bio = req->biotail = bio; req->rq_disk = bio->bi_bdev->bd_disk; req->start_time = jiffies; + add_request(q, req, insert_here); out: if (freereq) __blk_put_request(q, freereq); if (blk_queue_plugged(q)) { - int nr_queued = (queue_nr_requests - q->rq[0].count) + - (queue_nr_requests - q->rq[1].count); + int nr_queued = q->rq.count[0] + q->rq.count[1]; + if (nr_queued == q->unplug_thresh) __generic_unplug_device(q); } @@ -1981,6 +1920,81 @@ return 1; } +/** + * blk_rq_next_segment + * @rq: the request being processed + * + * Description: + * Points to the next segment in the request if the current segment + * is complete. Leaves things unchanged if this segment is not over + * or if no more segments are left in this request. + * + * Meant to be used for bio traversal during I/O submission + * Does not affect any I/O completions or update completion state + * in the request, and does not modify any bio fields. + * + * Decrementing rq->nr_sectors, rq->current_nr_sectors and + * rq->nr_cbio_sectors as data is transferred is the caller's + * responsibility and should be done before calling this routine. + **/ +void blk_rq_next_segment(struct request *rq) +{ + if (rq->current_nr_sectors > 0) + return; + + if (rq->nr_cbio_sectors > 0) { + --rq->nr_cbio_segments; + rq->current_nr_sectors = blk_rq_vec(rq)->bv_len >> 9; + } else { + if ((rq->cbio = rq->cbio->bi_next)) { + rq->nr_cbio_segments = bio_segments(rq->cbio); + rq->nr_cbio_sectors = bio_sectors(rq->cbio); + rq->current_nr_sectors = bio_cur_sectors(rq->cbio); + } + } + + /* remember the size of this segment before we start I/O */ + rq->hard_cur_sectors = rq->current_nr_sectors; +} + +/** + * process_that_request_first - process partial request submission + * @req: the request being processed + * @nr_sectors: number of sectors I/O has been submitted on + * + * Description: + * May be used for processing bio's while submitting I/O without + * signalling completion. Fails if more data is requested than is + * available in the request in which case it doesn't advance any + * pointers. + * + * Assumes a request is correctly set up. No sanity checks. + * + * Return: + * 0 - no more data left to submit (not processed) + * 1 - data available to submit for this request (processed) + **/ +int process_that_request_first(struct request *req, unsigned int nr_sectors) +{ + unsigned int nsect; + + if (req->nr_sectors < nr_sectors) + return 0; + + req->nr_sectors -= nr_sectors; + req->sector += nr_sectors; + while (nr_sectors) { + nsect = min_t(unsigned, req->current_nr_sectors, nr_sectors); + req->current_nr_sectors -= nsect; + nr_sectors -= nsect; + if (req->cbio) { + req->nr_cbio_sectors -= nsect; + blk_rq_next_segment(req); + } + } + return 1; +} + void blk_recalc_rq_segments(struct request *rq) { struct bio *bio; @@ -1989,8 +2003,6 @@ if (!rq->bio) return; - rq->buffer = bio_data(rq->bio); - nr_phys_segs = nr_hw_segs = 0; rq_for_each_bio(bio, rq) { /* Force bio hw/phys segs to be recalculated. */ @@ -2008,11 +2020,24 @@ { if (blk_fs_request(rq)) { rq->hard_sector += nsect; - rq->nr_sectors = rq->hard_nr_sectors -= nsect; - rq->sector = rq->hard_sector; + rq->hard_nr_sectors -= nsect; + + /* + * Move the I/O submission pointers ahead if required, + * i.e. for drivers not aware of rq->cbio. + */ + if ((rq->nr_sectors >= rq->hard_nr_sectors) && + (rq->sector <= rq->hard_sector)) { + rq->sector = rq->hard_sector; + rq->nr_sectors = rq->hard_nr_sectors; + rq->hard_cur_sectors = bio_cur_sectors(rq->bio); + rq->current_nr_sectors = rq->hard_cur_sectors; + rq->nr_cbio_segments = bio_segments(rq->bio); + rq->nr_cbio_sectors = bio_sectors(rq->bio); + rq->buffer = bio_data(rq->bio); - rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9; - rq->hard_cur_sectors = rq->current_nr_sectors; + rq->cbio = rq->bio; + } /* * if total number of sectors is less than the first segment @@ -2206,14 +2231,31 @@ rq->current_nr_sectors = bio_cur_sectors(bio); rq->hard_cur_sectors = rq->current_nr_sectors; rq->hard_nr_sectors = rq->nr_sectors = bio_sectors(bio); + rq->nr_cbio_segments = bio_segments(bio); + rq->nr_cbio_sectors = bio_sectors(bio); rq->buffer = bio_data(bio); - rq->bio = rq->biotail = bio; + rq->cbio = rq->bio = rq->biotail = bio; +} + +void blk_rq_prep_restart(struct request *rq) +{ + struct bio *bio; + + bio = rq->cbio = rq->bio; + if (bio) { + rq->nr_cbio_segments = bio_segments(bio); + rq->nr_cbio_sectors = bio_sectors(bio); + rq->hard_cur_sectors = bio_cur_sectors(bio); + rq->buffer = bio_data(bio); + } + rq->sector = rq->hard_sector; + rq->nr_sectors = rq->hard_nr_sectors; + rq->current_nr_sectors = rq->hard_cur_sectors; } int __init blk_dev_init(void) { - int total_ram = nr_free_pages() << (PAGE_SHIFT - 10); int i; request_cachep = kmem_cache_create("blkdev_requests", @@ -2221,24 +2263,11 @@ if (!request_cachep) panic("Can't create request pool slab cache\n"); - /* - * Free request slots per queue. One per quarter-megabyte. - * We use this many requests for reads, and this many for writes. - */ - queue_nr_requests = (total_ram >> 9) & ~7; - if (queue_nr_requests < 16) - queue_nr_requests = 16; - if (queue_nr_requests > 128) - queue_nr_requests = 128; - - batch_requests = queue_nr_requests / 8; - if (batch_requests > 8) - batch_requests = 8; + queue_nr_requests = BLKDEV_MAX_RQ; printk("block request queues:\n"); - printk(" %d requests per read queue\n", queue_nr_requests); - printk(" %d requests per write queue\n", queue_nr_requests); - printk(" %d requests per batch\n", batch_requests); + printk(" %d/%d requests per read queue\n", BLKDEV_MIN_RQ, queue_nr_requests); + printk(" %d/%d requests per write queue\n", BLKDEV_MIN_RQ, queue_nr_requests); printk(" enter congestion at %d\n", queue_congestion_on_threshold()); printk(" exit congestion at %d\n", queue_congestion_off_threshold()); @@ -2250,6 +2279,7 @@ return 0; }; +EXPORT_SYMBOL(process_that_request_first); EXPORT_SYMBOL(end_that_request_first); EXPORT_SYMBOL(end_that_request_chunk); EXPORT_SYMBOL(end_that_request_last); @@ -2281,7 +2311,6 @@ EXPORT_SYMBOL(blk_phys_contig_segment); EXPORT_SYMBOL(blk_hw_contig_segment); EXPORT_SYMBOL(blk_get_request); -EXPORT_SYMBOL(__blk_get_request); EXPORT_SYMBOL(blk_put_request); EXPORT_SYMBOL(blk_insert_request); diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c --- a/drivers/block/loop.c Sat May 24 12:48:25 2003 +++ b/drivers/block/loop.c Sat May 24 12:48:25 2003 @@ -651,7 +651,8 @@ int lo_flags = 0; int error; - MOD_INC_USE_COUNT; + /* This is safe, since we have a reference from open(). */ + __module_get(THIS_MODULE); error = -EBUSY; if (lo->lo_state != Lo_unbound) @@ -751,7 +752,8 @@ out_putf: fput(file); out: - MOD_DEC_USE_COUNT; + /* This is safe: open() is still holding a reference. */ + module_put(THIS_MODULE); return error; } @@ -824,7 +826,8 @@ filp->f_dentry->d_inode->i_mapping->gfp_mask = gfp; lo->lo_state = Lo_unbound; fput(filp); - MOD_DEC_USE_COUNT; + /* This is safe: open() is still holding a reference. */ + module_put(THIS_MODULE); return 0; } diff -Nru a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c --- a/drivers/block/paride/pg.c Sat May 24 12:48:31 2003 +++ b/drivers/block/paride/pg.c Sat May 24 12:48:31 2003 @@ -652,11 +652,8 @@ devfs_mk_dir ("pg"); for (unit=0; unitref_count++; + if (!rq->sense) { + memset(sense, 0, sizeof(sense)); + rq->sense = sense; + rq->sense_len = 0; + } + rq->flags |= REQ_NOMERGE; rq->waiting = &wait; drive_stat_acct(rq, rq->nr_sectors, 1); @@ -212,7 +219,7 @@ } } - rq = blk_get_request(q, WRITE, __GFP_WAIT); + rq = blk_get_request(q, writing ? WRITE : READ, __GFP_WAIT); /* * fill in request structure @@ -227,8 +234,6 @@ rq->sense_len = 0; rq->flags |= REQ_BLOCK_PC; - if (writing) - rq->flags |= REQ_RW; rq->hard_nr_sectors = rq->nr_sectors = nr_sectors; rq->hard_cur_sectors = rq->current_nr_sectors = nr_sectors; @@ -299,13 +304,14 @@ #define MOVE_MEDIUM_TIMEOUT (5 * 60 * HZ) #define READ_ELEMENT_STATUS_TIMEOUT (5 * 60 * HZ) #define READ_DEFECT_DATA_TIMEOUT (60 * HZ ) +#define OMAX_SB_LEN 16 /* For backward compatibility */ static int sg_scsi_ioctl(request_queue_t *q, struct block_device *bdev, Scsi_Ioctl_Command *sic) { struct request *rq; int err, in_len, out_len, bytes, opcode, cmdlen; - char *buffer = NULL, sense[24]; + char *buffer = NULL, sense[SCSI_SENSE_BUFFERSIZE]; /* * get in an out lengths, verify they don't exceed a page worth of data @@ -328,7 +334,7 @@ memset(buffer, 0, bytes); } - rq = blk_get_request(q, WRITE, __GFP_WAIT); + rq = blk_get_request(q, in_len ? WRITE : READ, __GFP_WAIT); cmdlen = COMMAND_SIZE(opcode); @@ -372,15 +378,16 @@ rq->data = buffer; rq->data_len = bytes; rq->flags |= REQ_BLOCK_PC; - if (in_len) - rq->flags |= REQ_RW; blk_do_rq(q, bdev, rq); err = rq->errors & 0xff; /* only 8 bit SCSI status */ if (err) { - if (rq->sense_len) - if (copy_to_user(sic->data, rq->sense, rq->sense_len)) + if (rq->sense_len && rq->sense) { + bytes = (OMAX_SB_LEN > rq->sense_len) ? + rq->sense_len : OMAX_SB_LEN; + if (copy_to_user(sic->data, rq->sense, bytes)) err = -EFAULT; + } } else { if (copy_to_user(sic->data, buffer, out_len)) err = -EFAULT; diff -Nru a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c --- a/drivers/bluetooth/hci_ldisc.c Sat May 24 12:48:30 2003 +++ b/drivers/bluetooth/hci_ldisc.c Sat May 24 12:48:30 2003 @@ -535,6 +535,7 @@ hci_uart_ldisc.receive_room= hci_uart_tty_room; hci_uart_ldisc.receive_buf = hci_uart_tty_receive; hci_uart_ldisc.write_wakeup= hci_uart_tty_wakeup; + hci_uart_ldisc.owner = THIS_MODULE; if ((err = tty_register_ldisc(N_HCI, &hci_uart_ldisc))) { BT_ERR("HCI line discipline registration failed. (%d)", err); diff -Nru a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c --- a/drivers/bluetooth/hci_usb.c Sat May 24 12:48:32 2003 +++ b/drivers/bluetooth/hci_usb.c Sat May 24 12:48:32 2003 @@ -64,8 +64,8 @@ #endif #ifndef CONFIG_BT_USB_ZERO_PACKET -#undef USB_ZERO_PACKET -#define USB_ZERO_PACKET 0 +#undef URB_ZERO_PACKET +#define URB_ZERO_PACKET 0 #endif static struct usb_driver hci_usb_driver; @@ -458,7 +458,7 @@ pipe = usb_sndbulkpipe(husb->udev, husb->bulk_out_ep->desc.bEndpointAddress); usb_fill_bulk_urb(urb, husb->udev, pipe, skb->data, skb->len, hci_usb_tx_complete, husb); - urb->transfer_flags = USB_ZERO_PACKET; + urb->transfer_flags = URB_ZERO_PACKET; BT_DBG("%s skb %p len %d", husb->hdev.name, skb, skb->len); diff -Nru a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig --- a/drivers/char/agp/Kconfig Sat May 24 12:48:25 2003 +++ b/drivers/char/agp/Kconfig Sat May 24 12:48:25 2003 @@ -1,6 +1,6 @@ config AGP tristate "/dev/agpgart (AGP Support)" if !GART_IOMMU - default AGP_GART if GART_IOMMU + default y if GART_IOMMU ---help--- AGP (Accelerated Graphics Port) is a bus system mainly used to connect graphics cards to the rest of the system. @@ -25,113 +25,117 @@ a module, say M here and read . The module will be called agpgart. -config AGP_GART - bool "/dev/agpgart (AGP Support)" - depends on GART_IOMMU - -config AGP_INTEL - tristate "Intel 440LX/BX/GX, I8xx and E7x05 support" - depends on AGP && !X86_64 - help - This option gives you AGP support for the GLX component of the - XFree86 4.x on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860 - E7205 and E7505 chipsets and full support for the 810, 815, 830M, 845G, - 852GM, 855GM and 865G integrated graphics chipsets. - - You should say Y here if you use XFree86 3.3.6 or 4.x and want to - use GLX or DRI, or if you have any Intel integrated graphics - chipsets. If unsure, say Y. - -#config AGP_I810 -# tristate "Intel I810/I815/I830M (on-board) support" -# depends on AGP && !X86_64 -# help -# This option gives you AGP support for the Xserver on the Intel 810 -# 815 and 830m chipset boards for their on-board integrated graphics. This -# is required to do any useful video modes with these boards. +config AGP_ALI + tristate "ALI chipset support" + depends on AGP && X86 && !X86_64 + ---help--- + This option gives you AGP support for the GLX component of + XFree86 4.x on the following ALi chipsets. The supported chipsets + include M1541, M1621, M1631, M1632, M1641,M1647,and M1651. + For the ALi-chipset question, ALi suggests you refer to + . -config AGP_VIA - tristate "VIA chipset support" - depends on AGP && !X86_64 - help - This option gives you AGP support for the GLX component of the - XFree86 4.x on VIA MPV3/Apollo Pro chipsets. + The M1541 chipset can do AGP 1x and 2x, but note that there is an + acknowledged incompatibility with Matrox G200 cards. Due to + timing issues, this chipset cannot do AGP 2x with the G200. + This is a hardware limitation. AGP 1x seems to be fine, though. You should say Y here if you use XFree86 3.3.6 or 4.x and want to use GLX or DRI. If unsure, say N. config AGP_AMD - tristate "AMD Irongate, 761, and 762 support" - depends on AGP && !X86_64 + tristate "AMD Irongate, 761, and 762 chipset support" + depends on AGP && X86 && !X86_64 help - This option gives you AGP support for the GLX component of the + This option gives you AGP support for the GLX component of XFree86 4.x on AMD Irongate, 761, and 762 chipsets. You should say Y here if you use XFree86 3.3.6 or 4.x and want to use GLX or DRI. If unsure, say N. -config AGP_SIS - tristate "Generic SiS support" - depends on AGP && !X86_64 +config AGP_AMD_8151 + tristate "AMD Opteron/Athlon64 on-CPU GART support" + depends on AGP && X86 + default GART_IOMMU help - This option gives you AGP support for the GLX component of the "soon - to be released" XFree86 4.x on Silicon Integrated Systems [SiS] - chipsets. + This option gives you AGP support for the GLX component of + XFree86 4.x using the on-CPU AGP bridge of the AMD Athlon64/Opteron CPUs. + You should say Y here if you use XFree86 3.3.6 or 4.x and want to + use GLX or DRI. If unsure, say N - Note that 5591/5592 AGP chipsets are NOT supported. +config AGP_INTEL + tristate "Intel 440LX/BX/GX, I8xx and E7x05 chipset support" + depends on AGP && X86 && !X86_64 + help + This option gives you AGP support for the GLX component of + XFree86 4.x on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860 + E7205 and E7505 chipsets and full support for the 810, 815, 830M, 845G, + 852GM, 855GM and 865G integrated graphics chipsets. You should say Y here if you use XFree86 3.3.6 or 4.x and want to - use GLX or DRI. If unsure, say N. + use GLX or DRI, or if you have any Intel integrated graphics + chipsets. If unsure, say Y. -config AGP_ALI - tristate "ALI chipset support" - depends on AGP && !X86_64 - ---help--- - This option gives you AGP support for the GLX component of the - XFree86 4.x on the following ALi chipsets. The supported chipsets - include M1541, M1621, M1631, M1632, M1641,M1647,and M1651. - For the ALi-chipset question, ALi suggests you refer to - . +config AGP_NVIDIA + tristate "NVIDIA nForce/nForce2 chipset support" + depends on AGP && X86 && !X86_64 + help + This option gives you AGP support for the GLX component of + XFree86 4.x on the following NVIDIA chipsets. The supported chipsets + include nForce and nForce2 - The M1541 chipset can do AGP 1x and 2x, but note that there is an - acknowledged incompatibility with Matrox G200 cards. Due to - timing issues, this chipset cannot do AGP 2x with the G200. - This is a hardware limitation. AGP 1x seems to be fine, though. +config AGP_SIS + tristate "SiS chipset support" + depends on AGP && X86 && !X86_64 + help + This option gives you AGP support for the GLX component of + XFree86 4.x on Silicon Integrated Systems [SiS] chipsets. + + Note that 5591/5592 AGP chipsets are NOT supported. You should say Y here if you use XFree86 3.3.6 or 4.x and want to use GLX or DRI. If unsure, say N. config AGP_SWORKS - tristate "Serverworks LE/HE support" - depends on AGP && !X86_64 + tristate "Serverworks LE/HE chipset support" + depends on AGP && X86 && !X86_64 help Say Y here to support the Serverworks AGP card. See for product descriptions and images. -config AGP_AMD_8151 - tristate "AMD 8151 support" - depends on AGP - default GART_IOMMU +config AGP_VIA + tristate "VIA chipset support" + depends on AGP && X86 && !X86_64 help - Say Y here to support the AMD 8151 AGP bridge and the builtin - GART on the AMD Athlon64/Opteron ("Hammer") CPUs. + This option gives you AGP support for the GLX component of + XFree86 4.x on VIA MPV3/Apollo Pro chipsets. + + You should say Y here if you use XFree86 3.3.6 or 4.x and want to + use GLX or DRI. If unsure, say N. config AGP_I460 - tristate "Intel 460GX support" + tristate "Intel 460GX chipset support" depends on AGP && IA64 help This option gives you AGP GART support for the Intel 460GX chipset for IA64 processors. config AGP_HP_ZX1 - tristate "HP ZX1 AGP support" + tristate "HP ZX1 chipset AGP support" depends on AGP && IA64 help This option gives you AGP GART support for the HP ZX1 chipset for IA64 processors. config AGP_ALPHA_CORE - tristate + tristate "Alpha AGP support" depends on AGP && (ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL) default AGP + +config AGP_UNINORTH + tristate "Apple UniNorth AGP support" + depends on AGP && ALL_PPC + help + This option gives you AGP support for Apple machines with a + UniNorth bridge. diff -Nru a/drivers/char/agp/Makefile b/drivers/char/agp/Makefile --- a/drivers/char/agp/Makefile Sat May 24 12:48:22 2003 +++ b/drivers/char/agp/Makefile Sat May 24 12:48:22 2003 @@ -1,21 +1,16 @@ -# -# Makefile for the agpgart device driver. This driver adds a user -# space ioctl interface to use agp memory. It also adds a kernel interface -# that other drivers could use to manipulate agp memory. +agpgart-y := backend.o frontend.o generic.o isoch.o -agpgart-y := backend.o frontend.o generic.o generic-3.0.o -agpgart-objs := $(agpgart-y) -obj-$(CONFIG_AGP) += agpgart.o - -obj-$(CONFIG_AGP_INTEL) += intel-agp.o -obj-$(CONFIG_AGP_VIA) += via-agp.o -obj-$(CONFIG_AGP_AMD) += amd-k7-agp.o -obj-$(CONFIG_AGP_SIS) += sis-agp.o +obj-$(CONFIG_AGP) += agpgart.o obj-$(CONFIG_AGP_ALI) += ali-agp.o -obj-$(CONFIG_AGP_SWORKS) += sworks-agp.o -obj-$(CONFIG_AGP_I460) += i460-agp.o -obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o +obj-$(CONFIG_AGP_AMD) += amd-k7-agp.o obj-$(CONFIG_AGP_AMD_8151) += amd-k8-agp.o obj-$(CONFIG_AGP_ALPHA_CORE) += alpha-agp.o - +obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o +obj-$(CONFIG_AGP_I460) += i460-agp.o +obj-$(CONFIG_AGP_INTEL) += intel-agp.o +obj-$(CONFIG_AGP_NVIDIA) += nvidia-agp.o +obj-$(CONFIG_AGP_SIS) += sis-agp.o +obj-$(CONFIG_AGP_SWORKS) += sworks-agp.o +obj-$(CONFIG_AGP_UNINORTH) += uninorth-agp.o +obj-$(CONFIG_AGP_VIA) += via-agp.o diff -Nru a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h --- a/drivers/char/agp/agp.h Sat May 24 12:48:24 2003 +++ b/drivers/char/agp/agp.h Sat May 24 12:48:24 2003 @@ -30,27 +30,16 @@ #include /* for flush_agp_cache() */ -extern struct agp_bridge_data *agp_bridge; - #define PFX "agpgart: " -#ifdef CONFIG_SMP -static void ipi_handler(void *null) -{ - flush_agp_cache(); -} - -static void __attribute__((unused)) global_cache_flush(void) -{ - if (on_each_cpu(ipi_handler, NULL, 1, 1) != 0) - panic(PFX "timed out waiting for the other CPUs!\n"); -} +//#define AGP_DEBUG 1 +#ifdef AGP_DEBUG +#define DBG(x,y...) printk (KERN_DEBUG PFX "%s: " x "\n", __FUNCTION__ , ## y) #else -static void global_cache_flush(void) -{ - flush_agp_cache(); -} -#endif /* !CONFIG_SMP */ +#define DBG(x,y...) do { } while (0) +#endif + +extern struct agp_bridge_data *agp_bridge; enum aper_size_type { U8_APER_SIZE, @@ -101,14 +90,39 @@ int page_order; }; +struct agp_bridge_driver { + struct module *owner; + void *aperture_sizes; + int num_aperture_sizes; + enum aper_size_type size_type; + int cant_use_aperture; + int needs_scratch_page; + struct gatt_mask *masks; + int (*fetch_size)(void); + int (*configure)(void); + void (*agp_enable)(u32); + void (*cleanup)(void); + void (*tlb_flush)(struct agp_memory *); + unsigned long (*mask_memory)(unsigned long, int); + void (*cache_flush)(void); + int (*create_gatt_table)(void); + int (*free_gatt_table)(void); + int (*insert_memory)(struct agp_memory *, off_t, int); + int (*remove_memory)(struct agp_memory *, off_t, int); + struct agp_memory *(*alloc_by_type) (size_t, int); + void (*free_by_type)(struct agp_memory *); + void *(*agp_alloc_page)(void); + void (*agp_destroy_page)(void *); +}; + struct agp_bridge_data { struct agp_version *version; - void *aperture_sizes; + struct agp_bridge_driver *driver; + struct vm_operations_struct *vm_ops; void *previous_size; void *current_size; void *dev_private_data; struct pci_dev *dev; - struct gatt_mask *masks; u32 *gatt_table; u32 *gatt_table_real; unsigned long scratch_page; @@ -117,38 +131,14 @@ unsigned long gatt_bus_addr; u32 mode; enum chipset_type type; - enum aper_size_type size_type; unsigned long *key_list; atomic_t current_memory_agp; atomic_t agp_in_use; int max_memory_agp; /* in number of pages */ - int needs_scratch_page; int aperture_size_idx; - int num_aperture_sizes; int capndx; - int cant_use_aperture; - struct vm_operations_struct *vm_ops; - - /* Links to driver specific functions */ - - int (*fetch_size) (void); - int (*configure) (void); - void (*agp_enable) (u32); - void (*cleanup) (void); - void (*tlb_flush) (agp_memory *); - unsigned long (*mask_memory) (unsigned long, int); - void (*cache_flush) (void); - int (*create_gatt_table) (void); - int (*free_gatt_table) (void); - int (*insert_memory) (agp_memory *, off_t, int); - int (*remove_memory) (agp_memory *, off_t, int); - agp_memory *(*alloc_by_type) (size_t, int); - void (*free_by_type) (agp_memory *); - void *(*agp_alloc_page) (void); - void (*agp_destroy_page) (void *); - int (*suspend)(void); - void (*resume)(void); - + char major_version; + char minor_version; }; #define OUTREG64(mmap, addr, val) __raw_writeq((val), (mmap)+(addr)) @@ -165,20 +155,17 @@ #define MB(x) (KB (KB (x))) #define GB(x) (MB (KB (x))) -#define CACHE_FLUSH agp_bridge->cache_flush #define A_SIZE_8(x) ((struct aper_size_info_8 *) x) #define A_SIZE_16(x) ((struct aper_size_info_16 *) x) #define A_SIZE_32(x) ((struct aper_size_info_32 *) x) #define A_SIZE_LVL2(x) ((struct aper_size_info_lvl2 *) x) #define A_SIZE_FIX(x) ((struct aper_size_info_fixed *) x) -#define A_IDX8() (A_SIZE_8(agp_bridge->aperture_sizes) + i) -#define A_IDX16() (A_SIZE_16(agp_bridge->aperture_sizes) + i) -#define A_IDX32() (A_SIZE_32(agp_bridge->aperture_sizes) + i) -#define A_IDXLVL2() (A_SIZE_LVL2(agp_bridge->aperture_sizes) + i) -#define A_IDXFIX() (A_SIZE_FIX(agp_bridge->aperture_sizes) + i) +#define A_IDX8(bridge) (A_SIZE_8((bridge)->driver->aperture_sizes) + i) +#define A_IDX16(bridge) (A_SIZE_16((bridge)->driver->aperture_sizes) + i) +#define A_IDX32(bridge) (A_SIZE_32((bridge)->driver->aperture_sizes) + i) #define MAXKEY (4096 * 32) -#define PGE_EMPTY(p) (!(p) || (p) == (unsigned long) agp_bridge->scratch_page) +#define PGE_EMPTY(b, p) (!(p) || (p) == (unsigned long) (b)->scratch_page) /* intel register */ #define INTEL_APBASE 0x10 @@ -374,31 +361,63 @@ int (*chipset_setup) (struct pci_dev *pdev); /* used to override generic */ }; -struct agp_driver { - struct module *owner; - struct pci_dev *dev; -}; - +/* Driver registration */ +struct agp_bridge_data *agp_alloc_bridge(void); +void agp_put_bridge(struct agp_bridge_data *bridge); +int agp_add_bridge(struct agp_bridge_data *bridge); +void agp_remove_bridge(struct agp_bridge_data *bridge); + +/* Frontend routines. */ +int agp_frontend_initialize(void); +void agp_frontend_cleanup(void); /* Generic routines. */ void agp_generic_enable(u32 mode); int agp_generic_create_gatt_table(void); int agp_generic_free_gatt_table(void); -agp_memory *agp_create_memory(int scratch_pages); -int agp_generic_insert_memory(agp_memory * mem, off_t pg_start, int type); -int agp_generic_remove_memory(agp_memory * mem, off_t pg_start, int type); -agp_memory *agp_generic_alloc_by_type(size_t page_count, int type); -void agp_generic_free_by_type(agp_memory * curr); +struct agp_memory *agp_create_memory(int scratch_pages); +int agp_generic_insert_memory(struct agp_memory *mem, off_t pg_start, int type); +int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type); +struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type); +void agp_generic_free_by_type(struct agp_memory *curr); void *agp_generic_alloc_page(void); void agp_generic_destroy_page(void *addr); -int agp_generic_suspend(void); -void agp_generic_resume(void); void agp_free_key(int key); int agp_num_entries(void); -int agp_register_driver (struct agp_driver *drv); -int agp_unregister_driver(struct agp_driver *drv); u32 agp_collect_device_status(u32 mode, u32 command); void agp_device_command(u32 command, int agp_v3); -int agp_3_0_node_enable(u32 mode, u32 minor); +int agp_3_5_enable(struct agp_bridge_data *bridge); +void global_cache_flush(void); +void get_agp_version(struct agp_bridge_data *bridge); +unsigned long agp_generic_mask_memory(unsigned long addr, int type); + +/* Standard agp registers */ +#define AGPSTAT 0x4 +#define AGPCMD 0x8 +#define AGPNISTAT 0xc +#define AGPNEPG 0x16 +#define AGPNICMD 0x20 + +#define AGP_MAJOR_VERSION_SHIFT (20) +#define AGP_MINOR_VERSION_SHIFT (16) + +#define AGPSTAT_RQ_DEPTH (0xff000000) + +#define AGPSTAT_CAL_MASK (1<<12|1<<11|1<<10) +#define AGPSTAT_ARQSZ (1<<15|1<<14|1<<13) +#define AGPSTAT_ARQSZ_SHIFT 13 + +#define AGPSTAT_SBA (1<<9) +#define AGPSTAT_AGP_ENABLE (1<<8) +#define AGPSTAT_FW (1<<4) +#define AGPSTAT_MODE_3_0 (1<<3) + +#define AGPSTAT2_1X (1<<0) +#define AGPSTAT2_2X (1<<1) +#define AGPSTAT2_4X (1<<2) + +#define AGPSTAT3_RSVD (1<<2) +#define AGPSTAT3_8X (1<<1) +#define AGPSTAT3_4X (1) #endif /* _AGP_BACKEND_PRIV_H */ diff -Nru a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c --- a/drivers/char/agp/ali-agp.c Sat May 24 12:48:27 2003 +++ b/drivers/char/agp/ali-agp.c Sat May 24 12:48:27 2003 @@ -19,9 +19,9 @@ pci_read_config_dword(agp_bridge->dev, ALI_ATTBASE, &temp); temp &= ~(0xfffffff0); - values = A_SIZE_32(agp_bridge->aperture_sizes); + values = A_SIZE_32(agp_bridge->driver->aperture_sizes); - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { if (temp == values[i].size_value) { agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i); @@ -33,14 +33,14 @@ return 0; } -static void ali_tlbflush(agp_memory * mem) +static void ali_tlbflush(struct agp_memory *mem) { u32 temp; pci_read_config_dword(agp_bridge->dev, ALI_TLBCTRL, &temp); -// clear tag - pci_write_config_dword(agp_bridge->dev, ALI_TAGCTRL, - ((temp & 0xfffffff0) | 0x00000001|0x00000002)); + temp &= 0xfffffff0; + temp |= (1<<0 | 1<<1); + pci_write_config_dword(agp_bridge->dev, ALI_TAGCTRL, temp); } static void ali_cleanup(void) @@ -114,51 +114,49 @@ return 0; } -static unsigned long ali_mask_memory(unsigned long addr, int type) -{ - /* Memory type is ignored */ - return addr | agp_bridge->masks[0].mask; -} - -static void ali_cache_flush(void) +static void m1541_cache_flush(void) { - global_cache_flush(); + int i, page_count; + u32 temp; - if (agp_bridge->type == ALI_M1541) { - int i, page_count; - u32 temp; + global_cache_flush(); - page_count = 1 << A_SIZE_32(agp_bridge->current_size)->page_order; - for (i = 0; i < PAGE_SIZE * page_count; i += PAGE_SIZE) { - pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); - pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, - (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | - (agp_bridge->gatt_bus_addr + i)) | - ALI_CACHE_FLUSH_EN)); - } + page_count = 1 << A_SIZE_32(agp_bridge->current_size)->page_order; + for (i = 0; i < PAGE_SIZE * page_count; i += PAGE_SIZE) { + pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, + &temp); + pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, + (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | + (agp_bridge->gatt_bus_addr + i)) | + ALI_CACHE_FLUSH_EN)); } } -static void *ali_alloc_page(void) +static void *m1541_alloc_page(void) { - void *adr = agp_generic_alloc_page(); + void *addr = agp_generic_alloc_page(); u32 temp; - if (adr == 0) - return 0; + if (!addr) + return NULL; + + pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); + pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, + (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | + virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN )); + return addr; +} - if (agp_bridge->type == ALI_M1541) { - pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); - pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, - (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | - virt_to_phys(adr)) | - ALI_CACHE_FLUSH_EN )); +static void ali_destroy_page(void * addr) +{ + if (addr) { + global_cache_flush(); /* is this really needed? --hch */ + agp_generic_destroy_page(addr); } - return adr; } -static void ali_destroy_page(void * addr) +static void m1541_destroy_page(void * addr) { u32 temp; @@ -167,22 +165,15 @@ global_cache_flush(); - if (agp_bridge->type == ALI_M1541) { - pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); - pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, - (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | - virt_to_phys(addr)) | - ALI_CACHE_FLUSH_EN)); - } - + pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); + pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, + (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | + virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN)); agp_generic_destroy_page(addr); } + /* Setup function */ -static struct gatt_mask ali_generic_masks[] = -{ - {.mask = 0x00000000, .type = 0} -}; static struct aper_size_info_32 ali_generic_sizes[7] = { @@ -195,170 +186,181 @@ {4, 1024, 0, 3} }; -static int __init ali_generic_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = ali_generic_masks; - agp_bridge->aperture_sizes = (void *) ali_generic_sizes; - agp_bridge->size_type = U32_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = ali_configure; - agp_bridge->fetch_size = ali_fetch_size; - agp_bridge->cleanup = ali_cleanup; - agp_bridge->tlb_flush = ali_tlbflush; - agp_bridge->mask_memory = ali_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = ali_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = ali_alloc_page; - agp_bridge->agp_destroy_page = ali_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} +struct agp_bridge_driver ali_generic_bridge = { + .owner = THIS_MODULE, + .aperture_sizes = ali_generic_sizes, + .size_type = U32_APER_SIZE, + .num_aperture_sizes = 7, + .configure = ali_configure, + .fetch_size = ali_fetch_size, + .cleanup = ali_cleanup, + .tlb_flush = ali_tlbflush, + .mask_memory = agp_generic_mask_memory, + .masks = NULL, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = ali_destroy_page, +}; + +struct agp_bridge_driver ali_m1541_bridge = { + .owner = THIS_MODULE, + .aperture_sizes = ali_generic_sizes, + .size_type = U32_APER_SIZE, + .num_aperture_sizes = 7, + .configure = ali_configure, + .fetch_size = ali_fetch_size, + .cleanup = ali_cleanup, + .tlb_flush = ali_tlbflush, + .mask_memory = agp_generic_mask_memory, + .masks = NULL, + .agp_enable = agp_generic_enable, + .cache_flush = m1541_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = m1541_alloc_page, + .agp_destroy_page = m1541_destroy_page, +}; + struct agp_device_ids ali_agp_device_ids[] __initdata = { { .device_id = PCI_DEVICE_ID_AL_M1541, - .chipset = ALI_M1541, .chipset_name = "M1541", }, { .device_id = PCI_DEVICE_ID_AL_M1621, - .chipset = ALI_M1621, .chipset_name = "M1621", }, { .device_id = PCI_DEVICE_ID_AL_M1631, - .chipset = ALI_M1631, .chipset_name = "M1631", }, { .device_id = PCI_DEVICE_ID_AL_M1632, - .chipset = ALI_M1632, .chipset_name = "M1632", }, { .device_id = PCI_DEVICE_ID_AL_M1641, - .chipset = ALI_M1641, .chipset_name = "M1641", }, { .device_id = PCI_DEVICE_ID_AL_M1644, - .chipset = ALI_M1644, .chipset_name = "M1644", }, { .device_id = PCI_DEVICE_ID_AL_M1647, - .chipset = ALI_M1647, .chipset_name = "M1647", }, { .device_id = PCI_DEVICE_ID_AL_M1651, - .chipset = ALI_M1651, .chipset_name = "M1651", }, { .device_id = PCI_DEVICE_ID_AL_M1671, - .chipset = ALI_M1671, .chipset_name = "M1671", }, { }, /* dummy final entry, always present */ }; -/* scan table above for supported devices */ -static int __init agp_lookup_host_bridge (struct pci_dev *pdev) +static int __init agp_ali_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - int j=0; - struct agp_device_ids *devs; - - devs = ali_agp_device_ids; + struct agp_device_ids *devs = ali_agp_device_ids; + struct agp_bridge_data *bridge; + u8 hidden_1621_id, cap_ptr; + int j; - while (devs[j].chipset_name != NULL) { - if (pdev->device == devs[j].device_id) { - if (pdev->device == PCI_DEVICE_ID_AL_M1621) { - u8 hidden_1621_id; - - pci_read_config_byte(pdev, 0xFB, &hidden_1621_id); - switch (hidden_1621_id) { - case 0x31: - devs[j].chipset_name="M1631"; - break; - case 0x32: - devs[j].chipset_name="M1632"; - break; - case 0x41: - devs[j].chipset_name="M1641"; - break; - case 0x43: - break; - case 0x47: - devs[j].chipset_name="M1647"; - break; - case 0x51: - devs[j].chipset_name="M1651"; - break; - default: - break; - } - } - - printk (KERN_INFO PFX "Detected ALi %s chipset\n", - devs[j].chipset_name); - agp_bridge->type = devs[j].chipset; - - if (devs[j].chipset_setup != NULL) - return devs[j].chipset_setup(pdev); - else - return ali_generic_setup(pdev); - } - j++; + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + if (!cap_ptr) + return -ENODEV; + + /* probe for known chipsets */ + for (j = 0; devs[j].chipset_name; j++) { + if (pdev->device == devs[j].device_id) + goto found; } - /* try init anyway, if user requests it */ - if (agp_try_unsupported) { - printk(KERN_WARNING PFX "Trying generic ALi routines" - " for device id: %04x\n", pdev->device); - agp_bridge->type = ALI_GENERIC; - return ali_generic_setup(pdev); + if (!agp_try_unsupported) { + printk(KERN_ERR PFX + "Unsupported ALi chipset (device id: %04x)," + " you might want to try agp_try_unsupported=1.\n", + pdev->device); + return -ENODEV; } - printk(KERN_ERR PFX "Unsupported ALi chipset (device id: %04x)," - " you might want to try agp_try_unsupported=1.\n", pdev->device); - return -ENODEV; -} + printk(KERN_WARNING PFX "Trying generic ALi routines" + " for device id: %04x\n", pdev->device); -static struct agp_driver ali_agp_driver = { - .owner = THIS_MODULE, -}; +found: + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; + + bridge->dev = pdev; + bridge->capndx = cap_ptr; + + switch (pdev->device) { + case PCI_DEVICE_ID_AL_M1541: + bridge->driver = &ali_m1541_bridge; + break; + case PCI_DEVICE_ID_AL_M1621: + pci_read_config_byte(pdev, 0xFB, &hidden_1621_id); + switch (hidden_1621_id) { + case 0x31: + devs[j].chipset_name = "M1631"; + break; + case 0x32: + devs[j].chipset_name = "M1632"; + break; + case 0x41: + devs[j].chipset_name = "M1641"; + break; + case 0x43: + break; + case 0x47: + devs[j].chipset_name = "M1647"; + break; + case 0x51: + devs[j].chipset_name = "M1651"; + break; + default: + break; + } + /*FALLTHROUGH*/ + default: + bridge->driver = &ali_generic_bridge; + } -static int __init agp_ali_probe (struct pci_dev *dev, const struct pci_device_id *ent) -{ - u8 cap_ptr = 0; + printk(KERN_INFO PFX "Detected ALi %s chipset\n", + devs[j].chipset_name); - cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP); - if (cap_ptr == 0) - return -ENODEV; + /* Fill in the mode register */ + pci_read_config_dword(pdev, + bridge->capndx+PCI_AGP_STATUS, + &bridge->mode); - /* probe for known chipsets */ - if (agp_lookup_host_bridge(dev) != -ENODEV) { - agp_bridge->dev = dev; - agp_bridge->capndx = cap_ptr; - /* Fill in the mode register */ - pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode); - ali_agp_driver.dev = dev; - agp_register_driver(&ali_agp_driver); - return 0; - } - return -ENODEV; + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); +} + +static void __devexit agp_ali_remove(struct pci_dev *pdev) +{ + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + + agp_remove_bridge(bridge); + agp_put_bridge(bridge); } static struct pci_device_id agp_ali_pci_table[] __initdata = { @@ -375,26 +377,20 @@ MODULE_DEVICE_TABLE(pci, agp_ali_pci_table); -static struct __initdata pci_driver agp_ali_pci_driver = { +static struct pci_driver agp_ali_pci_driver = { .name = "agpgart-ali", .id_table = agp_ali_pci_table, .probe = agp_ali_probe, + .remove = agp_ali_remove, }; static int __init agp_ali_init(void) { - int ret_val; - - ret_val = pci_module_init(&agp_ali_pci_driver); - if (ret_val) - agp_bridge->type = NOT_SUPPORTED; - - return ret_val; + return pci_module_init(&agp_ali_pci_driver); } static void __exit agp_ali_cleanup(void) { - agp_unregister_driver(&ali_agp_driver); pci_unregister_driver(&agp_ali_pci_driver); } diff -Nru a/drivers/char/agp/alpha-agp.c b/drivers/char/agp/alpha-agp.c --- a/drivers/char/agp/alpha-agp.c Sat May 24 12:48:27 2003 +++ b/drivers/char/agp/alpha-agp.c Sat May 24 12:48:27 2003 @@ -38,10 +38,6 @@ { 0, 0, 0 }, /* filled in by alpha_core_agp_setup */ }; -static struct gatt_mask alpha_core_agp_masks[] = { - { .mask = 0, .type = 0 }, -}; - struct vm_operations_struct alpha_core_agp_vm_ops = { .nopage = alpha_core_agp_vm_nopage, }; @@ -72,18 +68,12 @@ agp->ops->cleanup(agp); } -static void alpha_core_agp_tlbflush(agp_memory *mem) +static void alpha_core_agp_tlbflush(struct agp_memory *mem) { alpha_agp_info *agp = agp_bridge->dev_private_data; alpha_mv.mv_pci_tbi(agp->hose, 0, -1); } -static unsigned long alpha_core_agp_mask_memory(unsigned long addr, int type) -{ - /* Memory type is ignored */ - return addr | agp_bridge->masks[0].mask; -} - static void alpha_core_agp_enable(u32 mode) { alpha_agp_info *agp = agp_bridge->dev_private_data; @@ -96,7 +86,7 @@ agp_device_command(agp->mode.lw, 0); } -static int alpha_core_agp_insert_memory(agp_memory *mem, off_t pg_start, +static int alpha_core_agp_insert_memory(struct agp_memory *mem, off_t pg_start, int type) { alpha_agp_info *agp = agp_bridge->dev_private_data; @@ -109,105 +99,109 @@ status = agp->ops->bind(agp, pg_start, mem); mb(); - agp_bridge->tlb_flush(mem); + alpha_core_agp_tlbflush(mem); return status; } -static int alpha_core_agp_remove_memory(agp_memory *mem, off_t pg_start, +static int alpha_core_agp_remove_memory(struct agp_memory *mem, off_t pg_start, int type) { alpha_agp_info *agp = agp_bridge->dev_private_data; int status; status = agp->ops->unbind(agp, pg_start, mem); - agp_bridge->tlb_flush(mem); + alpha_core_agp_tlbflush(mem); return status; } - -static struct agp_driver alpha_core_agp_driver = { - .owner = THIS_MODULE, +struct agp_bridge_driver alpha_core_agp_driver = { + .owner = THIS_MODULE, + .aperture_sizes = alpha_core_agp_sizes, + .num_aperture_sizes = 1, + .size_type = FIXED_APER_SIZE, + .cant_use_aperture = 1, + .masks = NULL, + + .fetch_size = alpha_core_agp_fetch_size, + .configure = alpha_core_agp_configure, + .agp_enable = alpha_core_agp_enable, + .cleanup = alpha_core_agp_cleanup, + .tlb_flush = alpha_core_agp_tlbflush, + .mask_memory = agp_generic_mask_memory, + .cache_flush = global_cache_flush, + .create_gatt_table = alpha_core_agp_nop, + .free_gatt_table = alpha_core_agp_nop, + .insert_memory = alpha_core_agp_insert_memory, + .remove_memory = alpha_core_agp_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, }; +struct agp_bridge_data *alpha_bridge; + int __init alpha_core_agp_setup(void) { alpha_agp_info *agp = alpha_mv.agp_info(); + struct pci_dev *pdev; /* faked */ struct aper_size_info_fixed *aper_size; - if (!agp) return -ENODEV; - if (agp->ops->setup(agp)) return -ENODEV; + if (!agp) + return -ENODEV; + if (agp->ops->setup(agp)) + return -ENODEV; /* * Build the aperture size descriptor */ aper_size = alpha_core_agp_sizes; - if (!aper_size) return -ENOMEM; aper_size->size = agp->aperture.size / (1024 * 1024); aper_size->num_entries = agp->aperture.size / PAGE_SIZE; - aper_size->page_order = ffs(aper_size->num_entries / 1024) - 1; + aper_size->page_order = __ffs(aper_size->num_entries / 1024); /* * Build a fake pci_dev struct */ - if (!(agp_bridge->dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL))) { + pdev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); + if (!pdev) return -ENOMEM; - } - agp_bridge->dev->vendor = 0xffff; - agp_bridge->dev->device = 0xffff; - agp_bridge->dev->sysdata = agp->hose; + pdev->vendor = 0xffff; + pdev->device = 0xffff; + pdev->sysdata = agp->hose; + + alpha_bridge = agp_alloc_bridge(); + if (!alpha_bridge) + goto fail; + + alpha_bridge->driver = &alpha_core_agp_driver; + alpha_bridge->vm_ops = &alpha_core_agp_vm_ops; + alpha_bridge->current_size = aper_size; /* only 1 size */ + alpha_bridge->dev_private_data = agp; + alpha_bridge->dev = pdev; + alpha_bridge->mode = agp->capability.lw; - /* - * Fill in the rest of the agp_bridge struct - */ - agp_bridge->masks = alpha_core_agp_masks; - agp_bridge->aperture_sizes = aper_size; - agp_bridge->current_size = aper_size; /* only one entry */ - agp_bridge->size_type = FIXED_APER_SIZE; - agp_bridge->num_aperture_sizes = 1; - agp_bridge->dev_private_data = agp; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = alpha_core_agp_configure; - agp_bridge->fetch_size = alpha_core_agp_fetch_size; - agp_bridge->cleanup = alpha_core_agp_cleanup; - agp_bridge->tlb_flush = alpha_core_agp_tlbflush; - agp_bridge->mask_memory = alpha_core_agp_mask_memory; - agp_bridge->agp_enable = alpha_core_agp_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = alpha_core_agp_nop; - agp_bridge->free_gatt_table = alpha_core_agp_nop; - agp_bridge->insert_memory = alpha_core_agp_insert_memory; - agp_bridge->remove_memory = alpha_core_agp_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->mode = agp->capability.lw; - agp_bridge->cant_use_aperture = 1; - agp_bridge->vm_ops = &alpha_core_agp_vm_ops; - - alpha_core_agp_driver.dev = agp_bridge->dev; - agp_register_driver(&alpha_core_agp_driver); printk(KERN_INFO "Detected AGP on hose %d\n", agp->hose->index); - return 0; + return agp_add_bridge(alpha_bridge); + + fail: + kfree(pdev); + return -ENOMEM; } static int __init agp_alpha_core_init(void) { - int ret_val = -ENODEV; - if (alpha_mv.agp_info) { - agp_bridge->type = ALPHA_CORE_AGP; - ret_val = alpha_core_agp_setup(); - } - - return ret_val; + if (alpha_mv.agp_info) + return alpha_core_agp_setup(); + return -ENODEV; } static void __exit agp_alpha_core_cleanup(void) { - agp_unregister_driver(&alpha_core_agp_driver); - /* no pci driver for core */ + agp_remove_bridge(alpha_bridge); + agp_put_bridge(alpha_bridge); } module_init(agp_alpha_core_init); diff -Nru a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c --- a/drivers/char/agp/amd-k7-agp.c Sat May 24 12:48:33 2003 +++ b/drivers/char/agp/amd-k7-agp.c Sat May 24 12:48:33 2003 @@ -29,11 +29,11 @@ int i; page_map->real = (unsigned long *) __get_free_page(GFP_KERNEL); - if (page_map->real == NULL) { + if (page_map->real == NULL) return -ENOMEM; - } + SetPageReserved(virt_to_page(page_map->real)); - CACHE_FLUSH(); + global_cache_flush(); page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), PAGE_SIZE); if (page_map->remapped == NULL) { @@ -42,11 +42,10 @@ page_map->real = NULL; return -ENOMEM; } - CACHE_FLUSH(); + global_cache_flush(); - for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) { + for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) page_map->remapped[i] = agp_bridge->scratch_page; - } return 0; } @@ -65,16 +64,16 @@ struct amd_page_map *entry; tables = amd_irongate_private.gatt_pages; - for(i = 0; i < amd_irongate_private.num_tables; i++) { + for (i = 0; i < amd_irongate_private.num_tables; i++) { entry = tables[i]; if (entry != NULL) { - if (entry->real != NULL) { + if (entry->real != NULL) amd_free_page_map(entry); - } kfree(entry); } } kfree(tables); + amd_irongate_private.gatt_pages = NULL; } static int amd_create_gatt_pages(int nr_tables) @@ -86,25 +85,27 @@ tables = kmalloc((nr_tables + 1) * sizeof(struct amd_page_map *), GFP_KERNEL); - if (tables == NULL) { + if (tables == NULL) return -ENOMEM; - } - memset(tables, 0, sizeof(struct amd_page_map *) * (nr_tables + 1)); + + memset (tables, 0, sizeof(struct amd_page_map *) * (nr_tables + 1)); for (i = 0; i < nr_tables; i++) { entry = kmalloc(sizeof(struct amd_page_map), GFP_KERNEL); if (entry == NULL) { retval = -ENOMEM; break; } - memset(entry, 0, sizeof(struct amd_page_map)); + memset (entry, 0, sizeof(struct amd_page_map)); tables[i] = entry; retval = amd_create_page_map(entry); - if (retval != 0) break; + if (retval != 0) + break; } amd_irongate_private.num_tables = nr_tables; amd_irongate_private.gatt_pages = tables; - if (retval != 0) amd_free_gatt_pages(); + if (retval != 0) + amd_free_gatt_pages(); return retval; } @@ -131,9 +132,8 @@ value = A_SIZE_LVL2(agp_bridge->current_size); retval = amd_create_page_map(&page_dir); - if (retval != 0) { + if (retval != 0) return retval; - } retval = amd_create_gatt_pages(value->num_entries / 1024); if (retval != 0) { @@ -155,7 +155,7 @@ agp_bridge->gart_bus_addr = addr; /* Calculate the agp offset */ - for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) { + for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) { page_dir.remapped[GET_PAGE_DIR_OFF(addr)] = virt_to_phys(amd_irongate_private.gatt_pages[i]->real); page_dir.remapped[GET_PAGE_DIR_OFF(addr)] |= 0x00000001; @@ -184,8 +184,8 @@ pci_read_config_dword(agp_bridge->dev, AMD_APSIZE, &temp); temp = (temp & 0x0000000e); - values = A_SIZE_LVL2(agp_bridge->aperture_sizes); - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + values = A_SIZE_LVL2(agp_bridge->driver->aperture_sizes); + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { if (temp == values[i].size_value) { agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i); @@ -265,20 +265,12 @@ * entries. */ -static void amd_irongate_tlbflush(agp_memory * temp) +static void amd_irongate_tlbflush(struct agp_memory *temp) { OUTREG32(amd_irongate_private.registers, AMD_TLBFLUSH, 0x00000001); } -static unsigned long amd_irongate_mask_memory(unsigned long addr, int type) -{ - /* Only type 0 is supported by the irongate */ - - return addr | agp_bridge->masks[0].mask; -} - -static int amd_insert_memory(agp_memory * mem, - off_t pg_start, int type) +static int amd_insert_memory(struct agp_memory *mem, off_t pg_start, int type) { int i, j, num_entries; unsigned long *cur_gatt; @@ -286,25 +278,23 @@ num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries; - if (type != 0 || mem->type != 0) { + if (type != 0 || mem->type != 0) return -EINVAL; - } - if ((pg_start + mem->page_count) > num_entries) { + + if ((pg_start + mem->page_count) > num_entries) return -EINVAL; - } j = pg_start; while (j < (pg_start + mem->page_count)) { addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr; cur_gatt = GET_GATT(addr); - if (!PGE_EMPTY(cur_gatt[GET_GATT_OFF(addr)])) { + if (!PGE_EMPTY(agp_bridge, cur_gatt[GET_GATT_OFF(addr)])) return -EBUSY; - } j++; } if (mem->is_flushed == FALSE) { - CACHE_FLUSH(); + global_cache_flush(); mem->is_flushed = TRUE; } @@ -312,22 +302,21 @@ addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr; cur_gatt = GET_GATT(addr); cur_gatt[GET_GATT_OFF(addr)] = - agp_bridge->mask_memory(mem->memory[i], mem->type); + agp_generic_mask_memory(mem->memory[i], mem->type); } - agp_bridge->tlb_flush(mem); + amd_irongate_tlbflush(mem); return 0; } -static int amd_remove_memory(agp_memory * mem, off_t pg_start, - int type) +static int amd_remove_memory(struct agp_memory *mem, off_t pg_start, int type) { int i; unsigned long *cur_gatt; unsigned long addr; - if (type != 0 || mem->type != 0) { + if (type != 0 || mem->type != 0) return -EINVAL; - } + for (i = pg_start; i < (mem->page_count + pg_start); i++) { addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr; cur_gatt = GET_GATT(addr); @@ -335,7 +324,7 @@ (unsigned long) agp_bridge->scratch_page; } - agp_bridge->tlb_flush(mem); + amd_irongate_tlbflush(mem); return 0; } @@ -352,118 +341,105 @@ static struct gatt_mask amd_irongate_masks[] = { - {.mask = 0x00000001, .type = 0} + {.mask = 1, .type = 0} }; -static int __init amd_irongate_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = amd_irongate_masks; - agp_bridge->aperture_sizes = (void *) amd_irongate_sizes; - agp_bridge->size_type = LVL2_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = (void *) &amd_irongate_private; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = amd_irongate_configure; - agp_bridge->fetch_size = amd_irongate_fetch_size; - agp_bridge->cleanup = amd_irongate_cleanup; - agp_bridge->tlb_flush = amd_irongate_tlbflush; - agp_bridge->mask_memory = amd_irongate_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = amd_create_gatt_table; - agp_bridge->free_gatt_table = amd_free_gatt_table; - agp_bridge->insert_memory = amd_insert_memory; - agp_bridge->remove_memory = amd_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} +struct agp_bridge_driver amd_irongate_driver = { + .owner = THIS_MODULE, + .aperture_sizes = amd_irongate_sizes, + .size_type = LVL2_APER_SIZE, + .num_aperture_sizes = 7, + .configure = amd_irongate_configure, + .fetch_size = amd_irongate_fetch_size, + .cleanup = amd_irongate_cleanup, + .tlb_flush = amd_irongate_tlbflush, + .mask_memory = agp_generic_mask_memory, + .masks = amd_irongate_masks, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = amd_create_gatt_table, + .free_gatt_table = amd_free_gatt_table, + .insert_memory = amd_insert_memory, + .remove_memory = amd_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, +}; struct agp_device_ids amd_agp_device_ids[] __initdata = { { .device_id = PCI_DEVICE_ID_AMD_FE_GATE_7006, - .chipset = AMD_IRONGATE, .chipset_name = "Irongate", }, { .device_id = PCI_DEVICE_ID_AMD_FE_GATE_700E, - .chipset = AMD_761, .chipset_name = "761", }, { .device_id = PCI_DEVICE_ID_AMD_FE_GATE_700C, - .chipset = AMD_762, .chipset_name = "760MP", }, { }, /* dummy final entry, always present */ }; - -/* scan table above for supported devices */ -static int __init agp_lookup_host_bridge (struct pci_dev *pdev) +static int __init agp_amdk7_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - int j=0; - struct agp_device_ids *devs; - - devs = amd_agp_device_ids; + struct agp_device_ids *devs = amd_agp_device_ids; + struct agp_bridge_data *bridge; + u8 cap_ptr; + int j; - while (devs[j].chipset_name != NULL) { - if (pdev->device == devs[j].device_id) { - printk (KERN_INFO PFX "Detected AMD %s chipset\n", devs[j].chipset_name); - agp_bridge->type = devs[j].chipset; + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + if (!cap_ptr) + return -ENODEV; - if (devs[j].chipset_setup != NULL) - return devs[j].chipset_setup(pdev); - else - return amd_irongate_setup(pdev); + for (j = 0; devs[j].chipset_name; j++) { + if (pdev->device == devs[j].device_id) { + printk (KERN_INFO PFX "Detected AMD %s chipset\n", + devs[j].chipset_name); + goto found; } - j++; } - /* try init anyway, if user requests it */ - if (agp_try_unsupported) { - printk(KERN_WARNING PFX "Trying generic AMD routines" - " for device id: %04x\n", pdev->device); - agp_bridge->type = AMD_GENERIC; - return amd_irongate_setup(pdev); + if (!agp_try_unsupported) { + printk(KERN_ERR PFX + "Unsupported AMD chipset (device id: %04x)," + " you might want to try agp_try_unsupported=1.\n", + pdev->device); + return -ENODEV; } - printk(KERN_ERR PFX "Unsupported AMD chipset (device id: %04x)," - " you might want to try agp_try_unsupported=1.\n", pdev->device); - return -ENODEV; -} + printk(KERN_WARNING PFX "Trying generic AMD routines" + " for device id: %04x\n", pdev->device); +found: + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; -static struct agp_driver amd_k7_agp_driver = { - .owner = THIS_MODULE, -}; + bridge->driver = &amd_irongate_driver; + bridge->dev_private_data = &amd_irongate_private, + bridge->dev = pdev; + bridge->capndx = cap_ptr; -/* Supported Device Scanning routine */ + /* Fill in the mode register */ + pci_read_config_dword(pdev, + bridge->capndx+PCI_AGP_STATUS, + &bridge->mode); -static int __init agp_amdk7_probe (struct pci_dev *dev, const struct pci_device_id *ent) -{ - u8 cap_ptr = 0; + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); +} - cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP); - if (cap_ptr == 0) - return -ENODEV; +static void __devexit agp_amdk7_remove(struct pci_dev *pdev) +{ + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); - if (agp_lookup_host_bridge(dev) != -ENODEV) { - agp_bridge->dev = dev; - agp_bridge->capndx = cap_ptr; - /* Fill in the mode register */ - pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode); - amd_k7_agp_driver.dev = dev; - agp_register_driver(&amd_k7_agp_driver); - return 0; - } - return -ENODEV; + agp_remove_bridge(bridge); + agp_put_bridge(bridge); } static struct pci_device_id agp_amdk7_pci_table[] __initdata = { @@ -480,26 +456,20 @@ MODULE_DEVICE_TABLE(pci, agp_amdk7_pci_table); -static struct __initdata pci_driver agp_amdk7_pci_driver = { +static struct pci_driver agp_amdk7_pci_driver = { .name = "agpgart-amdk7", .id_table = agp_amdk7_pci_table, .probe = agp_amdk7_probe, + .remove = agp_amdk7_remove, }; static int __init agp_amdk7_init(void) { - int ret_val; - - ret_val = pci_module_init(&agp_amdk7_pci_driver); - if (ret_val) - agp_bridge->type = NOT_SUPPORTED; - - return ret_val; + return pci_module_init(&agp_amdk7_pci_driver); } static void __exit agp_amdk7_cleanup(void) { - agp_unregister_driver(&amd_k7_agp_driver); pci_unregister_driver(&agp_amdk7_pci_driver); } @@ -508,4 +478,3 @@ MODULE_PARM(agp_try_unsupported, "1i"); MODULE_LICENSE("GPL and additional rights"); - diff -Nru a/drivers/char/agp/amd-k8-agp.c b/drivers/char/agp/amd-k8-agp.c --- a/drivers/char/agp/amd-k8-agp.c Sat May 24 12:48:28 2003 +++ b/drivers/char/agp/amd-k8-agp.c Sat May 24 12:48:28 2003 @@ -29,7 +29,22 @@ static int gart_iterator; #define for_each_nb() for(gart_iterator=0;gart_iteratorpage_count)) { - if (!PGE_EMPTY(agp_bridge->gatt_table[j])) + if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j])) return -EBUSY; j++; } if (mem->is_flushed == FALSE) { - CACHE_FLUSH(); + global_cache_flush(); mem->is_flushed = TRUE; } for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { - addr = agp_bridge->mask_memory(mem->memory[i], mem->type); + addr = agp_bridge->driver->mask_memory(mem->memory[i], mem->type); tmp = addr; BUG_ON(tmp & 0xffffff0000000ffc); @@ -71,7 +86,7 @@ agp_bridge->gatt_table[j] = pte; } - agp_bridge->tlb_flush(mem); + amd_x86_64_tlbflush(mem); return 0; } @@ -113,7 +128,7 @@ temp = (temp & 0xe); values = A_SIZE_32(x86_64_aperture_sizes); - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { if (temp == values[i].size_value) { agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i); @@ -125,25 +140,6 @@ return 0; } - -static void flush_x86_64_tlb(struct pci_dev *dev) -{ - u32 tmp; - - pci_read_config_dword (dev, AMD_X86_64_GARTCACHECTL, &tmp); - tmp |= 1<<0; - pci_write_config_dword (dev, AMD_X86_64_GARTCACHECTL, tmp); -} - - -static void amd_x86_64_tlbflush(agp_memory * temp) -{ - for_each_nb() { - flush_x86_64_tlb (hammers[gart_iterator]); - } -} - - /* * In a multiprocessor x86-64 system, this function gets * called once for each CPU. @@ -216,141 +212,116 @@ } -static unsigned long amd_8151_mask_memory(unsigned long addr, int type) -{ - return addr | agp_bridge->masks[0].mask; -} - - static struct gatt_mask amd_8151_masks[] = { - {.mask = 0x00000001, .type = 0} + { .mask = 1, .type = 0 } }; +struct agp_bridge_driver amd_8151_driver = { + .owner = THIS_MODULE, + .aperture_sizes = amd_8151_sizes, + .size_type = U32_APER_SIZE, + .num_aperture_sizes = 7, + .configure = amd_8151_configure, + .fetch_size = amd_x86_64_fetch_size, + .cleanup = amd_8151_cleanup, + .tlb_flush = amd_x86_64_tlbflush, + .mask_memory = agp_generic_mask_memory, + .masks = amd_8151_masks, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = x86_64_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, +}; -/* - * Try to configure an AGP v3 capable setup. - * If we fail (typically because we don't have an AGP v3 - * card in the system) we fall back to the generic AGP v2 - * routines. - */ -static void agp_x86_64_agp_enable(u32 mode) +static int __init agp_amdk8_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - struct pci_dev *device = NULL; - u32 command, scratch; + struct agp_bridge_data *bridge; + struct pci_dev *loop_dev; + u8 rev_id; u8 cap_ptr; - u8 v3_devs=0; + int i = 0; + char *revstring=" "; - /* FIXME: If 'mode' is x1/x2/x4 should we call the AGPv2 routines directly ? - * Messy, as some AGPv3 cards can only do x4 as a minimum. - */ - - /* PASS1: Count # of devs capable of AGPv3 mode. */ - pci_for_each_dev(device) { - cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP); - if (cap_ptr != 0x00) { - pci_read_config_dword(device, cap_ptr, &scratch); - scratch &= (1<<20|1<<21|1<<22|1<<23); - scratch = scratch>>20; - /* AGP v3 capable ? */ - if (scratch>=3) { - v3_devs++; - printk (KERN_INFO "AGP: Found AGPv3 capable device at %d:%d:%d\n", - device->bus->number, PCI_FUNC(device->devfn), PCI_SLOT(device->devfn)); - } else { - printk (KERN_INFO "AGP: Meh. version %x AGP device found.\n", scratch); - } - } - } - /* If not enough, go to AGP v2 setup */ - if (v3_devs<2) { - printk (KERN_INFO "AGP: Only %d devices found, not enough, trying AGPv2\n", v3_devs); - return agp_generic_enable(mode); - } else { - printk (KERN_INFO "AGP: Enough AGPv3 devices found, setting up...\n"); - } - - - pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &command); - - command = agp_collect_device_status(mode, command); - command |= 0x100; - - pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_COMMAND, command); - - agp_device_command(command, 1); -} + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + if (!cap_ptr) + return -ENODEV; + printk(KERN_INFO PFX "Detected Opteron/Athlon64 on-CPU GART\n"); -static int __init amd_8151_setup (struct pci_dev *pdev) -{ - struct pci_dev *dev; - int i=0; + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; + + if (pdev->vendor == PCI_VENDOR_ID_AMD && + pdev->device == PCI_DEVICE_ID_AMD_8151_0) { + + pci_read_config_byte(pdev, PCI_REVISION_ID, &rev_id); + switch (rev_id) { + case 0x01: revstring="A0"; + break; + case 0x02: revstring="A1"; + break; + case 0x11: revstring="B0"; + break; + case 0x12: revstring="B1"; + break; + case 0x13: revstring="B2"; + break; + default: revstring="??"; + break; + } + printk ("Detected AMD 8151 AGP Bridge rev %s", revstring); + /* + * Work around errata. + * Chips before B2 stepping incorrectly reporting v3.5 + */ + if (rev_id < 0x13) { + bridge->major_version = 3; + bridge->minor_version = 0; + } + } - agp_bridge->masks = amd_8151_masks; - agp_bridge->aperture_sizes = (void *) amd_8151_sizes; - agp_bridge->size_type = U32_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = amd_8151_configure; - agp_bridge->fetch_size = amd_x86_64_fetch_size; - agp_bridge->cleanup = amd_8151_cleanup; - agp_bridge->tlb_flush = amd_x86_64_tlbflush; - agp_bridge->mask_memory = amd_8151_mask_memory; - agp_bridge->agp_enable = agp_x86_64_agp_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = x86_64_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; + bridge->driver = &amd_8151_driver; + bridge->dev = pdev; + bridge->capndx = cap_ptr; + /* Fill in the mode register */ + pci_read_config_dword(pdev, bridge->capndx+PCI_AGP_STATUS, &bridge->mode); /* cache pci_devs of northbridges. */ - pci_for_each_dev(dev) { - if (dev->bus->number==0 && PCI_FUNC(dev->devfn)==3 && - (PCI_SLOT(dev->devfn) >=24) && (PCI_SLOT(dev->devfn) <=31)) { - - hammers[i++] = dev; + pci_for_each_dev(loop_dev) { + if (loop_dev->bus->number == 0 && + PCI_FUNC(loop_dev->devfn) == 3 && + PCI_SLOT(loop_dev->devfn) >=24 && + PCI_SLOT(loop_dev->devfn) <=31) { + hammers[i++] = loop_dev; nr_garts = i; - if (i==MAX_HAMMER_GARTS) - return 0; + if (i == MAX_HAMMER_GARTS) + goto out_free; } } - return 0; + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); +out_free: + agp_put_bridge(bridge); + return -ENOMEM; } -static struct agp_driver amd_k8_agp_driver = { - .owner = THIS_MODULE, -}; - -static int __init agp_amdk8_probe (struct pci_dev *dev, const struct pci_device_id *ent) +static void __devexit agp_amdk8_remove(struct pci_dev *pdev) { - u8 cap_ptr = 0; - - cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP); - if (cap_ptr == 0) - return -ENODEV; - - printk (KERN_INFO PFX "Detected Opteron/Athlon64 on-CPU GART\n"); + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); - agp_bridge->dev = dev; - agp_bridge->capndx = cap_ptr; - - /* Fill in the mode register */ - pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode); - amd_8151_setup(dev); - amd_k8_agp_driver.dev = dev; - agp_register_driver(&amd_k8_agp_driver); - return 0; + agp_remove_bridge(bridge); + agp_put_bridge(bridge); } static struct pci_device_id agp_amdk8_pci_table[] __initdata = { @@ -362,34 +333,34 @@ .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, + { + .class = (PCI_CLASS_BRIDGE_HOST << 8), + .class_mask = ~0, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_K8T400M_0, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, { } }; MODULE_DEVICE_TABLE(pci, agp_amdk8_pci_table); -static struct __initdata pci_driver agp_amdk8_pci_driver = { +static struct pci_driver agp_amdk8_pci_driver = { .name = "agpgart-amd-k8", .id_table = agp_amdk8_pci_table, .probe = agp_amdk8_probe, + .remove = agp_amdk8_remove, }; /* Not static due to IOMMU code calling it early. */ int __init agp_amdk8_init(void) { - int ret_val; - - ret_val = pci_module_init(&agp_amdk8_pci_driver); - if (ret_val) - agp_bridge->type = NOT_SUPPORTED; - - agp_bridge->type = AMD_8151; - - return ret_val; + return pci_module_init(&agp_amdk8_pci_driver); } static void __exit agp_amdk8_cleanup(void) { - agp_unregister_driver(&amd_k8_agp_driver); pci_unregister_driver(&agp_amdk8_pci_driver); } diff -Nru a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c --- a/drivers/char/agp/backend.c Sat May 24 12:48:28 2003 +++ b/drivers/char/agp/backend.c Sat May 24 12:48:28 2003 @@ -43,37 +43,54 @@ * past 0.99 at all due to some boolean logic error. */ #define AGPGART_VERSION_MAJOR 0 #define AGPGART_VERSION_MINOR 100 +static struct agp_version agp_current_version = +{ + .major = AGPGART_VERSION_MAJOR, + .minor = AGPGART_VERSION_MINOR, +}; + +static int agp_count=0; struct agp_bridge_data agp_bridge_dummy = { .type = NOT_SUPPORTED }; struct agp_bridge_data *agp_bridge = &agp_bridge_dummy; +EXPORT_SYMBOL(agp_bridge); + +/** + * agp_backend_acquire - attempt to acquire the agp backend. + * + * returns -EBUSY if agp is in use, + * returns 0 if the caller owns the agp backend + */ int agp_backend_acquire(void) { if (agp_bridge->type == NOT_SUPPORTED) return -EINVAL; - - if (atomic_read(&agp_bridge->agp_in_use) != 0) + if (atomic_read(&agp_bridge->agp_in_use)) return -EBUSY; - atomic_inc(&agp_bridge->agp_in_use); return 0; } +EXPORT_SYMBOL(agp_backend_acquire); + +/** + * agp_backend_release - release the lock on the agp backend. + * + * The caller must insure that the graphics aperture translation table + * is read for use by another entity. + * + * (Ensure that all memory it bound is unbound.) + */ void agp_backend_release(void) { - if (agp_bridge->type == NOT_SUPPORTED) - return; - - atomic_dec(&agp_bridge->agp_in_use); + if (agp_bridge->type != NOT_SUPPORTED) + atomic_dec(&agp_bridge->agp_in_use); } +EXPORT_SYMBOL(agp_backend_release); -struct agp_max_table { - int mem; - int agp; -}; -static struct agp_max_table maxes_table[9] = -{ +struct { int mem, agp; } maxes_table[] = { {0, 0}, {32, 4}, {64, 28}, @@ -85,7 +102,7 @@ {4096, 3932} }; -static int agp_find_max (void) +static int agp_find_max(void) { long memory, index, result; @@ -105,48 +122,43 @@ return result; } -static struct agp_version agp_current_version = -{ - .major = AGPGART_VERSION_MAJOR, - .minor = AGPGART_VERSION_MINOR, -}; -static int agp_backend_initialize(struct pci_dev *dev) +static int agp_backend_initialize(struct agp_bridge_data *bridge) { int size_value, rc, got_gatt=0, got_keylist=0; - agp_bridge->max_memory_agp = agp_find_max(); - agp_bridge->version = &agp_current_version; + bridge->max_memory_agp = agp_find_max(); + bridge->version = &agp_current_version; - if (agp_bridge->needs_scratch_page == TRUE) { - void *addr; - addr = agp_bridge->agp_alloc_page(); + if (bridge->driver->needs_scratch_page) { + void *addr = bridge->driver->agp_alloc_page(); - if (addr == NULL) { + if (!addr) { printk(KERN_ERR PFX "unable to get memory for scratch page.\n"); return -ENOMEM; } - agp_bridge->scratch_page_real = virt_to_phys(addr); - agp_bridge->scratch_page = - agp_bridge->mask_memory(agp_bridge->scratch_page_real, 0); - } - size_value = agp_bridge->fetch_size(); + bridge->scratch_page_real = virt_to_phys(addr); + bridge->scratch_page = + bridge->driver->mask_memory(bridge->scratch_page_real, 0); + } + size_value = bridge->driver->fetch_size(); if (size_value == 0) { printk(KERN_ERR PFX "unable to determine aperture size.\n"); rc = -EINVAL; goto err_out; } - if (agp_bridge->create_gatt_table()) { - printk(KERN_ERR PFX "unable to get memory for graphics translation table.\n"); + if (bridge->driver->create_gatt_table()) { + printk(KERN_ERR PFX + "unable to get memory for graphics translation table.\n"); rc = -ENOMEM; goto err_out; } got_gatt = 1; - agp_bridge->key_list = vmalloc(PAGE_SIZE * 4); - if (agp_bridge->key_list == NULL) { + bridge->key_list = vmalloc(PAGE_SIZE * 4); + if (bridge->key_list == NULL) { printk(KERN_ERR PFX "error allocating memory for key lists.\n"); rc = -ENOMEM; goto err_out; @@ -154,61 +166,49 @@ got_keylist = 1; /* FIXME vmalloc'd memory not guaranteed contiguous */ - memset(agp_bridge->key_list, 0, PAGE_SIZE * 4); + memset(bridge->key_list, 0, PAGE_SIZE * 4); - if (agp_bridge->configure()) { + if (bridge->driver->configure()) { printk(KERN_ERR PFX "error configuring host chipset.\n"); rc = -EINVAL; goto err_out; } printk(KERN_INFO PFX "AGP aperture is %dM @ 0x%lx\n", - size_value, agp_bridge->gart_bus_addr); + size_value, bridge->gart_bus_addr); return 0; err_out: - if (agp_bridge->needs_scratch_page == TRUE) { - agp_bridge->agp_destroy_page(phys_to_virt(agp_bridge->scratch_page_real)); - } + if (bridge->driver->needs_scratch_page) + bridge->driver->agp_destroy_page( + phys_to_virt(bridge->scratch_page_real)); if (got_gatt) - agp_bridge->free_gatt_table(); - if (got_keylist) - vfree(agp_bridge->key_list); + bridge->driver->free_gatt_table(); + if (got_keylist) { + vfree(bridge->key_list); + bridge->key_list = NULL; + } return rc; } - /* cannot be __exit b/c as it could be called from __init code */ -static void agp_backend_cleanup(void) +static void agp_backend_cleanup(struct agp_bridge_data *bridge) { - if (agp_bridge->cleanup != NULL) - agp_bridge->cleanup(); - if (agp_bridge->free_gatt_table != NULL) - agp_bridge->free_gatt_table(); - if (agp_bridge->key_list) - vfree(agp_bridge->key_list); - - if ((agp_bridge->agp_destroy_page!=NULL) && - (agp_bridge->needs_scratch_page == TRUE)) - agp_bridge->agp_destroy_page(phys_to_virt(agp_bridge->scratch_page_real)); -} - -static int agp_power(struct pm_dev *dev, pm_request_t rq, void *data) -{ - switch(rq) - { - case PM_SUSPEND: - return agp_bridge->suspend(); - case PM_RESUME: - agp_bridge->resume(); - return 0; - } - return 0; -} + if (bridge->driver->cleanup) + bridge->driver->cleanup(); + if (bridge->driver->free_gatt_table) + bridge->driver->free_gatt_table(); + if (bridge->key_list) { + vfree(bridge->key_list); + bridge->key_list = NULL; + } -extern int agp_frontend_initialize(void); -extern void agp_frontend_cleanup(void); + if (bridge->driver->agp_destroy_page && + bridge->driver->needs_scratch_page) + bridge->driver->agp_destroy_page( + phys_to_virt(bridge->scratch_page_real)); +} static const drm_agp_t drm_agp = { &agp_free_memory, @@ -221,78 +221,85 @@ &agp_copy_info }; -static int agp_count=0; +/* XXX Kludge alert: agpgart isn't ready for multiple bridges yet */ +struct agp_bridge_data *agp_alloc_bridge(void) +{ + return agp_bridge; +} +EXPORT_SYMBOL(agp_alloc_bridge); + + +void agp_put_bridge(struct agp_bridge_data *bridge) +{ +} +EXPORT_SYMBOL(agp_put_bridge); -int agp_register_driver (struct agp_driver *drv) + +int agp_add_bridge(struct agp_bridge_data *bridge) { - int ret_val; + int error; - if (drv->dev == NULL) { + if (!bridge->dev) { printk (KERN_DEBUG PFX "Erk, registering with no pci_dev!\n"); return -EINVAL; } - if (agp_count==1) { - printk (KERN_DEBUG PFX "Only one agpgart device currently supported.\n"); + if (agp_count) { + printk (KERN_INFO PFX + "Only one agpgart device currently supported.\n"); return -ENODEV; } /* Grab reference on the chipset driver. */ - if (!try_module_get(drv->owner)) + if (!try_module_get(bridge->driver->owner)) { + printk (KERN_INFO PFX "Couldn't lock chipset driver.\n"); return -EINVAL; + } + + bridge->type = SUPPORTED; - ret_val = agp_backend_initialize(drv->dev); - if (ret_val) + error = agp_backend_initialize(agp_bridge); + if (error) { + printk (KERN_INFO PFX "agp_backend_initialize() failed.\n"); goto err_out; + } - ret_val = agp_frontend_initialize(); - if (ret_val) + error = agp_frontend_initialize(); + if (error) { + printk (KERN_INFO PFX "agp_frontend_initialize() failed.\n"); goto frontend_err; + } /* FIXME: What to do with this? */ inter_module_register("drm_agp", THIS_MODULE, &drm_agp); - pm_register(PM_PCI_DEV, PM_PCI_ID(agp_bridge->dev), agp_power); agp_count++; return 0; frontend_err: - agp_backend_cleanup(); + agp_backend_cleanup(agp_bridge); err_out: - agp_bridge->type = NOT_SUPPORTED; - module_put(drv->owner); - drv->dev = NULL; - return ret_val; + bridge->type = NOT_SUPPORTED; + module_put(bridge->driver->owner); + return error; } +EXPORT_SYMBOL_GPL(agp_add_bridge); -int agp_unregister_driver(struct agp_driver *drv) -{ - if (drv->dev==NULL) - return -ENODEV; - agp_bridge->type = NOT_SUPPORTED; - pm_unregister_all(agp_power); +void agp_remove_bridge(struct agp_bridge_data *bridge) +{ + bridge->type = NOT_SUPPORTED; agp_frontend_cleanup(); - agp_backend_cleanup(); + agp_backend_cleanup(bridge); inter_module_unregister("drm_agp"); agp_count--; - module_put(drv->owner); - return 0; + module_put(bridge->driver->owner); } +EXPORT_SYMBOL_GPL(agp_remove_bridge); -int __init agp_init(void) +static int __init agp_init(void) { - static int already_initialised=0; - - if (already_initialised!=0) - return 0; - - already_initialised = 1; - - memset(agp_bridge, 0, sizeof(struct agp_bridge_data)); - agp_bridge->type = NOT_SUPPORTED; - printk(KERN_INFO "Linux agpgart interface v%d.%d (c) Dave Jones\n", AGPGART_VERSION_MAJOR, AGPGART_VERSION_MINOR); return 0; @@ -300,19 +307,13 @@ void __exit agp_exit(void) { - if (agp_count!=0) - BUG(); } -#ifndef CONFIG_GART_IOMMU -module_init(agp_init); -module_exit(agp_exit); -#endif - -EXPORT_SYMBOL(agp_backend_acquire); -EXPORT_SYMBOL(agp_backend_release); -EXPORT_SYMBOL_GPL(agp_register_driver); -EXPORT_SYMBOL_GPL(agp_unregister_driver); MODULE_AUTHOR("Dave Jones "); +MODULE_DESCRIPTION("AGP GART driver"); MODULE_LICENSE("GPL and additional rights"); + +module_init(agp_init); +module_exit(agp_exit); + diff -Nru a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c --- a/drivers/char/agp/frontend.c Sat May 24 12:48:20 2003 +++ b/drivers/char/agp/frontend.c Sat May 24 12:48:20 2003 @@ -42,9 +42,9 @@ static struct agp_front_data agp_fe; -static agp_memory *agp_find_mem_by_key(int key) +static struct agp_memory *agp_find_mem_by_key(int key) { - agp_memory *curr; + struct agp_memory *curr; if (agp_fe.current_controller == NULL) return NULL; @@ -53,20 +53,22 @@ while (curr != NULL) { if (curr->key == key) - return curr; + break; curr = curr->next; } - return NULL; + DBG("key=%d -> mem=%p", key, curr); + return curr; } -static void agp_remove_from_pool(agp_memory * temp) +static void agp_remove_from_pool(struct agp_memory *temp) { - agp_memory *prev; - agp_memory *next; + struct agp_memory *prev; + struct agp_memory *next; /* Check to see if this is even in the memory pool */ + DBG("mem=%p", temp); if (agp_find_mem_by_key(temp->key) != NULL) { next = temp->next; prev = temp->prev; @@ -92,11 +94,12 @@ * to each auth'ed client. */ -static agp_segment_priv *agp_find_seg_in_client(const agp_client * client, +static struct +agp_segment_priv *agp_find_seg_in_client(const struct agp_client *client, unsigned long offset, int size, pgprot_t page_prot) { - agp_segment_priv *seg; + struct agp_segment_priv *seg; int num_segments, i; off_t pg_start; size_t pg_count; @@ -117,25 +120,32 @@ return NULL; } -static void agp_remove_seg_from_client(agp_client * client) +static void agp_remove_seg_from_client(struct agp_client *client) { + DBG("client=%p", client); + if (client->segments != NULL) { - if (*(client->segments) != NULL) + if (*(client->segments) != NULL) { + DBG("Freeing %p from client %p", *(client->segments), client); kfree(*(client->segments)); + } + DBG("Freeing %p from client %p", client->segments, client); kfree(client->segments); + client->segments = NULL; } } -static void agp_add_seg_to_client(agp_client * client, - agp_segment_priv ** seg, int num_segments) +static void agp_add_seg_to_client(struct agp_client *client, + struct agp_segment_priv ** seg, int num_segments) { - agp_segment_priv **prev_seg; + struct agp_segment_priv **prev_seg; prev_seg = client->segments; if (prev_seg != NULL) agp_remove_seg_from_client(client); + DBG("Adding seg %p (%d segments) to client %p", seg, num_segments, client); client->num_segments = num_segments; client->segments = seg; } @@ -171,19 +181,20 @@ return temp; } -static int agp_create_segment(agp_client * client, agp_region * region) +static int agp_create_segment(struct agp_client *client, struct agp_region *region) { - agp_segment_priv **ret_seg; - agp_segment_priv *seg; - agp_segment *user_seg; + struct agp_segment_priv **ret_seg; + struct agp_segment_priv *seg; + struct agp_segment *user_seg; size_t i; - seg = kmalloc((sizeof(agp_segment_priv) * region->seg_count), GFP_KERNEL); + seg = kmalloc((sizeof(struct agp_segment_priv) * region->seg_count), GFP_KERNEL); if (seg == NULL) { kfree(region->seg_list); + region->seg_list = NULL; return -ENOMEM; } - memset(seg, 0, (sizeof(agp_segment_priv) * region->seg_count)); + memset(seg, 0, (sizeof(struct agp_segment_priv) * region->seg_count)); user_seg = region->seg_list; for (i = 0; i < region->seg_count; i++) { @@ -191,14 +202,15 @@ seg[i].pg_count = user_seg[i].pg_count; seg[i].prot = agp_convert_mmap_flags(user_seg[i].prot); } + kfree(region->seg_list); + region->seg_list = NULL; + ret_seg = kmalloc(sizeof(void *), GFP_KERNEL); if (ret_seg == NULL) { - kfree(region->seg_list); kfree(seg); return -ENOMEM; } *ret_seg = seg; - kfree(region->seg_list); agp_add_seg_to_client(client, ret_seg, region->seg_count); return 0; } @@ -206,9 +218,9 @@ /* End - Routines for managing each client's segment list */ /* This function must only be called when current_controller != NULL */ -static void agp_insert_into_pool(agp_memory * temp) +static void agp_insert_into_pool(struct agp_memory * temp) { - agp_memory *prev; + struct agp_memory *prev; prev = agp_fe.current_controller->pool; @@ -222,9 +234,9 @@ /* File private list routines */ -agp_file_private *agp_find_private(pid_t pid) +struct agp_file_private *agp_find_private(pid_t pid) { - agp_file_private *curr; + struct agp_file_private *curr; curr = agp_fe.file_priv_list; @@ -237,9 +249,9 @@ return NULL; } -void agp_insert_file_private(agp_file_private * priv) +void agp_insert_file_private(struct agp_file_private * priv) { - agp_file_private *prev; + struct agp_file_private *prev; prev = agp_fe.file_priv_list; @@ -249,10 +261,10 @@ agp_fe.file_priv_list = priv; } -void agp_remove_file_private(agp_file_private * priv) +void agp_remove_file_private(struct agp_file_private * priv) { - agp_file_private *next; - agp_file_private *prev; + struct agp_file_private *next; + struct agp_file_private *prev; next = priv->next; prev = priv->prev; @@ -277,15 +289,15 @@ * Wrappers for agp_free_memory & agp_allocate_memory * These make sure that internal lists are kept updated. */ -static void agp_free_memory_wrap(agp_memory * memory) +static void agp_free_memory_wrap(struct agp_memory *memory) { agp_remove_from_pool(memory); agp_free_memory(memory); } -static agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type) +static struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type) { - agp_memory *memory; + struct agp_memory *memory; memory = agp_allocate_memory(pg_count, type); printk(KERN_DEBUG "agp_allocate_memory: %p\n", memory); @@ -301,9 +313,9 @@ * controllers */ -static agp_controller *agp_find_controller_by_pid(pid_t id) +static struct agp_controller *agp_find_controller_by_pid(pid_t id) { - agp_controller *controller; + struct agp_controller *controller; controller = agp_fe.controllers; @@ -316,24 +328,24 @@ return NULL; } -static agp_controller *agp_create_controller(pid_t id) +static struct agp_controller *agp_create_controller(pid_t id) { - agp_controller *controller; + struct agp_controller *controller; - controller = kmalloc(sizeof(agp_controller), GFP_KERNEL); + controller = kmalloc(sizeof(struct agp_controller), GFP_KERNEL); if (controller == NULL) return NULL; - memset(controller, 0, sizeof(agp_controller)); + memset(controller, 0, sizeof(struct agp_controller)); controller->pid = id; return controller; } -static int agp_insert_controller(agp_controller * controller) +static int agp_insert_controller(struct agp_controller *controller) { - agp_controller *prev_controller; + struct agp_controller *prev_controller; prev_controller = agp_fe.controllers; controller->next = prev_controller; @@ -346,15 +358,15 @@ return 0; } -static void agp_remove_all_clients(agp_controller * controller) +static void agp_remove_all_clients(struct agp_controller *controller) { - agp_client *client; - agp_client *temp; + struct agp_client *client; + struct agp_client *temp; client = controller->clients; while (client) { - agp_file_private *priv; + struct agp_file_private *priv; temp = client; agp_remove_seg_from_client(temp); @@ -369,10 +381,10 @@ } } -static void agp_remove_all_memory(agp_controller * controller) +static void agp_remove_all_memory(struct agp_controller *controller) { - agp_memory *memory; - agp_memory *temp; + struct agp_memory *memory; + struct agp_memory *temp; memory = controller->pool; @@ -383,10 +395,10 @@ } } -static int agp_remove_controller(agp_controller * controller) +static int agp_remove_controller(struct agp_controller *controller) { - agp_controller *prev_controller; - agp_controller *next_controller; + struct agp_controller *prev_controller; + struct agp_controller *next_controller; prev_controller = controller->prev; next_controller = controller->next; @@ -415,14 +427,14 @@ return 0; } -static void agp_controller_make_current(agp_controller * controller) +static void agp_controller_make_current(struct agp_controller *controller) { - agp_client *clients; + struct agp_client *clients; clients = controller->clients; while (clients != NULL) { - agp_file_private *priv; + struct agp_file_private *priv; priv = agp_find_private(clients->pid); @@ -436,16 +448,16 @@ agp_fe.current_controller = controller; } -static void agp_controller_release_current(agp_controller * controller, - agp_file_private * controller_priv) +static void agp_controller_release_current(struct agp_controller *controller, + struct agp_file_private *controller_priv) { - agp_client *clients; + struct agp_client *clients; clear_bit(AGP_FF_IS_VALID, &controller_priv->access_flags); clients = controller->clients; while (clients != NULL) { - agp_file_private *priv; + struct agp_file_private *priv; priv = agp_find_private(clients->pid); @@ -465,10 +477,10 @@ * These routines are for managing the list of auth'ed clients. */ -static agp_client *agp_find_client_in_controller(agp_controller * controller, - pid_t id) +static struct agp_client +*agp_find_client_in_controller(struct agp_controller *controller, pid_t id) { - agp_client *client; + struct agp_client *client; if (controller == NULL) return NULL; @@ -484,9 +496,9 @@ return NULL; } -static agp_controller *agp_find_controller_for_client(pid_t id) +static struct agp_controller *agp_find_controller_for_client(pid_t id) { - agp_controller *controller; + struct agp_controller *controller; controller = agp_fe.controllers; @@ -499,9 +511,9 @@ return NULL; } -static agp_client *agp_find_client_by_pid(pid_t id) +static struct agp_client *agp_find_client_by_pid(pid_t id) { - agp_client *temp; + struct agp_client *temp; if (agp_fe.current_controller == NULL) return NULL; @@ -510,9 +522,9 @@ return temp; } -static void agp_insert_client(agp_client * client) +static void agp_insert_client(struct agp_client *client) { - agp_client *prev_client; + struct agp_client *prev_client; prev_client = agp_fe.current_controller->clients; client->next = prev_client; @@ -524,16 +536,16 @@ agp_fe.current_controller->num_clients++; } -static agp_client *agp_create_client(pid_t id) +static struct agp_client *agp_create_client(pid_t id) { - agp_client *new_client; + struct agp_client *new_client; - new_client = kmalloc(sizeof(agp_client), GFP_KERNEL); + new_client = kmalloc(sizeof(struct agp_client), GFP_KERNEL); if (new_client == NULL) return NULL; - memset(new_client, 0, sizeof(agp_client)); + memset(new_client, 0, sizeof(struct agp_client)); new_client->pid = id; agp_insert_client(new_client); return new_client; @@ -541,10 +553,10 @@ static int agp_remove_client(pid_t id) { - agp_client *client; - agp_client *prev_client; - agp_client *next_client; - agp_controller *controller; + struct agp_client *client; + struct agp_client *prev_client; + struct agp_client *next_client; + struct agp_controller *controller; controller = agp_find_controller_for_client(id); if (controller == NULL) @@ -582,11 +594,11 @@ { unsigned int size, current_size; unsigned long offset; - agp_client *client; - agp_file_private *priv = (agp_file_private *) file->private_data; - agp_kern_info kerninfo; + struct agp_client *client; + struct agp_file_private *priv = file->private_data; + struct agp_kern_info kerninfo; - AGP_LOCK(); + down(&(agp_fe.agp_mutex)); if (agp_fe.backend_acquired != TRUE) goto out_eperm; @@ -599,6 +611,7 @@ current_size = kerninfo.aper_size; current_size = current_size * 0x100000; offset = vma->vm_pgoff << PAGE_SHIFT; + DBG("%lx:%lx", offset, offset+size); if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) { if ((size + offset) > current_size) @@ -612,6 +625,7 @@ if (!agp_find_seg_in_client(client, offset, size, vma->vm_page_prot)) goto out_inval; + DBG("client vm_ops=%p", kerninfo.vm_ops); if (kerninfo.vm_ops) { vma->vm_ops = kerninfo.vm_ops; } else if (remap_page_range(vma, vma->vm_start, @@ -619,7 +633,7 @@ size, vma->vm_page_prot)) { goto out_again; } - AGP_UNLOCK(); + up(&(agp_fe.agp_mutex)); return 0; } @@ -627,6 +641,7 @@ if (size != current_size) goto out_inval; + DBG("controller vm_ops=%p", kerninfo.vm_ops); if (kerninfo.vm_ops) { vma->vm_ops = kerninfo.vm_ops; } else if (remap_page_range(vma, vma->vm_start, @@ -634,68 +649,71 @@ size, vma->vm_page_prot)) { goto out_again; } - AGP_UNLOCK(); + up(&(agp_fe.agp_mutex)); return 0; } out_eperm: - AGP_UNLOCK(); + up(&(agp_fe.agp_mutex)); return -EPERM; out_inval: - AGP_UNLOCK(); + up(&(agp_fe.agp_mutex)); return -EINVAL; out_again: - AGP_UNLOCK(); + up(&(agp_fe.agp_mutex)); return -EAGAIN; } static int agp_release(struct inode *inode, struct file *file) { - agp_file_private *priv = (agp_file_private *) file->private_data; + struct agp_file_private *priv = file->private_data; - AGP_LOCK(); + down(&(agp_fe.agp_mutex)); + + DBG("priv=%p", priv); if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) { - agp_controller *controller; + struct agp_controller *controller; controller = agp_find_controller_by_pid(priv->my_pid); if (controller != NULL) { - if (controller == agp_fe.current_controller) { - agp_controller_release_current(controller, - priv); - } + if (controller == agp_fe.current_controller) + agp_controller_release_current(controller, priv); agp_remove_controller(controller); + controller = NULL; } } - if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) { + + if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) agp_remove_client(priv->my_pid); - } + agp_remove_file_private(priv); kfree(priv); - AGP_UNLOCK(); + file->private_data = NULL; + up(&(agp_fe.agp_mutex)); return 0; } static int agp_open(struct inode *inode, struct file *file) { int minor = minor(inode->i_rdev); - agp_file_private *priv; - agp_client *client; + struct agp_file_private *priv; + struct agp_client *client; int rc = -ENXIO; - AGP_LOCK(); + down(&(agp_fe.agp_mutex)); if (minor != AGPGART_MINOR) goto err_out; - priv = kmalloc(sizeof(agp_file_private), GFP_KERNEL); + priv = kmalloc(sizeof(struct agp_file_private), GFP_KERNEL); if (priv == NULL) goto err_out_nomem; - memset(priv, 0, sizeof(agp_file_private)); + memset(priv, 0, sizeof(struct agp_file_private)); set_bit(AGP_FF_ALLOW_CLIENT, &priv->access_flags); priv->my_pid = current->pid; @@ -711,13 +729,14 @@ } file->private_data = (void *) priv; agp_insert_file_private(priv); - AGP_UNLOCK(); + DBG("private=%p, client=%p", priv, client); + up(&(agp_fe.agp_mutex)); return 0; err_out_nomem: rc = -ENOMEM; err_out: - AGP_UNLOCK(); + up(&(agp_fe.agp_mutex)); return rc; } @@ -734,10 +753,10 @@ return -EINVAL; } -static int agpioc_info_wrap(agp_file_private * priv, unsigned long arg) +static int agpioc_info_wrap(struct agp_file_private *priv, unsigned long arg) { - agp_info userinfo; - agp_kern_info kerninfo; + struct agp_info userinfo; + struct agp_kern_info kerninfo; agp_copy_info(&kerninfo); @@ -751,17 +770,19 @@ userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory; userinfo.pg_used = kerninfo.current_memory; - if (copy_to_user((void *) arg, &userinfo, sizeof(agp_info))) + if (copy_to_user((void *) arg, &userinfo, sizeof(struct agp_info))) return -EFAULT; return 0; } -static int agpioc_acquire_wrap(agp_file_private * priv, unsigned long arg) +static int agpioc_acquire_wrap(struct agp_file_private *priv, unsigned long arg) { int ret; + struct agp_controller *controller; + + DBG(""); - agp_controller *controller; if (!(test_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags))) return -EPERM; @@ -795,33 +816,36 @@ return 0; } -static int agpioc_release_wrap(agp_file_private * priv, unsigned long arg) +static int agpioc_release_wrap(struct agp_file_private *priv, unsigned long arg) { + DBG(""); agp_controller_release_current(agp_fe.current_controller, priv); return 0; } -static int agpioc_setup_wrap(agp_file_private * priv, unsigned long arg) +static int agpioc_setup_wrap(struct agp_file_private *priv, unsigned long arg) { - agp_setup mode; + struct agp_setup mode; - if (copy_from_user(&mode, (void *) arg, sizeof(agp_setup))) { + DBG(""); + if (copy_from_user(&mode, (void *) arg, sizeof(struct agp_setup))) return -EFAULT; - } + agp_enable(mode.agp_mode); return 0; } -static int agpioc_reserve_wrap(agp_file_private * priv, unsigned long arg) +static int agpioc_reserve_wrap(struct agp_file_private *priv, unsigned long arg) { - agp_region reserve; - agp_client *client; - agp_file_private *client_priv; + struct agp_region reserve; + struct agp_client *client; + struct agp_file_private *client_priv; - if (copy_from_user(&reserve, (void *) arg, sizeof(agp_region))) + DBG(""); + if (copy_from_user(&reserve, (void *) arg, sizeof(struct agp_region))) return -EFAULT; - if ((unsigned) reserve.seg_count >= ~0U/sizeof(agp_segment)) + if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment)) return -EFAULT; client = agp_find_client_by_pid(reserve.pid); @@ -831,10 +855,8 @@ client_priv = agp_find_private(reserve.pid); if (client_priv != NULL) { - set_bit(AGP_FF_IS_CLIENT, - &client_priv->access_flags); - set_bit(AGP_FF_IS_VALID, - &client_priv->access_flags); + set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags); + set_bit(AGP_FF_IS_VALID, &client_priv->access_flags); } if (client == NULL) { /* client is already removed */ @@ -842,19 +864,19 @@ } return agp_remove_client(reserve.pid); } else { - agp_segment *segment; + struct agp_segment *segment; if (reserve.seg_count >= 16384) return -EINVAL; - - segment = kmalloc((sizeof(agp_segment) * reserve.seg_count), + + segment = kmalloc((sizeof(struct agp_segment) * reserve.seg_count), GFP_KERNEL); if (segment == NULL) return -ENOMEM; if (copy_from_user(segment, (void *) reserve.seg_list, - sizeof(agp_segment) * reserve.seg_count)) { + sizeof(struct agp_segment) * reserve.seg_count)) { kfree(segment); return -EFAULT; } @@ -871,32 +893,30 @@ client_priv = agp_find_private(reserve.pid); if (client_priv != NULL) { - set_bit(AGP_FF_IS_CLIENT, - &client_priv->access_flags); - set_bit(AGP_FF_IS_VALID, - &client_priv->access_flags); + set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags); + set_bit(AGP_FF_IS_VALID, &client_priv->access_flags); } - return agp_create_segment(client, &reserve); - } else { - return agp_create_segment(client, &reserve); } + return agp_create_segment(client, &reserve); } /* Will never really happen */ return -EINVAL; } -static int agpioc_protect_wrap(agp_file_private * priv, unsigned long arg) +static int agpioc_protect_wrap(struct agp_file_private *priv, unsigned long arg) { + DBG(""); /* This function is not currently implemented */ return -EINVAL; } -static int agpioc_allocate_wrap(agp_file_private * priv, unsigned long arg) +static int agpioc_allocate_wrap(struct agp_file_private *priv, unsigned long arg) { - agp_memory *memory; - agp_allocate alloc; + struct agp_memory *memory; + struct agp_allocate alloc; - if (copy_from_user(&alloc, (void *) arg, sizeof(agp_allocate))) + DBG(""); + if (copy_from_user(&alloc, (void *) arg, sizeof(struct agp_allocate))) return -EFAULT; memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type); @@ -907,17 +927,18 @@ alloc.key = memory->key; alloc.physical = memory->physical; - if (copy_to_user((void *) arg, &alloc, sizeof(agp_allocate))) { + if (copy_to_user((void *) arg, &alloc, sizeof(struct agp_allocate))) { agp_free_memory_wrap(memory); return -EFAULT; } return 0; } -static int agpioc_deallocate_wrap(agp_file_private * priv, unsigned long arg) +static int agpioc_deallocate_wrap(struct agp_file_private *priv, unsigned long arg) { - agp_memory *memory; + struct agp_memory *memory; + DBG(""); memory = agp_find_mem_by_key((int) arg); if (memory == NULL) @@ -927,12 +948,13 @@ return 0; } -static int agpioc_bind_wrap(agp_file_private * priv, unsigned long arg) +static int agpioc_bind_wrap(struct agp_file_private *priv, unsigned long arg) { - agp_bind bind_info; - agp_memory *memory; + struct agp_bind bind_info; + struct agp_memory *memory; - if (copy_from_user(&bind_info, (void *) arg, sizeof(agp_bind))) + DBG(""); + if (copy_from_user(&bind_info, (void *) arg, sizeof(struct agp_bind))) return -EFAULT; memory = agp_find_mem_by_key(bind_info.key); @@ -943,12 +965,13 @@ return agp_bind_memory(memory, bind_info.pg_start); } -static int agpioc_unbind_wrap(agp_file_private * priv, unsigned long arg) +static int agpioc_unbind_wrap(struct agp_file_private *priv, unsigned long arg) { - agp_memory *memory; - agp_unbind unbind; + struct agp_memory *memory; + struct agp_unbind unbind; - if (copy_from_user(&unbind, (void *) arg, sizeof(agp_unbind))) + DBG(""); + if (copy_from_user(&unbind, (void *) arg, sizeof(struct agp_unbind))) return -EFAULT; memory = agp_find_mem_by_key(unbind.key); @@ -962,10 +985,11 @@ static int agp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - agp_file_private *curr_priv = (agp_file_private *) file->private_data; + struct agp_file_private *curr_priv = file->private_data; int ret_val = -ENOTTY; - AGP_LOCK(); + DBG("priv=%p, cmd=%x", curr_priv, cmd); + down(&(agp_fe.agp_mutex)); if ((agp_fe.current_controller == NULL) && (cmd != AGPIOC_ACQUIRE)) { @@ -1034,7 +1058,8 @@ } ioctl_out: - AGP_UNLOCK(); + DBG("ioctl returns %d\n", ret_val); + up(&(agp_fe.agp_mutex)); return ret_val; } @@ -1060,7 +1085,7 @@ int agp_frontend_initialize(void) { memset(&agp_fe, 0, sizeof(struct agp_front_data)); - AGP_LOCK_INIT(); + sema_init(&(agp_fe.agp_mutex), 1); if (misc_register(&agp_miscdev)) { printk(KERN_ERR PFX "unable to get minor: %d\n", AGPGART_MINOR); diff -Nru a/drivers/char/agp/generic-3.0.c b/drivers/char/agp/generic-3.0.c --- a/drivers/char/agp/generic-3.0.c Sat May 24 12:48:21 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,529 +0,0 @@ -/* - * Generic routines for AGP 3.0 compliant bridges. - */ - -#include -#include -#include -#include - -#include "agp.h" - -/* Generic AGP 3.0 enabling routines */ - -struct agp_3_0_dev { - struct list_head list; - u8 capndx; - u32 maxbw; - struct pci_dev *dev; -}; - -static int agp_3_0_dev_list_insert(struct list_head *head, struct list_head *new) -{ - struct agp_3_0_dev *cur, *n = list_entry(new, struct agp_3_0_dev, list); - struct list_head *pos; - - list_for_each(pos, head) { - cur = list_entry(pos, struct agp_3_0_dev, list); - if(cur->maxbw > n->maxbw) - break; - } - list_add_tail(new, pos); - - return 0; -} - -static int agp_3_0_dev_list_sort(struct agp_3_0_dev *list, unsigned int ndevs) -{ - struct agp_3_0_dev *cur; - struct pci_dev *dev; - struct list_head *pos, *tmp, *head = &list->list, *start = head->next; - u32 nistat; - - INIT_LIST_HEAD(head); - - for(pos = start; pos != head;) { - cur = list_entry(pos, struct agp_3_0_dev, list); - dev = cur->dev; - - pci_read_config_dword(dev, cur->capndx + 0x0c, &nistat); - cur->maxbw = (nistat >> 16) & 0xff; - - tmp = pos; - pos = pos->next; - agp_3_0_dev_list_insert(head, tmp); - } - return 0; -} - -/* - * Initialize all isochronous transfer parameters for an AGP 3.0 - * node (i.e. a host bridge in combination with the adapters - * lying behind it...) - */ - -static int agp_3_0_isochronous_node_enable(struct agp_3_0_dev *dev_list, unsigned int ndevs) -{ - /* - * Convenience structure to make the calculations clearer - * here. The field names come straight from the AGP 3.0 spec. - */ - struct isoch_data { - u32 maxbw; - u32 n; - u32 y; - u32 l; - u32 rq; - struct agp_3_0_dev *dev; - }; - - struct pci_dev *td = agp_bridge->dev, *dev; - struct list_head *head = &dev_list->list, *pos; - struct agp_3_0_dev *cur; - struct isoch_data *master, target; - unsigned int cdev = 0; - u32 mnistat, tnistat, tstatus, mcmd; - u16 tnicmd, mnicmd; - u8 mcapndx; - u32 tot_bw = 0, tot_n = 0, tot_rq = 0, y_max, rq_isoch, rq_async; - u32 step, rem, rem_isoch, rem_async; - int ret = 0; - - /* - * We'll work with an array of isoch_data's (one for each - * device in dev_list) throughout this function. - */ - if((master = kmalloc(ndevs * sizeof(*master), GFP_KERNEL)) == NULL) { - ret = -ENOMEM; - goto get_out; - } - - /* - * Sort the device list by maxbw. We need to do this because the - * spec suggests that the devices with the smallest requirements - * have their resources allocated first, with all remaining resources - * falling to the device with the largest requirement. - * - * We don't exactly do this, we divide target resources by ndevs - * and split them amongst the AGP 3.0 devices. The remainder of such - * division operations are dropped on the last device, sort of like - * the spec mentions it should be done. - * - * We can't do this sort when we initially construct the dev_list - * because we don't know until this function whether isochronous - * transfers are enabled and consequently whether maxbw will mean - * anything. - */ - if((ret = agp_3_0_dev_list_sort(dev_list, ndevs)) != 0) - goto free_and_exit; - - pci_read_config_dword(td, agp_bridge->capndx + 0x0c, &tnistat); - pci_read_config_dword(td, agp_bridge->capndx + 0x04, &tstatus); - - /* Extract power-on defaults from the target */ - target.maxbw = (tnistat >> 16) & 0xff; - target.n = (tnistat >> 8) & 0xff; - target.y = (tnistat >> 6) & 0x3; - target.l = (tnistat >> 3) & 0x7; - target.rq = (tstatus >> 24) & 0xff; - - y_max = target.y; - - /* - * Extract power-on defaults for each device in dev_list. Along - * the way, calculate the total isochronous bandwidth required - * by these devices and the largest requested payload size. - */ - list_for_each(pos, head) { - cur = list_entry(pos, struct agp_3_0_dev, list); - dev = cur->dev; - - mcapndx = cur->capndx; - - pci_read_config_dword(dev, cur->capndx + 0x0c, &mnistat); - - master[cdev].maxbw = (mnistat >> 16) & 0xff; - master[cdev].n = (mnistat >> 8) & 0xff; - master[cdev].y = (mnistat >> 6) & 0x3; - master[cdev].dev = cur; - - tot_bw += master[cdev].maxbw; - y_max = max(y_max, master[cdev].y); - - cdev++; - } - - /* Check if this configuration has any chance of working */ - if(tot_bw > target.maxbw) { - printk(KERN_ERR PFX "isochronous bandwidth required " - "by AGP 3.0 devices exceeds that which is supported by " - "the AGP 3.0 bridge!\n"); - ret = -ENODEV; - goto free_and_exit; - } - - target.y = y_max; - - /* - * Write the calculated payload size into the target's NICMD - * register. Doing this directly effects the ISOCH_N value - * in the target's NISTAT register, so we need to do this now - * to get an accurate value for ISOCH_N later. - */ - pci_read_config_word(td, agp_bridge->capndx + 0x20, &tnicmd); - tnicmd &= ~(0x3 << 6); - tnicmd |= target.y << 6; - pci_write_config_word(td, agp_bridge->capndx + 0x20, tnicmd); - - /* Reread the target's ISOCH_N */ - pci_read_config_dword(td, agp_bridge->capndx + 0x0c, &tnistat); - target.n = (tnistat >> 8) & 0xff; - - /* Calculate the minimum ISOCH_N needed by each master */ - for(cdev = 0; cdev < ndevs; cdev++) { - master[cdev].y = target.y; - master[cdev].n = master[cdev].maxbw / (master[cdev].y + 1); - - tot_n += master[cdev].n; - } - - /* Exit if the minimal ISOCH_N allocation among the masters is more - * than the target can handle. */ - if(tot_n > target.n) { - printk(KERN_ERR PFX "number of isochronous " - "transactions per period required by AGP 3.0 devices " - "exceeds that which is supported by the AGP 3.0 " - "bridge!\n"); - ret = -ENODEV; - goto free_and_exit; - } - - /* Calculate left over ISOCH_N capability in the target. We'll give - * this to the hungriest device (as per the spec) */ - rem = target.n - tot_n; - - /* - * Calculate the minimum isochronous RQ depth needed by each master. - * Along the way, distribute the extra ISOCH_N capability calculated - * above. - */ - for(cdev = 0; cdev < ndevs; cdev++) { - /* - * This is a little subtle. If ISOCH_Y > 64B, then ISOCH_Y - * byte isochronous writes will be broken into 64B pieces. - * This means we need to budget more RQ depth to account for - * these kind of writes (each isochronous write is actually - * many writes on the AGP bus). - */ - master[cdev].rq = master[cdev].n; - if(master[cdev].y > 0x1) { - master[cdev].rq *= (1 << (master[cdev].y - 1)); - } - - tot_rq += master[cdev].rq; - - if(cdev == ndevs - 1) - master[cdev].n += rem; - } - - /* Figure the number of isochronous and asynchronous RQ slots the - * target is providing. */ - rq_isoch = (target.y > 0x1) ? target.n * (1 << (target.y - 1)) : target.n; - rq_async = target.rq - rq_isoch; - - /* Exit if the minimal RQ needs of the masters exceeds what the target - * can provide. */ - if(tot_rq > rq_isoch) { - printk(KERN_ERR PFX "number of request queue slots " - "required by the isochronous bandwidth requested by " - "AGP 3.0 devices exceeds the number provided by the " - "AGP 3.0 bridge!\n"); - ret = -ENODEV; - goto free_and_exit; - } - - /* Calculate asynchronous RQ capability in the target (per master) as - * well as the total number of leftover isochronous RQ slots. */ - step = rq_async / ndevs; - rem_async = step + (rq_async % ndevs); - rem_isoch = rq_isoch - tot_rq; - - /* Distribute the extra RQ slots calculated above and write our - * isochronous settings out to the actual devices. */ - for(cdev = 0; cdev < ndevs; cdev++) { - cur = master[cdev].dev; - dev = cur->dev; - - mcapndx = cur->capndx; - - master[cdev].rq += (cdev == ndevs - 1) - ? (rem_async + rem_isoch) : step; - - pci_read_config_word(dev, cur->capndx + 0x20, &mnicmd); - pci_read_config_dword(dev, cur->capndx + 0x08, &mcmd); - - mnicmd &= ~(0xff << 8); - mnicmd &= ~(0x3 << 6); - mcmd &= ~(0xff << 24); - - mnicmd |= master[cdev].n << 8; - mnicmd |= master[cdev].y << 6; - mcmd |= master[cdev].rq << 24; - - pci_write_config_dword(dev, cur->capndx + 0x08, mcmd); - pci_write_config_word(dev, cur->capndx + 0x20, mnicmd); - } - -free_and_exit: - kfree(master); - -get_out: - return ret; -} - -/* - * This function basically allocates request queue slots among the - * AGP 3.0 systems in nonisochronous nodes. The algorithm is - * pretty stupid, divide the total number of RQ slots provided by the - * target by ndevs. Distribute this many slots to each AGP 3.0 device, - * giving any left over slots to the last device in dev_list. - */ -static int agp_3_0_nonisochronous_node_enable(struct agp_3_0_dev *dev_list, unsigned int ndevs) -{ - struct agp_3_0_dev *cur; - struct list_head *head = &dev_list->list, *pos; - u32 tstatus, mcmd; - u32 trq, mrq, rem; - unsigned int cdev = 0; - - pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + 0x04, &tstatus); - - trq = (tstatus >> 24) & 0xff; - mrq = trq / ndevs; - - rem = mrq + (trq % ndevs); - - for(pos = head->next; cdev < ndevs; cdev++, pos = pos->next) { - cur = list_entry(pos, struct agp_3_0_dev, list); - - pci_read_config_dword(cur->dev, cur->capndx + 0x08, &mcmd); - mcmd &= ~(0xff << 24); - mcmd |= ((cdev == ndevs - 1) ? rem : mrq) << 24; - pci_write_config_dword(cur->dev, cur->capndx + 0x08, mcmd); - } - - return 0; -} - -/* - * Fully configure and enable an AGP 3.0 host bridge and all the devices - * lying behind it. - */ -int agp_3_0_node_enable(u32 mode, u32 minor) -{ - struct pci_dev *td = agp_bridge->dev, *dev; - u8 mcapndx; - u32 isoch, arqsz, cal_cycle, tmp, rate; - u32 tstatus, tcmd, mcmd, mstatus, ncapid; - u32 mmajor, mminor; - u16 mpstat; - struct agp_3_0_dev *dev_list, *cur; - struct list_head *head, *pos; - unsigned int ndevs = 0; - int ret = 0; - - /* - * Allocate a head for our AGP 3.0 device list (multiple AGP 3.0 - * devices are allowed behind a single bridge). - */ - if((dev_list = kmalloc(sizeof(*dev_list), GFP_KERNEL)) == NULL) { - ret = -ENOMEM; - goto get_out; - } - head = &dev_list->list; - INIT_LIST_HEAD(head); - - /* Find all AGP devices, and add them to dev_list. */ - pci_for_each_dev(dev) { - switch ((dev->class >>8) & 0xff00) { - case 0x0001: /* Unclassified device */ - case 0x0300: /* Display controller */ - case 0x0400: /* Multimedia controller */ - case 0x0600: /* Bridge */ - mcapndx = pci_find_capability(dev, PCI_CAP_ID_AGP); - if (mcapndx == 0) - continue; - - if((cur = kmalloc(sizeof(*cur), GFP_KERNEL)) == NULL) { - ret = -ENOMEM; - goto free_and_exit; - } - cur->dev = dev; - - pos = &cur->list; - list_add(pos, head); - ndevs++; - continue; - - default: - continue; - } - } - - /* Extract some power-on defaults from the target */ - pci_read_config_dword(td, agp_bridge->capndx + 0x04, &tstatus); - isoch = (tstatus >> 17) & 0x1; - arqsz = (tstatus >> 13) & 0x7; - cal_cycle = (tstatus >> 10) & 0x7; - rate = tstatus & 0x7; - - /* - * Take an initial pass through the devices lying behind our host - * bridge. Make sure each one is actually an AGP 3.0 device, otherwise - * exit with an error message. Along the way store the AGP 3.0 - * cap_ptr for each device, the minimum supported cal_cycle, and the - * minimum supported data rate. - */ - list_for_each(pos, head) { - cur = list_entry(pos, struct agp_3_0_dev, list); - dev = cur->dev; - - pci_read_config_word(dev, PCI_STATUS, &mpstat); - if((mpstat & PCI_STATUS_CAP_LIST) == 0) - continue; - - pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &mcapndx); - if (mcapndx != 0x00) { - do { - pci_read_config_dword(dev, mcapndx, &ncapid); - if ((ncapid & 0xff) != 0x02) - mcapndx = (ncapid >> 8) & 0xff; - } - while (((ncapid & 0xff) != 0x02) && (mcapndx != 0x00)); - } - - if(mcapndx == 0) { - printk(KERN_ERR PFX "woah! Non-AGP device " - "found on the secondary bus of an AGP 3.0 bridge!\n"); - ret = -ENODEV; - goto free_and_exit; - } - - mmajor = (ncapid >> 20) & 0xf; - mminor = (ncapid >> 16) & 0xf; - - if(mmajor < 3) { - printk(KERN_ERR PFX "woah! AGP 2.0 device " - "found on the secondary bus of an AGP 3.0 " - "bridge operating with AGP 3.0 electricals!\n"); - ret = -ENODEV; - goto free_and_exit; - } - - cur->capndx = mcapndx; - - pci_read_config_dword(dev, cur->capndx + 0x04, &mstatus); - - if(((mstatus >> 3) & 0x1) == 0) { - printk(KERN_ERR PFX "woah! AGP 3.0 device " - "not operating in AGP 3.0 mode found on the " - "secondary bus of an AGP 3.0 bridge operating " - "with AGP 3.0 electricals!\n"); - ret = -ENODEV; - goto free_and_exit; - } - - tmp = (mstatus >> 10) & 0x7; - cal_cycle = min(cal_cycle, tmp); - - /* figure the lesser rate */ - tmp = mstatus & 0x7; - if(tmp < rate) - rate = tmp; - - } - - /* Turn rate into something we can actually write out to AGPCMD */ - switch(rate) { - case 0x1: - case 0x2: - break; - case 0x3: - rate = 0x2; - break; - default: - printk(KERN_ERR PFX "woah! Bogus AGP rate (%d) " - "value found advertised behind an AGP 3.0 bridge!\n", rate); - ret = -ENODEV; - goto free_and_exit; - } - - /* - * Call functions to divide target resources amongst the AGP 3.0 - * masters. This process is dramatically different depending on - * whether isochronous transfers are supported. - */ - if(isoch != 0) { - if((ret = agp_3_0_isochronous_node_enable(dev_list, ndevs)) != 0) - goto free_and_exit; - } else { - if((ret = agp_3_0_nonisochronous_node_enable(dev_list,ndevs)) != 0) - goto free_and_exit; - } - - /* - * Set the calculated minimum supported cal_cycle and minimum - * supported transfer rate in the target's AGPCMD register. - * Also set the AGP_ENABLE bit, effectively 'turning on' the - * target (this has to be done _before_ turning on the masters). - */ - pci_read_config_dword(td, agp_bridge->capndx + 0x08, &tcmd); - - tcmd &= ~(0x7 << 10); - tcmd &= ~0x7; - - tcmd |= cal_cycle << 10; - tcmd |= 0x1 << 8; - tcmd |= rate; - - pci_write_config_dword(td, agp_bridge->capndx + 0x08, tcmd); - - /* - * Set the target's advertised arqsz value, the minimum supported - * transfer rate, and the AGP_ENABLE bit in each master's AGPCMD - * register. - */ - list_for_each(pos, head) { - cur = list_entry(pos, struct agp_3_0_dev, list); - dev = cur->dev; - - mcapndx = cur->capndx; - - pci_read_config_dword(dev, cur->capndx + 0x08, &mcmd); - - mcmd &= ~(0x7 << 13); - mcmd &= ~0x7; - - mcmd |= arqsz << 13; - mcmd |= 0x1 << 8; - mcmd |= rate; - - pci_write_config_dword(dev, cur->capndx + 0x08, mcmd); - } - -free_and_exit: - /* Be sure to free the dev_list */ - for(pos = head->next; pos != head;) { - cur = list_entry(pos, struct agp_3_0_dev, list); - - pos = pos->next; - kfree(cur); - } - kfree(dev_list); - -get_out: - return ret; -} - -EXPORT_SYMBOL_GPL(agp_3_0_node_enable); - diff -Nru a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c --- a/drivers/char/agp/generic.c Sat May 24 12:48:23 2003 +++ b/drivers/char/agp/generic.c Sat May 24 12:48:23 2003 @@ -1,6 +1,6 @@ /* * AGPGART driver. - * Copyright (C) 2002 Dave Jones. + * Copyright (C) 2002-2003 Dave Jones. * Copyright (C) 1999 Jeff Hartmann. * Copyright (C) 1999 Precision Insight, Inc. * Copyright (C) 1999 Xi Graphics, Inc. @@ -42,19 +42,19 @@ /* * Generic routines for handling agp_memory structures - - * They use the basic page allocation routines to do the - * brunt of the work. + * They use the basic page allocation routines to do the brunt of the work. */ void agp_free_key(int key) { - if (key < 0) return; if (key < MAXKEY) clear_bit(key, agp_bridge->key_list); } +EXPORT_SYMBOL(agp_free_key); + static int agp_get_key(void) { @@ -68,16 +68,17 @@ return -1; } -agp_memory *agp_create_memory(int scratch_pages) + +struct agp_memory *agp_create_memory(int scratch_pages) { - agp_memory *new; + struct agp_memory *new; - new = kmalloc(sizeof(agp_memory), GFP_KERNEL); + new = kmalloc(sizeof(struct agp_memory), GFP_KERNEL); if (new == NULL) return NULL; - memset(new, 0, sizeof(agp_memory)); + memset(new, 0, sizeof(struct agp_memory)); new->key = agp_get_key(); if (new->key < 0) { @@ -94,8 +95,17 @@ new->num_scratch_pages = scratch_pages; return new; } +EXPORT_SYMBOL(agp_create_memory); -void agp_free_memory(agp_memory * curr) +/** + * agp_free_memory - free memory associated with an agp_memory pointer. + * + * @curr: agp_memory pointer to be freed. + * + * It is the only function that can be called when the backend is not owned + * by the caller. (So it can free memory on client death.) + */ +void agp_free_memory(struct agp_memory *curr) { size_t i; @@ -106,25 +116,37 @@ agp_unbind_memory(curr); if (curr->type != 0) { - agp_bridge->free_by_type(curr); + agp_bridge->driver->free_by_type(curr); return; } if (curr->page_count != 0) { for (i = 0; i < curr->page_count; i++) { - agp_bridge->agp_destroy_page(phys_to_virt(curr->memory[i])); + agp_bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[i])); } } agp_free_key(curr->key); vfree(curr->memory); kfree(curr); } +EXPORT_SYMBOL(agp_free_memory); #define ENTRIES_PER_PAGE (PAGE_SIZE / sizeof(unsigned long)) -agp_memory *agp_allocate_memory(size_t page_count, u32 type) +/** + * agp_allocate_memory - allocate a group of pages of a certain type. + * + * @page_count: size_t argument of the number of pages + * @type: u32 argument of the type of memory to be allocated. + * + * Every agp bridge device will allow you to allocate AGP_NORMAL_MEMORY which + * maps to physical ram. Any other type is device dependent. + * + * It returns NULL whenever memory is unavailable. + */ +struct agp_memory *agp_allocate_memory(size_t page_count, u32 type) { int scratch_pages; - agp_memory *new; + struct agp_memory *new; size_t i; if (agp_bridge->type == NOT_SUPPORTED) @@ -134,7 +156,7 @@ return NULL; if (type != 0) { - new = agp_bridge->alloc_by_type(page_count, type); + new = agp_bridge->driver->alloc_by_type(page_count, type); return new; } @@ -146,7 +168,7 @@ return NULL; for (i = 0; i < page_count; i++) { - void *addr = agp_bridge->agp_alloc_page(); + void *addr = agp_bridge->driver->agp_alloc_page(); if (addr == NULL) { agp_free_memory(new); @@ -160,9 +182,12 @@ return new; } +EXPORT_SYMBOL(agp_allocate_memory); + /* End - Generic routines for handling agp_memory structures */ + static int agp_return_size(void) { int current_size; @@ -170,7 +195,7 @@ temp = agp_bridge->current_size; - switch (agp_bridge->size_type) { + switch (agp_bridge->driver->size_type) { case U8_APER_SIZE: current_size = A_SIZE_8(temp)->size; break; @@ -197,6 +222,7 @@ return current_size; } + int agp_num_entries(void) { int num_entries; @@ -204,7 +230,7 @@ temp = agp_bridge->current_size; - switch (agp_bridge->size_type) { + switch (agp_bridge->driver->size_type) { case U8_APER_SIZE: num_entries = A_SIZE_8(temp)->num_entries; break; @@ -230,52 +256,77 @@ num_entries = 0; return num_entries; } +EXPORT_SYMBOL_GPL(agp_num_entries); -/* Routine to copy over information structure */ -int agp_copy_info(agp_kern_info * info) +/** + * agp_copy_info - copy bridge state information + * + * @info: agp_kern_info pointer. The caller should insure that this pointer is valid. + * + * This function copies information about the agp bridge device and the state of + * the agp backend into an agp_kern_info pointer. + */ +int agp_copy_info(struct agp_kern_info *info) { - memset(info, 0, sizeof(agp_kern_info)); - if (agp_bridge->type == NOT_SUPPORTED) { - info->chipset = agp_bridge->type; + memset(info, 0, sizeof(struct agp_kern_info)); + if (!agp_bridge || agp_bridge->type == NOT_SUPPORTED || + !agp_bridge->version) { + info->chipset = NOT_SUPPORTED; return -EIO; } + info->version.major = agp_bridge->version->major; info->version.minor = agp_bridge->version->minor; - info->device = agp_bridge->dev; info->chipset = agp_bridge->type; + info->device = agp_bridge->dev; info->mode = agp_bridge->mode; info->aper_base = agp_bridge->gart_bus_addr; info->aper_size = agp_return_size(); info->max_memory = agp_bridge->max_memory_agp; info->current_memory = atomic_read(&agp_bridge->current_memory_agp); - info->cant_use_aperture = agp_bridge->cant_use_aperture; + info->cant_use_aperture = agp_bridge->driver->cant_use_aperture; info->vm_ops = agp_bridge->vm_ops; info->page_mask = ~0UL; return 0; } +EXPORT_SYMBOL(agp_copy_info); + /* End - Routine to copy over information structure */ + /* * Routines for handling swapping of agp_memory into the GATT - * These routines take agp_memory and insert them into the GATT. * They call device specific routines to actually write to the GATT. */ -int agp_bind_memory(agp_memory * curr, off_t pg_start) +/** + * agp_bind_memory - Bind an agp_memory structure into the GATT. + * + * @curr: agp_memory pointer + * @pg_start: an offset into the graphics aperture translation table + * + * It returns -EINVAL if the pointer == NULL. + * It returns -EBUSY if the area of the table requested is already in use. + */ +int agp_bind_memory(struct agp_memory *curr, off_t pg_start) { int ret_val; - if ((agp_bridge->type == NOT_SUPPORTED) || - (curr == NULL) || (curr->is_bound == TRUE)) { + if ((agp_bridge->type == NOT_SUPPORTED) || (curr == NULL)) + return -EINVAL; + + if (curr->is_bound == TRUE) { + printk (KERN_INFO PFX "memory %p is already bound!\n", curr); return -EINVAL; } if (curr->is_flushed == FALSE) { - CACHE_FLUSH(); + agp_bridge->driver->cache_flush(); curr->is_flushed = TRUE; } - ret_val = agp_bridge->insert_memory(curr, pg_start, curr->type); + ret_val = agp_bridge->driver->insert_memory(curr, pg_start, curr->type); if (ret_val != 0) return ret_val; @@ -284,18 +335,30 @@ curr->pg_start = pg_start; return 0; } +EXPORT_SYMBOL(agp_bind_memory); -int agp_unbind_memory(agp_memory * curr) + +/** + * agp_unbind_memory - Removes an agp_memory structure from the GATT + * + * @curr: agp_memory pointer to be removed from the GATT. + * + * It returns -EINVAL if this piece of agp_memory is not currently bound to + * the graphics aperture translation table or if the agp_memory pointer == NULL + */ +int agp_unbind_memory(struct agp_memory *curr) { int ret_val; if ((agp_bridge->type == NOT_SUPPORTED) || (curr == NULL)) return -EINVAL; - if (curr->is_bound != TRUE) + if (curr->is_bound != TRUE) { + printk (KERN_INFO PFX "memory %p was not bound!\n", curr); return -EINVAL; + } - ret_val = agp_bridge->remove_memory(curr, curr->pg_start, curr->type); + ret_val = agp_bridge->driver->remove_memory(curr, curr->pg_start, curr->type); if (ret_val != 0) return ret_val; @@ -304,74 +367,138 @@ curr->pg_start = 0; return 0; } +EXPORT_SYMBOL(agp_unbind_memory); /* End - Routines for handling swapping of agp_memory into the GATT */ /* Generic Agp routines - Start */ +static void agp_v2_parse_one(u32 *mode, u32 *cmd, u32 *tmp) +{ + /* disable SBA if it's not supported */ + if (!((*cmd & AGPSTAT_SBA) && (*tmp & AGPSTAT_SBA) && (*mode & AGPSTAT_SBA))) + *cmd &= ~AGPSTAT_SBA; + + /* Set speed */ + if (!((*cmd & AGPSTAT2_4X) && (*tmp & AGPSTAT2_4X) && (*mode & AGPSTAT2_4X))) + *cmd &= ~AGPSTAT2_4X; + + if (!((*cmd & AGPSTAT2_2X) && (*tmp & AGPSTAT2_2X) && (*mode & AGPSTAT2_2X))) + *cmd &= ~AGPSTAT2_2X; -u32 agp_collect_device_status(u32 mode, u32 command) + if (!((*cmd & AGPSTAT2_1X) && (*tmp & AGPSTAT2_1X) && (*mode & AGPSTAT2_1X))) + *cmd &= ~AGPSTAT2_1X; + + /* Now we know what mode it should be, clear out the unwanted bits. */ + if (*cmd & AGPSTAT2_4X) + *cmd &= ~(AGPSTAT2_1X | AGPSTAT2_2X); /* 4X */ + + if (*cmd & AGPSTAT2_2X) + *cmd &= ~(AGPSTAT2_1X | AGPSTAT2_4X); /* 2X */ + + if (*cmd & AGPSTAT2_1X) + *cmd &= ~(AGPSTAT2_2X | AGPSTAT2_4X); /* 1Xf */ +} + + +static void agp_v3_parse_one(u32 *mode, u32 *cmd, u32 *tmp) +{ + /* ARQSZ - Set the value to the maximum one. + * Don't allow the mode register to override values. */ + *cmd = ((*cmd & ~AGPSTAT_ARQSZ) | + max_t(u32,(*cmd & AGPSTAT_ARQSZ),(*tmp & AGPSTAT_ARQSZ))); + + /* Calibration cycle. + * Don't allow the mode register to override values. */ + *cmd = ((*cmd & ~AGPSTAT_CAL_MASK) | + min_t(u32,(*cmd & AGPSTAT_CAL_MASK),(*tmp & AGPSTAT_CAL_MASK))); + + /* SBA *must* be supported for AGP v3 */ + *cmd |= AGPSTAT_SBA; + + /* + * Set speed. + * Check for invalid speeds. This can happen when applications + * written before the AGP 3.0 standard pass AGP2.x modes to AGP3 hardware + */ + if (*mode & AGPSTAT_MODE_3_0) { + /* + * Caller hasn't a clue what its doing. We are in 3.0 mode, + * have been passed a 3.0 mode, but with 2.x speed bits set. + * AGP2.x 4x -> AGP3.0 4x. + */ + if (*mode & AGPSTAT2_4X) { + printk (KERN_INFO PFX "%s passes broken AGP3 flags (%x). Fixed.\n", + current->comm, *mode); + *mode &= ~AGPSTAT2_4X; + *mode |= AGPSTAT3_4X; + } + } else { + /* + * The caller doesn't know what they are doing. We are in 3.0 mode, + * but have been passed an AGP 2.x mode. + * Convert AGP 1x,2x,4x -> AGP 3.0 4x. + */ + printk (KERN_INFO PFX "%s passes broken AGP2 flags (%x) in AGP3 mode. Fixed.\n", + current->comm, *mode); + *mode &= ~(AGPSTAT2_4X | AGPSTAT2_2X | AGPSTAT2_1X); + *mode |= AGPSTAT3_4X; + } + + if (!((*cmd & AGPSTAT3_8X) && (*tmp & AGPSTAT3_8X) && (*mode & AGPSTAT3_8X))) + *cmd &= ~AGPSTAT3_8X; + + if (!((*cmd & AGPSTAT3_4X) && (*tmp & AGPSTAT3_4X) && (*mode & AGPSTAT3_4X))) + *cmd &= ~AGPSTAT3_4X; + + /* Clear out unwanted bits. */ + if (*cmd & AGPSTAT3_8X) + *cmd = ~(AGPSTAT3_4X | AGPSTAT3_RSVD); + if (*cmd & AGPSTAT3_4X) + *cmd = ~(AGPSTAT3_8X | AGPSTAT3_RSVD); +} + +//FIXME: This doesn't smell right. +//We need a function we pass an agp_device to. +u32 agp_collect_device_status(u32 mode, u32 cmd) { struct pci_dev *device; - u8 agp; - u32 scratch; + u8 cap_ptr; + u32 tmp; + u32 agp3; pci_for_each_dev(device) { - agp = pci_find_capability(device, PCI_CAP_ID_AGP); - if (!agp) + cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP); + if (!cap_ptr) continue; /* * Ok, here we have a AGP device. Disable impossible * settings, and adjust the readqueue to the minimum. */ - pci_read_config_dword(device, agp + PCI_AGP_STATUS, &scratch); + pci_read_config_dword(device, cap_ptr+PCI_AGP_STATUS, &tmp); /* adjust RQ depth */ - command = ((command & ~0xff000000) | - min_t(u32, (mode & 0xff000000), - min_t(u32, (command & 0xff000000), - (scratch & 0xff000000)))); - - /* disable SBA if it's not supported */ - if (!((command & 0x00000200) && - (scratch & 0x00000200) && - (mode & 0x00000200))) - command &= ~0x00000200; - + cmd = ((cmd & ~AGPSTAT_RQ_DEPTH) | + min_t(u32, (mode & AGPSTAT_RQ_DEPTH), + min_t(u32, (cmd & AGPSTAT_RQ_DEPTH), (tmp & AGPSTAT_RQ_DEPTH)))); + /* disable FW if it's not supported */ - if (!((command & 0x00000010) && - (scratch & 0x00000010) && - (mode & 0x00000010))) - command &= ~0x00000010; + if (!((cmd & AGPSTAT_FW) && (tmp & AGPSTAT_FW) && (mode & AGPSTAT_FW))) + cmd &= ~AGPSTAT_FW; - if (!((command & 4) && - (scratch & 4) && - (mode & 4))) - command &= ~0x00000004; - - if (!((command & 2) && - (scratch & 2) && - (mode & 2))) - command &= ~0x00000002; - - if (!((command & 1) && - (scratch & 1) && - (mode & 1))) - command &= ~0x00000001; + /* Check to see if we are operating in 3.0 mode */ + pci_read_config_dword(device, cap_ptr+AGPSTAT, &agp3); + if (agp3 & AGPSTAT_MODE_3_0) { + agp_v3_parse_one(&mode, &cmd, &tmp); + } else { + agp_v2_parse_one(&mode, &cmd, &tmp); + } } - - if (command & 4) - command &= ~3; /* 4X */ - - if (command & 2) - command &= ~5; /* 2X (8X for AGP3.0) */ - - if (command & 1) - command &= ~6; /* 1X (4X for AGP3.0) */ - - return command; + return cmd; } +EXPORT_SYMBOL(agp_collect_device_status); + void agp_device_command(u32 command, int agp_v3) { @@ -392,40 +519,68 @@ pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command); } } +EXPORT_SYMBOL(agp_device_command); -void agp_generic_enable(u32 mode) + +void get_agp_version(struct agp_bridge_data *bridge) { - u32 command, ncapid, major, minor; + u32 ncapid; + + /* Exit early if already set by errata workarounds. */ + if (agp_bridge->major_version != 0) + return; pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx, &ncapid); - major = (ncapid >> 20) & 0xf; - minor = (ncapid >> 16) & 0xf; - printk(KERN_INFO PFX "Found an AGP %d.%d compliant device.\n",major, minor); + agp_bridge->major_version = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf; + agp_bridge->minor_version = (ncapid >> AGP_MINOR_VERSION_SHIFT) & 0xf; +} +EXPORT_SYMBOL(get_agp_version); - if(major >= 3) { - u32 agp_3_0; - pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + 0x4, &agp_3_0); - /* Check to see if we are operating in 3.0 mode */ - if((agp_3_0 >> 3) & 0x1) { - agp_3_0_node_enable(mode, minor); - return; - } else { - printk (KERN_INFO PFX "not in AGP 3.0 mode, falling back to 2.x\n"); - } - } +void agp_generic_enable(u32 mode) +{ + u32 command; + u32 agp3; + + get_agp_version(agp_bridge); + + printk(KERN_INFO PFX "Found an AGP %d.%d compliant device at %s.\n", + agp_bridge->major_version, + agp_bridge->minor_version, + agp_bridge->dev->slot_name); - /* AGP v<3 */ pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + PCI_AGP_STATUS, &command); command = agp_collect_device_status(mode, command); - command |= 0x100; + command |= AGPSTAT_AGP_ENABLE; pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx + PCI_AGP_COMMAND, command); - agp_device_command(command, 0); + + /* Do AGP version specific frobbing. */ + if(agp_bridge->major_version >= 3) { + pci_read_config_dword(agp_bridge->dev, + agp_bridge->capndx+AGPSTAT, &agp3); + + /* Check to see if we are operating in 3.0 mode */ + if (agp3 & AGPSTAT_MODE_3_0) { + /* If we have 3.5, we can do the isoch stuff. */ + if (agp_bridge->minor_version >= 5) + agp_3_5_enable(agp_bridge); + agp_device_command(command, TRUE); + return; + } else { + printk (KERN_INFO PFX "Device is in legacy mode," + " falling back to 2.x\n"); + } + } + + /* AGP v<3 */ + agp_device_command(command, FALSE); } +EXPORT_SYMBOL(agp_generic_enable); + int agp_generic_create_gatt_table(void) { @@ -439,7 +594,7 @@ struct page *page; /* The generic routines can't handle 2 level gatt's */ - if (agp_bridge->size_type == LVL2_APER_SIZE) + if (agp_bridge->driver->size_type == LVL2_APER_SIZE) return -EINVAL; table = NULL; @@ -447,9 +602,9 @@ temp = agp_bridge->current_size; size = page_order = num_entries = 0; - if (agp_bridge->size_type != FIXED_APER_SIZE) { + if (agp_bridge->driver->size_type != FIXED_APER_SIZE) { do { - switch (agp_bridge->size_type) { + switch (agp_bridge->driver->size_type) { case U8_APER_SIZE: size = A_SIZE_8(temp)->size; page_order = @@ -480,19 +635,17 @@ if (table == NULL) { i++; - switch (agp_bridge->size_type) { + switch (agp_bridge->driver->size_type) { case U8_APER_SIZE: - agp_bridge->current_size = A_IDX8(); + agp_bridge->current_size = A_IDX8(agp_bridge); break; case U16_APER_SIZE: - agp_bridge->current_size = A_IDX16(); + agp_bridge->current_size = A_IDX16(agp_bridge); break; case U32_APER_SIZE: - agp_bridge->current_size = A_IDX32(); + agp_bridge->current_size = A_IDX32(agp_bridge); break; - /* This case will never really - * happen. - */ + /* This case will never really happen. */ case FIXED_APER_SIZE: case LVL2_APER_SIZE: default: @@ -504,7 +657,7 @@ } else { agp_bridge->aperture_size_idx = i; } - } while ((table == NULL) && (i < agp_bridge->num_aperture_sizes)); + } while (!table && (i < agp_bridge->driver->num_aperture_sizes)); } else { size = ((struct aper_size_info_fixed *) temp)->size; page_order = ((struct aper_size_info_fixed *) temp)->page_order; @@ -522,10 +675,11 @@ agp_bridge->gatt_table_real = (u32 *) table; agp_gatt_table = (void *)table; - CACHE_FLUSH(); + + agp_bridge->driver->cache_flush(); agp_bridge->gatt_table = ioremap_nocache(virt_to_phys(table), (PAGE_SIZE * (1 << page_order))); - CACHE_FLUSH(); + agp_bridge->driver->cache_flush(); if (agp_bridge->gatt_table == NULL) { for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) @@ -543,16 +697,7 @@ return 0; } - -int agp_generic_suspend(void) -{ - return 0; -} - -void agp_generic_resume(void) -{ - return; -} +EXPORT_SYMBOL(agp_generic_create_gatt_table); int agp_generic_free_gatt_table(void) { @@ -563,7 +708,7 @@ temp = agp_bridge->current_size; - switch (agp_bridge->size_type) { + switch (agp_bridge->driver->size_type) { case U8_APER_SIZE: page_order = A_SIZE_8(temp)->page_order; break; @@ -587,8 +732,7 @@ /* Do not worry about freeing memory, because if this is * called, then all agp memory is deallocated and removed - * from the table. - */ + * from the table. */ iounmap(agp_bridge->gatt_table); table = (char *) agp_bridge->gatt_table_real; @@ -598,10 +742,18 @@ ClearPageReserved(page); free_pages((unsigned long) agp_bridge->gatt_table_real, page_order); + + agp_gatt_table = NULL; + agp_bridge->gatt_table = NULL; + agp_bridge->gatt_table_real = NULL; + agp_bridge->gatt_bus_addr = 0; + return 0; } +EXPORT_SYMBOL(agp_generic_free_gatt_table); + -int agp_generic_insert_memory(agp_memory * mem, off_t pg_start, int type) +int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type) { int num_entries; size_t i; @@ -610,7 +762,7 @@ temp = agp_bridge->current_size; - switch (agp_bridge->size_type) { + switch (agp_bridge->driver->size_type) { case U8_APER_SIZE: num_entries = A_SIZE_8(temp)->num_entries; break; @@ -647,26 +799,29 @@ j = pg_start; while (j < (pg_start + mem->page_count)) { - if (!PGE_EMPTY(agp_bridge->gatt_table[j])) { + if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j])) { return -EBUSY; } j++; } if (mem->is_flushed == FALSE) { - CACHE_FLUSH(); + agp_bridge->driver->cache_flush(); mem->is_flushed = TRUE; } for (i = 0, j = pg_start; i < mem->page_count; i++, j++) agp_bridge->gatt_table[j] = - agp_bridge->mask_memory(mem->memory[i], mem->type); + agp_bridge->driver->mask_memory( + mem->memory[i], mem->type); - agp_bridge->tlb_flush(mem); + agp_bridge->driver->tlb_flush(mem); return 0; } +EXPORT_SYMBOL(agp_generic_insert_memory); -int agp_generic_remove_memory(agp_memory * mem, off_t pg_start, int type) + +int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type) { size_t i; @@ -681,16 +836,20 @@ (unsigned long) agp_bridge->scratch_page; } - agp_bridge->tlb_flush(mem); + agp_bridge->driver->tlb_flush(mem); return 0; } +EXPORT_SYMBOL(agp_generic_remove_memory); -agp_memory *agp_generic_alloc_by_type(size_t page_count, int type) + +struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type) { return NULL; } +EXPORT_SYMBOL(agp_generic_alloc_by_type); + -void agp_generic_free_by_type(agp_memory * curr) +void agp_generic_free_by_type(struct agp_memory *curr) { if (curr->memory != NULL) vfree(curr->memory); @@ -698,13 +857,13 @@ agp_free_key(curr->key); kfree(curr); } +EXPORT_SYMBOL(agp_generic_free_by_type); + /* * Basic Page Allocation Routines - - * These routines handle page allocation - * and by default they reserve the allocated - * memory. They also handle incrementing the - * current_memory_agp value, Which is checked + * These routines handle page allocation and by default they reserve the allocated + * memory. They also handle incrementing the current_memory_agp value, Which is checked * against a maximum value. */ @@ -723,6 +882,8 @@ atomic_inc(&agp_bridge->current_memory_agp); return page_address(page); } +EXPORT_SYMBOL(agp_generic_alloc_page); + void agp_generic_destroy_page(void *addr) { @@ -738,41 +899,50 @@ free_page((unsigned long)addr); atomic_dec(&agp_bridge->current_memory_agp); } +EXPORT_SYMBOL(agp_generic_destroy_page); /* End Basic Page Allocation Routines */ + +/** + * agp_enable - initialise the agp point-to-point connection. + * + * @mode: agp mode register value to configure with. + */ void agp_enable(u32 mode) { if (agp_bridge->type == NOT_SUPPORTED) return; - agp_bridge->agp_enable(mode); + agp_bridge->driver->agp_enable(mode); } - -EXPORT_SYMBOL(agp_free_memory); -EXPORT_SYMBOL(agp_allocate_memory); -EXPORT_SYMBOL(agp_copy_info); -EXPORT_SYMBOL(agp_create_memory); -EXPORT_SYMBOL(agp_bind_memory); -EXPORT_SYMBOL(agp_unbind_memory); -EXPORT_SYMBOL(agp_free_key); EXPORT_SYMBOL(agp_enable); -EXPORT_SYMBOL(agp_bridge); -EXPORT_SYMBOL(agp_generic_alloc_page); -EXPORT_SYMBOL(agp_generic_destroy_page); -EXPORT_SYMBOL(agp_generic_suspend); -EXPORT_SYMBOL(agp_generic_resume); -EXPORT_SYMBOL(agp_generic_enable); -EXPORT_SYMBOL(agp_generic_create_gatt_table); -EXPORT_SYMBOL(agp_generic_free_gatt_table); -EXPORT_SYMBOL(agp_generic_insert_memory); -EXPORT_SYMBOL(agp_generic_remove_memory); -EXPORT_SYMBOL(agp_generic_alloc_by_type); -EXPORT_SYMBOL(agp_generic_free_by_type); -EXPORT_SYMBOL(global_cache_flush); -EXPORT_SYMBOL(agp_device_command); -EXPORT_SYMBOL(agp_collect_device_status); +#ifdef CONFIG_SMP +static void ipi_handler(void *null) +{ + flush_agp_cache(); +} +#endif -EXPORT_SYMBOL_GPL(agp_num_entries); +void global_cache_flush(void) +{ +#ifdef CONFIG_SMP + if (on_each_cpu(ipi_handler, NULL, 1, 1) != 0) + panic(PFX "timed out waiting for the other CPUs!\n"); +#else + flush_agp_cache(); +#endif +} +EXPORT_SYMBOL(global_cache_flush); + +unsigned long agp_generic_mask_memory(unsigned long addr, int type) +{ + /* memory type is ignored in the generic routine */ + if (agp_bridge->driver->masks) + return addr | agp_bridge->driver->masks[0].mask; + else + return addr; +} +EXPORT_SYMBOL(agp_generic_mask_memory); diff -Nru a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c --- a/drivers/char/agp/hp-agp.c Sat May 24 12:48:30 2003 +++ b/drivers/char/agp/hp-agp.c Sat May 24 12:48:30 2003 @@ -212,7 +212,7 @@ iounmap((void *) hp->registers); } -static void hp_zx1_tlbflush(agp_memory * mem) +static void hp_zx1_tlbflush(struct agp_memory *mem) { struct _hp_private *hp = &hp_private; @@ -259,7 +259,8 @@ return 0; } -static int hp_zx1_insert_memory(agp_memory * mem, off_t pg_start, int type) +static int hp_zx1_insert_memory(struct agp_memory *mem, off_t pg_start, + int type) { struct _hp_private *hp = &hp_private; int i, k; @@ -285,7 +286,7 @@ } if (mem->is_flushed == FALSE) { - CACHE_FLUSH(); + global_cache_flush(); mem->is_flushed = TRUE; } @@ -296,15 +297,16 @@ for (k = 0; k < hp->io_pages_per_kpage; k++, j++, paddr += hp->io_page_size) { - hp->gatt[j] = agp_bridge->mask_memory(paddr, type); + hp->gatt[j] = agp_bridge->driver->mask_memory(paddr, type); } } - agp_bridge->tlb_flush(mem); + agp_bridge->driver->tlb_flush(mem); return 0; } -static int hp_zx1_remove_memory(agp_memory * mem, off_t pg_start, int type) +static int hp_zx1_remove_memory(struct agp_memory *mem, off_t pg_start, + int type) { struct _hp_private *hp = &hp_private; int i, io_pg_start, io_pg_count; @@ -319,7 +321,7 @@ hp->gatt[i] = agp_bridge->scratch_page; } - agp_bridge->tlb_flush(mem); + agp_bridge->driver->tlb_flush(mem); return 0; } @@ -328,58 +330,62 @@ return HP_ZX1_PDIR_VALID_BIT | addr; } -static int __init hp_zx1_setup (struct pci_dev *pdev __attribute__((unused))) -{ - agp_bridge->masks = hp_zx1_masks; - agp_bridge->dev_private_data = NULL; - agp_bridge->size_type = FIXED_APER_SIZE; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = hp_zx1_configure; - agp_bridge->fetch_size = hp_zx1_fetch_size; - agp_bridge->cleanup = hp_zx1_cleanup; - agp_bridge->tlb_flush = hp_zx1_tlbflush; - agp_bridge->mask_memory = hp_zx1_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = hp_zx1_create_gatt_table; - agp_bridge->free_gatt_table = hp_zx1_free_gatt_table; - agp_bridge->insert_memory = hp_zx1_insert_memory; - agp_bridge->remove_memory = hp_zx1_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->cant_use_aperture = 1; - return hp_zx1_ioc_init(); -} +struct agp_bridge_driver hp_zx1_driver = { + .owner = THIS_MODULE, + .size_type = FIXED_APER_SIZE, + .configure = hp_zx1_configure, + .fetch_size = hp_zx1_fetch_size, + .cleanup = hp_zx1_cleanup, + .tlb_flush = hp_zx1_tlbflush, + .mask_memory = hp_zx1_mask_memory, + .masks = hp_zx1_masks, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = hp_zx1_create_gatt_table, + .free_gatt_table = hp_zx1_free_gatt_table, + .insert_memory = hp_zx1_insert_memory, + .remove_memory = hp_zx1_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .cant_use_aperture = 1, +}; -static int __init agp_find_supported_device(struct pci_dev *dev) +static int __init agp_hp_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - agp_bridge->dev = dev; + struct agp_bridge_data *bridge; + int error; /* ZX1 LBAs can be either PCI or AGP bridges */ - if (pci_find_capability(dev, PCI_CAP_ID_AGP)) { - printk(KERN_INFO PFX "Detected HP ZX1 AGP chipset at %s\n", - dev->slot_name); - agp_bridge->type = HP_ZX1; - agp_bridge->dev = dev; - return hp_zx1_setup(dev); - } - return -ENODEV; -} + if (!pci_find_capability(pdev, PCI_CAP_ID_AGP)) + return -ENODEV; -static struct agp_driver hp_agp_driver = { - .owner = THIS_MODULE, -}; + printk(KERN_INFO PFX "Detected HP ZX1 AGP chipset at %s\n", + pdev->slot_name); + + error = hp_zx1_ioc_init(); + if (error) + return error; + + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; -static int __init agp_hp_probe (struct pci_dev *dev, const struct pci_device_id *ent) + bridge->driver = &hp_zx1_driver; + bridge->dev = pdev; + + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); +} + +static void __devexit agp_hp_remove(struct pci_dev *pdev) { - if (agp_find_supported_device(dev) == 0) { - hp_agp_driver.dev = dev; - agp_register_driver(&hp_agp_driver); - return 0; - } - return -ENODEV; + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + + agp_remove_bridge(bridge); + agp_put_bridge(bridge); } static struct pci_device_id agp_hp_pci_table[] __initdata = { @@ -396,26 +402,20 @@ MODULE_DEVICE_TABLE(pci, agp_hp_pci_table); -static struct __initdata pci_driver agp_hp_pci_driver = { +static struct pci_driver agp_hp_pci_driver = { .name = "agpgart-hp", .id_table = agp_hp_pci_table, .probe = agp_hp_probe, + .remove = agp_hp_remove, }; static int __init agp_hp_init(void) { - int ret_val; - - ret_val = pci_module_init(&agp_hp_pci_driver); - if (ret_val) - agp_bridge->type = NOT_SUPPORTED; - - return ret_val; + return pci_module_init(&agp_hp_pci_driver); } static void __exit agp_hp_cleanup(void) { - agp_unregister_driver(&hp_agp_driver); pci_unregister_driver(&agp_hp_pci_driver); } diff -Nru a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c --- a/drivers/char/agp/i460-agp.c Sat May 24 12:48:26 2003 +++ b/drivers/char/agp/i460-agp.c Sat May 24 12:48:26 2003 @@ -69,7 +69,7 @@ } *lp_desc; } i460; -static const struct aper_size_info_8 i460_sizes[3] = +static struct aper_size_info_8 i460_sizes[3] = { /* * The 32GB aperture is only available with a 4M GART page size. Due to the @@ -107,7 +107,7 @@ return 0; } - values = A_SIZE_8(agp_bridge->aperture_sizes); + values = A_SIZE_8(agp_bridge->driver->aperture_sizes); pci_read_config_byte(agp_bridge->dev, INTEL_I460_AGPSIZ, &temp); @@ -130,7 +130,7 @@ else i460.dynamic_apbase = INTEL_I460_APBASE; - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { /* * Dynamically calculate the proper num_entries and page_order values for * the define aperture sizes. Take care not to shift off the end of @@ -140,7 +140,7 @@ values[i].page_order = log2((sizeof(u32)*values[i].num_entries) >> PAGE_SHIFT); } - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { /* Neglect control bits when matching up size_value */ if ((temp & I460_AGPSIZ_MASK) == values[i].size_value) { agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i); @@ -153,7 +153,7 @@ } /* There isn't anything to do here since 460 has no GART TLB. */ -static void i460_tlb_flush (agp_memory * mem) +static void i460_tlb_flush (struct agp_memory *mem) { return; } @@ -273,7 +273,8 @@ * PAGE_SIZE. */ -static int i460_insert_memory_small_io_page (agp_memory *mem, off_t pg_start, int type) +static int i460_insert_memory_small_io_page (struct agp_memory *mem, + off_t pg_start, int type) { unsigned long paddr, io_pg_start, io_page_size; int i, j, k, num_entries; @@ -294,7 +295,7 @@ j = io_pg_start; while (j < (io_pg_start + I460_IOPAGES_PER_KPAGE * mem->page_count)) { - if (!PGE_EMPTY(RD_GATT(j))) { + if (!PGE_EMPTY(agp_bridge, RD_GATT(j))) { pr_debug("i460_insert_memory_small_io_page: GATT[%d]=0x%x is busy\n", j, RD_GATT(j)); return -EBUSY; @@ -306,13 +307,14 @@ for (i = 0, j = io_pg_start; i < mem->page_count; i++) { paddr = mem->memory[i]; for (k = 0; k < I460_IOPAGES_PER_KPAGE; k++, j++, paddr += io_page_size) - WR_GATT(j, agp_bridge->mask_memory(paddr, mem->type)); + WR_GATT(j, agp_bridge->driver->mask_memory(paddr, mem->type)); } WR_FLUSH_GATT(j - 1); return 0; } -static int i460_remove_memory_small_io_page(agp_memory * mem, off_t pg_start, int type) +static int i460_remove_memory_small_io_page(struct agp_memory *mem, + off_t pg_start, int type) { int i; @@ -377,7 +379,8 @@ atomic_sub(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp); } -static int i460_insert_memory_large_io_page (agp_memory * mem, off_t pg_start, int type) +static int i460_insert_memory_large_io_page (struct agp_memory *mem, + off_t pg_start, int type) { int i, start_offset, end_offset, idx, pg, num_entries; struct lp_desc *start, *end, *lp; @@ -417,7 +420,7 @@ if (i460_alloc_large_page(lp) < 0) return -ENOMEM; pg = lp - i460.lp_desc; - WR_GATT(pg, agp_bridge->mask_memory(lp->paddr, 0)); + WR_GATT(pg, agp_bridge->driver->mask_memory(lp->paddr, 0)); WR_FLUSH_GATT(pg); } @@ -433,13 +436,14 @@ return 0; } -static int i460_remove_memory_large_io_page (agp_memory * mem, off_t pg_start, int type) +static int i460_remove_memory_large_io_page (struct agp_memory *mem, + off_t pg_start, int type) { int i, pg, start_offset, end_offset, idx, num_entries; struct lp_desc *start, *end, *lp; void *temp; - temp = agp_bridge->current_size; + temp = agp_bridge->driver->current_size; num_entries = A_SIZE_8(temp)->num_entries; /* Figure out what pg_start means in terms of our large GART pages */ @@ -471,7 +475,8 @@ /* Wrapper routines to call the approriate {small_io_page,large_io_page} function */ -static int i460_insert_memory (agp_memory * mem, off_t pg_start, int type) +static int i460_insert_memory (struct agp_memory *mem, + off_t pg_start, int type) { if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) return i460_insert_memory_small_io_page(mem, pg_start, type); @@ -479,7 +484,8 @@ return i460_insert_memory_large_io_page(mem, pg_start, type); } -static int i460_remove_memory (agp_memory * mem, off_t pg_start, int type) +static int i460_remove_memory (struct agp_memory *mem, + off_t pg_start, int type) { if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) return i460_remove_memory_small_io_page(mem, pg_start, type); @@ -519,64 +525,69 @@ static unsigned long i460_mask_memory (unsigned long addr, int type) { /* Make sure the returned address is a valid GATT entry */ - return (agp_bridge->masks[0].mask + return (agp_bridge->driver->masks[0].mask | (((addr & ~((1 << I460_IO_PAGE_SHIFT) - 1)) & 0xffffff000) >> 12)); } -static int __init intel_i460_setup (struct pci_dev *pdev __attribute__((unused))) -{ - agp_bridge->masks = i460_masks; - agp_bridge->aperture_sizes = (void *) i460_sizes; - agp_bridge->size_type = U8_APER_SIZE; - agp_bridge->num_aperture_sizes = 3; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = i460_configure; - agp_bridge->fetch_size = i460_fetch_size; - agp_bridge->cleanup = i460_cleanup; - agp_bridge->tlb_flush = i460_tlb_flush; - agp_bridge->mask_memory = i460_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = i460_create_gatt_table; - agp_bridge->free_gatt_table = i460_free_gatt_table; +struct agp_bridge_driver intel_i460_driver = { + .owner = THIS_MODULE, + .aperture_sizes = i460_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 3, + .configure = i460_configure, + .fetch_size = i460_fetch_size, + .cleanup = i460_cleanup, + .tlb_flush = i460_tlb_flush, + .mask_memory = i460_mask_memory, + .masks = i460_masks, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = i460_create_gatt_table, + .free_gatt_table = i460_free_gatt_table, #if I460_LARGE_IO_PAGES - agp_bridge->insert_memory = i460_insert_memory; - agp_bridge->remove_memory = i460_remove_memory; - agp_bridge->agp_alloc_page = i460_alloc_page; - agp_bridge->agp_destroy_page = i460_destroy_page; + .insert_memory = i460_insert_memory, + .remove_memory = i460_remove_memory, + .agp_alloc_page = i460_alloc_page, + .agp_destroy_page = i460_destroy_page, #else - agp_bridge->insert_memory = i460_insert_memory_small_io_page; - agp_bridge->remove_memory = i460_remove_memory_small_io_page; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; + .insert_memory = i460_insert_memory_small_io_page, + .remove_memory = i460_remove_memory_small_io_page, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, #endif - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 1; - return 0; -} - -static struct agp_driver i460_agp_driver = { - .owner = THIS_MODULE, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .cant_use_aperture = 1, }; -static int __init agp_intel_i460_probe (struct pci_dev *dev, const struct pci_device_id *ent) +static int __init agp_intel_i460_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - u8 cap_ptr = 0; + struct agp_bridge_data *bridge; + u8 cap_ptr; - cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP); - if (cap_ptr == 0) + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + if (!cap_ptr) return -ENODEV; - agp_bridge->dev = dev; - agp_bridge->capndx = cap_ptr; - intel_i460_setup(dev); - i460_agp_driver.dev = dev; - agp_register_driver(&i460_agp_driver); - return 0; + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; + + bridge->driver = &intel_i460_driver; + bridge->dev = pdev; + bridge->capndx = cap_ptr; + + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); +} + +static void __devexit agp_intel_i460_remove(struct pci_dev *pdev) +{ + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + + agp_remove_bridge(bridge); + agp_put_bridge(bridge); } static struct pci_device_id agp_intel_i460_pci_table[] __initdata = { @@ -593,26 +604,20 @@ MODULE_DEVICE_TABLE(pci, agp_intel_i460_pci_table); -static struct __initdata pci_driver agp_intel_i460_pci_driver = { +static struct pci_driver agp_intel_i460_pci_driver = { .name = "agpgart-intel-i460", .id_table = agp_intel_i460_pci_table, .probe = agp_intel_i460_probe, + .remove = agp_intel_i460_remove, }; static int __init agp_intel_i460_init(void) { - int ret_val; - - ret_val = pci_module_init(&agp_intel_i460_pci_driver); - if (ret_val) - agp_bridge->type = NOT_SUPPORTED; - - return ret_val; + return pci_module_init(&agp_intel_i460_pci_driver); } static void __exit agp_intel_i460_cleanup(void) { - agp_unregister_driver(&i460_agp_driver); pci_unregister_driver(&agp_intel_i460_pci_driver); } diff -Nru a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c --- a/drivers/char/agp/intel-agp.c Sat May 24 12:48:24 2003 +++ b/drivers/char/agp/intel-agp.c Sat May 24 12:48:24 2003 @@ -45,7 +45,7 @@ struct aper_size_info_fixed *values; pci_read_config_dword(agp_bridge->dev, I810_SMRAM_MISCC, &smram_miscc); - values = A_SIZE_FIX(agp_bridge->aperture_sizes); + values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) { printk(KERN_WARNING PFX "i810 is disabled\n"); @@ -89,9 +89,9 @@ agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); OUTREG32(intel_i810_private.registers, I810_PGETBL_CTL, agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED); - CACHE_FLUSH(); + global_cache_flush(); - if (agp_bridge->needs_scratch_page == TRUE) { + if (agp_bridge->driver->needs_scratch_page) { for (i = 0; i < current_size->num_entries; i++) { OUTREG32(intel_i810_private.registers, I810_PTE_BASE + (i * 4), @@ -107,7 +107,7 @@ iounmap((void *) intel_i810_private.registers); } -static void intel_i810_tlbflush(agp_memory * mem) +static void intel_i810_tlbflush(struct agp_memory *mem) { return; } @@ -117,7 +117,7 @@ return; } -static int intel_i810_insert_entries(agp_memory * mem, off_t pg_start, +static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, int type) { int i, j, num_entries; @@ -130,23 +130,22 @@ return -EINVAL; } for (j = pg_start; j < (pg_start + mem->page_count); j++) { - if (!PGE_EMPTY(agp_bridge->gatt_table[j])) { + if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j])) return -EBUSY; - } } if (type != 0 || mem->type != 0) { if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) { /* special insert */ - CACHE_FLUSH(); + global_cache_flush(); for (i = pg_start; i < (pg_start + mem->page_count); i++) { OUTREG32(intel_i810_private.registers, I810_PTE_BASE + (i * 4), (i * 4096) | I810_PTE_LOCAL | I810_PTE_VALID); } - CACHE_FLUSH(); - agp_bridge->tlb_flush(mem); + global_cache_flush(); + agp_bridge->driver->tlb_flush(mem); return 0; } if((type == AGP_PHYS_MEMORY) && (mem->type == AGP_PHYS_MEMORY)) @@ -155,19 +154,19 @@ } insert: - CACHE_FLUSH(); + global_cache_flush(); for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { OUTREG32(intel_i810_private.registers, I810_PTE_BASE + (j * 4), - agp_bridge->mask_memory(mem->memory[i], mem->type)); + agp_bridge->driver->mask_memory(mem->memory[i], mem->type)); } - CACHE_FLUSH(); + global_cache_flush(); - agp_bridge->tlb_flush(mem); + agp_bridge->driver->tlb_flush(mem); return 0; } -static int intel_i810_remove_entries(agp_memory * mem, off_t pg_start, +static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start, int type) { int i; @@ -178,66 +177,69 @@ agp_bridge->scratch_page); } - CACHE_FLUSH(); - agp_bridge->tlb_flush(mem); + global_cache_flush(); + agp_bridge->driver->tlb_flush(mem); return 0; } -static agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type) +/* + * The i810/i830 requires a physical address to program its mouse + * pointer into hardware. + * However the Xserver still writes to it through the agp aperture. + */ +static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type) { - agp_memory *new; + struct agp_memory *new; + void *addr; + + if (pg_count != 1) + return NULL; + + addr = agp_bridge->driver->agp_alloc_page(); + if (addr == NULL) + return NULL; + + new = agp_create_memory(1); + if (new == NULL) + return NULL; + + new->memory[0] = virt_to_phys(addr); + new->page_count = 1; + new->num_scratch_pages = 1; + new->type = AGP_PHYS_MEMORY; + new->physical = new->memory[0]; + return new; +} + +static struct agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type) +{ + struct agp_memory *new; if (type == AGP_DCACHE_MEMORY) { - if (pg_count != intel_i810_private.num_dcache_entries) { + if (pg_count != intel_i810_private.num_dcache_entries) return NULL; - } - new = agp_create_memory(1); - if (new == NULL) { + new = agp_create_memory(1); + if (new == NULL) return NULL; - } + new->type = AGP_DCACHE_MEMORY; new->page_count = pg_count; new->num_scratch_pages = 0; vfree(new->memory); return new; } - if(type == AGP_PHYS_MEMORY) { - void *addr; - /* The I810 requires a physical address to program - * it's mouse pointer into hardware. However the - * Xserver still writes to it through the agp - * aperture - */ - if (pg_count != 1) - return NULL; - - new = agp_create_memory(1); - if (new == NULL) - return NULL; + if (type == AGP_PHYS_MEMORY) + return(alloc_agpphysmem_i8xx(pg_count, type)); - addr = agp_bridge->agp_alloc_page(); - - if (addr == NULL) { - /* Free this structure */ - agp_free_memory(new); - return NULL; - } - new->memory[0] = virt_to_phys(addr); - new->page_count = 1; - new->num_scratch_pages = 1; - new->type = AGP_PHYS_MEMORY; - new->physical = new->memory[0]; - return new; - } return NULL; } -static void intel_i810_free_by_type(agp_memory * curr) +static void intel_i810_free_by_type(struct agp_memory *curr) { agp_free_key(curr->key); if(curr->type == AGP_PHYS_MEMORY) { - agp_bridge->agp_destroy_page(phys_to_virt(curr->memory[0])); + agp_bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[0])); vfree(curr->memory); } kfree(curr); @@ -246,39 +248,7 @@ static unsigned long intel_i810_mask_memory(unsigned long addr, int type) { /* Type checking must be done elsewhere */ - return addr | agp_bridge->masks[type].mask; -} - -static int __init intel_i810_setup(struct pci_dev *i810_dev) -{ - intel_i810_private.i810_dev = i810_dev; - - agp_bridge->masks = intel_i810_masks; - agp_bridge->aperture_sizes = (void *) intel_i810_sizes; - agp_bridge->size_type = FIXED_APER_SIZE; - agp_bridge->num_aperture_sizes = 2; - agp_bridge->dev_private_data = (void *) &intel_i810_private; - agp_bridge->needs_scratch_page = TRUE; - agp_bridge->configure = intel_i810_configure; - agp_bridge->fetch_size = intel_i810_fetch_size; - agp_bridge->cleanup = intel_i810_cleanup; - agp_bridge->tlb_flush = intel_i810_tlbflush; - agp_bridge->mask_memory = intel_i810_mask_memory; - agp_bridge->agp_enable = intel_i810_agp_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = intel_i810_insert_entries; - agp_bridge->remove_memory = intel_i810_remove_entries; - agp_bridge->alloc_by_type = intel_i810_alloc_by_type; - agp_bridge->free_by_type = intel_i810_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - - return 0; + return addr | agp_bridge->driver->masks[type].mask; } static struct aper_size_info_fixed intel_i830_sizes[] = @@ -379,10 +349,11 @@ temp &= 0xfff80000; intel_i830_private.registers = (volatile u8 *) ioremap(temp,128 * 4096); - if (!intel_i830_private.registers) return (-ENOMEM); + if (!intel_i830_private.registers) + return (-ENOMEM); temp = INREG32(intel_i830_private.registers,I810_PGETBL_CTL) & 0xfffff000; - CACHE_FLUSH(); + global_cache_flush(); /* we have to call this as early as possible after the MMIO base address is known */ intel_i830_init_gtt_entries(); @@ -407,7 +378,7 @@ u16 gmch_ctrl; struct aper_size_info_fixed *values; - values = A_SIZE_FIX(agp_bridge->aperture_sizes); + values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); if (agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82830_HB && agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82845G_HB) { @@ -449,9 +420,9 @@ pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl); OUTREG32(intel_i830_private.registers,I810_PGETBL_CTL,agp_bridge->gatt_bus_addr | I810_PGETBL_ENABLED); - CACHE_FLUSH(); + global_cache_flush(); - if (agp_bridge->needs_scratch_page == TRUE) + if (agp_bridge->driver->needs_scratch_page) for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (i * 4),agp_bridge->scratch_page); @@ -463,7 +434,8 @@ iounmap((void *) intel_i830_private.registers); } -static int intel_i830_insert_entries(agp_memory *mem,off_t pg_start,int type) +static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, + int type) { int i,j,num_entries; void *temp; @@ -490,24 +462,25 @@ (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) return (-EINVAL); - CACHE_FLUSH(); + global_cache_flush(); for (i = 0, j = pg_start; i < mem->page_count; i++, j++) OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (j * 4), - agp_bridge->mask_memory(mem->memory[i], mem->type)); + agp_bridge->driver->mask_memory(mem->memory[i], mem->type)); - CACHE_FLUSH(); + global_cache_flush(); - agp_bridge->tlb_flush(mem); + agp_bridge->driver->tlb_flush(mem); return(0); } -static int intel_i830_remove_entries(agp_memory *mem,off_t pg_start,int type) +static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start, + int type) { int i; - CACHE_FLUSH (); + global_cache_flush(); if (pg_start < intel_i830_private.gtt_entries) { printk ("Trying to disable local/stolen memory\n"); @@ -517,90 +490,22 @@ for (i = pg_start; i < (mem->page_count + pg_start); i++) OUTREG32(intel_i830_private.registers,I810_PTE_BASE + (i * 4),agp_bridge->scratch_page); - CACHE_FLUSH(); + global_cache_flush(); - agp_bridge->tlb_flush(mem); + agp_bridge->driver->tlb_flush(mem); return (0); } -static agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type) +static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type) { - agp_memory *nw; - - /* always return NULL for now */ - if (type == AGP_DCACHE_MEMORY) return(NULL); - - if (type == AGP_PHYS_MEMORY) { - void *addr; - - /* The i830 requires a physical address to program - * it's mouse pointer into hardware. However the - * Xserver still writes to it through the agp - * aperture - */ - - if (pg_count != 1) return(NULL); - - nw = agp_create_memory(1); - - if (nw == NULL) return(NULL); - - addr = agp_bridge->agp_alloc_page(); - if (addr == NULL) { - /* free this structure */ - agp_free_memory(nw); - return(NULL); - } - - nw->memory[0] = virt_to_phys(addr); - nw->page_count = 1; - nw->num_scratch_pages = 1; - nw->type = AGP_PHYS_MEMORY; - nw->physical = nw->memory[0]; - return(nw); - } + if (type == AGP_PHYS_MEMORY) + return(alloc_agpphysmem_i8xx(pg_count, type)); + /* always return NULL for other allocation types for now */ return(NULL); } -static int __init intel_i830_setup(struct pci_dev *i830_dev) -{ - intel_i830_private.i830_dev = i830_dev; - - agp_bridge->masks = intel_i810_masks; - agp_bridge->aperture_sizes = (void *) intel_i830_sizes; - agp_bridge->size_type = FIXED_APER_SIZE; - agp_bridge->num_aperture_sizes = 2; - - agp_bridge->dev_private_data = (void *) &intel_i830_private; - agp_bridge->needs_scratch_page = TRUE; - - agp_bridge->configure = intel_i830_configure; - agp_bridge->fetch_size = intel_i830_fetch_size; - agp_bridge->cleanup = intel_i830_cleanup; - agp_bridge->tlb_flush = intel_i810_tlbflush; - agp_bridge->mask_memory = intel_i810_mask_memory; - agp_bridge->agp_enable = intel_i810_agp_enable; - agp_bridge->cache_flush = global_cache_flush; - - agp_bridge->create_gatt_table = intel_i830_create_gatt_table; - agp_bridge->free_gatt_table = intel_i830_free_gatt_table; - - agp_bridge->insert_memory = intel_i830_insert_entries; - agp_bridge->remove_memory = intel_i830_remove_entries; - agp_bridge->alloc_by_type = intel_i830_alloc_by_type; - agp_bridge->free_by_type = intel_i810_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - - return(0); -} - static int intel_fetch_size(void) { int i; @@ -608,9 +513,9 @@ struct aper_size_info_16 *values; pci_read_config_word(agp_bridge->dev, INTEL_APSIZE, &temp); - values = A_SIZE_16(agp_bridge->aperture_sizes); + values = A_SIZE_16(agp_bridge->driver->aperture_sizes); - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { if (temp == values[i].size_value) { agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i); agp_bridge->aperture_size_idx = i; @@ -621,22 +526,14 @@ return 0; } -static int intel_8xx_fetch_size(void) +static int __intel_8xx_fetch_size(u8 temp) { int i; - u8 temp; struct aper_size_info_8 *values; - pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp); - - /* Intel 815 chipsets have a _weird_ APSIZE register with only - * one non-reserved bit, so mask the others out ... */ - if (agp_bridge->type == INTEL_I815) - temp &= (1 << 3); - - values = A_SIZE_8(agp_bridge->aperture_sizes); + values = A_SIZE_8(agp_bridge->driver->aperture_sizes); - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { if (temp == values[i].size_value) { agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i); @@ -647,15 +544,34 @@ return 0; } +static int intel_8xx_fetch_size(void) +{ + u8 temp; + + pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp); + return __intel_8xx_fetch_size(temp); +} + +static int intel_815_fetch_size(void) +{ + u8 temp; + + /* Intel 815 chipsets have a _weird_ APSIZE register with only + * one non-reserved bit, so mask the others out ... */ + pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp); + temp &= (1 << 3); + + return __intel_8xx_fetch_size(temp); +} -static void intel_tlbflush(agp_memory * mem) +static void intel_tlbflush(struct agp_memory *mem) { pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2200); pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280); } -static void intel_8xx_tlbflush(agp_memory * mem) +static void intel_8xx_tlbflush(struct agp_memory *mem) { u32 temp; pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp); @@ -760,7 +676,7 @@ return 0; } -static void intel_820_tlbflush(agp_memory * mem) +static void intel_820_tlbflush(struct agp_memory *mem) { return; } @@ -868,11 +784,6 @@ return 0; } -static void intel_845_resume(void) -{ - intel_845_configure(); -} - static int intel_850_configure(void) { u32 temp; @@ -988,17 +899,6 @@ return 0; } -static unsigned long intel_mask_memory(unsigned long addr, int type) -{ - /* Memory type is ignored */ - return addr | agp_bridge->masks[0].mask; -} - -static void intel_resume(void) -{ - intel_configure(); -} - /* Setup function */ static struct gatt_mask intel_generic_masks[] = { @@ -1041,584 +941,480 @@ {32, 8192, 3, 56} }; -static int __init intel_generic_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = intel_generic_masks; - agp_bridge->aperture_sizes = (void *) intel_generic_sizes; - agp_bridge->size_type = U16_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = intel_configure; - agp_bridge->fetch_size = intel_fetch_size; - agp_bridge->cleanup = intel_cleanup; - agp_bridge->tlb_flush = intel_tlbflush; - agp_bridge->mask_memory = intel_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = intel_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} +struct agp_bridge_driver intel_generic_driver = { + .owner = THIS_MODULE, + .aperture_sizes = intel_generic_sizes, + .size_type = U16_APER_SIZE, + .num_aperture_sizes = 7, + .configure = intel_configure, + .fetch_size = intel_fetch_size, + .cleanup = intel_cleanup, + .tlb_flush = intel_tlbflush, + .mask_memory = agp_generic_mask_memory, + .masks = NULL, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, +}; -static int __init intel_815_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = intel_generic_masks; - agp_bridge->aperture_sizes = (void *) intel_815_sizes; - agp_bridge->size_type = U8_APER_SIZE; - agp_bridge->num_aperture_sizes = 2; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = intel_815_configure; - agp_bridge->fetch_size = intel_8xx_fetch_size; - agp_bridge->cleanup = intel_8xx_cleanup; - agp_bridge->tlb_flush = intel_8xx_tlbflush; - agp_bridge->mask_memory = intel_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} +struct agp_bridge_driver intel_810_driver = { + .owner = THIS_MODULE, + .aperture_sizes = intel_i810_sizes, + .size_type = FIXED_APER_SIZE, + .num_aperture_sizes = 2, + .needs_scratch_page = TRUE, + .configure = intel_i810_configure, + .fetch_size = intel_i810_fetch_size, + .cleanup = intel_i810_cleanup, + .tlb_flush = intel_i810_tlbflush, + .mask_memory = intel_i810_mask_memory, + .masks = intel_i810_masks, + .agp_enable = intel_i810_agp_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = intel_i810_insert_entries, + .remove_memory = intel_i810_remove_entries, + .alloc_by_type = intel_i810_alloc_by_type, + .free_by_type = intel_i810_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, +}; -static int __init intel_820_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = intel_generic_masks; - agp_bridge->aperture_sizes = (void *) intel_8xx_sizes; - agp_bridge->size_type = U8_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = intel_820_configure; - agp_bridge->fetch_size = intel_8xx_fetch_size; - agp_bridge->cleanup = intel_820_cleanup; - agp_bridge->tlb_flush = intel_820_tlbflush; - agp_bridge->mask_memory = intel_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} +struct agp_bridge_driver intel_815_driver = { + .owner = THIS_MODULE, + .aperture_sizes = intel_815_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 2, + .configure = intel_815_configure, + .fetch_size = intel_815_fetch_size, + .cleanup = intel_8xx_cleanup, + .tlb_flush = intel_8xx_tlbflush, + .mask_memory = agp_generic_mask_memory, + .masks = intel_generic_masks, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, +}; -static int __init intel_830mp_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = intel_generic_masks; - agp_bridge->aperture_sizes = (void *) intel_830mp_sizes; - agp_bridge->size_type = U8_APER_SIZE; - agp_bridge->num_aperture_sizes = 4; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = intel_830mp_configure; - agp_bridge->fetch_size = intel_8xx_fetch_size; - agp_bridge->cleanup = intel_8xx_cleanup; - agp_bridge->tlb_flush = intel_8xx_tlbflush; - agp_bridge->mask_memory = intel_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} +struct agp_bridge_driver intel_830_driver = { + .owner = THIS_MODULE, + .aperture_sizes = intel_i830_sizes, + .size_type = FIXED_APER_SIZE, + .num_aperture_sizes = 2, + .needs_scratch_page = TRUE, + .configure = intel_i830_configure, + .fetch_size = intel_i830_fetch_size, + .cleanup = intel_i830_cleanup, + .tlb_flush = intel_i810_tlbflush, + .mask_memory = intel_i810_mask_memory, + .masks = intel_i810_masks, + .agp_enable = intel_i810_agp_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = intel_i830_create_gatt_table, + .free_gatt_table = intel_i830_free_gatt_table, + .insert_memory = intel_i830_insert_entries, + .remove_memory = intel_i830_remove_entries, + .alloc_by_type = intel_i830_alloc_by_type, + .free_by_type = intel_i810_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, +}; -static int __init intel_840_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = intel_generic_masks; - agp_bridge->aperture_sizes = (void *) intel_8xx_sizes; - agp_bridge->size_type = U8_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = intel_840_configure; - agp_bridge->fetch_size = intel_8xx_fetch_size; - agp_bridge->cleanup = intel_8xx_cleanup; - agp_bridge->tlb_flush = intel_8xx_tlbflush; - agp_bridge->mask_memory = intel_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} -static int __init intel_845_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = intel_generic_masks; - agp_bridge->aperture_sizes = (void *) intel_8xx_sizes; - agp_bridge->size_type = U8_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = intel_845_configure; - agp_bridge->fetch_size = intel_8xx_fetch_size; - agp_bridge->cleanup = intel_8xx_cleanup; - agp_bridge->tlb_flush = intel_8xx_tlbflush; - agp_bridge->mask_memory = intel_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = intel_845_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} +struct agp_bridge_driver intel_820_driver = { + .owner = THIS_MODULE, + .aperture_sizes = intel_8xx_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 7, + .configure = intel_820_configure, + .fetch_size = intel_8xx_fetch_size, + .cleanup = intel_820_cleanup, + .tlb_flush = intel_820_tlbflush, + .mask_memory = agp_generic_mask_memory, + .masks = intel_generic_masks, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, +}; -static int __init intel_850_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = intel_generic_masks; - agp_bridge->aperture_sizes = (void *) intel_8xx_sizes; - agp_bridge->size_type = U8_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = intel_850_configure; - agp_bridge->fetch_size = intel_8xx_fetch_size; - agp_bridge->cleanup = intel_8xx_cleanup; - agp_bridge->tlb_flush = intel_8xx_tlbflush; - agp_bridge->mask_memory = intel_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} +struct agp_bridge_driver intel_830mp_driver = { + .owner = THIS_MODULE, + .aperture_sizes = intel_830mp_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 4, + .configure = intel_830mp_configure, + .fetch_size = intel_8xx_fetch_size, + .cleanup = intel_8xx_cleanup, + .tlb_flush = intel_8xx_tlbflush, + .mask_memory = agp_generic_mask_memory, + .masks = intel_generic_masks, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, +}; -static int __init intel_860_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = intel_generic_masks; - agp_bridge->aperture_sizes = (void *) intel_8xx_sizes; - agp_bridge->size_type = U8_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = intel_860_configure; - agp_bridge->fetch_size = intel_8xx_fetch_size; - agp_bridge->cleanup = intel_8xx_cleanup; - agp_bridge->tlb_flush = intel_8xx_tlbflush; - agp_bridge->mask_memory = intel_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} +struct agp_bridge_driver intel_840_driver = { + .owner = THIS_MODULE, + .aperture_sizes = intel_8xx_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 7, + .configure = intel_840_configure, + .fetch_size = intel_8xx_fetch_size, + .cleanup = intel_8xx_cleanup, + .tlb_flush = intel_8xx_tlbflush, + .mask_memory = agp_generic_mask_memory, + .masks = intel_generic_masks, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, +}; -static int __init intel_7505_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = intel_generic_masks; - agp_bridge->aperture_sizes = (void *) intel_8xx_sizes; - agp_bridge->size_type = U8_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = intel_7505_configure; - agp_bridge->fetch_size = intel_8xx_fetch_size; - agp_bridge->cleanup = intel_8xx_cleanup; - agp_bridge->tlb_flush = intel_8xx_tlbflush; - agp_bridge->mask_memory = intel_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - return 0; -} -struct agp_device_ids intel_agp_device_ids[] __initdata = -{ - { - .device_id = PCI_DEVICE_ID_INTEL_82443LX_0, - .chipset = INTEL_LX, - .chipset_name = "440LX", - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82443BX_0, - .chipset = INTEL_BX, - .chipset_name = "440BX", - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82443GX_0, - .chipset = INTEL_GX, - .chipset_name = "440GX", - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82815_MC, - .chipset = INTEL_I815, - .chipset_name = "i815", - .chipset_setup = intel_815_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82820_HB, - .chipset = INTEL_I820, - .chipset_name = "i820", - .chipset_setup = intel_820_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82820_UP_HB, - .chipset = INTEL_I820, - .chipset_name = "i820", - .chipset_setup = intel_820_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82830_HB, - .chipset = INTEL_I830_M, - .chipset_name = "830M", - .chipset_setup = intel_830mp_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82840_HB, - .chipset = INTEL_I840, - .chipset_name = "i840", - .chipset_setup = intel_840_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82845_HB, - .chipset = INTEL_I845, - .chipset_name = "i845", - .chipset_setup = intel_845_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82845G_HB, - .chipset = INTEL_I845_G, - .chipset_name = "845G", - .chipset_setup = intel_845_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82850_HB, - .chipset = INTEL_I850, - .chipset_name = "i850", - .chipset_setup = intel_850_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82855_HB, - .chipset = INTEL_I855_PM, - .chipset_name = "855PM", - .chipset_setup = intel_845_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82860_HB, - .chipset = INTEL_I860, - .chipset_name = "i860", - .chipset_setup = intel_860_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_82865_HB, - .chipset = INTEL_I865_G, - .chipset_name = "865G", - .chipset_setup = intel_845_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_7505_0, - .chipset = INTEL_E7505, - .chipset_name = "E7505", - .chipset_setup = intel_7505_setup - }, - { - .device_id = PCI_DEVICE_ID_INTEL_7205_0, - .chipset = INTEL_E7505, - .chipset_name = "E7205", - .chipset_setup = intel_7505_setup - }, - { }, /* dummy final entry, always present */ +struct agp_bridge_driver intel_845_driver = { + .owner = THIS_MODULE, + .aperture_sizes = intel_8xx_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 7, + .configure = intel_845_configure, + .fetch_size = intel_8xx_fetch_size, + .cleanup = intel_8xx_cleanup, + .tlb_flush = intel_8xx_tlbflush, + .mask_memory = agp_generic_mask_memory, + .masks = intel_generic_masks, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, +}; + +struct agp_bridge_driver intel_850_driver = { + .owner = THIS_MODULE, + .aperture_sizes = intel_8xx_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 7, + .configure = intel_850_configure, + .fetch_size = intel_8xx_fetch_size, + .cleanup = intel_8xx_cleanup, + .tlb_flush = intel_8xx_tlbflush, + .mask_memory = agp_generic_mask_memory, + .masks = intel_generic_masks, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, }; +struct agp_bridge_driver intel_860_driver = { + .owner = THIS_MODULE, + .aperture_sizes = intel_8xx_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 7, + .configure = intel_860_configure, + .fetch_size = intel_8xx_fetch_size, + .cleanup = intel_8xx_cleanup, + .tlb_flush = intel_8xx_tlbflush, + .mask_memory = agp_generic_mask_memory, + .masks = intel_generic_masks, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, +}; + +struct agp_bridge_driver intel_7505_driver = { + .owner = THIS_MODULE, + .aperture_sizes = intel_8xx_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 7, + .configure = intel_7505_configure, + .fetch_size = intel_8xx_fetch_size, + .cleanup = intel_8xx_cleanup, + .tlb_flush = intel_8xx_tlbflush, + .mask_memory = agp_generic_mask_memory, + .masks = intel_generic_masks, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, +}; -/* scan table above for supported devices */ -static int __init agp_lookup_host_bridge (struct pci_dev *pdev) +static int find_i810(u16 device, const char *name) { - int j=0; - struct agp_device_ids *devs; - - devs = intel_agp_device_ids; + struct pci_dev *i810_dev; - while (devs[j].chipset_name != NULL) { - if (pdev->device == devs[j].device_id) { - printk (KERN_INFO PFX "Detected Intel %s chipset\n", - devs[j].chipset_name); - agp_bridge->type = devs[j].chipset; - - if (devs[j].chipset_setup != NULL) - return devs[j].chipset_setup(pdev); - else - return intel_generic_setup(pdev); - } - j++; + i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, device, NULL); + if (!i810_dev) { + printk(KERN_ERR PFX "Detected an Intel %s Chipset, " + "but could not find the secondary device.\n", + name); + return 0; } - j--; + + intel_i810_private.i810_dev = i810_dev; + return 1; +} - /* try init anyway, if user requests it */ - if (agp_try_unsupported) { - printk(KERN_WARNING PFX "Trying generic Intel routines" - " for device id: %04x\n", pdev->device); - agp_bridge->type = INTEL_GENERIC; - return intel_generic_setup(pdev); - } +static int find_i830(u16 device) +{ + struct pci_dev *i830_dev; - printk(KERN_ERR PFX "Unsupported Intel chipset (device id: %04x)," - " you might want to try agp_try_unsupported=1.\n", pdev->device); - return -ENODEV; -} + i830_dev = pci_find_device(PCI_VENDOR_ID_INTEL, device, NULL); + if (i830_dev && PCI_FUNC(i830_dev->devfn) != 0) { + i830_dev = pci_find_device(PCI_VENDOR_ID_INTEL, + device, i830_dev); + } + if (!i830_dev) + return 0; -/* Supported Device Scanning routine */ + intel_i830_private.i830_dev = i830_dev; + return 1; +} -static int __init agp_find_supported_device(struct pci_dev *dev) +static int __init agp_intel_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - struct pci_dev *i810_dev; + struct agp_bridge_data *bridge; + char *name = "(unknown)"; u8 cap_ptr = 0; - agp_bridge->dev = dev; + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); - /* This shit needs moving into tables/init-routines. */ - switch (dev->device) { + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; + + switch (pdev->device) { + case PCI_DEVICE_ID_INTEL_82443LX_0: + bridge->driver = &intel_generic_driver; + name = "440LX"; + break; + case PCI_DEVICE_ID_INTEL_82443BX_0: + bridge->driver = &intel_generic_driver; + name = "440BX"; + break; + case PCI_DEVICE_ID_INTEL_82443GX_0: + bridge->driver = &intel_generic_driver; + name = "440GX"; + break; case PCI_DEVICE_ID_INTEL_82810_MC1: - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG1, NULL); - if (i810_dev == NULL) { - printk(KERN_ERR PFX "Detected an Intel i810," - " but could not find the secondary device.\n"); - return -ENODEV; - } - printk(KERN_INFO PFX "Detected an Intel i810 Chipset.\n"); - agp_bridge->type = INTEL_I810; - return intel_i810_setup (i810_dev); - + if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG1, "i810")) + goto fail; + bridge->driver = &intel_810_driver; + name = "i810"; + break; case PCI_DEVICE_ID_INTEL_82810_MC3: - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3, NULL); - if (i810_dev == NULL) { - printk(KERN_ERR PFX "Detected an Intel i810 DC100, but could not find the " - "secondary device.\n"); - return -ENODEV; - } - printk(KERN_INFO PFX "Detected an Intel i810 DC100 Chipset.\n"); - agp_bridge->type = INTEL_I810; - return intel_i810_setup(i810_dev); - + if (!find_i810(PCI_DEVICE_ID_INTEL_82810_IG3, "i810 DC100")) + goto fail; + bridge->driver = &intel_810_driver; + name = "i810 DC100"; + break; case PCI_DEVICE_ID_INTEL_82810E_MC: - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810E_IG, NULL); - if (i810_dev == NULL) { - printk(KERN_ERR PFX "Detected an Intel i810 E" - ", but could not find the secondary device.\n"); - return -ENODEV; - } - printk(KERN_INFO PFX "Detected an Intel i810 E Chipset.\n"); - agp_bridge->type = INTEL_I810; - return intel_i810_setup(i810_dev); - + if (!find_i810(PCI_DEVICE_ID_INTEL_82810E_IG, "i810 E")) + goto fail; + bridge->driver = &intel_810_driver; + name = "i810 E"; + break; case PCI_DEVICE_ID_INTEL_82815_MC: - /* The i815 can operate either as an i810 style + /* + * The i815 can operate either as an i810 style * integrated device, or as an AGP4X motherboard. - * - * This only addresses the first mode: */ - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC, NULL); - if (i810_dev == NULL) { - printk(KERN_ERR PFX "agpgart: Detected an " - "Intel i815, but could not find the" - " secondary device. Assuming a " - "non-integrated video card.\n"); - break; + if (find_i810(PCI_DEVICE_ID_INTEL_82815_CGC, "i815")) + bridge->driver = &intel_810_driver; + else + bridge->driver = &intel_815_driver; + name = "i815"; + break; + case PCI_DEVICE_ID_INTEL_82820_HB: + case PCI_DEVICE_ID_INTEL_82820_UP_HB: + bridge->driver = &intel_820_driver; + name = "i820"; + break; + case PCI_DEVICE_ID_INTEL_82830_HB: + if (find_i830(PCI_DEVICE_ID_INTEL_82830_CGC)) { + bridge->driver = &intel_830_driver; + } else { + bridge->driver = &intel_830mp_driver; } - printk(KERN_INFO PFX "agpgart: Detected an Intel i815 Chipset.\n"); - agp_bridge->type = INTEL_I810; - return intel_i810_setup(i810_dev); - + name = "830M"; + break; + case PCI_DEVICE_ID_INTEL_82840_HB: + bridge->driver = &intel_840_driver; + name = "i840"; + break; + case PCI_DEVICE_ID_INTEL_82845_HB: + bridge->driver = &intel_845_driver; + name = "i845"; + break; case PCI_DEVICE_ID_INTEL_82845G_HB: - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82845G_IG, NULL); - if (i810_dev && PCI_FUNC(i810_dev->devfn) != 0) { - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82845G_IG, i810_dev); - } - - if (i810_dev == NULL) { - /* - * We probably have a I845G chipset with an external graphics - * card. It will be initialized later - */ - agp_bridge->type = INTEL_I845_G; - break; + if (find_i830(PCI_DEVICE_ID_INTEL_82845G_IG)) { + bridge->driver = &intel_830_driver; + } else { + bridge->driver = &intel_845_driver; } - printk(KERN_INFO PFX "Detected an Intel(R) 845G Chipset.\n"); - agp_bridge->type = INTEL_I810; - return intel_i830_setup(i810_dev); - - case PCI_DEVICE_ID_INTEL_82830_HB: - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82830_CGC, NULL); - if(i810_dev && PCI_FUNC(i810_dev->devfn) != 0) - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82830_CGC, i810_dev); - - if (i810_dev == NULL) { - /* Intel 830MP with external graphic card */ - /* It will be initialized later */ - agp_bridge->type = INTEL_I830_M; - break; + name = "845G"; + break; + case PCI_DEVICE_ID_INTEL_82850_HB: + bridge->driver = &intel_850_driver; + name = "i850"; + break; + case PCI_DEVICE_ID_INTEL_82855PM_HB: + bridge->driver = &intel_845_driver; + name = "855PM"; + break; + case PCI_DEVICE_ID_INTEL_82855GM_HB: + if (find_i830(PCI_DEVICE_ID_INTEL_82855GM_IG)) { + bridge->driver = &intel_830_driver; + name = "855"; + } else { + bridge->driver = &intel_845_driver; + name = "855GM"; } - printk(KERN_INFO PFX "Detected an Intel(R) 830M Chipset.\n"); - agp_bridge->type = INTEL_I810; - return intel_i830_setup(i810_dev); - - case PCI_DEVICE_ID_INTEL_82855_HB: - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855_IG, NULL); - if(i810_dev && PCI_FUNC(i810_dev->devfn) != 0) - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855_IG, i810_dev); - - if (i810_dev == NULL) { - /* Intel 855PM with external graphic card */ - /* It will be initialized later */ - agp_bridge->type = INTEL_I855_PM; - break; + break; + case PCI_DEVICE_ID_INTEL_82860_HB: + bridge->driver = &intel_860_driver; + name = "i860"; + break; + case PCI_DEVICE_ID_INTEL_82865_HB: + if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG)) { + bridge->driver = &intel_830_driver; + } else { + bridge->driver = &intel_845_driver; } - { - u32 capval = 0; - const char *name = "855GM/852GM"; - pci_read_config_dword(dev, I85X_CAPID, &capval); - switch ((capval >> I85X_VARIANT_SHIFT) & - I85X_VARIANT_MASK) { - case I855_GME: - name = "855GME"; - break; - case I855_GM: - name = "855GM"; - break; - case I852_GME: - name = "852GME"; - break; - case I852_GM: - name = "852GM"; - break; - } - printk(KERN_INFO PFX - "Detected an Intel(R) %s Chipset.\n", name); + name = "865"; + break; + case PCI_DEVICE_ID_INTEL_82875_HB: + bridge->driver = &intel_845_driver; + name = "i875"; + break; + case PCI_DEVICE_ID_INTEL_7505_0: + bridge->driver = &intel_7505_driver; + name = "E7505"; + break; + case PCI_DEVICE_ID_INTEL_7205_0: + bridge->driver = &intel_7505_driver; + name = "E7205"; + break; + default: + if (!agp_try_unsupported) { + printk(KERN_ERR PFX + "Unsupported Intel chipset (device id: %04x)," + " you might want to try agp_try_unsupported=1.\n", + pdev->device); + return -ENODEV; } - agp_bridge->type = INTEL_I810; - return intel_i830_setup(i810_dev); + bridge->driver = &intel_generic_driver; + break; + }; - case PCI_DEVICE_ID_INTEL_82865_HB: - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82865_IG, NULL); - if (i810_dev && PCI_FUNC(i810_dev->devfn) != 0) { - i810_dev = pci_find_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82865_IG, i810_dev); - } + bridge->dev = pdev; + bridge->capndx = cap_ptr; - if (i810_dev == NULL) { - /* - * We probably have a 865G chipset with an external graphics - * card. It will be initialized later - */ - agp_bridge->type = INTEL_I865_G; - break; - } - printk(KERN_INFO PFX "Detected an Intel(R) 865G Chipset.\n"); - agp_bridge->type = INTEL_I810; - return intel_i830_setup(i810_dev); + if (bridge->driver == &intel_810_driver) + bridge->dev_private_data = &intel_i810_private; + else if (bridge->driver == &intel_830_driver) + bridge->dev_private_data = &intel_i830_private; - default: - break; + printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n", name); + + /* Fill in the mode register */ + if (cap_ptr) { + pci_read_config_dword(pdev, + bridge->capndx+PCI_AGP_STATUS, + &bridge->mode); } - cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP); - if (cap_ptr == 0) - return -ENODEV; - agp_bridge->capndx = cap_ptr; + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); + fail: + agp_put_bridge(bridge); + return -ENODEV; +} - /* Fill in the mode register */ - pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode); +static void __devexit agp_intel_remove(struct pci_dev *pdev) +{ + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); - /* probe for known chipsets */ - return agp_lookup_host_bridge(dev); + agp_remove_bridge(bridge); + agp_put_bridge(bridge); } -static struct agp_driver intel_agp_driver = { - .owner = THIS_MODULE, -}; +static int agp_intel_suspend(struct pci_dev *dev, u32 state) +{ + return 0; +} -static int __init agp_intel_probe (struct pci_dev *dev, const struct pci_device_id *ent) +static int agp_intel_resume(struct pci_dev *pdev) { - if (agp_find_supported_device(dev) == 0) { - intel_agp_driver.dev = dev; - agp_register_driver(&intel_agp_driver); - return 0; - } - return -ENODEV; + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + + if (bridge->driver == &intel_generic_driver) + intel_configure(); + else if (bridge->driver == &intel_845_driver) + intel_845_configure(); + + return 0; } static struct pci_device_id agp_intel_pci_table[] __initdata = { @@ -1635,33 +1431,30 @@ MODULE_DEVICE_TABLE(pci, agp_intel_pci_table); -static struct __initdata pci_driver agp_intel_pci_driver = { +static struct pci_driver agp_intel_pci_driver = { .name = "agpgart-intel", .id_table = agp_intel_pci_table, .probe = agp_intel_probe, + .remove = agp_intel_remove, + .suspend = agp_intel_suspend, + .resume = agp_intel_resume, }; /* intel_agp_init() must not be declared static for explicit early initialization to work (ie i810fb) */ int __init agp_intel_init(void) { - int ret_val; static int agp_initialised=0; - if (agp_initialised==1) + if (agp_initialised == 1) return 0; agp_initialised=1; - ret_val = pci_module_init(&agp_intel_pci_driver); - if (ret_val) - agp_bridge->type = NOT_SUPPORTED; - - return ret_val; + return pci_module_init(&agp_intel_pci_driver); } static void __exit agp_intel_cleanup(void) { - agp_unregister_driver(&intel_agp_driver); pci_unregister_driver(&agp_intel_pci_driver); } diff -Nru a/drivers/char/agp/isoch.c b/drivers/char/agp/isoch.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/agp/isoch.c Sat May 24 12:48:34 2003 @@ -0,0 +1,470 @@ +/* + * Setup routines for AGP 3.5 compliant bridges. + */ + +#include +#include +#include +#include + +#include "agp.h" + +/* Generic AGP 3.5 enabling routines */ + +struct agp_3_5_dev { + struct list_head list; + u8 capndx; + u32 maxbw; + struct pci_dev *dev; +}; + +static void agp_3_5_dev_list_insert(struct list_head *head, struct list_head *new) +{ + struct agp_3_5_dev *cur, *n = list_entry(new, struct agp_3_5_dev, list); + struct list_head *pos; + + list_for_each(pos, head) { + cur = list_entry(pos, struct agp_3_5_dev, list); + if(cur->maxbw > n->maxbw) + break; + } + list_add_tail(new, pos); +} + +static void agp_3_5_dev_list_sort(struct agp_3_5_dev *list, unsigned int ndevs) +{ + struct agp_3_5_dev *cur; + struct pci_dev *dev; + struct list_head *pos, *tmp, *head = &list->list, *start = head->next; + u32 nistat; + + INIT_LIST_HEAD(head); + + for (pos=start; pos!=head; ) { + cur = list_entry(pos, struct agp_3_5_dev, list); + dev = cur->dev; + + pci_read_config_dword(dev, cur->capndx+AGPNISTAT, &nistat); + cur->maxbw = (nistat >> 16) & 0xff; + + tmp = pos; + pos = pos->next; + agp_3_5_dev_list_insert(head, tmp); + } +} + +/* + * Initialize all isochronous transfer parameters for an AGP 3.0 + * node (i.e. a host bridge in combination with the adapters + * lying behind it...) + */ + +static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge, + struct agp_3_5_dev *dev_list, unsigned int ndevs) +{ + /* + * Convenience structure to make the calculations clearer + * here. The field names come straight from the AGP 3.0 spec. + */ + struct isoch_data { + u32 maxbw; + u32 n; + u32 y; + u32 l; + u32 rq; + struct agp_3_5_dev *dev; + }; + + struct pci_dev *td = bridge->dev, *dev; + struct list_head *head = &dev_list->list, *pos; + struct agp_3_5_dev *cur; + struct isoch_data *master, target; + unsigned int cdev = 0; + u32 mnistat, tnistat, tstatus, mcmd; + u16 tnicmd, mnicmd; + u8 mcapndx; + u32 tot_bw = 0, tot_n = 0, tot_rq = 0, y_max, rq_isoch, rq_async; + u32 step, rem, rem_isoch, rem_async; + int ret = 0; + + /* + * We'll work with an array of isoch_data's (one for each + * device in dev_list) throughout this function. + */ + if ((master = kmalloc(ndevs * sizeof(*master), GFP_KERNEL)) == NULL) { + ret = -ENOMEM; + goto get_out; + } + + /* + * Sort the device list by maxbw. We need to do this because the + * spec suggests that the devices with the smallest requirements + * have their resources allocated first, with all remaining resources + * falling to the device with the largest requirement. + * + * We don't exactly do this, we divide target resources by ndevs + * and split them amongst the AGP 3.0 devices. The remainder of such + * division operations are dropped on the last device, sort of like + * the spec mentions it should be done. + * + * We can't do this sort when we initially construct the dev_list + * because we don't know until this function whether isochronous + * transfers are enabled and consequently whether maxbw will mean + * anything. + */ + agp_3_5_dev_list_sort(dev_list, ndevs); + + pci_read_config_dword(td, bridge->capndx+AGPNISTAT, &tnistat); + pci_read_config_dword(td, bridge->capndx+AGPSTAT, &tstatus); + + /* Extract power-on defaults from the target */ + target.maxbw = (tnistat >> 16) & 0xff; + target.n = (tnistat >> 8) & 0xff; + target.y = (tnistat >> 6) & 0x3; + target.l = (tnistat >> 3) & 0x7; + target.rq = (tstatus >> 24) & 0xff; + + y_max = target.y; + + /* + * Extract power-on defaults for each device in dev_list. Along + * the way, calculate the total isochronous bandwidth required + * by these devices and the largest requested payload size. + */ + list_for_each(pos, head) { + cur = list_entry(pos, struct agp_3_5_dev, list); + dev = cur->dev; + + mcapndx = cur->capndx; + + pci_read_config_dword(dev, cur->capndx+AGPNISTAT, &mnistat); + + master[cdev].maxbw = (mnistat >> 16) & 0xff; + master[cdev].n = (mnistat >> 8) & 0xff; + master[cdev].y = (mnistat >> 6) & 0x3; + master[cdev].dev = cur; + + tot_bw += master[cdev].maxbw; + y_max = max(y_max, master[cdev].y); + + cdev++; + } + + /* Check if this configuration has any chance of working */ + if (tot_bw > target.maxbw) { + printk(KERN_ERR PFX "isochronous bandwidth required " + "by AGP 3.0 devices exceeds that which is supported by " + "the AGP 3.0 bridge!\n"); + ret = -ENODEV; + goto free_and_exit; + } + + target.y = y_max; + + /* + * Write the calculated payload size into the target's NICMD + * register. Doing this directly effects the ISOCH_N value + * in the target's NISTAT register, so we need to do this now + * to get an accurate value for ISOCH_N later. + */ + pci_read_config_word(td, bridge->capndx+AGPNICMD, &tnicmd); + tnicmd &= ~(0x3 << 6); + tnicmd |= target.y << 6; + pci_write_config_word(td, bridge->capndx+AGPNICMD, tnicmd); + + /* Reread the target's ISOCH_N */ + pci_read_config_dword(td, bridge->capndx+AGPNISTAT, &tnistat); + target.n = (tnistat >> 8) & 0xff; + + /* Calculate the minimum ISOCH_N needed by each master */ + for (cdev=0; cdev target.n) { + printk(KERN_ERR PFX "number of isochronous " + "transactions per period required by AGP 3.0 devices " + "exceeds that which is supported by the AGP 3.0 " + "bridge!\n"); + ret = -ENODEV; + goto free_and_exit; + } + + /* Calculate left over ISOCH_N capability in the target. We'll give + * this to the hungriest device (as per the spec) */ + rem = target.n - tot_n; + + /* + * Calculate the minimum isochronous RQ depth needed by each master. + * Along the way, distribute the extra ISOCH_N capability calculated + * above. + */ + for (cdev=0; cdev 64B, then ISOCH_Y + * byte isochronous writes will be broken into 64B pieces. + * This means we need to budget more RQ depth to account for + * these kind of writes (each isochronous write is actually + * many writes on the AGP bus). + */ + master[cdev].rq = master[cdev].n; + if(master[cdev].y > 0x1) + master[cdev].rq *= (1 << (master[cdev].y - 1)); + + tot_rq += master[cdev].rq; + + if (cdev == ndevs-1) + master[cdev].n += rem; + } + + /* Figure the number of isochronous and asynchronous RQ slots the + * target is providing. */ + rq_isoch = (target.y > 0x1) ? target.n * (1 << (target.y - 1)) : target.n; + rq_async = target.rq - rq_isoch; + + /* Exit if the minimal RQ needs of the masters exceeds what the target + * can provide. */ + if (tot_rq > rq_isoch) { + printk(KERN_ERR PFX "number of request queue slots " + "required by the isochronous bandwidth requested by " + "AGP 3.0 devices exceeds the number provided by the " + "AGP 3.0 bridge!\n"); + ret = -ENODEV; + goto free_and_exit; + } + + /* Calculate asynchronous RQ capability in the target (per master) as + * well as the total number of leftover isochronous RQ slots. */ + step = rq_async / ndevs; + rem_async = step + (rq_async % ndevs); + rem_isoch = rq_isoch - tot_rq; + + /* Distribute the extra RQ slots calculated above and write our + * isochronous settings out to the actual devices. */ + for (cdev=0; cdevdev; + + mcapndx = cur->capndx; + + master[cdev].rq += (cdev == ndevs - 1) + ? (rem_async + rem_isoch) : step; + + pci_read_config_word(dev, cur->capndx+AGPNICMD, &mnicmd); + pci_read_config_dword(dev, cur->capndx+AGPCMD, &mcmd); + + mnicmd &= ~(0xff << 8); + mnicmd &= ~(0x3 << 6); + mcmd &= ~(0xff << 24); + + mnicmd |= master[cdev].n << 8; + mnicmd |= master[cdev].y << 6; + mcmd |= master[cdev].rq << 24; + + pci_write_config_dword(dev, cur->capndx+AGPCMD, mcmd); + pci_write_config_word(dev, cur->capndx+AGPNICMD, mnicmd); + } + +free_and_exit: + kfree(master); + +get_out: + return ret; +} + +/* + * This function basically allocates request queue slots among the + * AGP 3.0 systems in nonisochronous nodes. The algorithm is + * pretty stupid, divide the total number of RQ slots provided by the + * target by ndevs. Distribute this many slots to each AGP 3.0 device, + * giving any left over slots to the last device in dev_list. + */ +static void agp_3_5_nonisochronous_node_enable(struct agp_bridge_data *bridge, + struct agp_3_5_dev *dev_list, unsigned int ndevs) +{ + struct agp_3_5_dev *cur; + struct list_head *head = &dev_list->list, *pos; + u32 tstatus, mcmd; + u32 trq, mrq, rem; + unsigned int cdev = 0; + + pci_read_config_dword(bridge->dev, bridge->capndx+AGPSTAT, &tstatus); + + trq = (tstatus >> 24) & 0xff; + mrq = trq / ndevs; + + rem = mrq + (trq % ndevs); + + for (pos=head->next; cdevnext) { + cur = list_entry(pos, struct agp_3_5_dev, list); + + pci_read_config_dword(cur->dev, cur->capndx+AGPCMD, &mcmd); + mcmd &= ~(0xff << 24); + mcmd |= ((cdev == ndevs - 1) ? rem : mrq) << 24; + pci_write_config_dword(cur->dev, cur->capndx+AGPCMD, mcmd); + } +} + +/* + * Fully configure and enable an AGP 3.0 host bridge and all the devices + * lying behind it. + */ +int agp_3_5_enable(struct agp_bridge_data *bridge) +{ + struct pci_dev *td = bridge->dev, *dev; + u8 mcapndx; + u32 isoch, arqsz; + u32 tstatus, mstatus, ncapid; + u32 mmajor; + u16 mpstat; + struct agp_3_5_dev *dev_list, *cur; + struct list_head *head, *pos; + unsigned int ndevs = 0; + int ret = 0; + + /* Extract some power-on defaults from the target */ + pci_read_config_dword(td, bridge->capndx+AGPSTAT, &tstatus); + isoch = (tstatus >> 17) & 0x1; + if (isoch == 0) /* isoch xfers not available, bail out. */ + return -ENODEV; + + arqsz = (tstatus >> 13) & 0x7; + + /* + * Allocate a head for our AGP 3.5 device list + * (multiple AGP v3 devices are allowed behind a single bridge). + */ + if ((dev_list = kmalloc(sizeof(*dev_list), GFP_KERNEL)) == NULL) { + ret = -ENOMEM; + goto get_out; + } + head = &dev_list->list; + INIT_LIST_HEAD(head); + + /* Find all AGP devices, and add them to dev_list. */ + pci_for_each_dev(dev) { + mcapndx = pci_find_capability(dev, PCI_CAP_ID_AGP); + if (mcapndx == 0) + continue; + + switch ((dev->class >>8) & 0xff00) { + case 0x0600: /* Bridge */ + /* Skip bridges. We should call this function for each one. */ + continue; + + case 0x0001: /* Unclassified device */ + /* Don't know what this is, but log it for investigation. */ + if (mcapndx != 0) { + printk (KERN_INFO PFX "Wacky, found unclassified AGP device. %x:%x\n", + dev->vendor, dev->device); + } + continue; + + case 0x0300: /* Display controller */ + case 0x0400: /* Multimedia controller */ + if((cur = kmalloc(sizeof(*cur), GFP_KERNEL)) == NULL) { + ret = -ENOMEM; + goto free_and_exit; + } + cur->dev = dev; + + pos = &cur->list; + list_add(pos, head); + ndevs++; + continue; + + default: + continue; + } + } + + /* + * Take an initial pass through the devices lying behind our host + * bridge. Make sure each one is actually an AGP 3.0 device, otherwise + * exit with an error message. Along the way store the AGP 3.0 + * cap_ptr for each device + */ + list_for_each(pos, head) { + cur = list_entry(pos, struct agp_3_5_dev, list); + dev = cur->dev; + + pci_read_config_word(dev, PCI_STATUS, &mpstat); + if ((mpstat & PCI_STATUS_CAP_LIST) == 0) + continue; + + pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &mcapndx); + if (mcapndx != 0) { + do { + pci_read_config_dword(dev, mcapndx, &ncapid); + if ((ncapid & 0xff) != 2) + mcapndx = (ncapid >> 8) & 0xff; + } + while (((ncapid & 0xff) != 2) && (mcapndx != 0)); + } + + if (mcapndx == 0) { + printk(KERN_ERR PFX "woah! Non-AGP device " + "found on the secondary bus of an AGP 3.5 bridge!\n"); + ret = -ENODEV; + goto free_and_exit; + } + + mmajor = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf; + if (mmajor < 3) { + printk(KERN_ERR PFX "woah! AGP 2.0 device " + "found on the secondary bus of an AGP 3.5 " + "bridge operating with AGP 3.0 electricals!\n"); + ret = -ENODEV; + goto free_and_exit; + } + + cur->capndx = mcapndx; + + pci_read_config_dword(dev, cur->capndx+AGPSTAT, &mstatus); + + if (((mstatus >> 3) & 0x1) == 0) { + printk(KERN_ERR PFX "woah! AGP 3.x device " + "not operating in AGP 3.x mode found on the " + "secondary bus of an AGP 3.5 bridge operating " + "with AGP 3.0 electricals!\n"); + ret = -ENODEV; + goto free_and_exit; + } + } + + /* + * Call functions to divide target resources amongst the AGP 3.0 + * masters. This process is dramatically different depending on + * whether isochronous transfers are supported. + */ + if (isoch) { + ret = agp_3_5_isochronous_node_enable(bridge, dev_list, ndevs); + if (ret) { + printk(KERN_INFO PFX "Something bad happened setting " + "up isochronous xfers. Falling back to " + "non-isochronous xfer mode.\n"); + } else { + goto free_and_exit; + } + } + agp_3_5_nonisochronous_node_enable(bridge, dev_list, ndevs); + +free_and_exit: + /* Be sure to free the dev_list */ + for (pos=head->next; pos!=head; ) { + cur = list_entry(pos, struct agp_3_5_dev, list); + + pos = pos->next; + kfree(cur); + } + kfree(dev_list); + +get_out: + return ret; +} + diff -Nru a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/agp/nvidia-agp.c Sat May 24 12:48:34 2003 @@ -0,0 +1,377 @@ +/* + * Nvidia AGPGART routines. + * Based upon a 2.4 agpgart diff by the folks from NVIDIA, and hacked up + * to work in 2.5 by Dave Jones + */ + +#include +#include +#include +#include +#include +#include +#include +#include "agp.h" + + +/* registers */ +#define NVIDIA_0_APBASE 0x10 +#define NVIDIA_0_APSIZE 0x80 +#define NVIDIA_1_WBC 0xf0 +#define NVIDIA_2_GARTCTRL 0xd0 +#define NVIDIA_2_APBASE 0xd8 +#define NVIDIA_2_APLIMIT 0xdc +#define NVIDIA_2_ATTBASE(i) (0xe0 + (i) * 4) +#define NVIDIA_3_APBASE 0x50 +#define NVIDIA_3_APLIMIT 0x54 + + +static int agp_try_unsupported __initdata = 0; + +static struct _nvidia_private { + struct pci_dev *dev_1; + struct pci_dev *dev_2; + struct pci_dev *dev_3; + volatile u32 *aperture; + int num_active_entries; + off_t pg_offset; + u32 wbc_mask; +} nvidia_private; + + +static int nvidia_fetch_size(void) +{ + int i; + u8 size_value; + struct aper_size_info_8 *values; + + pci_read_config_byte(agp_bridge->dev, NVIDIA_0_APSIZE, &size_value); + size_value &= 0x0f; + values = A_SIZE_8(agp_bridge->driver->aperture_sizes); + + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { + if (size_value == values[i].size_value) { + agp_bridge->previous_size = + agp_bridge->current_size = (void *) (values + i); + agp_bridge->aperture_size_idx = i; + return values[i].size; + } + } + + return 0; +} + + +static int nvidia_configure(void) +{ + int i, num_dirs; + u32 apbase, aplimit; + struct aper_size_info_8 *current_size; + u32 temp; + + current_size = A_SIZE_8(agp_bridge->current_size); + + /* aperture size */ + pci_write_config_byte(agp_bridge->dev, NVIDIA_0_APSIZE, + current_size->size_value); + + /* address to map to */ + pci_read_config_dword(agp_bridge->dev, NVIDIA_0_APBASE, &apbase); + apbase &= PCI_BASE_ADDRESS_MEM_MASK; + agp_bridge->gart_bus_addr = apbase; + aplimit = apbase + (current_size->size * 1024 * 1024) - 1; + pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_APBASE, apbase); + pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_APLIMIT, aplimit); + pci_write_config_dword(nvidia_private.dev_3, NVIDIA_3_APBASE, apbase); + pci_write_config_dword(nvidia_private.dev_3, NVIDIA_3_APLIMIT, aplimit); + + /* directory size is 64k */ + num_dirs = current_size->size / 64; + nvidia_private.num_active_entries = current_size->num_entries; + nvidia_private.pg_offset = 0; + if (num_dirs == 0) { + num_dirs = 1; + nvidia_private.num_active_entries /= (64 / current_size->size); + nvidia_private.pg_offset = (apbase & (64 * 1024 * 1024 - 1) & + ~(current_size->size * 1024 * 1024 - 1)) / PAGE_SIZE; + } + + /* attbase */ + for(i = 0; i < 8; i++) { + pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_ATTBASE(i), + (agp_bridge->gatt_bus_addr + (i % num_dirs) * 64 * 1024) | 1); + } + + /* gtlb control */ + pci_read_config_dword(nvidia_private.dev_2, NVIDIA_2_GARTCTRL, &temp); + pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_GARTCTRL, temp | 0x11); + + /* gart control */ + pci_read_config_dword(agp_bridge->dev, NVIDIA_0_APSIZE, &temp); + pci_write_config_dword(agp_bridge->dev, NVIDIA_0_APSIZE, temp | 0x100); + + /* map aperture */ + nvidia_private.aperture = + (volatile u32 *) ioremap(apbase, 33 * PAGE_SIZE); + + return 0; +} + +static void nvidia_cleanup(void) +{ + struct aper_size_info_8 *previous_size; + u32 temp; + + /* gart control */ + pci_read_config_dword(agp_bridge->dev, NVIDIA_0_APSIZE, &temp); + pci_write_config_dword(agp_bridge->dev, NVIDIA_0_APSIZE, temp & ~(0x100)); + + /* gtlb control */ + pci_read_config_dword(nvidia_private.dev_2, NVIDIA_2_GARTCTRL, &temp); + pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_GARTCTRL, temp & ~(0x11)); + + /* unmap aperture */ + iounmap((void *) nvidia_private.aperture); + + /* restore previous aperture size */ + previous_size = A_SIZE_8(agp_bridge->previous_size); + pci_write_config_byte(agp_bridge->dev, NVIDIA_0_APSIZE, + previous_size->size_value); +} + + +/* + * Note we can't use the generic routines, even though they are 99% the same. + * Aperture sizes <64M still requires a full 64k GART directory, but + * only use the portion of the TLB entries that correspond to the apertures + * alignment inside the surrounding 64M block. + */ +extern int agp_memory_reserved; + +static int nvidia_insert_memory(struct agp_memory *mem, off_t pg_start, int type) +{ + int i, j; + + if ((type != 0) || (mem->type != 0)) + return -EINVAL; + + if ((pg_start + mem->page_count) > + (nvidia_private.num_active_entries - agp_memory_reserved/PAGE_SIZE)) + return -EINVAL; + + for(j = pg_start; j < (pg_start + mem->page_count); j++) { + if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[nvidia_private.pg_offset + j])) + return -EBUSY; + } + + if (mem->is_flushed == FALSE) { + global_cache_flush(); + mem->is_flushed = TRUE; + } + for (i = 0, j = pg_start; i < mem->page_count; i++, j++) + agp_bridge->gatt_table[nvidia_private.pg_offset + j] = mem->memory[i]; + + agp_bridge->driver->tlb_flush(mem); + return 0; +} + + +static int nvidia_remove_memory(struct agp_memory *mem, off_t pg_start, int type) +{ + int i; + + if ((type != 0) || (mem->type != 0)) + return -EINVAL; + + for (i = pg_start; i < (mem->page_count + pg_start); i++) { + agp_bridge->gatt_table[nvidia_private.pg_offset + i] = + (unsigned long) agp_bridge->scratch_page; + } + + agp_bridge->driver->tlb_flush(mem); + return 0; +} + + +static void nvidia_tlbflush(struct agp_memory *mem) +{ + unsigned long end; + u32 wbc_reg, temp; + int i; + + /* flush chipset */ + if (nvidia_private.wbc_mask) { + pci_read_config_dword(nvidia_private.dev_1, NVIDIA_1_WBC, &wbc_reg); + wbc_reg |= nvidia_private.wbc_mask; + pci_write_config_dword(nvidia_private.dev_1, NVIDIA_1_WBC, wbc_reg); + + end = jiffies + 3*HZ; + do { + pci_read_config_dword(nvidia_private.dev_1, + NVIDIA_1_WBC, &wbc_reg); + if ((signed)(end - jiffies) <= 0) { + printk(KERN_ERR + "TLB flush took more than 3 seconds.\n"); + } + } while (wbc_reg & nvidia_private.wbc_mask); + } + + /* flush TLB entries */ + for(i = 0; i < 32 + 1; i++) + temp = nvidia_private.aperture[i * PAGE_SIZE / sizeof(u32)]; + for(i = 0; i < 32 + 1; i++) + temp = nvidia_private.aperture[i * PAGE_SIZE / sizeof(u32)]; +} + + +static struct aper_size_info_8 nvidia_generic_sizes[5] = +{ + {512, 131072, 7, 0}, + {256, 65536, 6, 8}, + {128, 32768, 5, 12}, + {64, 16384, 4, 14}, + /* The 32M mode still requires a 64k gatt */ + {32, 16384, 4, 15} +}; + + +static struct gatt_mask nvidia_generic_masks[] = +{ + { .mask = 1, .type = 0} +}; + + +struct agp_bridge_driver nvidia_driver = { + .owner = THIS_MODULE, + .aperture_sizes = nvidia_generic_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 5, + .configure = nvidia_configure, + .fetch_size = nvidia_fetch_size, + .cleanup = nvidia_cleanup, + .tlb_flush = nvidia_tlbflush, + .mask_memory = agp_generic_mask_memory, + .masks = nvidia_generic_masks, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = nvidia_insert_memory, + .remove_memory = nvidia_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, +}; + +static int __init agp_nvidia_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct agp_bridge_data *bridge; + u8 cap_ptr; + + nvidia_private.dev_1 = + pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 1)); + nvidia_private.dev_2 = + pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 2)); + nvidia_private.dev_3 = + pci_find_slot((unsigned int)pdev->bus->number, PCI_DEVFN(30, 0)); + + if (!nvidia_private.dev_1 || !nvidia_private.dev_2 || !nvidia_private.dev_3) { + printk(KERN_INFO PFX "agpgart: Detected an NVIDIA " + "nForce/nForce2 chipset, but could not find " + "the secondary devices.\n"); + return -ENODEV; + } + + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + if (!cap_ptr) + return -ENODEV; + + switch (pdev->device) { + case PCI_DEVICE_ID_NVIDIA_NFORCE: + printk(KERN_INFO PFX "Detected NVIDIA nForce chipset\n"); + nvidia_private.wbc_mask = 0x00010000; + break; + case PCI_DEVICE_ID_NVIDIA_NFORCE2: + printk(KERN_INFO PFX "Detected NVIDIA nForce2 chipset\n"); + nvidia_private.wbc_mask = 0x80000000; + break; + default: + if (!agp_try_unsupported) { + printk(KERN_ERR PFX + "Unsupported NVIDIA chipset (device id: %04x)," + " you might want to try agp_try_unsupported=1.\n", + pdev->device); + return -ENODEV; + } + printk(KERN_WARNING PFX + "Trying generic NVIDIA routines for device id: %04x\n", + pdev->device); + break; + } + + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; + + bridge->driver = &nvidia_driver; + bridge->dev_private_data = &nvidia_private, + bridge->dev = pdev; + bridge->capndx = cap_ptr; + + /* Fill in the mode register */ + pci_read_config_dword(pdev, + bridge->capndx+PCI_AGP_STATUS, + &bridge->mode); + + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); +} + +static void __devexit agp_nvidia_remove(struct pci_dev *pdev) +{ + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + + agp_remove_bridge(bridge); + agp_put_bridge(bridge); +} + +static struct pci_device_id agp_nvidia_pci_table[] __initdata = { + { + .class = (PCI_CLASS_BRIDGE_HOST << 8), + .class_mask = ~0, + .vendor = PCI_VENDOR_ID_NVIDIA, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { } +}; + +MODULE_DEVICE_TABLE(pci, agp_nvidia_pci_table); + +static struct pci_driver agp_nvidia_pci_driver = { + .name = "agpgart-nvidia", + .id_table = agp_nvidia_pci_table, + .probe = agp_nvidia_probe, + .remove = agp_nvidia_remove, +}; + +static int __init agp_nvidia_init(void) +{ + return pci_module_init(&agp_nvidia_pci_driver); +} + +static void __exit agp_nvidia_cleanup(void) +{ + pci_unregister_driver(&agp_nvidia_pci_driver); +} + +module_init(agp_nvidia_init); +module_exit(agp_nvidia_cleanup); + +MODULE_PARM(agp_try_unsupported, "1i"); +MODULE_LICENSE("GPL and additional rights"); +MODULE_AUTHOR("NVIDIA Corporation"); + diff -Nru a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c --- a/drivers/char/agp/sis-agp.c Sat May 24 12:48:20 2003 +++ b/drivers/char/agp/sis-agp.c Sat May 24 12:48:20 2003 @@ -17,8 +17,8 @@ struct aper_size_info_8 *values; pci_read_config_byte(agp_bridge->dev, SIS_APSIZE, &temp_size); - values = A_SIZE_8(agp_bridge->aperture_sizes); - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + values = A_SIZE_8(agp_bridge->driver->aperture_sizes); + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { if ((temp_size == values[i].size_value) || ((temp_size & ~(0x03)) == (values[i].size_value & ~(0x03)))) { @@ -33,7 +33,7 @@ return 0; } -static void sis_tlbflush(agp_memory * mem) +static void sis_tlbflush(struct agp_memory *mem) { pci_write_config_byte(agp_bridge->dev, SIS_TLBFLUSH, 0x02); } @@ -63,13 +63,6 @@ (previous_size->size_value & ~(0x03))); } -static unsigned long sis_mask_memory(unsigned long addr, int type) -{ - /* Memory type is ignored */ - - return addr | agp_bridge->masks[0].mask; -} - static struct aper_size_info_8 sis_generic_sizes[7] = { {256, 65536, 6, 99}, @@ -81,169 +74,142 @@ {4, 1024, 0, 3} }; -static struct gatt_mask sis_generic_masks[] = -{ - {.mask = 0x00000000, .type = 0} +struct agp_bridge_driver sis_driver = { + .owner = THIS_MODULE, + .aperture_sizes = sis_generic_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 7, + .configure = sis_configure, + .fetch_size = sis_fetch_size, + .cleanup = sis_cleanup, + .tlb_flush = sis_tlbflush, + .mask_memory = agp_generic_mask_memory, + .masks = NULL, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = agp_generic_create_gatt_table, + .free_gatt_table = agp_generic_free_gatt_table, + .insert_memory = agp_generic_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, }; -static int __init sis_generic_setup (struct pci_dev *pdev) -{ - agp_bridge->masks = sis_generic_masks; - agp_bridge->aperture_sizes = (void *) sis_generic_sizes; - agp_bridge->size_type = U8_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->configure = sis_configure; - agp_bridge->fetch_size = sis_fetch_size; - agp_bridge->cleanup = sis_cleanup; - agp_bridge->tlb_flush = sis_tlbflush; - agp_bridge->mask_memory = sis_mask_memory; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = agp_generic_create_gatt_table; - agp_bridge->free_gatt_table = agp_generic_free_gatt_table; - agp_bridge->insert_memory = agp_generic_insert_memory; - agp_bridge->remove_memory = agp_generic_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - - return 0; -} - struct agp_device_ids sis_agp_device_ids[] __initdata = { { .device_id = PCI_DEVICE_ID_SI_740, - .chipset = SIS_GENERIC, .chipset_name = "740", }, { .device_id = PCI_DEVICE_ID_SI_650, - .chipset = SIS_GENERIC, .chipset_name = "650", }, { .device_id = PCI_DEVICE_ID_SI_651, - .chipset = SIS_GENERIC, .chipset_name = "651", }, { .device_id = PCI_DEVICE_ID_SI_645, - .chipset = SIS_GENERIC, .chipset_name = "645", }, { .device_id = PCI_DEVICE_ID_SI_646, - .chipset = SIS_GENERIC, .chipset_name = "646", }, { .device_id = PCI_DEVICE_ID_SI_735, - .chipset = SIS_GENERIC, .chipset_name = "735", }, { .device_id = PCI_DEVICE_ID_SI_745, - .chipset = SIS_GENERIC, .chipset_name = "745", }, { .device_id = PCI_DEVICE_ID_SI_730, - .chipset = SIS_GENERIC, .chipset_name = "730", }, { .device_id = PCI_DEVICE_ID_SI_630, - .chipset = SIS_GENERIC, .chipset_name = "630", }, { .device_id = PCI_DEVICE_ID_SI_540, - .chipset = SIS_GENERIC, .chipset_name = "540", }, { .device_id = PCI_DEVICE_ID_SI_620, - .chipset = SIS_GENERIC, .chipset_name = "620", }, { .device_id = PCI_DEVICE_ID_SI_530, - .chipset = SIS_GENERIC, .chipset_name = "530", }, { .device_id = PCI_DEVICE_ID_SI_550, - .chipset = SIS_GENERIC, .chipset_name = "550", }, { }, /* dummy final entry, always present */ }; -/* scan table above for supported devices */ -static int __init agp_lookup_host_bridge (struct pci_dev *pdev) +static int __init agp_sis_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - int j=0; - struct agp_device_ids *devs; - - devs = sis_agp_device_ids; + struct agp_device_ids *devs = sis_agp_device_ids; + struct agp_bridge_data *bridge; + u8 cap_ptr; + int j; - while (devs[j].chipset_name != NULL) { + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + if (!cap_ptr) + return -ENODEV; + + /* probe for known chipsets */ + for (j = 0; devs[j].chipset_name; j++) { if (pdev->device == devs[j].device_id) { - printk (KERN_INFO PFX "Detected SiS %s chipset\n", - devs[j].chipset_name); - agp_bridge->type = devs[j].chipset; - - if (devs[j].chipset_setup != NULL) - return devs[j].chipset_setup(pdev); - else - return sis_generic_setup(pdev); + printk(KERN_INFO PFX "Detected SiS %s chipset\n", + devs[j].chipset_name); + goto found; } - j++; } - /* try init anyway, if user requests it */ - if (agp_try_unsupported) { - printk(KERN_WARNING PFX "Trying generic SiS routines" - " for device id: %04x\n", pdev->device); - agp_bridge->type = SIS_GENERIC; - return sis_generic_setup(pdev); + if (!agp_try_unsupported) { + printk(KERN_ERR PFX + "Unsupported SiS chipset (device id: %04x)," + " you might want to try agp_try_unsupported=1.\n", + pdev->device); + return -ENODEV; } - printk(KERN_ERR PFX "Unsupported SiS chipset (device id: %04x)," - " you might want to try agp_try_unsupported=1.\n", pdev->device); - return -ENODEV; -} + printk(KERN_WARNING PFX "Trying generic SiS routines" + " for device id: %04x\n", pdev->device); -static struct agp_driver sis_agp_driver = { - .owner = THIS_MODULE, -}; +found: + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; -static int __init agp_sis_probe (struct pci_dev *dev, const struct pci_device_id *ent) -{ - u8 cap_ptr = 0; + bridge->driver = &sis_driver; + bridge->dev = pdev; + bridge->capndx = cap_ptr; - cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP); - if (cap_ptr == 0) - return -ENODEV; + /* Fill in the mode register */ + pci_read_config_dword(pdev, + bridge->capndx+PCI_AGP_STATUS, + &bridge->mode); - /* probe for known chipsets */ - if (agp_lookup_host_bridge(dev) != -ENODEV) { - agp_bridge->dev = dev; - agp_bridge->capndx = cap_ptr; - /* Fill in the mode register */ - pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode); - sis_agp_driver.dev = dev; - agp_register_driver(&sis_agp_driver); - return 0; - } - return -ENODEV; + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); +} + +static void __devexit agp_sis_remove(struct pci_dev *pdev) +{ + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + + agp_remove_bridge(bridge); + agp_put_bridge(bridge); } static struct pci_device_id agp_sis_pci_table[] __initdata = { @@ -260,26 +226,20 @@ MODULE_DEVICE_TABLE(pci, agp_sis_pci_table); -static struct __initdata pci_driver agp_sis_pci_driver = { +static struct pci_driver agp_sis_pci_driver = { .name = "agpgart-sis", .id_table = agp_sis_pci_table, .probe = agp_sis_probe, + .remove = agp_sis_remove, }; static int __init agp_sis_init(void) { - int ret_val; - - ret_val = pci_module_init(&agp_sis_pci_driver); - if (ret_val) - agp_bridge->type = NOT_SUPPORTED; - - return ret_val; + return pci_module_init(&agp_sis_pci_driver); } static void __exit agp_sis_cleanup(void) { - agp_unregister_driver(&sis_agp_driver); pci_unregister_driver(&agp_sis_pci_driver); } diff -Nru a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c --- a/drivers/char/agp/sworks-agp.c Sat May 24 12:48:23 2003 +++ b/drivers/char/agp/sworks-agp.c Sat May 24 12:48:23 2003 @@ -35,7 +35,7 @@ return -ENOMEM; } SetPageReserved(virt_to_page(page_map->real)); - CACHE_FLUSH(); + global_cache_flush(); page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), PAGE_SIZE); if (page_map->remapped == NULL) { @@ -44,7 +44,7 @@ page_map->real = NULL; return -ENOMEM; } - CACHE_FLUSH(); + global_cache_flush(); for(i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) { page_map->remapped[i] = agp_bridge->scratch_page; @@ -203,7 +203,7 @@ u32 temp2; struct aper_size_info_lvl2 *values; - values = A_SIZE_LVL2(agp_bridge->aperture_sizes); + values = A_SIZE_LVL2(agp_bridge->driver->aperture_sizes); pci_read_config_dword(agp_bridge->dev,serverworks_private.gart_addr_ofs,&temp); pci_write_config_dword(agp_bridge->dev,serverworks_private.gart_addr_ofs, SVWRKS_SIZE_MASK); @@ -211,7 +211,7 @@ pci_write_config_dword(agp_bridge->dev,serverworks_private.gart_addr_ofs,temp); temp2 &= SVWRKS_SIZE_MASK; - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { if (temp2 == values[i].size_value) { agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i); @@ -224,6 +224,37 @@ return 0; } +/* + * This routine could be implemented by taking the addresses + * written to the GATT, and flushing them individually. However + * currently it just flushes the whole table. Which is probably + * more efficent, since agp_memory blocks can be a large number of + * entries. + */ +static void serverworks_tlbflush(struct agp_memory *temp) +{ + unsigned long end; + + OUTREG8(serverworks_private.registers, SVWRKS_POSTFLUSH, 0x01); + end = jiffies + 3*HZ; + while(INREG8(serverworks_private.registers, + SVWRKS_POSTFLUSH) == 0x01) { + if((signed)(end - jiffies) <= 0) { + printk(KERN_ERR "Posted write buffer flush took more" + "then 3 seconds\n"); + } + } + OUTREG32(serverworks_private.registers, SVWRKS_DIRFLUSH, 0x00000001); + end = jiffies + 3*HZ; + while(INREG32(serverworks_private.registers, + SVWRKS_DIRFLUSH) == 0x00000001) { + if((signed)(end - jiffies) <= 0) { + printk(KERN_ERR "TLB flush took more" + "then 3 seconds\n"); + } + } +} + static int serverworks_configure(void) { struct aper_size_info_lvl2 *current_size; @@ -253,7 +284,7 @@ enable_reg |= 0x1; /* Agp Enable bit */ pci_write_config_byte(serverworks_private.svrwrks_dev, SVWRKS_AGP_ENABLE, enable_reg); - agp_bridge->tlb_flush(NULL); + serverworks_tlbflush(NULL); agp_bridge->capndx = pci_find_capability(serverworks_private.svrwrks_dev, PCI_CAP_ID_AGP); @@ -277,46 +308,7 @@ iounmap((void *) serverworks_private.registers); } -/* - * This routine could be implemented by taking the addresses - * written to the GATT, and flushing them individually. However - * currently it just flushes the whole table. Which is probably - * more efficent, since agp_memory blocks can be a large number of - * entries. - */ - -static void serverworks_tlbflush(agp_memory * temp) -{ - unsigned long end; - - OUTREG8(serverworks_private.registers, SVWRKS_POSTFLUSH, 0x01); - end = jiffies + 3*HZ; - while(INREG8(serverworks_private.registers, - SVWRKS_POSTFLUSH) == 0x01) { - if((signed)(end - jiffies) <= 0) { - printk(KERN_ERR "Posted write buffer flush took more" - "then 3 seconds\n"); - } - } - OUTREG32(serverworks_private.registers, SVWRKS_DIRFLUSH, 0x00000001); - end = jiffies + 3*HZ; - while(INREG32(serverworks_private.registers, - SVWRKS_DIRFLUSH) == 0x00000001) { - if((signed)(end - jiffies) <= 0) { - printk(KERN_ERR "TLB flush took more" - "then 3 seconds\n"); - } - } -} - -static unsigned long serverworks_mask_memory(unsigned long addr, int type) -{ - /* Only type 0 is supported by the serverworks chipsets */ - - return addr | agp_bridge->masks[0].mask; -} - -static int serverworks_insert_memory(agp_memory * mem, +static int serverworks_insert_memory(struct agp_memory *mem, off_t pg_start, int type) { int i, j, num_entries; @@ -336,14 +328,14 @@ while (j < (pg_start + mem->page_count)) { addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr; cur_gatt = SVRWRKS_GET_GATT(addr); - if (!PGE_EMPTY(cur_gatt[GET_GATT_OFF(addr)])) { + if (!PGE_EMPTY(agp_bridge, cur_gatt[GET_GATT_OFF(addr)])) { return -EBUSY; } j++; } if (mem->is_flushed == FALSE) { - CACHE_FLUSH(); + global_cache_flush(); mem->is_flushed = TRUE; } @@ -351,13 +343,13 @@ addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr; cur_gatt = SVRWRKS_GET_GATT(addr); cur_gatt[GET_GATT_OFF(addr)] = - agp_bridge->mask_memory(mem->memory[i], mem->type); + agp_bridge->driver->mask_memory(mem->memory[i], mem->type); } - agp_bridge->tlb_flush(mem); + serverworks_tlbflush(mem); return 0; } -static int serverworks_remove_memory(agp_memory * mem, off_t pg_start, +static int serverworks_remove_memory(struct agp_memory *mem, off_t pg_start, int type) { int i; @@ -368,8 +360,8 @@ return -EINVAL; } - CACHE_FLUSH(); - agp_bridge->tlb_flush(mem); + global_cache_flush(); + serverworks_tlbflush(mem); for (i = pg_start; i < (mem->page_count + pg_start); i++) { addr = (i * PAGE_SIZE) + agp_bridge->gart_bus_addr; @@ -378,13 +370,13 @@ (unsigned long) agp_bridge->scratch_page; } - agp_bridge->tlb_flush(mem); + serverworks_tlbflush(mem); return 0; } static struct gatt_mask serverworks_masks[] = { - {.mask = 0x00000001, .type = 0} + {.mask = 1, .type = 0} }; static struct aper_size_info_lvl2 serverworks_sizes[7] = @@ -420,123 +412,101 @@ agp_device_command(command, 0); } -static int __init serverworks_setup (struct pci_dev *pdev) +struct agp_bridge_driver sworks_driver = { + .owner = THIS_MODULE, + .aperture_sizes = serverworks_sizes, + .size_type = LVL2_APER_SIZE, + .num_aperture_sizes = 7, + .configure = serverworks_configure, + .fetch_size = serverworks_fetch_size, + .cleanup = serverworks_cleanup, + .tlb_flush = serverworks_tlbflush, + .mask_memory = agp_generic_mask_memory, + .masks = serverworks_masks, + .agp_enable = serverworks_agp_enable, + .cache_flush = global_cache_flush, + .create_gatt_table = serverworks_create_gatt_table, + .free_gatt_table = serverworks_free_gatt_table, + .insert_memory = serverworks_insert_memory, + .remove_memory = serverworks_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, +}; + +static int __init agp_serverworks_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - u32 temp; - u32 temp2; + struct agp_bridge_data *bridge; + struct pci_dev *bridge_dev; + u32 temp, temp2; - serverworks_private.svrwrks_dev = pdev; + /* Everything is on func 1 here so we are hardcoding function one */ + bridge_dev = pci_find_slot((unsigned int)pdev->bus->number, + PCI_DEVFN(0, 1)); + if (!bridge_dev) { + printk(KERN_INFO PFX "agpgart: Detected a Serverworks " + "Chipset, but could not find the secondary " + "device.\n"); + return -ENODEV; + } - agp_bridge->masks = serverworks_masks; - agp_bridge->aperture_sizes = (void *) serverworks_sizes; - agp_bridge->size_type = LVL2_APER_SIZE; - agp_bridge->num_aperture_sizes = 7; - agp_bridge->dev_private_data = (void *) &serverworks_private; - agp_bridge->needs_scratch_page = TRUE; - agp_bridge->configure = serverworks_configure; - agp_bridge->fetch_size = serverworks_fetch_size; - agp_bridge->cleanup = serverworks_cleanup; - agp_bridge->tlb_flush = serverworks_tlbflush; - agp_bridge->mask_memory = serverworks_mask_memory; - agp_bridge->agp_enable = serverworks_agp_enable; - agp_bridge->cache_flush = global_cache_flush; - agp_bridge->create_gatt_table = serverworks_create_gatt_table; - agp_bridge->free_gatt_table = serverworks_free_gatt_table; - agp_bridge->insert_memory = serverworks_insert_memory; - agp_bridge->remove_memory = serverworks_remove_memory; - agp_bridge->alloc_by_type = agp_generic_alloc_by_type; - agp_bridge->free_by_type = agp_generic_free_by_type; - agp_bridge->agp_alloc_page = agp_generic_alloc_page; - agp_bridge->agp_destroy_page = agp_generic_destroy_page; - agp_bridge->suspend = agp_generic_suspend; - agp_bridge->resume = agp_generic_resume; - agp_bridge->cant_use_aperture = 0; - - pci_read_config_dword(agp_bridge->dev, - SVWRKS_APSIZE, - &temp); + switch (pdev->device) { + case PCI_DEVICE_ID_SERVERWORKS_HE: + case PCI_DEVICE_ID_SERVERWORKS_LE: + case 0x0007: + break; + default: + if (!agp_try_unsupported) + return -ENODEV; + break; + } + serverworks_private.svrwrks_dev = bridge_dev; serverworks_private.gart_addr_ofs = 0x10; - - if(temp & PCI_BASE_ADDRESS_MEM_TYPE_64) { - pci_read_config_dword(agp_bridge->dev, - SVWRKS_APSIZE + 4, - &temp2); - if(temp2 != 0) { + + pci_read_config_dword(pdev, SVWRKS_APSIZE, &temp); + if (temp & PCI_BASE_ADDRESS_MEM_TYPE_64) { + pci_read_config_dword(pdev, SVWRKS_APSIZE + 4, &temp2); + if (temp2 != 0) { printk("Detected 64 bit aperture address, but top " "bits are not zero. Disabling agp\n"); return -ENODEV; } serverworks_private.mm_addr_ofs = 0x18; - } else { + } else serverworks_private.mm_addr_ofs = 0x14; - } - pci_read_config_dword(agp_bridge->dev, - serverworks_private.mm_addr_ofs, - &temp); - if(temp & PCI_BASE_ADDRESS_MEM_TYPE_64) { - pci_read_config_dword(agp_bridge->dev, - serverworks_private.mm_addr_ofs + 4, - &temp2); - if(temp2 != 0) { + pci_read_config_dword(pdev, serverworks_private.mm_addr_ofs, &temp); + if (temp & PCI_BASE_ADDRESS_MEM_TYPE_64) { + pci_read_config_dword(pdev, + serverworks_private.mm_addr_ofs + 4, &temp2); + if (temp2 != 0) { printk("Detected 64 bit MMIO address, but top " "bits are not zero. Disabling agp\n"); return -ENODEV; } } - return 0; -} - - -static int __init agp_find_supported_device(struct pci_dev *dev) -{ - struct pci_dev *bridge_dev; - - /* Everything is on func 1 here so we are hardcoding function one */ - bridge_dev = pci_find_slot ((unsigned int)dev->bus->number, PCI_DEVFN(0, 1)); - if(bridge_dev == NULL) { - printk(KERN_INFO PFX "agpgart: Detected a Serverworks " - "Chipset, but could not find the secondary " - "device.\n"); - return -ENODEV; - } - - agp_bridge->dev = dev; - - switch (dev->device) { - case PCI_DEVICE_ID_SERVERWORKS_HE: - agp_bridge->type = SVWRKS_HE; - return serverworks_setup(bridge_dev); + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; - case PCI_DEVICE_ID_SERVERWORKS_LE: - case 0x0007: - agp_bridge->type = SVWRKS_LE; - return serverworks_setup(bridge_dev); + bridge->driver = &sworks_driver; + bridge->dev_private_data = &serverworks_private, + bridge->dev = pdev; - default: - if(agp_try_unsupported) { - agp_bridge->type = SVWRKS_GENERIC; - return serverworks_setup(bridge_dev); - } - break; - } - return -ENODEV; + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); } -static struct agp_driver serverworks_agp_driver = { - .owner = THIS_MODULE, -}; - -static int __init agp_serverworks_probe (struct pci_dev *dev, const struct pci_device_id *ent) +static void __devexit agp_serverworks_remove(struct pci_dev *pdev) { - if (agp_find_supported_device(dev) == 0) { - serverworks_agp_driver.dev = dev; - agp_register_driver(&serverworks_agp_driver); - return 0; - } - return -ENODEV; + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + + agp_remove_bridge(bridge); + agp_put_bridge(bridge); } static struct pci_device_id agp_serverworks_pci_table[] __initdata = { @@ -553,26 +523,20 @@ MODULE_DEVICE_TABLE(pci, agp_serverworks_pci_table); -static struct __initdata pci_driver agp_serverworks_pci_driver = { +static struct pci_driver agp_serverworks_pci_driver = { .name = "agpgart-serverworks", .id_table = agp_serverworks_pci_table, .probe = agp_serverworks_probe, + .remove = agp_serverworks_remove, }; static int __init agp_serverworks_init(void) { - int ret_val; - - ret_val = pci_module_init(&agp_serverworks_pci_driver); - if (ret_val) - agp_bridge->type = NOT_SUPPORTED; - - return ret_val; + return pci_module_init(&agp_serverworks_pci_driver); } static void __exit agp_serverworks_cleanup(void) { - agp_unregister_driver(&serverworks_agp_driver); pci_unregister_driver(&agp_serverworks_pci_driver); } diff -Nru a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/agp/uninorth-agp.c Sat May 24 12:48:34 2003 @@ -0,0 +1,397 @@ +/* + * UniNorth AGPGART routines. + */ +#include +#include +#include +#include +#include +#include +#include +#include "agp.h" + +static int agp_try_unsupported __initdata = 0; + +static int uninorth_fetch_size(void) +{ + int i; + u32 temp; + struct aper_size_info_32 *values; + + pci_read_config_dword(agp_bridge->dev, UNI_N_CFG_GART_BASE, &temp); + temp &= ~(0xfffff000); + values = A_SIZE_32(agp_bridge->driver->aperture_sizes); + + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { + if (temp == values[i].size_value) { + agp_bridge->previous_size = + agp_bridge->current_size = (void *) (values + i); + agp_bridge->aperture_size_idx = i; + return values[i].size; + } + } + + agp_bridge->previous_size = + agp_bridge->current_size = (void *) (values + 1); + agp_bridge->aperture_size_idx = 1; + return values[1].size; + + return 0; +} + +static void uninorth_tlbflush(struct agp_memory *mem) +{ + pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, + UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_INVAL); + pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, + UNI_N_CFG_GART_ENABLE); + pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, + UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_2xRESET); + pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, + UNI_N_CFG_GART_ENABLE); +} + +static void uninorth_cleanup(void) +{ + pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, + UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_INVAL); + pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, + 0); + pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, + UNI_N_CFG_GART_2xRESET); + pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, + 0); +} + +static int uninorth_configure(void) +{ + struct aper_size_info_32 *current_size; + + current_size = A_SIZE_32(agp_bridge->current_size); + + printk(KERN_INFO PFX "configuring for size idx: %d\n", + current_size->size_value); + + /* aperture size and gatt addr */ + pci_write_config_dword(agp_bridge->dev, + UNI_N_CFG_GART_BASE, + (agp_bridge->gatt_bus_addr & 0xfffff000) + | current_size->size_value); + + /* HACK ALERT + * UniNorth seem to be buggy enough not to handle properly when + * the AGP aperture isn't mapped at bus physical address 0 + */ + agp_bridge->gart_bus_addr = 0; + pci_write_config_dword(agp_bridge->dev, + UNI_N_CFG_AGP_BASE, agp_bridge->gart_bus_addr); + + return 0; +} + +static int uninorth_insert_memory(struct agp_memory *mem, off_t pg_start, + int type) +{ + int i, j, num_entries; + void *temp; + + temp = agp_bridge->current_size; + num_entries = A_SIZE_32(temp)->num_entries; + + if (type != 0 || mem->type != 0) + /* We know nothing of memory types */ + return -EINVAL; + if ((pg_start + mem->page_count) > num_entries) + return -EINVAL; + + j = pg_start; + + while (j < (pg_start + mem->page_count)) { + if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j])) + return -EBUSY; + j++; + } + + for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { + agp_bridge->gatt_table[j] = cpu_to_le32((mem->memory[i] & 0xfffff000) | 0x00000001UL); + flush_dcache_range((unsigned long)__va(mem->memory[i]), + (unsigned long)__va(mem->memory[i])+0x1000); + } + (void)in_le32((volatile u32*)&agp_bridge->gatt_table[pg_start]); + mb(); + flush_dcache_range((unsigned long)&agp_bridge->gatt_table[pg_start], + (unsigned long)&agp_bridge->gatt_table[pg_start + mem->page_count]); + + uninorth_tlbflush(mem); + return 0; +} + +static void uninorth_agp_enable(u32 mode) +{ + u32 command, scratch; + int timeout; + + pci_read_config_dword(agp_bridge->dev, + agp_bridge->capndx + PCI_AGP_STATUS, + &command); + + command = agp_collect_device_status(mode, command); + command |= 0x100; + + uninorth_tlbflush(NULL); + + timeout = 0; + do { + pci_write_config_dword(agp_bridge->dev, + agp_bridge->capndx + PCI_AGP_COMMAND, + command); + pci_read_config_dword(agp_bridge->dev, + agp_bridge->capndx + PCI_AGP_COMMAND, + &scratch); + } while ((scratch & 0x100) == 0 && ++timeout < 1000); + if ((scratch & 0x100) == 0) + printk(KERN_ERR PFX "failed to write UniNorth AGP command reg\n"); + + agp_device_command(command, 0); + + uninorth_tlbflush(NULL); +} + +static int uninorth_create_gatt_table(void) +{ + char *table; + char *table_end; + int size; + int page_order; + int num_entries; + int i; + void *temp; + struct page *page; + + /* We can't handle 2 level gatt's */ + if (agp_bridge->driver->size_type == LVL2_APER_SIZE) + return -EINVAL; + + table = NULL; + i = agp_bridge->aperture_size_idx; + temp = agp_bridge->current_size; + size = page_order = num_entries = 0; + + do { + size = A_SIZE_32(temp)->size; + page_order = A_SIZE_32(temp)->page_order; + num_entries = A_SIZE_32(temp)->num_entries; + + table = (char *) __get_free_pages(GFP_KERNEL, page_order); + + if (table == NULL) { + i++; + agp_bridge->current_size = A_IDX32(agp_bridge); + } else { + agp_bridge->aperture_size_idx = i; + } + } while (!table && (i < agp_bridge->driver->num_aperture_sizes)); + + if (table == NULL) + return -ENOMEM; + + table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1); + + for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) + SetPageReserved(page); + + agp_bridge->gatt_table_real = (u32 *) table; + agp_bridge->gatt_table = (u32 *)table; + agp_bridge->gatt_bus_addr = virt_to_phys(table); + + for (i = 0; i < num_entries; i++) { + agp_bridge->gatt_table[i] = + (unsigned long) agp_bridge->scratch_page; + } + + flush_dcache_range((unsigned long)table, (unsigned long)table_end); + + return 0; +} + +static int uninorth_free_gatt_table(void) +{ + int page_order; + char *table, *table_end; + void *temp; + struct page *page; + + temp = agp_bridge->current_size; + page_order = A_SIZE_32(temp)->page_order; + + /* Do not worry about freeing memory, because if this is + * called, then all agp memory is deallocated and removed + * from the table. + */ + + table = (char *) agp_bridge->gatt_table_real; + table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1); + + for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) + ClearPageReserved(page); + + free_pages((unsigned long) agp_bridge->gatt_table_real, page_order); + + return 0; +} + +void null_cache_flush(void) +{ + mb(); +} + +/* Setup function */ + +static struct aper_size_info_32 uninorth_sizes[7] = +{ +#if 0 /* Not sure uninorth supports that high aperture sizes */ + {256, 65536, 6, 64}, + {128, 32768, 5, 32}, + {64, 16384, 4, 16}, +#endif + {32, 8192, 3, 8}, + {16, 4096, 2, 4}, + {8, 2048, 1, 2}, + {4, 1024, 0, 1} +}; + +struct agp_bridge_driver uninorth_agp_driver = { + .owner = THIS_MODULE, + .aperture_sizes = (void *)uninorth_sizes, + .size_type = U32_APER_SIZE, + .num_aperture_sizes = 4, + .configure = uninorth_configure, + .fetch_size = uninorth_fetch_size, + .cleanup = uninorth_cleanup, + .tlb_flush = uninorth_tlbflush, + .mask_memory = agp_generic_mask_memory, + .masks = NULL, + .cache_flush = null_cache_flush, + .agp_enable = uninorth_agp_enable, + .create_gatt_table = uninorth_create_gatt_table, + .free_gatt_table = uninorth_free_gatt_table, + .insert_memory = uninorth_insert_memory, + .remove_memory = agp_generic_remove_memory, + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, + .cant_use_aperture = 1, +}; + +struct agp_device_ids uninorth_agp_device_ids[] __initdata = { + { + .device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP, + .chipset_name = "UniNorth", + }, + { + .device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP_P, + .chipset_name = "UniNorth/Pangea", + }, + { + .device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP15, + .chipset_name = "UniNorth 1.5", + }, + { + .device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP2, + .chipset_name = "UniNorth 2", + }, +}; + +static int __init agp_uninorth_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct agp_device_ids *devs = uninorth_agp_device_ids; + struct agp_bridge_data *bridge; + u8 cap_ptr; + int j; + + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + if (cap_ptr == 0) + return -ENODEV; + + /* probe for known chipsets */ + for (j = 0; devs[j].chipset_name != NULL; ++j) { + if (pdev->device == devs[j].device_id) { + printk(KERN_INFO PFX "Detected Apple %s chipset\n", + devs[j].chipset_name); + goto found; + } + } + + if (!agp_try_unsupported) { + printk(KERN_ERR PFX "Unsupported Apple chipset" + " (device id: %04x).\n", pdev->device); + printk(KERN_ERR PFX "You might want to try" + " agp_try_unsupported=1\n"); + return -ENODEV; + } + printk(KERN_ERR PFX "Trying generic Uninorth routines" + " for device id %04x\n", pdev->device); + + found: + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; + + bridge->driver = &uninorth_agp_driver; + bridge->dev = pdev; + bridge->capndx = cap_ptr; + + /* Fill in the mode register */ + pci_read_config_dword(pdev, cap_ptr+PCI_AGP_STATUS, &bridge->mode); + + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); +} + +static void __devexit agp_uninorth_remove(struct pci_dev *pdev) +{ + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + + agp_remove_bridge(bridge); + agp_put_bridge(bridge); +} + +static struct pci_device_id agp_uninorth_pci_table[] __initdata = { + { + .class = (PCI_CLASS_BRIDGE_HOST << 8), + .class_mask = ~0, + .vendor = PCI_VENDOR_ID_APPLE, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { } +}; + +MODULE_DEVICE_TABLE(pci, agp_uninorth_pci_table); + +static struct pci_driver agp_uninorth_pci_driver = { + .name = "agpgart-uninorth", + .id_table = agp_uninorth_pci_table, + .probe = agp_uninorth_probe, + .remove = agp_uninorth_remove, +}; + +static int __init agp_uninorth_init(void) +{ + return pci_module_init(&agp_uninorth_pci_driver); +} + +static void __exit agp_uninorth_cleanup(void) +{ + pci_unregister_driver(&agp_uninorth_pci_driver); +} + +module_init(agp_uninorth_init); +module_exit(agp_uninorth_cleanup); + +MODULE_PARM(agp_try_unsupported, "1i"); +MODULE_AUTHOR("Ben Herrenschmidt & Paul Mackerras"); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c --- a/drivers/char/agp/via-agp.c Sat May 24 12:48:31 2003 +++ b/drivers/char/agp/via-agp.c Sat May 24 12:48:31 2003 @@ -18,9 +18,9 @@ u8 temp; struct aper_size_info_8 *values; - values = A_SIZE_8(agp_bridge->aperture_sizes); + values = A_SIZE_8(agp_bridge->driver->aperture_sizes); pci_read_config_byte(agp_bridge->dev, VIA_APSIZE, &temp); - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { if (temp == values[i].size_value) { agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i); @@ -68,21 +68,13 @@ } -static void via_tlbflush(agp_memory * mem) +static void via_tlbflush(struct agp_memory *mem) { pci_write_config_dword(agp_bridge->dev, VIA_GARTCTRL, 0x0000008f); pci_write_config_dword(agp_bridge->dev, VIA_GARTCTRL, 0x0000000f); } -static unsigned long via_mask_memory(unsigned long addr, int type) -{ - /* Memory type is ignored */ - - return addr | agp_bridge->masks[0].mask; -} - - static struct aper_size_info_8 via_generic_sizes[7] = { {256, 65536, 6, 0}, @@ -95,23 +87,17 @@ }; -static struct gatt_mask via_generic_masks[] = -{ - {.mask = 0x00000000, .type = 0} -}; - - static int via_fetch_size_agp3(void) { int i; u16 temp; struct aper_size_info_16 *values; - values = A_SIZE_16(agp_bridge->aperture_sizes); + values = A_SIZE_16(agp_bridge->driver->aperture_sizes); pci_read_config_word(agp_bridge->dev, VIA_AGP3_APSIZE, &temp); temp &= 0xfff; - for (i = 0; i < agp_bridge->num_aperture_sizes; i++) { + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { if