# 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.1144 # drivers/video/fbmem.c 1.74 -> 1.75 # drivers/i2c/chips/w83781d.c 1.5 -> 1.6 # drivers/hotplug/cpqphp_core.c 1.15.1.1 -> 1.17 # arch/i386/kernel/process.c 1.49 -> 1.50 # arch/alpha/kernel/entry.S 1.28 -> 1.29 # net/ipv4/netfilter/ip_conntrack_core.c 1.28 -> 1.29 # 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.16 # include/asm-i386/mpspec.h 1.11 -> 1.12 # drivers/scsi/megaraid.c 1.43 -> 1.44 # drivers/pcmcia/cs_internal.h 1.12 -> 1.13 # Documentation/DocBook/kernel-api.tmpl 1.23.1.2 -> 1.25 # include/linux/file.h 1.9 -> 1.10 # arch/ppc64/kernel/signal.c 1.26 -> 1.27 # include/linux/proc_fs.h 1.15 -> 1.17 # drivers/i2c/chips/lm75.c 1.14 -> 1.15 # drivers/scsi/aic7xxx/aic79xx_core.c 1.17 -> 1.24 # arch/i386/kernel/timers/Makefile 1.6 -> 1.7 # drivers/scsi/dpti.h 1.8 -> 1.9 # drivers/atm/horizon.c 1.10 -> 1.11 # drivers/media/video/tda9887.c 1.5 -> 1.6 # drivers/scsi/imm.h 1.7 -> 1.8 # drivers/scsi/in2000.h 1.9 -> 1.10 # include/linux/netfilter_ipv4/ip_nat_core.h 1.1 -> 1.2 # drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped 1.8 -> 1.10 # drivers/block/acsi_slm.c 1.11 -> 1.12 # 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 # 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 # ipc/msg.c 1.13 -> 1.14 # 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.5 # arch/ia64/hp/sim/simscsi.h 1.6 -> 1.7 # kernel/rcupdate.c 1.3 -> 1.4 # include/linux/agpgart.h 1.2 -> 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.20 # arch/ia64/kernel/palinfo.c 1.13 -> 1.14 # drivers/usb/misc/tiglusb.c 1.17 -> 1.19 # include/asm-ppc64/page.h 1.18 -> 1.19 # drivers/scsi/fcal.h 1.6 -> 1.7 # drivers/ieee1394/raw1394.c 1.24 -> 1.25 # 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/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.199 # include/asm-ppc64/unistd.h 1.19 -> 1.20 # net/ipv4/tcp_diag.c 1.5 -> 1.7 # include/linux/if_frad.h 1.2 -> 1.3 # drivers/scsi/aic7xxx_old/aic7xxx.h 1.13 -> 1.14 # 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.12 # 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/wan/cosa.c 1.20 -> 1.21 # drivers/scsi/pci2220i.c 1.20 -> 1.21 # drivers/pci/quirks.c 1.25 -> 1.26 # 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 # drivers/sbus/char/bpp.c 1.13 -> 1.14 # 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.20 # drivers/char/isicom.c 1.17 -> 1.18 # drivers/usb/class/usb-midi.c 1.16 -> 1.17 # include/linux/swap.h 1.76 -> 1.77 # drivers/isdn/i4l/isdn_net_lib.c 1.38 -> 1.39 # 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.12 # drivers/net/bmac.c 1.13 -> 1.14 # 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.10 # include/linux/mm.h 1.117 -> 1.120 # 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 # drivers/char/agp/sis-agp.c 1.15 -> 1.19 # drivers/input/serio/rpckbd.c 1.8 -> 1.9 # drivers/scsi/fcal.c 1.9 -> 1.10 # arch/ia64/kernel/fw-emu.c 1.7 -> 1.8 # arch/i386/kernel/apm.c 1.50 -> 1.52 # drivers/scsi/hosts.c 1.58 -> 1.64 # lib/Makefile 1.21 -> 1.22 # fs/open.c 1.38 -> 1.39 # arch/i386/kernel/cpu/cpufreq/longhaul.c 1.17 -> 1.18 # include/asm-i386/fixmap.h 1.11 -> 1.12 # net/sctp/objcnt.c 1.5 -> 1.6 # drivers/net/skfp/skfddi.c 1.11 -> 1.12 # net/Kconfig 1.11 -> 1.13 # 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/ppc64/kernel/udbg.c 1.7 -> 1.8 # net/ipv6/ip6_output.c 1.20 -> 1.23 # drivers/net/sb1000.c 1.16 -> 1.18 # drivers/scsi/cpqfcTSinit.c 1.35 -> 1.37 # drivers/scsi/aic7xxx/aic7xxx_pci.c 1.12 -> 1.14 # drivers/scsi/aacraid/comminit.c 1.2 -> 1.5 # drivers/usb/class/Kconfig 1.6 -> 1.7 # sound/core/seq/oss/seq_oss_ioctl.c 1.2 -> 1.3 # 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/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.36 # include/asm-ppc64/processor.h 1.27 -> 1.29 # drivers/scsi/aacraid/README 1.1 -> 1.2 # sound/core/seq/oss/seq_oss_rw.c 1.2 -> 1.3 # drivers/video/vesafb.c 1.31 -> 1.32 # include/asm-ia64/spinlock.h 1.9 -> 1.11 # drivers/char/random.c 1.32 -> 1.33 # net/bridge/br_fdb.c 1.5 -> 1.6 # drivers/char/dz.c 1.18 -> 1.20 # arch/sparc/kernel/sparc_ksyms.c 1.17 -> 1.18 # 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 # fs/ext3/Makefile 1.9 -> 1.10 # include/net/ipx.h 1.6 -> 1.9 # 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.10 # net/ipv6/datagram.c 1.8 -> 1.9 # drivers/acorn/scsi/cumana_1.c 1.14 -> 1.15 # include/asm-arm/arch-cl7500/time.h 1.5 -> 1.6 # drivers/scsi/lasi700.c 1.7 -> 1.8 # arch/i386/kernel/head.S 1.26 -> 1.27 # kernel/fork.c 1.118 -> 1.120 # include/linux/sched.h 1.142 -> 1.144 # 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 # arch/arm/kernel/ptrace.c 1.18 -> 1.19 # net/ipv4/xfrm4_tunnel.c 1.4 -> 1.5 # drivers/media/radio/miropcm20-rds.c 1.10 -> 1.11 # drivers/atm/ambassador.c 1.11 -> 1.12 # drivers/i2c/chips/via686a.c 1.6 -> 1.7 # drivers/media/video/bttv-if.c 1.11 -> 1.13 # drivers/media/video/bt819.c 1.7 -> 1.8 # drivers/isdn/eicon/eicon_mod.c 1.12 -> 1.13 # include/net/tcp.h 1.35 -> 1.37 # 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.21 # include/net/sctp/ulpevent.h 1.7 -> 1.9 # include/asm-ia64/page.h 1.15 -> 1.17 # sound/core/seq/seq_clientmgr.c 1.14 -> 1.15 # net/ipv4/protocol.c 1.5 -> 1.7 # net/bridge/br_ioctl.c 1.8 -> 1.9 # fs/dcache.c 1.51 -> 1.52 # net/sctp/endpointola.c 1.19 -> 1.23 # arch/arm/kernel/asm-offsets.c 1.2 -> 1.3 # include/asm-arm/arch-rpc/time.h 1.4 -> 1.5 # net/ipv4/af_inet.c 1.44 -> 1.47 # mm/vmscan.c 1.156 -> 1.157 # 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.9 # 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.37 # include/net/iw_handler.h 1.5 -> 1.6 # drivers/scsi/lasi700.h 1.4 -> 1.5 # 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.25 # 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/sk98lin/skge.c 1.15 -> 1.16 # drivers/char/agp/generic-3.0.c 1.9 -> (deleted) # 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.26 # include/asm-i386/uaccess.h 1.23 -> 1.25 # 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.9 # arch/ia64/lib/do_csum.S 1.9 -> 1.10 # net/ipv4/netfilter/ip_nat_helper.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.32 # net/ipv4/udp.c 1.35 -> 1.37 # 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 # fs/devfs/base.c 1.87 -> 1.89 # init/main.c 1.98 -> 1.99 # fs/intermezzo/sysctl.c 1.8 -> 1.9 # include/asm-i386/numnodes.h 1.3 -> 1.4 # drivers/scsi/fd_mcs.h 1.6 -> 1.7 # 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.40 # net/ipv4/fib_semantics.c 1.10 -> 1.11 # 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.17 # drivers/pcmcia/sa11xx_core.c 1.1 -> 1.2 # 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 # 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 # include/asm-x86_64/hardirq.h 1.3 -> 1.4 # 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.78 # include/asm-ppc64/sigcontext.h 1.3 -> 1.4 # drivers/net/wan/x25_asy.c 1.5 -> 1.6 # net/sctp/output.c 1.23 -> 1.30 # net/sctp/Kconfig 1.3 -> 1.5 # fs/ioctl.c 1.8 -> 1.9 # kernel/cpufreq.c 1.29 -> 1.31 # 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 # security/dummy.c 1.19 -> 1.20 # net/bridge/br_stp.c 1.5 -> 1.6 # drivers/atm/eni.c 1.12 -> 1.13 # net/ipv6/netfilter/ip6t_frag.c 1.4 -> 1.5 # 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 # drivers/net/fc/iph5526.c 1.20 -> 1.21 # drivers/scsi/aacraid/aacraid.h 1.4 -> 1.7 # drivers/atm/zatm.c 1.11 -> 1.12 # drivers/block/cciss_scsi.c 1.12 -> 1.14 # net/decnet/Makefile 1.5 -> 1.6 # drivers/serial/core.c 1.59 -> 1.60 # drivers/scsi/3w-xxxx.h 1.20 -> 1.21 # include/asm-m68k/elf.h 1.2 -> 1.3 # arch/i386/kernel/cpu/mtrr/if.c 1.5 -> 1.7 # drivers/scsi/ips.h 1.25 -> 1.29 # include/net/compat.h 1.3 -> 1.4 # include/linux/major.h 1.8 -> 1.9 # sound/core/seq/oss/seq_oss_timer.c 1.2 -> 1.3 # net/bluetooth/sco.c 1.15 -> 1.17 # arch/ia64/kernel/smpboot.c 1.28 -> 1.32 # net/key/af_key.c 1.33 -> 1.36 # drivers/scsi/aha1740.c 1.14 -> 1.15 # 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 # include/linux/fs.h 1.238 -> 1.243 # 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 # 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 # drivers/block/paride/pt.c 1.15 -> 1.16 # drivers/md/dm-ioctl.c 1.19 -> 1.20 # 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 # 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 # 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 # drivers/net/mace.c 1.13 -> 1.14 # include/asm-ppc64/types.h 1.2 -> 1.3 # 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.61 # drivers/md/md.c 1.166 -> 1.167 # net/atm/proc.c 1.9 -> 1.11 # drivers/scsi/advansys.c 1.31 -> 1.33 # drivers/scsi/ncr53c8xx.c 1.25 -> 1.27 # arch/i386/kernel/reboot.c 1.7 -> 1.8 # net/ipv6/icmp.c 1.26 -> 1.28 # drivers/scsi/inia100.c 1.21 -> 1.22 # drivers/i2c/busses/i2c-piix4.c 1.8 -> 1.9 # include/net/sctp/ulpqueue.h 1.9 -> 1.10 # net/sunrpc/rpc_pipe.c 1.8 -> 1.10 # drivers/usb/media/se401.c 1.35 -> 1.36 # net/atm/pvc.c 1.5 -> 1.6 # arch/ppc64/kernel/ras.c 1.3 -> 1.4 # 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 # 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.40 # 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.24 # include/asm-ppc64/machdep.h 1.14 -> 1.16 # 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.54 # drivers/media/video/tvaudio.c 1.17 -> 1.18 # arch/i386/kernel/io_apic.c 1.64 -> 1.67 # drivers/ide/ide-tape.c 1.22 -> 1.23 # 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 # net/decnet/dn_dev.c 1.10 -> 1.12 # include/net/sctp/constants.h 1.12 -> 1.14 # 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/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 # 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 # 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.42 # drivers/isdn/i4l/isdn_common.c 1.73 -> 1.74 # arch/ia64/ia32/ia32_traps.c 1.4 -> 1.5 # arch/i386/Makefile 1.50 -> 1.51 # net/socket.c 1.56 -> 1.60 # drivers/scsi/ncr53c8xx.h 1.11 -> 1.12 # include/asm-ia64/processor.h 1.34 -> 1.36 # 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/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 # 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.28 # ipc/sem.c 1.17 -> 1.18 # include/linux/brlock.h 1.8 -> (deleted) # 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 # net/sctp/proc.c 1.2 -> 1.3 # include/linux/ide.h 1.48 -> 1.50 # drivers/scsi/nsp32.c 1.10 -> 1.11 # drivers/char/rio/riotty.c 1.8 -> 1.9 # fs/exec.c 1.80 -> 1.81 # include/asm-ia64/machvec_sn2.h 1.7 -> 1.8 # 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 # net/sunrpc/clnt.c 1.34 -> 1.37 # drivers/acorn/scsi/fas216.c 1.15 -> 1.16 # drivers/net/pcmcia/xirc2ps_cs.c 1.17 -> 1.18 # drivers/char/ftape/zftape/zftape-init.c 1.17 -> 1.18 # net/netlink/netlink_dev.c 1.15 -> 1.16 # 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.5 # net/ipv6/raw.c 1.23 -> 1.26 # 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.82 # drivers/scsi/cpqfcTS.h 1.7 -> 1.8 # include/linux/net.h 1.15 -> 1.16 # drivers/scsi/atp870u.c 1.19 -> 1.20 # net/ipv6/proc.c 1.11 -> 1.12 # 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 # drivers/message/fusion/mptscsih.c 1.22 -> 1.23 # net/netsyms.c 1.66 -> 1.73 # 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.5 # drivers/media/video/dpc7146.c 1.1 -> 1.2 # include/asm-i386/mach-bigsmp/mach_ipi.h 1.1 -> 1.2 # include/linux/pci_ids.h 1.91.1.1 -> 1.96 # drivers/ide/ide-disk.c 1.40 -> 1.43 # drivers/usb/serial/usb-serial.c 1.77 -> 1.78 # drivers/scsi/aic7xxx_old.c 1.48 -> 1.49 # drivers/scsi/sym53c8xx.h 1.12 -> 1.13 # fs/xattr.c 1.13 -> 1.14 # 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 # include/net/protocol.h 1.9 -> 1.10 # arch/arm/kernel/traps.c 1.26 -> 1.27 # 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.68 # arch/i386/kernel/msr.c 1.11 -> 1.12 # arch/x86_64/kernel/irq.c 1.13 -> 1.14 # include/asm-mips/elf.h 1.4 -> 1.5 # drivers/mtd/chips/cfi_cmdset_0002.c 1.7 -> 1.8 # include/linux/usb.h 1.75 -> 1.77 # drivers/char/serial167.c 1.21 -> 1.22 # drivers/media/video/tda9875.c 1.12 -> 1.13 # include/asm-i386/mach-summit/mach_mpparse.h 1.5 -> 1.6 # arch/ppc64/kernel/irq.c 1.23 -> 1.25 # 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) # drivers/scsi/seagate.c 1.17 -> 1.18 # drivers/input/mouse/rpcmouse.c 1.13 -> 1.14 # drivers/ide/ide-cd.c 1.43 -> 1.45 # fs/fat/inode.c 1.63 -> 1.64 # 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.4 # 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 # arch/i386/kernel/signal.c 1.31 -> 1.32 # drivers/scsi/BusLogic.h 1.13 -> 1.14 # drivers/scsi/sg.c 1.52 -> 1.55 # 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 # include/linux/blkpg.h 1.4 -> 1.5 # drivers/scsi/aacraid/dpcsup.c 1.1 -> 1.3 # lib/inflate.c 1.2 -> 1.4 # drivers/usb/usb-skeleton.c 1.32 -> 1.35 # drivers/usb/serial/ir-usb.c 1.27 -> 1.28 # arch/ia64/kernel/efivars.c 1.10 -> 1.11 # drivers/net/acenic.c 1.28 -> 1.29 # arch/ppc64/kernel/rtas-proc.c 1.4 -> 1.6 # drivers/usb/net/catc.c 1.22 -> 1.23 # arch/ppc64/kernel/setup.c 1.21.1.1 -> 1.24 # arch/ia64/kernel/mca.c 1.22 -> 1.29 # drivers/scsi/aic7xxx/aic79xx_pci.c 1.9 -> 1.10 # 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/i386/kernel/setup.c 1.79 -> 1.81 # 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.9 # arch/ia64/kernel/process.c 1.30 -> 1.34 # drivers/scsi/pci2220i.h 1.5 -> 1.6 # net/wanrouter/wanproc.c 1.15 -> 1.17 # fs/ncpfs/ncplib_kernel.c 1.10 -> 1.11 # drivers/atm/idt77252.c 1.10 -> 1.12 # drivers/usb/core/hcd-pci.c 1.13 -> 1.14 # arch/i386/kernel/smpboot.c 1.57 -> 1.59 # drivers/scsi/scsi_debug.h 1.12 -> 1.15 # arch/ppc/kernel/process.c 1.32 -> 1.33 # include/asm-m68k/hardirq.h 1.3 -> 1.4 # arch/i386/kernel/module.c 1.10 -> 1.11 # net/ipv4/fib_hash.c 1.11 -> 1.12 # 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.8 # 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.38 # arch/ia64/kernel/acpi.c 1.36 -> 1.40 # include/asm-ppc64/naca.h 1.5 -> 1.6 # 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/rclanmtl.h 1.7 -> 1.8 # sound/oss/soundcard.c 1.15 -> 1.16 # drivers/i2c/busses/i2c-i801.c 1.8 -> 1.9 # 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.5 # include/linux/tty.h 1.15 -> 1.16 # 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.8 # drivers/scsi/dmx3191d.h 1.5 -> 1.6 # net/core/dev.c 1.68 -> 1.73 # net/xfrm/xfrm_policy.c 1.24 -> 1.25 # drivers/ide/ide-dma.c 1.13 -> 1.15 # fs/ext3/hash.c 1.1 -> 1.2 # sound/core/seq/oss/seq_oss_device.h 1.2 -> 1.3 # 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 # kernel/posix-timers.c 1.15 -> 1.16 # arch/ppc64/kernel/head.S 1.26 -> 1.31 # drivers/net/depca.c 1.18 -> 1.19 # drivers/usb/host/ohci-sa1111.c 1.14 -> 1.15 # 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 # 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.28 # drivers/acorn/scsi/arxescsi.c 1.16 -> 1.17 # 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 # net/decnet/af_decnet.c 1.24 -> 1.25 # drivers/scsi/ultrastor.c 1.16 -> 1.18 # 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 # include/asm-parisc/kmap_types.h 1.2 -> 1.3 # 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 # arch/ia64/sn/kernel/machvec.c 1.4 -> 1.5 # drivers/scsi/aic7xxx/aic7xxx.h 1.12 -> 1.13 # include/linux/msg.h 1.3 -> 1.4 # 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/asm-ia64/unwind.h 1.4 -> 1.5 # drivers/scsi/NCR_D700.h 1.2 -> 1.3 # fs/pipe.c 1.24 -> 1.26 # 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 # fs/lockd/host.c 1.5 -> 1.6 # drivers/input/input.c 1.30 -> 1.31 # fs/cifs/cifsfs.c 1.11 -> 1.12 # 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 # arch/ppc64/kernel/xics.c 1.19 -> 1.22 # arch/ia64/ia32/ia32_entry.S 1.23 -> 1.24 # 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 # 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.35 # 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.54 # net/ipv6/af_inet6.c 1.32 -> 1.40 # drivers/char/ipmi/ipmi_msghandler.c 1.4 -> 1.5 # drivers/sbus/char/vfc_dev.c 1.10 -> 1.11 # include/asm-ia64/iosapic.h 1.9 -> 1.10 # 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 # 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.19 # arch/ia64/kernel/signal.c 1.22 -> 1.24 # include/asm-arm/arch-arc/time.h 1.4 -> 1.5 # drivers/usb/input/hid-core.c 1.54 -> 1.56 # drivers/scsi/dmx3191d.c 1.11 -> 1.12 # drivers/ide/ide-probe.c 1.41 -> 1.46 # drivers/video/logo/logo.c 1.5 -> 1.6 # drivers/scsi/aacraid/sa.c 1.3 -> 1.4 # drivers/usb/serial/belkin_sa.c 1.34 -> 1.35 # 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/scsi/ppa.c 1.20 -> 1.21 # 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.10 # include/asm-i386/smp.h 1.23 -> 1.24 # drivers/char/tty_io.c 1.90 -> 1.94 # drivers/scsi/pcmcia/fdomain_stub.c 1.15 -> 1.16 # drivers/char/agp/i460-agp.c 1.16 -> 1.21 # drivers/net/tulip/tulip_core.c 1.41 -> 1.42 # include/asm-arm/arch-shark/time.h 1.7 -> 1.8 # net/ipv6/ndisc.c 1.33 -> 1.34 # fs/bio.c 1.42 -> 1.43 # drivers/char/pcxx.c 1.10 -> 1.11 # arch/ppc64/kernel/process.c 1.30 -> 1.31 # 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.38 # net/sctp/protocol.c 1.40.1.2 -> 1.47 # MAINTAINERS 1.136 -> 1.139 # drivers/s390/char/tubfs.c 1.16 -> 1.17 # drivers/usb/net/rtl8150.c 1.22 -> 1.24 # fs/jffs/inode-v23.c 1.44 -> 1.45 # include/asm-arm/arch-l7200/time.h 1.5 -> 1.6 # net/ipv6/netfilter/ip6t_esp.c 1.4 -> 1.5 # arch/ppc64/kernel/pci_dma.c 1.11 -> 1.14 # include/asm-generic/rmap.h 1.4 -> 1.5 # 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.8 # include/linux/if_ether.h 1.5 -> 1.6 # drivers/media/video/msp3400.c 1.17 -> 1.18 # drivers/char/istallion.c 1.20 -> 1.22 # net/atm/lec.c 1.17 -> 1.21 # drivers/scsi/aic7xxx/aic79xx_osm.h 1.22 -> 1.29 # drivers/char/raw.c 1.31 -> 1.32 # mm/mmap.c 1.79 -> 1.81 # arch/s390/kernel/s390_ksyms.c 1.11 -> 1.12 # arch/ia64/hp/sim/simeth.c 1.5 -> 1.7 # drivers/scsi/gdth.c 1.26 -> 1.27 # fs/ext2/xattr.c 1.12 -> 1.13 # 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.15 # 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.24 # 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 # net/bluetooth/rfcomm/sock.c 1.15 -> 1.17 # drivers/scsi/st.c 1.60 -> 1.62 # drivers/scsi/ide-scsi.c 1.23 -> 1.24 # 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 # include/asm-i386/unistd.h 1.24 -> 1.25 # include/linux/futex.h 1.6 -> 1.7 # fs/namespace.c 1.39 -> 1.40 # net/atm/svc.c 1.5 -> 1.7 # drivers/char/agp/ali-agp.c 1.15 -> 1.21 # drivers/char/agp/alpha-agp.c 1.3 -> 1.5 # include/linux/wireless.h 1.7 -> 1.8 # drivers/acorn/scsi/powertec.c 1.21 -> 1.23 # 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 # include/asm-ia64/ptrace.h 1.9 -> 1.10 # net/sctp/sm_sideeffect.c 1.36.1.1 -> 1.43 # drivers/scsi/pci2000.c 1.15 -> 1.16 # 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 # fs/fcntl.c 1.25 -> 1.26 # fs/ext2/xattr.h 1.5 -> 1.7 # 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.24 # drivers/net/pcmcia/fmvj18x_cs.c 1.19 -> 1.20 # drivers/scsi/sym53c8xx.c 1.33 -> 1.34 # drivers/char/agp/amd-k8-agp.c 1.30 -> 1.36 # 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.26 # 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.16 # include/asm-i386/elf.h 1.8 -> 1.9 # include/net/ip.h 1.17 -> 1.19 # 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 # arch/ppc64/mm/numa.c 1.2 -> 1.4 # net/bluetooth/l2cap.c 1.24 -> 1.28 # drivers/mtd/mtdchar.c 1.12 -> 1.13 # 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 # 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 # drivers/char/agp/backend.c 1.72 -> 1.81 # arch/ppc64/kernel/syscalls.c 1.9 -> 1.10 # include/linux/netfilter_ipv4/compat_firewall.h 1.1 -> 1.2 # 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 # drivers/media/video/cpia.c 1.24 -> 1.25 # arch/ppc64/kernel/sys_ppc32.c 1.53.1.5 -> 1.59 # include/linux/ipv6.h 1.6 -> 1.7 # drivers/char/vt_ioctl.c 1.22 -> 1.23 # net/sunrpc/xdr.c 1.13 -> 1.14 # drivers/video/riva/fbdev.c 1.45 -> 1.46 # net/decnet/TODO 1.4 -> 1.5 # CREDITS 1.81 -> 1.83 # include/asm-sparc64/hardirq.h 1.13 -> 1.15 # drivers/media/video/tda7432.c 1.10 -> 1.11 # drivers/net/wireless/wavelan.p.h 1.11 -> 1.12 # fs/seq_file.c 1.9 -> 1.10 # drivers/scsi/aacraid/commsup.c 1.3 -> 1.5 # net/ipv4/netfilter/ip_fw_compat_redir.c 1.5 -> 1.6 # drivers/video/console/fbcon.h 1.30 -> 1.31 # fs/lockd/mon.c 1.8 -> 1.9 # 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.25 # 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/linux/security.h 1.16 -> 1.18 # arch/ia64/kernel/salinfo.c 1.2 -> 1.3 # drivers/isdn/pcbit/drv.c 1.10 -> 1.11 # drivers/ieee1394/dv1394.c 1.30 -> 1.31 # include/net/sock.h 1.37 -> 1.38 # 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 # arch/ia64/lib/swiotlb.c 1.14 -> 1.16 # include/asm-parisc/elf.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/devfs_fs_kernel.h 1.44 -> 1.46 # include/asm-arm/bugs.h 1.2 -> 1.3 # arch/ppc64/kernel/smp.c 1.31.2.1 -> 1.34 # net/ipv6/ip6_input.c 1.11 -> 1.12 # fs/nfs/write.c 1.39 -> 1.40 # drivers/media/video/bt832.c 1.2 -> 1.3 # fs/ext2/Makefile 1.8 -> 1.9 # include/asm-ia64/sn/addrs.h 1.4 -> 1.5 # arch/ia64/ia32/ia32_ioctl.c 1.8 -> 1.9 # include/net/ip6_fib.h 1.3 -> 1.4 # 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.32 # drivers/scsi/sym53c416.h 1.6 -> 1.7 # include/asm-ia64/percpu.h 1.6 -> 1.7 # 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 # 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.58 # drivers/block/DAC960.h 1.20 -> 1.21 # drivers/scsi/aic7xxx/aic79xx_proc.c 1.6 -> 1.9 # drivers/usb/storage/unusual_devs.h 1.33 -> 1.38 # drivers/i2c/chips/it87.c 1.3 -> 1.9 # drivers/i2c/i2c-dev.c 1.27 -> 1.29 # net/atm/signaling.c 1.5 -> 1.7 # arch/ia64/kernel/brl_emu.c 1.5 -> 1.6 # net/sched/sch_ingress.c 1.12 -> 1.13 # net/core/wireless.c 1.9 -> 1.12 # arch/alpha/kernel/irq.c 1.20 -> 1.21 # mm/slab.c 1.75 -> 1.80 # arch/i386/kernel/suspend.c 1.14 -> 1.15 # 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.41 # net/atm/mpoa_proc.c 1.5 -> 1.6 # net/ipv4/netfilter/ip_nat_standalone.c 1.22 -> 1.23 # include/net/bluetooth/rfcomm.h 1.6 -> 1.8 # arch/arm/mm/consistent.c 1.10 -> 1.11 # fs/filesystems.c 1.14 -> 1.15 # drivers/scsi/scsi_scan.c 1.80 -> 1.85 # include/linux/rtnetlink.h 1.10 -> 1.12 # 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.181 # include/linux/agp_backend.h 1.27 -> 1.36 # 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/sctp/adler32.c 1.6.1.1 -> 1.8 # drivers/char/agp/hp-agp.c 1.16 -> 1.21 # drivers/block/deadline-iosched.c 1.17 -> 1.19 # drivers/Makefile 1.32 -> 1.33 # net/ipv6/ip6_fib.c 1.11 -> 1.17 # drivers/scsi/Makefile 1.41 -> 1.42 # drivers/usb/host/ehci-q.c 1.45 -> 1.46 # 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/net/cs89x0.c 1.16 -> 1.17 # init/Kconfig 1.13 -> 1.14 # include/asm-x86_64/elf.h 1.5 -> 1.6 # include/net/ipv6.h 1.11 -> 1.12 # 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.14 # 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.32 # drivers/char/drm/drm_drv.h 1.17 -> 1.18 # drivers/hotplug/cpqphp.h 1.6.1.1 -> 1.9 # drivers/i2c/busses/i2c-amd8111.c 1.7 -> 1.8 # include/linux/atmdev.h 1.8 -> 1.12 # arch/sparc64/kernel/sparc64_ksyms.c 1.47 -> 1.48 # drivers/usb/serial/console.c 1.2 -> 1.4 # include/net/xfrm.h 1.34 -> 1.37 # arch/ia64/hp/sim/hpsim_console.c 1.6 -> 1.7 # kernel/timer.c 1.52 -> 1.53 # arch/x86_64/kernel/reboot.c 1.3 -> 1.4 # 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.18 # drivers/char/agp/via-agp.c 1.33 -> 1.39 # arch/um/kernel/sys_call_table.c 1.19 -> 1.20 # drivers/tc/zs.c 1.14 -> 1.16 # drivers/char/ipmi/ipmi_devintf.c 1.7 -> 1.8 # drivers/block/paride/pg.c 1.15 -> 1.16 # include/linux/pfkeyv2.h 1.5 -> 1.6 # 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 # drivers/scsi/aic7xxx/aic79xx.seq 1.8 -> 1.10 # 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 # 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.26 # 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.6 # net/ipv6/mcast.c 1.18 -> 1.19 # drivers/scsi/eata.c 1.30 -> 1.31 # drivers/char/drm/Kconfig 1.4 -> 1.5 # net/ipv4/arp.c 1.19 -> 1.21 # include/asm-i386/ipc.h 1.2 -> 1.3 # arch/ppc64/kernel/misc.S 1.52.2.3 -> 1.57 # arch/ia64/kernel/mca_asm.S 1.6 -> 1.8 # 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/arm/mach-pxa/irq.c 1.6 -> 1.7 # 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/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/bridge/br_stp_if.c 1.6 -> 1.7 # include/asm-arm/mach/arch.h 1.7 -> 1.8 # include/asm-i386/mach-default/mach_ipi.h 1.1 -> 1.2 # fs/bfs/dir.c 1.18 -> 1.19 # drivers/scsi/pcmcia/aha152x_stub.c 1.14 -> 1.15 # drivers/media/video/tvmixer.c 1.13 -> 1.15 # 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/t128.c 1.10 -> 1.11 # include/asm-ia64/bitops.h 1.12 -> 1.13 # arch/ia64/tools/print_offsets.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/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 # include/net/ip_fib.h 1.8 -> 1.9 # arch/parisc/hpux/wrappers.S 1.2 -> 1.3 # 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 # 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 # drivers/scsi/pci2000.h 1.6 -> 1.7 # include/asm-ia64/pci.h 1.14 -> 1.16 # 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/net/setup.c 1.6 -> 1.10 # 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 # 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.19 # 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 # net/atm/raw.c 1.2 -> 1.3 # net/ipv6/addrconf.c 1.38 -> 1.40 # 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 # crypto/Kconfig 1.12 -> 1.13 # drivers/hotplug/cpqphp_pci.c 1.16 -> 1.18 # drivers/net/ppp_generic.c 1.24 -> 1.26 # drivers/isdn/hisax/diva.c 1.41 -> 1.42 # include/asm-ia64/compat.h 1.11 -> 1.12 # arch/x86_64/mm/ioremap.c 1.9 -> 1.10 # net/sctp/ulpqueue.c 1.17.1.1 -> 1.22 # fs/locks.c 1.40 -> 1.41 # include/asm-i386/mach-bigsmp/mach_apic.h 1.8 -> 1.10 # net/ipv4/icmp.c 1.27 -> 1.28 # include/linux/efi.h 1.1 -> 1.2 # drivers/usb/Makefile 1.41 -> 1.43 # include/linux/netdevice.h 1.33 -> 1.34 # fs/ext3/xattr.h 1.6 -> 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 # 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 # include/asm-ppc64/io.h 1.7 -> 1.8 # 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 # sound/core/info.c 1.24 -> 1.26 # arch/i386/kernel/timers/timer.c 1.6 -> 1.7 # arch/ia64/kernel/traps.c 1.28 -> 1.29 # include/sound/seq_kernel.h 1.5 -> 1.6 # arch/ia64/kernel/sal.c 1.5 -> 1.6 # drivers/scsi/scsi_ioctl.c 1.16 -> 1.17 # arch/ia64/mm/fault.c 1.13 -> 1.14 # 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.18 # drivers/net/wireless/netwave_cs.c 1.15 -> 1.16 # drivers/net/hamradio/mkiss.c 1.9 -> 1.10 # 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/isdn/hisax/sedlbauer.c 1.35 -> 1.36 # include/asm-ppc64/topology.h 1.6 -> 1.7 # net/atm/clip.c 1.7 -> 1.11 # net/decnet/dn_nsp_out.c 1.7 -> 1.8 # 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 # drivers/acorn/net/ether3.c 1.13 -> 1.14 # 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 # net/ipv4/ip_output.c 1.34 -> 1.35 # drivers/scsi/pcmcia/nsp_cs.c 1.20 -> 1.21 # drivers/scsi/esp.c 1.24 -> 1.25 # drivers/scsi/aic7xxx/aic79xx_seq.h_shipped 1.8 -> 1.10 # 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.7 # drivers/scsi/aic7xxx/Makefile 1.20 -> 1.21 # mm/mincore.c 1.3 -> 1.4 # drivers/scsi/wd7000.c 1.22 -> 1.24 # include/scsi/scsi.h 1.9 -> 1.11 # drivers/scsi/advansys.h 1.9 -> 1.10 # net/bridge/br_if.c 1.11 -> 1.12 # 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.25 # net/decnet/Kconfig 1.1 -> 1.2 # net/ipv4/route.c 1.52 -> 1.56 # drivers/base/class.c 1.26 -> 1.28 # 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.5 # include/linux/slab.h 1.20 -> 1.21 # 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/arm/mach-rpc/dma.c 1.9 -> 1.10 # drivers/block/scsi_ioctl.c 1.24 -> 1.26 # drivers/scsi/qla1280.h 1.14 -> 1.15 # drivers/ide/ide-tcq.c 1.2 -> 1.5 # net/ipv4/fib_frontend.c 1.10 -> 1.11 # include/asm-arm/arch-epxa10db/time.h 1.4 -> 1.5 # net/appletalk/ddp.c 1.20 -> 1.21 # drivers/scsi/sym53c8xx_2/sym53c8xx.h 1.8 -> 1.9 # net/sctp/Makefile 1.7 -> 1.9 # 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.6 # arch/ppc64/kernel/ioctl32.c 1.25.1.2 -> 1.30 # drivers/char/amiserial.c 1.19 -> 1.20 # drivers/usb/core/file.c 1.7 -> 1.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 # 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 # drivers/usb/misc/speedtch.c 1.80 -> 1.81 # include/asm-i386/mach-default/mach_apic.h 1.22 -> 1.24 # drivers/scsi/aic7xxx/aic7xxx_inline.h 1.8 -> 1.10 # drivers/char/tty_ioctl.c 1.8 -> 1.9 # drivers/macintosh/adb.c 1.18 -> 1.19 # net/sctp/primitive.c 1.9 -> 1.10 # arch/ia64/kernel/acpi-ext.c 1.1 -> 1.3 # fs/fs-writeback.c 1.34 -> 1.35 # arch/arm/mach-footbridge/dc21285.c 1.7 -> 1.9 # net/ipv6/netfilter/ip6t_ipv6header.c 1.4 -> 1.5 # include/asm-arm/arch-sa1100/time.h 1.7 -> 1.8 # drivers/usb/serial/bus.c 1.7 -> 1.8 # drivers/net/slip.c 1.13 -> 1.14 # net/decnet/dn_fib.c 1.4 -> 1.6 # drivers/char/agp/amd-k7-agp.c 1.19 -> 1.26 # drivers/hotplug/ibmphp_core.c 1.24 -> 1.26 # arch/arm/kernel/calls.S 1.11 -> 1.12 # 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 # 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.11 # 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 # 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.20 # 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.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.7 drivers/usb/gadget/net2280.c # (new) -> 1.1 include/linux/atm_he.h # (new) -> 1.1 drivers/usb/gadget/Makefile # (new) -> 1.6 drivers/atm/he.c # (new) -> 1.5 drivers/char/agp/nvidia-agp.c # (new) -> 1.1 arch/i386/mach-generic/bigsmp.c # (new) -> 1.4 drivers/usb/gadget/Kconfig # (new) -> 1.1 drivers/scsi/scsi_devinfo.c # (new) -> 1.1 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.4 drivers/usb/gadget/zero.c # (new) -> 1.2 include/linux/usb_gadget.h # (new) -> 1.3 drivers/atm/he.h # (new) -> 1.1 fs/ext3/xattr_security.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 arch/i386/mach-generic/Makefile # (new) -> 1.1 net/decnet/netfilter/Makefile # (new) -> 1.1 include/asm-i386/genapic.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.1 drivers/usb/gadget/net2280.h # (new) -> 1.5 net/sctp/chunk.c # (new) -> 1.1 include/asm-i386/mach-generic/mach_ipi.h # (new) -> 1.1 net/decnet/netfilter/Kconfig # (new) -> 1.5 drivers/char/agp/isoch.c # (new) -> 1.1 arch/i386/mach-generic/summit.c # (new) -> 1.3 drivers/usb/gadget/ether.c # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/05/04 torvalds@home.transmeta.com 1.1042.114.10 # Linux 2.5.69 # -------------------------------------------- # 03/05/05 anton@samba.org 1.1057.2.13 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/tmp3 # -------------------------------------------- # 03/05/04 davem@nuts.ninka.net 1.1042.1.183 # [ATM]: mpc.c warning fixes. # -------------------------------------------- # 03/05/04 davem@nuts.ninka.net 1.1042.1.184 # [NETFILTER IPV6]: Fix warnings. # -------------------------------------------- # 03/05/04 davem@nuts.ninka.net 1.1042.1.185 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/05/05 davej@tetrachloride.(none) 1.1042.114.11 # 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.114.12 # [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.115.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.111.2 # o list.h: implement list_for_each_entry_safe # -------------------------------------------- # 03/05/05 acme@conectiva.com.br 1.1042.111.3 # o ipx: convert ipx_interface handling to use list_head # -------------------------------------------- # 03/05/05 jgrimm@touki.austin.ibm.com 1.1042.116.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.114.13 # [AGPGART] Skip devices with no AGP headers sooner. # -------------------------------------------- # 03/05/05 jgrimm@touki.austin.ibm.com 1.1042.23.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 davej@codemonkey.org.uk 1.1042.114.14 # [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.114.15 # [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.100.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.100.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.100.5 # [PATCH] USB speedtouch fix # # Missing header file. Please apply. # -------------------------------------------- # 03/05/05 philipp@void.at 1.1042.100.6 # [PATCH] USB: unusual_devs.h patch # -------------------------------------------- # 03/05/05 greg@kroah.com 1.1063.1.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.1.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 jgrimm@touki.austin.ibm.com 1.1042.23.18 # [SCTP] Support SCTP ECN on ipv6. # -------------------------------------------- # 03/05/05 acme@conectiva.com.br 1.1042.111.4 # o ipx: convert ipx_route to use list_head # -------------------------------------------- # 03/05/05 davem@nuts.ninka.net 1.1063.2.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.2.2 # [IPSEC]: Fix SADB_EALG_{3,}DESCBC values. # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.2.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.2.4 # [ATM]: Fix some CPP pasting in ambassador driver. # -------------------------------------------- # 03/05/06 chas@locutus.cmf.nrl.navy.mil 1.1063.2.5 # [ATM]: Fix excessive stack usage in iphase driver. # -------------------------------------------- # 03/05/06 chas@locutus.cmf.nrl.navy.mil 1.1063.2.6 # [ATM]: svcs possible race with sigd. # -------------------------------------------- # 03/05/06 steve@gw.chygwyn.com 1.1063.2.7 # [FS]: Add seq_release_private and proc_net_fops_create helpers. # -------------------------------------------- # 03/05/06 steve@gw.chygwyn.com 1.1063.2.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.2.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.2.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.2.11 # [NETFILTER]: ip_nat_proto_{icmp,udp}.c need ip_nat_core.h # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.2.12 # [IPV6]: Kill spurious module_{get,put}(). # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.2.13 # [BLUETOOTH]: Fix hci_usb build. # -------------------------------------------- # 03/05/06 yoshfuji@linux-ipv6.org 1.1063.2.14 # [IPV6]: Fix offset in ICMPV6_HDR_FIELD messages. # -------------------------------------------- # 03/05/06 yoshfuji@linux-ipv6.org 1.1063.2.15 # [IPV^]: Use correct icmp6 type in ip6_pkt_discard. # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.3.1 # [SPARC64]: Only use power interrupt when button property exists. # -------------------------------------------- # 03/05/06 chas@cmf.nrl.navy.mil 1.1063.2.16 # [ATM]: Fix foul up in lec driver. # -------------------------------------------- # 03/05/06 torvalds@home.transmeta.com 1.1063.4.1 # Merge bk://kernel.bkbits.net/davem/sparc-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.2.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.2.18 # [IPV6]: Remove illogical bug check in fib6_del. # -------------------------------------------- # 03/05/06 davej@codemonkey.org.uk 1.1042.114.16 # [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.114.17 # [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.4.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.5.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.6.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.7.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.5.2 # [PATCH] PCI Hotplug: fix up the compaq driver to work properly again. # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.5.3 # [PATCH] PCI Hotplug: fix up the ibm driver to work properly again. # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.5.4 # [PATCH] PCI Hotplug: fix compiler warning in ibm driver. # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.5.5 # [PATCH] PCI Hotplug: fix up the acpi driver to work properly again. # -------------------------------------------- # 03/05/06 greg@kroah.com 1.1063.5.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.5.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.4.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.7.2 # mca.c: # (show_min_state): Fix typo r11 -> r12. # -------------------------------------------- # 03/05/06 sri@us.ibm.com 1.1042.117.1 # Manual merge. # -------------------------------------------- # 03/05/06 kraxel@bytesex.org 1.1063.4.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.4.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.4.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.5.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.4.7 # [PATCH] i2c: fix compile error due to previous patches. # -------------------------------------------- # 03/05/06 warp@mercury.d2dc.net 1.1063.4.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.6.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.4.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.4.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.4.11 # [PATCH] n_hdlc update # # - Use C99 initializers # -------------------------------------------- # 03/05/06 arun.sharma@intel.com 1.1063.7.3 # [PATCH] ia64: fix sys32_select() # # -------------------------------------------- # 03/05/06 davem@nuts.ninka.net 1.1063.2.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.2.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.2.21 # [IPV4/IPV6]: Set owner field in family ops. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.1.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.1.4 # [PATCH] USB: converted usblp over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.1.5 # [PATCH] USB: converted mdc800 over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.1.6 # [PATCH] USB: converted scanner over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.1.7 # [PATCH] USB: converted dabusb over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.1.8 # [PATCH] USB: converted auerswald over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.1.9 # [PATCH] USB: converted brlvger over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.1.10 # [PATCH] USB: converted rio500 over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.1.11 # [PATCH] USB: converted usblcd over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.1.12 # [PATCH] USB: converted usb-skeleton over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.1.13 # [PATCH] USB: remove #include from some drivers that do not need it. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.1.14 # USB: converted hiddev over to new usb_register_dev() changes. # -------------------------------------------- # 03/05/07 rddunlap@osdl.org 1.1063.2.22 # [NET]: Spelling/typo fixes in rtnetlink.h # -------------------------------------------- # 03/05/07 rddunlap@osdl.org 1.1063.2.23 # [IPV6]: Convert /proc/net/rt6_stats to seq_file. # -------------------------------------------- # 03/05/07 bdschuym@pandora.be 1.1063.2.24 # [BRIDGE]: Change pkt_type to PACKET_HOST earlier. # -------------------------------------------- # 03/05/07 shemminger@osdl.org 1.1063.2.25 # [IPV4]: Replace explicit dev->refcount bumps with dev_hold. # -------------------------------------------- # 03/05/07 akpm@digeo.com 1.1063.2.26 # [NET]: Remove duplicated alloc_skb debug check. # -------------------------------------------- # 03/05/07 chas@cmf.nrl.navy.mil 1.1063.2.27 # [ATM]: Add Forerunner HE support. # -------------------------------------------- # 03/05/07 chas@cmf.nrl.navy.mil 1.1063.2.28 # [ATM]: Forward port br2864 to 2.5.x # -------------------------------------------- # 03/05/07 chas@cmf.nrl.navy.mil 1.1063.2.29 # [ATM]: Clip locking and more atmvcc cleanup. # -------------------------------------------- # 03/05/07 rddunlap@osdl.org 1.1063.2.30 # [IPV6]: Fix typos in ip6_fib.c # -------------------------------------------- # 03/05/07 rddunlap@osdl.org 1.1063.2.31 # [IPV6]: Use time_after() etc. for comparing jiffies. # -------------------------------------------- # 03/05/07 olof@austin.ibm.com 1.1063.2.32 # [TCP]: tcp_twkill leaves death row list in inconsistent state over tcp_timewait_kill. # -------------------------------------------- # 03/05/07 davem@nuts.ninka.net 1.1063.2.33 # [ATM]: Fix build of HE driver. # -------------------------------------------- # 03/05/07 trond.myklebust@fys.uio.no 1.1063.4.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.4.13 # Fix typos in close-to-open cache consistency checking. # -------------------------------------------- # 03/05/07 trond.myklebust@fys.uio.no 1.1063.4.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.4.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.4.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.4.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.4.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.4.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.4.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.8.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.2.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.9.1 # Whee. Fix ancient mailing address. # -------------------------------------------- # 03/05/07 torvalds@penguin.transmeta.com 1.1063.10.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.1.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.1.16 # [PATCH] USB: update my copyrights in a few locations. # -------------------------------------------- # 03/05/07 torvalds@penguin.transmeta.com 1.1063.11.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.2.35 # [ATM]: assorted atm patches # -------------------------------------------- # 03/05/07 chas@cmf.nrl.navy.mil 1.1063.2.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.2.37 # [IPV4]: Use time_{before,after}() and proper jiffies types in route.c # -------------------------------------------- # 03/05/07 davem@nuts.ninka.net 1.1063.2.38 # [IPV4]: Two minor errors in jiffies changes. # -------------------------------------------- # 03/05/07 shemminger@osdl.org 1.1063.2.39 # [NET]: Kill more direct references to netdev->refcnt. # -------------------------------------------- # 03/05/07 kuznet@ms2.inr.ac.ru 1.1063.2.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.2.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.12.1 # [PATCH] tc_zs tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.2 # [PATCH] specialix tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.3 # [PATCH] stallion tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.4 # [PATCH] serial_tx3912 tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.5 # [PATCH] sh-sci tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.6 # [PATCH] ser_a2232 tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.7 # [PATCH] serial167 tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.8 # [PATCH] rocket tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.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.12.10 # [PATCH] rio tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.11 # [PATCH] riscom8 tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.12 # [PATCH] pcxx tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.13 # [PATCH] mxser tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.14 # [PATCH] istallion tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.15 # [PATCH] moxa tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.16 # [PATCH] ip2main tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.17 # [PATCH] isicom tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.18 # [PATCH] esp tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.19 # [PATCH] hvc_console tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.20 # [PATCH] dz tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.21 # [PATCH] cyclades tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.22 # [PATCH] amiserial tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.23 # [PATCH] macintosh/macserial tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.24 # [PATCH] isdn/capi tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 hannal@us.ibm.com 1.1063.12.25 # [PATCH] vme_scc tty_driver add .owner field remove MOD_INC/DEC_USE_COUNT # -------------------------------------------- # 03/05/07 davem@nuts.ninka.net 1.1063.2.42 # [PKT_SCHED]: Kill iovcnt reference from sch_atm.c # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.12.26 # TTY: add tty class support for all tty devices. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.12.27 # TTY: changes based on tty_register_device() paramater change. # -------------------------------------------- # 03/05/07 greg@kroah.com 1.1063.12.28 # TTY: remove usb-serial sysfs dev file as it is now redundant. # -------------------------------------------- # 03/05/07 torvalds@home.transmeta.com 1.1063.11.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.11.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.11.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.13.1 # Use "__attribute__" consistently. # -------------------------------------------- # 03/05/07 torvalds@home.transmeta.com 1.1063.13.2 # Allow external checkers to overrid the "cond_syscall()" macro. # -------------------------------------------- # 03/05/07 torvalds@home.transmeta.com 1.1063.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.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.13.34 # Merge conflicting tty devfs cleanups # -------------------------------------------- # 03/05/08 greg@kroah.com 1.1063.13.35 # TTY: fix up lost devfs_mk_cdev change. # -------------------------------------------- # 03/05/08 greg@kroah.com 1.1063.13.36 # USB: change core to use devfs_mk_cdev() instead of devfs_register() # -------------------------------------------- # 03/05/08 greg@kroah.com 1.1063.13.37 # USB: fix up compile error in tiglusb driver due to devfs_mk_cdev() changes. # -------------------------------------------- # 03/05/08 greg@kroah.com 1.1063.1.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.1.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.14.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.14.2 # [ATM]: Kill stray ATM_PDU_OVHD reference in lec.c # -------------------------------------------- # 03/05/08 mk@linux-ipv6.org 1.1063.14.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.14.4 # [IPV6]: Remove incorrect comment in ip6_fib.c # -------------------------------------------- # 03/05/08 shemminger@osdl.org 1.1063.14.5 # [SYSKONNECT]: /proc module handling fixup. # -------------------------------------------- # 03/05/08 shemminger@osdl.org 1.1063.14.6 # [PKTGEN]: Module and dev cleanup. # -------------------------------------------- # 03/05/08 steve@gw.chygwyn.com 1.1063.14.7 # [DECNET]: Decnet not obeying netdev locking (from shemminger@osdl.org). # -------------------------------------------- # 03/05/08 hch@lst.de 1.1063.14.8 # [SLIP]: Move over to initcalls. # -------------------------------------------- # 03/05/08 davem@nuts.ninka.net 1.1063.15.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.14.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.14.10 # [IPV4]: Fix expiration test in rt_check_expire. # -------------------------------------------- # 03/05/08 rusty@rustcorp.com.au 1.1063.14.11 # [NETFILTER]: Fix skb_checksum args in ip_nat_core.c # -------------------------------------------- # 03/05/08 davem@kernel.bkbits.net 1.1063.1.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.16.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.16.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.16.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.16.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.16.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.16.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.16.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.16.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.16.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.1.20 # Use the right CFLAGS for source checking. Fix grammar. # -------------------------------------------- # 03/05/08 greg@kroah.com 1.1063.17.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.14.12 # [MPLS]: Add ethernet protocol numbers. # -------------------------------------------- # 03/05/08 davem@nuts.ninka.net 1.1063.14.13 # [NETFILTER]: Fix icmp_reply_translation args. # -------------------------------------------- # 03/05/08 davem@nuts.ninka.net 1.1063.14.14 # [MPLS]: Add MPLS support to PPP. # -------------------------------------------- # 03/05/08 maxk@qualcomm.com 1.1063.11.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.18.1 # Merge bk://linux.bkbits.net/linux-2.5 # into qualcomm.com:/home/kernel/bt-2.5 # -------------------------------------------- # 03/05/08 davem@nuts.ninka.net 1.1063.14.15 # [SKFDDI]: Use SET_MODULE_OWNER. # -------------------------------------------- # 03/05/08 davem@nuts.ninka.net 1.1063.14.16 # [IPV6]: Pass route attributes all the way down. # -------------------------------------------- # 03/05/08 davidm@tiger.hpl.hp.com 1.1063.7.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.14.17 # [IPSEC]: Use xfrm_state_put in pfkey_msg2xfrm_state. # -------------------------------------------- # 03/05/08 chas@cmf.nrl.navy.mil 1.1063.14.18 # [ATM]: Make he driver code more palatable. # -------------------------------------------- # 03/05/08 davem@nuts.ninka.net 1.1063.14.19 # [NETFILTER]: Fix ip_nat_core.c:manip_pkt return value checks. # -------------------------------------------- # 03/05/08 willy@debian.org 1.1063.14.20 # [DLCI]: Use module_init and fix ioctl handling. # -------------------------------------------- # 03/05/08 ak@muc.de 1.1063.14.21 # [NET]: Clean up socket filter compat handling. # -------------------------------------------- # 03/05/09 nfsclient.adm@hostme.bitkeeper.com 1.1063.1.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.114.18 # [AGPGART] Remove duplicate copying of ->chipset in agp_copy_info() # -------------------------------------------- # 03/05/09 davem@nuts.ninka.net 1.1063.19.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.19.2 # [MAINTAINERS/CREDITS]: Add entries for USAGI hackers. # -------------------------------------------- # 03/05/09 jmorris@intercode.com.au 1.1063.19.3 # [XFRM]: Make use of xfrm_state_hold(). # -------------------------------------------- # 03/05/09 jmorris@intercode.com.au 1.1063.19.4 # [XFRM]: Use xfrm_pol_hold(). # -------------------------------------------- # 03/05/09 hch@lst.de 1.1063.19.5 # [NET]: Switch x25_asy over to initcalls. # -------------------------------------------- # 03/05/09 davem@nuts.ninka.net 1.1063.19.6 # [XFRM]: Fix typos in xfrm_state_put() changes. # -------------------------------------------- # 03/05/09 marcel@holtmann.org 1.1042.45.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.45.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.20.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.19.7 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into penguin.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/09 maxk@qualcomm.com 1.1063.18.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.21.1 # [PATCH] i2c: add i2c_adapter class support # -------------------------------------------- # 03/05/09 mark@alpha.dyndns.org 1.1063.21.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.19.8 # Annotate LDT system calls with user pointer annotations. # -------------------------------------------- # 03/05/09 torvalds@penguin.transmeta.com 1.1063.19.9 # Annotate x86 system calls with user pointer annotations. # -------------------------------------------- # 03/05/09 torvalds@penguin.transmeta.com 1.1063.19.10 # Fix mismatch between i387 user copy function declaration and # definition. # -------------------------------------------- # 03/05/09 torvalds@penguin.transmeta.com 1.1063.19.11 # Annotate IPC system calls with user pointer annotations # -------------------------------------------- # 03/05/09 torvalds@penguin.transmeta.com 1.1063.19.12 # Annotate vm86_info as a pointer to user space. # -------------------------------------------- # 03/05/09 warp@mercury.d2dc.net 1.1063.21.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.21.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.21.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.21.6 # [PATCH] i2c: register the i2c_adapter_driver so things link up properly in sysfs # -------------------------------------------- # 03/05/09 greg@kroah.com 1.1063.19.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.7.5 # [PATCH] ia64: enable 1G hugepage size for Mckinley # # -------------------------------------------- # 03/05/09 corbet@lwn.net 1.1063.22.1 # [PATCH] cpufreq class fix # -------------------------------------------- # 03/05/09 greg@kroah.com 1.1063.22.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.22.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.18.3 # [Bluetooth] Detect and log error condition when first L2CAP fragment is too long. # -------------------------------------------- # 03/05/09 vandrove@vc.cvut.cz 1.1063.23.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.18.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.18.5 # [Bluetooth] RFCOMM must wait for MSC exchange to complete before sending data. # -------------------------------------------- # 03/05/09 greg@kroah.com 1.1063.19.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.22.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.23.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.114.19 # [AGPGART] death of generic-3.0.c = folded into generic.c # -------------------------------------------- # 03/05/10 davej@codemonkey.org.uk 1.1042.114.20 # [AGPGART] Add proper AGP3 initialisation routine. # -------------------------------------------- # 03/05/10 davej@codemonkey.org.uk 1.1042.114.21 # [AGPGART] Make sure we don't poke reserved bits when enabling agp v3 # -------------------------------------------- # 03/05/10 davej@codemonkey.org.uk 1.1042.114.22 # [AGPGART] Add missing #defines from last checkin. # -------------------------------------------- # 03/05/10 davej@codemonkey.org.uk 1.1042.114.23 # [AGPGART] Use symbolic defines for isoch registers in isoch code. # -------------------------------------------- # 03/05/10 davej@codemonkey.org.uk 1.1042.114.24 # [AGPGART] CodingStyle nitpicks for isoch.c # -------------------------------------------- # 03/05/10 davidm@tiger.hpl.hp.com 1.1063.7.6 # ia64: Prepare for GCC v3.4. Sync with 2.5.69. # -------------------------------------------- # 03/05/10 davidm@tiger.hpl.hp.com 1.1063.7.7 # ia64: Patch by John Marvin: Add virtual mem-map support. # -------------------------------------------- # 03/05/10 davem@nuts.ninka.net 1.1063.24.1 # [TCP]: NULL out newsk->owner in tcp_create_openreq_child(). # -------------------------------------------- # 03/05/10 jgarzik@redhat.com 1.1063.24.2 # [SCTP]: Fix missing Kconfig dependency. # -------------------------------------------- # 03/05/10 shemminger@osdl.org 1.1063.24.3 # [IPV4/IPV6]: inetsw using RCU. # -------------------------------------------- # 03/05/10 yoshfuji@linux-ipv6.org 1.1063.24.4 # [IPV6]: Convert /proc/net/raw6 to seq_file. # -------------------------------------------- # 03/05/10 davej@codemonkey.org.uk 1.1042.114.25 # [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.24.5 # [ATM]: HE and IPHASE driver fixes. # -------------------------------------------- # 03/05/10 yoshfuji@linux-ipv6.org 1.1063.24.6 # [NET]: Set file_operations->owner as appropriate. # -------------------------------------------- # 03/05/10 davem@nuts.ninka.net 1.1063.24.7 # [VLAN]: vlanproc.c needs module.h # -------------------------------------------- # 03/05/10 torvalds@home.transmeta.com 1.1063.19.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.19.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.19.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.19.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.19.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.19.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.19.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.1.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.19.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.19.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.19.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.19.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.19.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.19.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.19.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.19.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.25.1 # [bk] add useful tip to bk kernel howto # # Kudos to Wayne Scott @ BitMover for this. # -------------------------------------------- # 03/05/11 axboe@suse.de 1.1063.19.30 # [PATCH] Proper 48-bit lba support # -------------------------------------------- # 03/05/11 torvalds@home.transmeta.com 1.1063.19.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.19.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.19.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.19.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.1.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.1.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.26.1 # [ALPHA] Fix titan_intr_nop for 2.5 irq api changes. # -------------------------------------------- # 03/05/11 davem@nuts.ninka.net 1.1063.27.1 # [IPV4/IPV6]; Missing schedule_net() in inet{,6}_del_protocol. # -------------------------------------------- # 03/05/11 davem@nuts.ninka.net 1.1063.27.2 # [NETFILTER]: Fix stale skb data pointer usage in ipv4 NAT. # -------------------------------------------- # 03/05/11 davem@kernel.bkbits.net 1.1063.1.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.114.26 # [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.28.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.29.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.27.3 # [IPV6]: Missing sk->family check in UDPv6 multicast handling. # -------------------------------------------- # 03/05/11 davem@kernel.bkbits.net 1.1063.1.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.1.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.1.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.1.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.1.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.1.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.30.1 # [NETFILTER]: Move ip_fw declarations into header file. # -------------------------------------------- # 03/05/11 zaitcev@redhat.com 1.1063.31.1 # [SPARC]: Fix shadowing of global max_pfn, kill BOOTMEM_DEBUG. # -------------------------------------------- # 03/05/11 zaitcev@redhat.com 1.1063.31.2 # [SPARC]: Allow esp to use highmem_io on sparc32. # -------------------------------------------- # 03/05/11 zaitcev@redhat.com 1.1063.31.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.1.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 davej@codemonkey.org.uk 1.1063.28.2 # [DRM] Intel i8xx DRM modules are dependant on their AGP counterparts. # Closes bugzilla #646 # -------------------------------------------- # 03/05/12 davej@tetrachloride.(none) 1.1063.32.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.1.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.1.34 # Add user pointer annotations. # -------------------------------------------- # 03/05/12 torvalds@penguin.transmeta.com 1.1063.1.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.1.36 # Add user pointer annotations to core sysctl files. # -------------------------------------------- # 03/05/12 maxk@qualcomm.com 1.1063.33.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.34.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.34.2 # [BRIDGE]: Bridge timer performance enhancement. # -------------------------------------------- # 03/05/12 shemminger@osdl.org 1.1063.34.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.34.4 # [BRLOCK]: Kill big reader locks, no longer used. # -------------------------------------------- # 03/05/12 shemminger@osdl.org 1.1063.34.5 # [IPV4/IPV6]: synchronize_kernel --> synchronize_net. # -------------------------------------------- # 03/05/12 davem@nuts.ninka.net 1.1063.34.6 # [BRLOCK]: Kill stray brlock.h references in sparc/sparc64 headers. # -------------------------------------------- # 03/05/12 jmorris@intercode.com.au 1.1063.34.7 # [IPSEC]: Implement proper IPIP tunnel handling for IPcomp. # -------------------------------------------- # 03/05/12 jmorris@intercode.com.au 1.1063.34.8 # [CRYPTO]: Fix config dependencies. # -------------------------------------------- # 03/05/12 kazunori@miyazawa.org 1.1063.34.9 # [IPV4]: Introduce ip6_append_data. # -------------------------------------------- # 03/05/12 torvalds@penguin.transmeta.com 1.1063.1.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.1.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.34.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.1.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 bunk@fs.tum.de 1.1063.34.11 # [NET]: wireless.c needs module.h # -------------------------------------------- # 03/05/12 davem@nuts.ninka.net 1.1063.34.12 # [NETFILTER]: ip_ct_gather_frags no longer needs to linearize. # -------------------------------------------- # 03/05/12 davem@nuts.ninka.net 1.1063.34.13 # [PKT_SCHED]: sch_ingress.c does not need to linearize SKBs. # -------------------------------------------- # 03/05/12 rmk@flint.arm.linux.org.uk 1.1063.35.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.36.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/13 rmk@flint.arm.linux.org.uk 1.1063.29.2 # [ARM] Update a variety of ARM drivers to use irqreturn_t. # -------------------------------------------- # 03/05/12 torvalds@home.transmeta.com 1.1063.37.1 # Add user pointer annotations to mtrr driver. # -------------------------------------------- # 03/05/12 torvalds@home.transmeta.com 1.1063.37.2 # Fix do_utimes() user pointer annotations. # -------------------------------------------- # 03/05/12 torvalds@home.transmeta.com 1.1063.37.3 # Make sys_open() declaration match definition. # -------------------------------------------- # 03/05/12 torvalds@home.transmeta.com 1.1063.37.4 # Don't use undefined preprocessor symbols in expressions. # -------------------------------------------- # 03/05/12 torvalds@home.transmeta.com 1.1063.36.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.1.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.1.41 # o wanrouter: add missing include module.h # -------------------------------------------- # 03/05/12 elenstev@mesatop.com 1.1063.38.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.38.2 # [RXRPC]: Put file_operations THIS_OWNER in correct place. # -------------------------------------------- # 03/05/12 davem@nuts.ninka.net 1.1063.1.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.1.43 # [NET]: nonet.c needs module.h # -------------------------------------------- # 03/05/12 acme@conectiva.com.br 1.1063.1.44 # [IPV4/IPV6]: Consolidate saddr resetting into inet_reset_saddr(). # -------------------------------------------- # 03/05/12 kaber@trash.net 1.1063.1.45 # [XFRM]: Fix typo in __xfrm4_find_acq. # -------------------------------------------- # 03/05/12 elenstev@mesatop.com 1.1063.39.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.39.2 # Remove extraneous NO_MATCH # -------------------------------------------- # 03/05/12 torvalds@home.transmeta.com 1.1063.39.3 # Fix broken aic7xxx preprocessor conditional (that's not how # C preprocessor expressions work, guys!) # -------------------------------------------- # 03/05/12 torvalds@home.transmeta.com 1.1063.1.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.1.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.1.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.1.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.1.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.1.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.1.52 # [PATCH] fix pnp_test_handler return # # It looks like I guessed wrong on this one. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.1.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.1.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.1.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.1.56 # [PATCH] small cleanup for __rmqueue # # From: Zwane Mwaikambo # # Removes an extra initialisation and general nitpicking. # -------------------------------------------- # 03/05/12 akpm@digeo.com 1.1063.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.1.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.29.3 # [ARM] Allow CONFIG_PM to be enabled on all ARM platforms # -------------------------------------------- # 03/05/13 nico@org.rmk.(none) 1.1063.29.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.29.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.29.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.29.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.29.8 # [ARM] Add prefetch support for ARMv5. # -------------------------------------------- # 03/05/13 rmk@flint.arm.linux.org.uk 1.1063.29.9 # [ARM] Fix test_bit to return 0 or 1. # -------------------------------------------- # 03/05/13 rmk@flint.arm.linux.org.uk 1.1063.29.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.29.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 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.29.12 # [ARM] Convert more structure initialisers to C99 syntax. # -------------------------------------------- # 03/05/13 greg@kroah.com 1.1093.2.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.2.2 # [PATCH] USB: patch to fix up coding style violations # -------------------------------------------- # 03/05/13 david-b@pacbell.net 1.1093.2.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.2.4 # [PATCH] USB: another usb storage addition # -------------------------------------------- # 03/05/13 david-b@pacbell.net 1.1093.2.5 # [PATCH] USB: fix for multiple definition of `usb_gadget_get_string' # -------------------------------------------- # 03/05/13 david-b@pacbell.net 1.1093.2.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.2.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.2.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.2.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 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.3.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 vojtech@suse.cz 1.1093.2.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 davem@nuts.ninka.net 1.1093.4.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.5.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 torvalds@penguin.transmeta.com 1.1113.1.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.1.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.2.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.2.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.2.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.2.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.1.3 # Merge home:v2.5/linux # into penguin.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/05/14 axboe@suse.de 1.1113.1.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.2.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.3.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.4.1 # [AF_KEY]: Force km.state to XFRM_STATE_DEAD in pfkey_msg2xfrm_state. # -------------------------------------------- # 03/05/14 kaber@trash.net 1.1113.4.2 # [NET]: Fix two bogus kfree(skb). # -------------------------------------------- # 03/05/14 torvalds@home.transmeta.com 1.1113.1.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.4.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.1.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.1.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.1.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.1.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.1.10 # [PATCH] sx memleak. # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.1.11 # [PATCH] Fix ISDN return types. # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.1.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.1.13 # [PATCH] pcwatchdog firmware memory leak # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.1.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.1.15 # [PATCH] ASUS P4B SMBus quirks. # # From Dominik Brodowski, comments says it all.. # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.1.16 # [PATCH] typo # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.1.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.1.18 # [PATCH] copy_to_user check for sgiserial # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.1.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.1.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.1.21 # [PATCH] byte counters for mkiss # # From 2.4 from way back 13 months ago.. # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.1.22 # [PATCH] shorten rclan debug output # # From 2.4 long long ago. # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.1.23 # [PATCH] i810 no codec fix. # # Syncs up with 2.4 # -------------------------------------------- # 03/05/14 davej@codemonkey.org.uk 1.1113.1.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 akpm@digeo.com 1.1128 # [PATCH] ipmi warning fixes # # CPU flags are unsigned long. # -------------------------------------------- # 03/05/15 akpm@digeo.com 1.1129 # [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.1130 # [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.1131 # [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.1132 # [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.1133 # [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.1134 # [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.1135 # [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.1136 # [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.1137 # [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.1138 # [PATCH] miropcm20-rds.c build fix # # It needs fs.h for struct inode. # -------------------------------------------- # 03/05/15 akpm@digeo.com 1.1139 # [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.1140 # [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.1141 # [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.1142 # [PATCH] visws: fix for generic-subarch # # From: Andy Wihitcroft # # The generic-subarch patch broke visws builds. # -------------------------------------------- # 03/05/15 akpm@digeo.com 1.1143 # [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 akpm@digeo.com 1.1144 # [PATCH] Allow architecture to overwrite stack flags # # This is a bit neater. # -------------------------------------------- # diff -Nru a/CREDITS b/CREDITS --- a/CREDITS Thu May 15 15:24:41 2003 +++ b/CREDITS Thu May 15 15:24:41 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 Thu May 15 15:24:39 2003 +++ b/Documentation/BK-usage/bk-kernel-howto.txt Thu May 15 15:24:39 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 Thu May 15 15:24:44 2003 +++ b/Documentation/Changes Thu May 15 15:24:44 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/scsi/aic79xx.txt b/Documentation/scsi/aic79xx.txt --- a/Documentation/scsi/aic79xx.txt Thu May 15 15:24:41 2003 +++ b/Documentation/scsi/aic79xx.txt Thu May 15 15:24:41 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 Thu May 15 15:24:35 2003 +++ b/Documentation/scsi/aic7xxx.txt Thu May 15 15:24:35 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/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS Thu May 15 15:24:40 2003 +++ b/MAINTAINERS Thu May 15 15:24:40 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 Thu May 15 15:24:41 2003 +++ b/Makefile Thu May 15 15:24:41 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 Thu May 15 15:24:33 2003 +++ b/arch/alpha/kernel/core_marvel.c Thu May 15 15:24:33 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, diff -Nru a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S --- a/arch/alpha/kernel/entry.S Thu May 15 15:24:32 2003 +++ b/arch/alpha/kernel/entry.S Thu May 15 15:24:32 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 Thu May 15 15:24:42 2003 +++ b/arch/alpha/kernel/irq.c Thu May 15 15:24:42 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 Thu May 15 15:24:33 2003 +++ b/arch/alpha/kernel/module.c Thu May 15 15:24:33 2003 @@ -300,3 +300,8 @@ { return 0; } + +void +module_arch_cleanup(struct module *mod) +{ +} diff -Nru a/arch/alpha/kernel/sys_titan.c b/arch/alpha/kernel/sys_titan.c --- a/arch/alpha/kernel/sys_titan.c Thu May 15 15:24:44 2003 +++ b/arch/alpha/kernel/sys_titan.c Thu May 15 15:24:44 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 Thu May 15 15:24:44 2003 +++ b/arch/arm/common/sa1111.c Thu May 15 15:24:44 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 Thu May 15 15:24:34 2003 +++ b/arch/arm/kernel/asm-offsets.c Thu May 15 15:24:34 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 Thu May 15 15:24:46 2003 +++ b/arch/arm/kernel/calls.S Thu May 15 15:24:46 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 Thu May 15 15:24:36 2003 +++ b/arch/arm/kernel/entry-armv.S Thu May 15 15:24:36 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 Thu May 15 15:24:32 2003 +++ b/arch/arm/kernel/irq.c Thu May 15 15:24:32 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 Thu May 15 15:24:33 2003 +++ b/arch/arm/kernel/module.c Thu May 15 15:24:33 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 Thu May 15 15:24:46 2003 +++ b/arch/arm/kernel/pm.c Thu May 15 15:24:46 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 Thu May 15 15:24:33 2003 +++ b/arch/arm/kernel/ptrace.c Thu May 15 15:24:33 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/traps.c b/arch/arm/kernel/traps.c --- a/arch/arm/kernel/traps.c Thu May 15 15:24:37 2003 +++ b/arch/arm/kernel/traps.c Thu May 15 15:24:37 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 Thu May 15 15:24:39 2003 +++ b/arch/arm/lib/copy_page.S Thu May 15 15:24:39 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 Thu May 15 15:24:46 2003 +++ b/arch/arm/mach-footbridge/dc21285.c Thu May 15 15:24:46 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 Thu May 15 15:24:46 2003 +++ b/arch/arm/mach-integrator/mm.c Thu May 15 15:24:46 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 Thu May 15 15:24:43 2003 +++ b/arch/arm/mach-pxa/irq.c Thu May 15 15:24:43 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 Thu May 15 15:24:37 2003 +++ b/arch/arm/mach-pxa/lubbock.c Thu May 15 15:24:37 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 Thu May 15 15:24:46 2003 +++ b/arch/arm/mach-rpc/dma.c Thu May 15 15:24:46 2003 @@ -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,7 +93,7 @@ status = iomd_readb(base + ST); if (!(status & DMA_ST_INT)) - return; + return IRQ_HANDLED; if (status & DMA_ST_OFL && !dma->sg) break; @@ -117,6 +117,8 @@ iomd_writeb(0, dma->dma_base + CR); disable_irq(irq); + + return IRQ_HANDLED; } static int iomd_request_dma(dmach_t channel, dma_t *dma) diff -Nru a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c --- a/arch/arm/mm/consistent.c Thu May 15 15:24:42 2003 +++ b/arch/arm/mm/consistent.c Thu May 15 15:24:42 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 Thu May 15 15:24:38 2003 +++ b/arch/arm/tools/mach-types Thu May 15 15:24:38 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 Thu May 15 15:24:37 2003 +++ b/arch/cris/drivers/eeprom.c Thu May 15 15:24:37 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 Thu May 15 15:24:34 2003 +++ b/arch/i386/Kconfig Thu May 15 15:24:34 2003 @@ -65,19 +65,16 @@ config X86_SUMMIT bool "Summit/EXA (IBM x440)" + depends on SMP help This option is needed for IBM systems that use the Summit/EXA chipset. In particular, it is needed for the x440. If you don't have one of these computers, you should say N here. -config ACPI_SRAT - bool - default y - depends on NUMA && X86_SUMMIT - config X86_BIGSMP bool "Support for other sub-arch SMP systems with more than 8 CPUs" + depends on SMP help This option is needed for the systems that have more than 8 CPUs and if the system is not of any sub-arch type above. @@ -95,8 +92,24 @@ A kernel compiled for the Visual Workstation will not run on PCs and vice versa. See for details. +config X86_GENERICARCH + bool "Generic architecture (Summit, bigsmp, default)" + depends on SMP + help + This option compiles in the Summit, bigsmp, default subarchitectures. + It is intended for a generic binary kernel. + endchoice +config ACPI_SRAT + bool + default y + depends on NUMA && (X86_SUMMIT || X86_GENERICARCH) + +config X86_CYCLONE_TIMER + bool + default y + depends on X86_SUMMIT || X86_GENERICARCH choice prompt "Processor family" @@ -666,7 +679,7 @@ # Common NUMA Features config NUMA bool "Numa Memory Allocation Support" - depends on SMP && HIGHMEM64G && (X86_PC || X86_NUMAQ || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY)) + depends on SMP && HIGHMEM64G && (X86_PC || X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY)) default n if X86_PC default y if (X86_NUMAQ || X86_SUMMIT) @@ -764,7 +777,7 @@ # Summit needs it only when NUMA is on config BOOT_IOREMAP bool - depends on (X86_SUMMIT && NUMA) + depends on ((X86_SUMMIT || X86_GENERICARCH) && NUMA) default y endmenu diff -Nru a/arch/i386/Makefile b/arch/i386/Makefile --- a/arch/i386/Makefile Thu May 15 15:24:36 2003 +++ b/arch/i386/Makefile Thu May 15 15:24:36 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 Thu May 15 15:24:34 2003 +++ b/arch/i386/kernel/Makefile Thu May 15 15:24:34 2003 @@ -17,7 +17,7 @@ obj-$(CONFIG_X86_MSR) += msr.o obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_MICROCODE) += microcode.o -obj-$(CONFIG_APM) += apm.o +obj-$(CONFIG_APM) += apm.o suspend.o obj-$(CONFIG_X86_SMP) += smp.o smpboot.o obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o obj-$(CONFIG_X86_MPPARSE) += mpparse.o diff -Nru a/arch/i386/kernel/acpi/sleep.c b/arch/i386/kernel/acpi/sleep.c --- a/arch/i386/kernel/acpi/sleep.c Thu May 15 15:24:38 2003 +++ b/arch/i386/kernel/acpi/sleep.c Thu May 15 15:24:38 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 Thu May 15 15:24:33 2003 +++ b/arch/i386/kernel/apm.c Thu May 15 15:24:33 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); 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 Thu May 15 15:24:38 2003 +++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c Thu May 15 15:24:38 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 Thu May 15 15:24:33 2003 +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c Thu May 15 15:24:33 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 Thu May 15 15:24:44 2003 +++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c Thu May 15 15:24:44 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 Thu May 15 15:24:33 2003 +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c Thu May 15 15:24:33 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 Thu May 15 15:24:35 2003 +++ b/arch/i386/kernel/cpu/mtrr/if.c Thu May 15 15:24:35 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 Thu May 15 15:24:37 2003 +++ b/arch/i386/kernel/dmi_scan.c Thu May 15 15:24:37 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/head.S b/arch/i386/kernel/head.S --- a/arch/i386/kernel/head.S Thu May 15 15:24:33 2003 +++ b/arch/i386/kernel/head.S Thu May 15 15:24:33 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 Thu May 15 15:24:46 2003 +++ b/arch/i386/kernel/i386_ksyms.c Thu May 15 15:24:46 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 Thu May 15 15:24:44 2003 +++ b/arch/i386/kernel/i8259.c Thu May 15 15:24:44 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 Thu May 15 15:24:36 2003 +++ b/arch/i386/kernel/io_apic.c Thu May 15 15:24:36 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 Thu May 15 15:24:38 2003 +++ b/arch/i386/kernel/ioport.c Thu May 15 15:24:38 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 Thu May 15 15:24:33 2003 +++ b/arch/i386/kernel/irq.c Thu May 15 15:24:33 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 Thu May 15 15:24:41 2003 +++ b/arch/i386/kernel/ldt.c Thu May 15 15:24:41 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 Thu May 15 15:24:38 2003 +++ b/arch/i386/kernel/module.c Thu May 15 15:24:38 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 Thu May 15 15:24:36 2003 +++ b/arch/i386/kernel/mpparse.c Thu May 15 15:24:36 2003 @@ -73,7 +73,9 @@ /* Bitmask of physically existing CPUs */ unsigned long phys_cpu_present_map; +#ifndef CONFIG_X86_GENERICARCH int x86_summit = 0; +#endif u8 bios_cpu_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID }; /* diff -Nru a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c --- a/arch/i386/kernel/msr.c Thu May 15 15:24:37 2003 +++ b/arch/i386/kernel/msr.c Thu May 15 15:24:37 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 Thu May 15 15:24:32 2003 +++ b/arch/i386/kernel/process.c Thu May 15 15:24:32 2003 @@ -529,12 +529,12 @@ 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); diff -Nru a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c --- a/arch/i386/kernel/ptrace.c Thu May 15 15:24:35 2003 +++ b/arch/i386/kernel/ptrace.c Thu May 15 15:24:35 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 Thu May 15 15:24:35 2003 +++ b/arch/i386/kernel/reboot.c Thu May 15 15:24:35 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 Thu May 15 15:24:38 2003 +++ b/arch/i386/kernel/setup.c Thu May 15 15:24:38 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; @@ -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 Thu May 15 15:24:38 2003 +++ b/arch/i386/kernel/signal.c Thu May 15 15:24:38 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 Thu May 15 15:24:33 2003 +++ b/arch/i386/kernel/smp.c Thu May 15 15:24:33 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 Thu May 15 15:24:38 2003 +++ b/arch/i386/kernel/smpboot.c Thu May 15 15:24:38 2003 @@ -1149,11 +1149,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 Thu May 15 15:24:42 2003 +++ b/arch/i386/kernel/suspend.c Thu May 15 15:24:42 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; diff -Nru a/arch/i386/kernel/suspend_asm.S b/arch/i386/kernel/suspend_asm.S --- a/arch/i386/kernel/suspend_asm.S Thu May 15 15:24:37 2003 +++ b/arch/i386/kernel/suspend_asm.S Thu May 15 15:24:37 2003 @@ -6,6 +6,28 @@ #include #include + .data +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 Thu May 15 15:24:45 2003 +++ b/arch/i386/kernel/sys_i386.c Thu May 15 15:24:45 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/timers/Makefile b/arch/i386/kernel/timers/Makefile --- a/arch/i386/kernel/timers/Makefile Thu May 15 15:24:32 2003 +++ b/arch/i386/kernel/timers/Makefile Thu May 15 15:24:32 2003 @@ -4,4 +4,4 @@ obj-y := timer.o timer_none.o timer_tsc.o timer_pit.o -obj-$(CONFIG_X86_SUMMIT) += timer_cyclone.o +obj-$(CONFIG_X86_CYCLONE_TIMER) += timer_cyclone.o diff -Nru a/arch/i386/kernel/timers/timer.c b/arch/i386/kernel/timers/timer.c --- a/arch/i386/kernel/timers/timer.c Thu May 15 15:24:45 2003 +++ b/arch/i386/kernel/timers/timer.c Thu May 15 15:24:45 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 Thu May 15 15:24:34 2003 +++ b/arch/i386/kernel/traps.c Thu May 15 15:24:34 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 Thu May 15 15:24:33 2003 +++ b/arch/i386/kernel/vm86.c Thu May 15 15:24:33 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 Thu May 15 15:24:32 2003 +++ b/arch/i386/lib/usercopy.c Thu May 15 15:24:32 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 Thu May 15 15:24:47 2003 @@ -0,0 +1,18 @@ +# +# Makefile for the generic architecture +# + +EXTRA_CFLAGS += -I../kernel + +obj-y := probe.o summit.o bigsmp.o default.o + + +# +# Makefile for the generic architecture +# + +EXTRA_CFLAGS += -I../kernel + +obj-y := probe.o summit.o bigsmp.o default.o + + diff -Nru a/arch/i386/mach-generic/bigsmp.c b/arch/i386/mach-generic/bigsmp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/mach-generic/bigsmp.c Thu May 15 15:24:47 2003 @@ -0,0 +1,23 @@ +/* + * APIC driver for "bigsmp" XAPIC machines with more than 8 virtual CPUs. + * Drives the local APIC in "clustered mode". + */ +#define APIC_DEFINITION 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int dmi_bigsmp; /* can be set by dmi scanners */ + +static __init int probe_bigsmp(void) +{ + return dmi_bigsmp; +} + +struct genapic apic_bigsmp = APIC_INIT("bigsmp", probe_bigsmp); diff -Nru a/arch/i386/mach-generic/default.c b/arch/i386/mach-generic/default.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/mach-generic/default.c Thu May 15 15:24:46 2003 @@ -0,0 +1,22 @@ +/* + * Default generic APIC driver. This handles upto 8 CPUs. + */ +#define APIC_DEFINITION 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* should be called last. */ +static __init int probe_default(void) +{ + return 1; +} + +struct genapic apic_default = APIC_INIT("default", probe_default); diff -Nru a/arch/i386/mach-generic/probe.c b/arch/i386/mach-generic/probe.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/mach-generic/probe.c Thu May 15 15:24:46 2003 @@ -0,0 +1,96 @@ +/* Copyright 2003 Andi Kleen, SuSE Labs. + * Subject to the GNU Public License, v.2 + * + * Generic x86 APIC driver probe layer. + */ +#include +#include +#include +#include +#include +#include +#include + +extern struct genapic apic_summit; +extern struct genapic apic_bigsmp; +extern struct genapic apic_default; + +struct genapic *genapic = &apic_default; + +struct genapic *apic_probe[] __initdata = { + &apic_summit, + &apic_bigsmp, + &apic_default, /* must be last */ + NULL, +}; + +void __init generic_apic_probe(char *command_line) +{ + char *s; + int i; + int changed = 0; + + s = strstr(command_line, "apic="); + if (s && (s == command_line || isspace(s[-1]))) { + char *p = strchr(s, ' '), old; + if (!p) + p = strchr(s, '\0'); + old = *p; + *p = 0; + for (i = 0; !changed && apic_probe[i]; i++) { + if (!strcmp(apic_probe[i]->name, s+5)) { + changed = 1; + genapic = apic_probe[i]; + } + } + if (!changed) + printk(KERN_ERR "Unknown genapic `%s' specified.\n", s); + *p = old; + } + for (i = 0; !changed && apic_probe[i]; i++) { + if (apic_probe[i]->probe()) { + changed = 1; + genapic = apic_probe[i]; + } + } + /* Not visible without early console */ + if (!changed) + panic("Didn't find an APIC driver"); + + printk(KERN_INFO "Using APIC driver %s\n", genapic->name); +} + +/* These functions can switch the APIC even after the initial ->probe() */ + +int __init mps_oem_check(struct mp_config_table *mpc, char *oem, char *productid) +{ + int i; + for (i = 0; apic_probe[i]; ++i) { + if (apic_probe[i]->mps_oem_check(mpc,oem,productid)) { + genapic = apic_probe[i]; + printk(KERN_INFO "Switched to APIC driver `%s'.\n", + genapic->name); + return 1; + } + } + return 0; +} + +int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + int i; + for (i = 0; apic_probe[i]; ++i) { + if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) { + genapic = apic_probe[i]; + printk(KERN_INFO "Switched to APIC driver `%s'.\n", + genapic->name); + return 1; + } + } + return 0; +} + +int hard_smp_processor_id(void) +{ + return genapic->get_apic_id(*(unsigned long *)(APIC_BASE+APIC_ID)); +} diff -Nru a/arch/i386/mach-generic/summit.c b/arch/i386/mach-generic/summit.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/mach-generic/summit.c Thu May 15 15:24:47 2003 @@ -0,0 +1,22 @@ +/* + * APIC driver for the IBM "Summit" chipset. + */ +#define APIC_DEFINITION 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static __init int probe_summit(void) +{ + /* probed later in mptable/ACPI hooks */ + return 0; +} + +struct genapic apic_summit = APIC_INIT("summit", probe_summit); diff -Nru a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c --- a/arch/i386/mm/fault.c Thu May 15 15:24:32 2003 +++ b/arch/i386/mm/fault.c Thu May 15 15:24:32 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 Thu May 15 15:24:39 2003 +++ b/arch/i386/mm/highmem.c Thu May 15 15:24:39 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 Thu May 15 15:24:44 2003 +++ b/arch/i386/mm/hugetlbpage.c Thu May 15 15:24:44 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 Thu May 15 15:24:42 2003 +++ b/arch/i386/mm/init.c Thu May 15 15:24:42 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 Thu May 15 15:24:35 2003 +++ b/arch/i386/mm/ioremap.c Thu May 15 15:24:35 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 Thu May 15 15:24:46 2003 +++ b/arch/i386/mm/pgtable.c Thu May 15 15:24:46 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 Thu May 15 15:24:39 2003 +++ b/arch/i386/oprofile/init.c Thu May 15 15:24:39 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 Thu May 15 15:24:34 2003 +++ b/arch/i386/vmlinux.lds.S Thu May 15 15:24:34 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 Thu May 15 15:24:45 2003 +++ b/arch/ia64/Kconfig Thu May 15 15:24:45 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 Thu May 15 15:24:33 2003 +++ b/arch/ia64/Makefile Thu May 15 15:24:33 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 Thu May 15 15:24:39 2003 +++ b/arch/ia64/dig/machvec.c Thu May 15 15:24:39 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 Thu May 15 15:24:34 2003 +++ b/arch/ia64/hp/common/sba_iommu.c Thu May 15 15:24:34 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 Thu May 15 15:24:43 2003 +++ b/arch/ia64/hp/sim/hpsim_console.c Thu May 15 15:24:43 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 Thu May 15 15:24:39 2003 +++ b/arch/ia64/hp/sim/hpsim_machvec.c Thu May 15 15:24:39 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 Thu May 15 15:24:40 2003 +++ b/arch/ia64/hp/sim/simeth.c Thu May 15 15:24:40 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 Thu May 15 15:24:38 2003 +++ b/arch/ia64/hp/sim/simscsi.c Thu May 15 15:24:38 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 Thu May 15 15:24:33 2003 +++ b/arch/ia64/hp/sim/simscsi.h Thu May 15 15:24:33 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 Thu May 15 15:24:38 2003 +++ b/arch/ia64/hp/sim/simserial.c Thu May 15 15:24:38 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 Thu May 15 15:24:45 2003 +++ b/arch/ia64/hp/zx1/Makefile Thu May 15 15:24:45 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 Thu May 15 15:24:37 2003 +++ b/arch/ia64/hp/zx1/hpzx1_machvec.c Thu May 15 15:24:37 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 Thu May 15 15:24:37 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 Thu May 15 15:24:44 2003 +++ b/arch/ia64/ia32/binfmt_elf32.c Thu May 15 15:24:44 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 Thu May 15 15:24:39 2003 +++ b/arch/ia64/ia32/ia32_entry.S Thu May 15 15:24:39 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 Thu May 15 15:24:41 2003 +++ b/arch/ia64/ia32/ia32_ioctl.c Thu May 15 15:24:41 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 Thu May 15 15:24:36 2003 +++ b/arch/ia64/ia32/ia32_traps.c Thu May 15 15:24:36 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 Thu May 15 15:24:40 2003 +++ b/arch/ia64/ia32/sys_ia32.c Thu May 15 15:24:40 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 Thu May 15 15:24:46 2003 +++ b/arch/ia64/kernel/Makefile Thu May 15 15:24:46 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 Thu May 15 15:24:46 2003 +++ b/arch/ia64/kernel/acpi-ext.c Thu May 15 15:24:46 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 Thu May 15 15:24:38 2003 +++ b/arch/ia64/kernel/acpi.c Thu May 15 15:24:38 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 Thu May 15 15:24:42 2003 +++ b/arch/ia64/kernel/brl_emu.c Thu May 15 15:24:42 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 Thu May 15 15:24:33 2003 +++ b/arch/ia64/kernel/efi.c Thu May 15 15:24:33 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 Thu May 15 15:24:38 2003 +++ b/arch/ia64/kernel/efivars.c Thu May 15 15:24:38 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 Thu May 15 15:24:41 2003 +++ b/arch/ia64/kernel/head.S Thu May 15 15:24:41 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 Thu May 15 15:24:38 2003 +++ b/arch/ia64/kernel/ia64_ksyms.c Thu May 15 15:24:38 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 Thu May 15 15:24:38 2003 +++ b/arch/ia64/kernel/iosapic.c Thu May 15 15:24:38 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 Thu May 15 15:24:43 2003 +++ b/arch/ia64/kernel/irq.c Thu May 15 15:24:43 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 Thu May 15 15:24:37 2003 +++ b/arch/ia64/kernel/irq_ia64.c Thu May 15 15:24:37 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 Thu May 15 15:24:38 2003 +++ b/arch/ia64/kernel/machvec.c Thu May 15 15:24:38 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 Thu May 15 15:24:38 2003 +++ b/arch/ia64/kernel/mca.c Thu May 15 15:24:38 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 Thu May 15 15:24:44 2003 +++ b/arch/ia64/kernel/perfmon.c Thu May 15 15:24:44 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 Thu May 15 15:24:41 2003 +++ b/arch/ia64/kernel/perfmon_mckinley.h Thu May 15 15:24:41 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 Thu May 15 15:24:38 2003 +++ b/arch/ia64/kernel/process.c Thu May 15 15:24:38 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 Thu May 15 15:24:45 2003 +++ b/arch/ia64/kernel/ptrace.c Thu May 15 15:24:45 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 Thu May 15 15:24:45 2003 +++ b/arch/ia64/kernel/sal.c Thu May 15 15:24:45 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 Thu May 15 15:24:41 2003 +++ b/arch/ia64/kernel/salinfo.c Thu May 15 15:24:41 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 Thu May 15 15:24:34 2003 +++ b/arch/ia64/kernel/setup.c Thu May 15 15:24:34 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 Thu May 15 15:24:39 2003 +++ b/arch/ia64/kernel/signal.c Thu May 15 15:24:39 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 Thu May 15 15:24:45 2003 +++ b/arch/ia64/kernel/smp.c Thu May 15 15:24:45 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 Thu May 15 15:24:35 2003 +++ b/arch/ia64/kernel/smpboot.c Thu May 15 15:24:35 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 Thu May 15 15:24:34 2003 +++ b/arch/ia64/kernel/time.c Thu May 15 15:24:34 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 Thu May 15 15:24:34 2003 +++ b/arch/ia64/lib/copy_user.S Thu May 15 15:24:34 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 Thu May 15 15:24:34 2003 +++ b/arch/ia64/lib/do_csum.S Thu May 15 15:24:34 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 Thu May 15 15:24:32 2003 +++ b/arch/ia64/lib/io.c Thu May 15 15:24:32 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 Thu May 15 15:24:41 2003 +++ b/arch/ia64/lib/swiotlb.c Thu May 15 15:24:41 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 Thu May 15 15:24:45 2003 +++ b/arch/ia64/mm/fault.c Thu May 15 15:24:45 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 Thu May 15 15:24:39 2003 +++ b/arch/ia64/mm/hugetlbpage.c Thu May 15 15:24:39 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 Thu May 15 15:24:37 2003 +++ b/arch/ia64/mm/init.c Thu May 15 15:24:37 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 Thu May 15 15:24:38 2003 +++ b/arch/ia64/pci/pci.c Thu May 15 15:24:38 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 Thu May 15 15:24:39 2003 +++ b/arch/ia64/sn/kernel/machvec.c Thu May 15 15:24:39 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 Thu May 15 15:24:43 2003 +++ b/arch/ia64/tools/print_offsets.c Thu May 15 15:24:43 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 Thu May 15 15:24:33 2003 +++ b/arch/m68k/kernel/entry.S Thu May 15 15:24:33 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 Thu May 15 15:24:43 2003 +++ b/arch/m68k/sun3/prom/init.c Thu May 15 15:24:43 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 Thu May 15 15:24:33 2003 +++ b/arch/m68k/sun3/prom/printf.c Thu May 15 15:24:33 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 Thu May 15 15:24:43 2003 +++ b/arch/m68knommu/platform/5249/MOTOROLA/crt0_ram.S Thu May 15 15:24:43 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 Thu May 15 15:24:34 2003 +++ b/arch/mips/arc/misc.c Thu May 15 15:24:34 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 Thu May 15 15:24:36 2003 +++ b/arch/mips/au1000/common/serial.c Thu May 15 15:24:36 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 Thu May 15 15:24:41 2003 +++ b/arch/mips64/arc/misc.c Thu May 15 15:24:41 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 Thu May 15 15:24:44 2003 +++ b/arch/parisc/hpux/wrappers.S Thu May 15 15:24:44 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 Thu May 15 15:24:46 2003 +++ b/arch/parisc/kernel/module.c Thu May 15 15:24:46 2003 @@ -568,3 +568,7 @@ #endif return 0; } + +void module_arch_cleanup(struct module *mod) +{ +} diff -Nru a/arch/ppc/kernel/module.c b/arch/ppc/kernel/module.c --- a/arch/ppc/kernel/module.c Thu May 15 15:24:35 2003 +++ b/arch/ppc/kernel/module.c Thu May 15 15:24:35 2003 @@ -269,3 +269,7 @@ { return 0; } + +void module_arch_cleanup(struct module *mod) +{ +} diff -Nru a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c --- a/arch/ppc/kernel/process.c Thu May 15 15:24:38 2003 +++ b/arch/ppc/kernel/process.c Thu May 15 15:24:38 2003 @@ -524,7 +524,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 +534,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/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c --- a/arch/ppc64/kernel/LparData.c Thu May 15 15:24:35 2003 +++ b/arch/ppc64/kernel/LparData.c Thu May 15 15:24:35 2003 @@ -61,7 +61,7 @@ 0xc8a5d9c4, /* desc = "HvRD" ebcdic */ sizeof(struct HvReleaseData), offsetof(struct naca_struct, xItVpdAreas), - (struct naca_struct *)(KERNELBASE+0x4000), /* 64-bit Naca address */ + (struct naca_struct *)(NACA_VIRT_ADDR), /* 64-bit Naca address */ 0x6000, /* offset of LparMap within loadarea (see head.S) */ 0, 1, /* tags inactive */ diff -Nru a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile --- a/arch/ppc64/kernel/Makefile Thu May 15 15:24:45 2003 +++ b/arch/ppc64/kernel/Makefile Thu May 15 15:24:45 2003 @@ -15,7 +15,7 @@ iSeries_IoMmTable.o iSeries_irq.o \ iSeries_VpdInfo.o XmPciLpEvent.o \ HvCall.o HvLpConfig.o LparData.o mf_proc.o \ - proc_pmc.o iSeries_setup.o ItLpQueue.o hvCall.o \ + iSeries_setup.o ItLpQueue.o hvCall.o \ mf.o HvLpEvent.o iSeries_proc.o obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \ @@ -25,6 +25,7 @@ obj-y += open_pic.o xics.o pSeries_htab.o rtas.o \ chrp_setup.o i8259.o ras.o prom.o +obj-$(CONFIG_PROC_FS) += proc_ppc64.o obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o diff -Nru a/arch/ppc64/kernel/align.c b/arch/ppc64/kernel/align.c --- a/arch/ppc64/kernel/align.c Thu May 15 15:24:46 2003 +++ b/arch/ppc64/kernel/align.c Thu May 15 15:24:46 2003 @@ -237,7 +237,7 @@ dsisr = regs->dsisr; /* Power4 doesn't set DSISR for an alignment interrupt */ - if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) { + if (!cpu_alignexc_sets_dsisr()) { unsigned int real_instr; if (__get_user(real_instr, (unsigned int *)regs->nip)) return 0; @@ -309,6 +309,7 @@ /* Doing stfs, have to convert to single */ enable_kernel_fp(); cvt_df(¤t->thread.fpr[reg], (float *)&data.v[4], ¤t->thread.fpscr); + disable_kernel_fp(); } else data.dd = current->thread.fpr[reg]; @@ -342,6 +343,7 @@ /* Doing lfs, have to convert to double */ enable_kernel_fp(); cvt_fd((float *)&data.v[4], ¤t->thread.fpr[reg], ¤t->thread.fpscr); + disable_kernel_fp(); } else current->thread.fpr[reg] = data.dd; diff -Nru a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c --- a/arch/ppc64/kernel/asm-offsets.c Thu May 15 15:24:41 2003 +++ b/arch/ppc64/kernel/asm-offsets.c Thu May 15 15:24:41 2003 @@ -59,14 +59,14 @@ /* naca */ DEFINE(PACA, offsetof(struct naca_struct, paca)); - DEFINE(DCACHEL1LINESIZE, offsetof(struct naca_struct, dCacheL1LineSize)); + DEFINE(DCACHEL1LINESIZE, offsetof(struct systemcfg, dCacheL1LineSize)); DEFINE(DCACHEL1LOGLINESIZE, offsetof(struct naca_struct, dCacheL1LogLineSize)); DEFINE(DCACHEL1LINESPERPAGE, offsetof(struct naca_struct, dCacheL1LinesPerPage)); - DEFINE(ICACHEL1LINESIZE, offsetof(struct naca_struct, iCacheL1LineSize)); + DEFINE(ICACHEL1LINESIZE, offsetof(struct systemcfg, iCacheL1LineSize)); DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct naca_struct, iCacheL1LogLineSize)); DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct naca_struct, iCacheL1LinesPerPage)); DEFINE(SLBSIZE, offsetof(struct naca_struct, slb_size)); - DEFINE(PLATFORM, offsetof(struct naca_struct, platform)); + DEFINE(PLATFORM, offsetof(struct systemcfg, platform)); /* paca */ DEFINE(PACA_SIZE, sizeof(struct paca_struct)); diff -Nru a/arch/ppc64/kernel/chrp_setup.c b/arch/ppc64/kernel/chrp_setup.c --- a/arch/ppc64/kernel/chrp_setup.c Thu May 15 15:24:33 2003 +++ b/arch/ppc64/kernel/chrp_setup.c Thu May 15 15:24:33 2003 @@ -263,6 +263,8 @@ char *os; static int display_character, set_indicator; static int max_width; + static spinlock_t progress_lock = SPIN_LOCK_UNLOCKED; + static int pending_newline = 0; /* did last write end with unprinted newline? */ if (!rtas.base) return; @@ -278,34 +280,79 @@ display_character = rtas_token("display-character"); set_indicator = rtas_token("set-indicator"); } - if (display_character == RTAS_UNKNOWN_SERVICE) { - /* use hex display */ - if (set_indicator == RTAS_UNKNOWN_SERVICE) - return; - rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex); + + if(display_character == RTAS_UNKNOWN_SERVICE) { + /* use hex display if available */ + if(set_indicator != RTAS_UNKNOWN_SERVICE) + rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex); return; } - rtas_call(display_character, 1, 1, NULL, '\r'); + spin_lock(&progress_lock); + /* Last write ended with newline, but we didn't print it since + * it would just clear the bottom line of output. Print it now + * instead. + * + * If no newline is pending, print a CR to start output at the + * beginning of the line. + */ + if(pending_newline) { + rtas_call(display_character, 1, 1, NULL, '\r'); + rtas_call(display_character, 1, 1, NULL, '\n'); + pending_newline = 0; + } else + rtas_call(display_character, 1, 1, NULL, '\r'); + width = max_width; os = s; - while ( *os ) - { - if ( (*os == '\n') || (*os == '\r') ) + while (*os) { + if(*os == '\n' || *os == '\r') { + /* Blank to end of line. */ + while(width-- > 0) + rtas_call(display_character, 1, 1, NULL, ' '); + + /* If newline is the last character, save it + * until next call to avoid bumping up the + * display output. + */ + if(*os == '\n' && !os[1]) { + pending_newline = 1; + spin_unlock(&progress_lock); + return; + } + + /* RTAS wants CR-LF, not just LF */ + + if(*os == '\n') { + rtas_call(display_character, 1, 1, NULL, '\r'); + rtas_call(display_character, 1, 1, NULL, '\n'); + } else { + /* CR might be used to re-draw a line, so we'll + * leave it alone and not add LF. + */ + rtas_call(display_character, 1, 1, NULL, *os); + } + width = max_width; - else + } else { width--; - rtas_call(display_character, 1, 1, NULL, *os++ ); + rtas_call(display_character, 1, 1, NULL, *os); + } + + os++; + /* if we overwrite the screen length */ - if ( width == 0 ) + if ( width <= 0 ) while ( (*os != 0) && (*os != '\n') && (*os != '\r') ) os++; } - + /* Blank to end of line. */ while ( width-- > 0 ) rtas_call(display_character, 1, 1, NULL, ' ' ); + + spin_unlock(&progress_lock); } extern void setup_default_decr(void); diff -Nru a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S --- a/arch/ppc64/kernel/entry.S Thu May 15 15:24:33 2003 +++ b/arch/ppc64/kernel/entry.S Thu May 15 15:24:33 2003 @@ -225,10 +225,6 @@ bl .sys32_rt_sigreturn b 80f -_GLOBAL(ppc64_sigreturn) - bl .sys_sigreturn - b 80f - _GLOBAL(ppc64_rt_sigreturn) bl .sys_rt_sigreturn @@ -412,11 +408,6 @@ ld r4,GPR4(r1) ld r1,GPR1(r1) - /* - * What if we took an exception and stole this segment, we may - * fault on the above addresses and globber SRR0/1. Should check RI - * bit and repeat - Anton - */ rfid /* Note: this must change if we start using the TIF_NOTIFY_RESUME bit */ diff -Nru a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S --- a/arch/ppc64/kernel/head.S Thu May 15 15:24:39 2003 +++ b/arch/ppc64/kernel/head.S Thu May 15 15:24:39 2003 @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include #include @@ -49,8 +51,9 @@ * 0x0100 - 0x2fff : pSeries Interrupt prologs * 0x3000 - 0x3fff : Interrupt support * 0x4000 - 0x4fff : NACA - * 0x5000 - 0x5fff : Initial segment table + * 0x5000 - 0x5fff : SystemCfg * 0x6000 : iSeries and common interrupt prologs + * 0x9000 - 0x9fff : Initial segment table */ /* @@ -123,6 +126,10 @@ * All of it must fit below the first exception vector at 0x100. */ _GLOBAL(__secondary_hold) + mfmsr r24 + ori r24,r24,MSR_RI + mtmsrd r24 /* RI on */ + /* Grab our linux cpu number */ mr r24,r3 @@ -362,11 +369,11 @@ STD_EXCEPTION_PSERIES( 0x1300, InstructionBreakpoint ) /* Space for the naca. Architected to be located at real address - * 0x4000. Various tools rely on this location being fixed. + * NACA_PHYS_ADDR. Various tools rely on this location being fixed. * The first dword of the naca is required by iSeries LPAR to * point to itVpdAreas. On pSeries native, this value is not used. */ - . = 0x4000 + . = NACA_PHYS_ADDR .globl __end_interrupts .globl __start_naca __end_interrupts: @@ -380,21 +387,14 @@ .llong 0x0 .llong paca - /* - * Space for the initial segment table - * For LPAR, the hypervisor must fill in at least one entry - * before we get control (with relocate on) - */ - . = 0x5000 + . = SYSTEMCFG_PHYS_ADDR .globl __end_naca - .globl __start_stab + .globl __start_systemcfg __end_naca: -__start_stab: - - - . = 0x6000 - .globl __end_stab -__end_stab: +__start_systemcfg: + . = (SYSTEMCFG_PHYS_ADDR + PAGE_SIZE) + .globl __end_systemcfg +__end_systemcfg: #ifdef CONFIG_PPC_ISERIES /* @@ -408,7 +408,7 @@ .llong 1 /* # ESIDs to be mapped by hypervisor */ .llong 1 /* # memory ranges to be mapped by hypervisor */ - .llong 5 /* Page # of segment table within load area */ + .llong STAB0_PAGE /* Page # of segment table within load area */ .llong 0 /* Reserved */ .llong 0 /* Reserved */ .llong 0 /* Reserved */ @@ -529,6 +529,20 @@ MachineCheck_FWNMI: EXCEPTION_PROLOG_PSERIES(0x200, MachineCheck_common) + /* + * Space for the initial segment table + * For LPAR, the hypervisor must fill in at least one entry + * before we get control (with relocate on) + */ + . = STAB0_PHYS_ADDR + .globl __start_stab +__start_stab: + + . = (STAB0_PHYS_ADDR + PAGE_SIZE) + .globl __end_stab +__end_stab: + + /*** Common interrupt handlers ***/ STD_EXCEPTION_COMMON( 0x100, SystemReset, .SystemResetException ) @@ -782,11 +796,16 @@ FPUnavailable_common: EXCEPTION_PROLOG_COMMON bne .load_up_fpu /* if from user, just load it up */ - li r20,0 + addi r3,r1,STACK_FRAME_OVERHEAD +#ifdef DO_SOFT_DISABLE + ld r20,SOFTE(r1) +#else + rldicl r20,r23,49,63 /* copy EE bit from saved MSR */ +#endif li r6,0x800 - bl .save_remaining_regs /* if from kernel, take a trap */ - bl .KernelFP - b .ret_from_except + bl .save_remaining_regs + bl .KernelFPUnavailableException + BUG_OPCODE .globl SystemCall_common SystemCall_common: @@ -1032,7 +1051,7 @@ slbmfee r23,r22 rldicl r23,r23,37,63 cmpwi r23,0 - beq 3f /* Found an invalid entry */ + beq 4f /* Found an invalid entry */ addi r22,r22,1 cmpldi r22,64 @@ -1041,18 +1060,37 @@ /* No free entry - just take the next entry, round-robin */ /* XXX we should get the number of SLB entries from the naca */ SLB_NUM_ENTRIES = 64 - mfspr r21,SPRG3 +2: mfspr r21,SPRG3 ld r22,PACASTABRR(r21) addi r23,r22,1 cmpdi r23,SLB_NUM_ENTRIES - blt 2f + blt 3f li r23,1 -2: std r23,PACASTABRR(r21) +3: std r23,PACASTABRR(r21) /* r20 = vsid, r22 = entry */ -3: + + /* + * Never cast out the segment for our kernel stack. Since we + * dont invalidate the ERAT we could have a valid translation + * for the kernel stack during the first part of exception exit + * which gets invalidated due to a tlbie from another cpu at a + * non recoverable point (after setting srr0/1) - Anton + */ + slbmfee r23,r22 + srdi r23,r23,28 + /* + * This is incorrect (r1 is not the kernel stack) if we entered + * from userspace but there is no critical window from userspace + * so this should be OK. Also if we cast out the userspace stack + * segment while in userspace we will fault it straight back in. + */ + srdi r21,r1,28 + cmpd r21,r23 + beq- 2b + /* Put together the vsid portion of the entry. */ - li r21,0 +4: li r21,0 rldimi r21,r20,12,0 ori r20,r21,1024 ori r20,r20,128 /* set class bit for kernel region */ @@ -1060,17 +1098,6 @@ ori r20,r20,256 /* map kernel region with large ptes */ #endif - /* - * XXX we should handle this in the exception exit path in 2.5, - * we need to make this path quick - Anton - */ - /* Invalidate the old entry */ - slbmfee r21,r22 - lis r23,-2049 - ori r23,r23,65535 - and r21,r21,r23 - slbie r21 - /* Put together the esid portion of the entry. */ mfspr r21,DAR /* Get the new esid */ rldicl r21,r21,36,28 /* Permits a full 36b of ESID */ @@ -1252,9 +1279,12 @@ addi r2,r2,0x4000 addi r2,r2,0x4000 + LOADADDR(r9,systemcfg) + SET_REG_TO_CONST(r4, SYSTEMCFG_VIRT_ADDR) + std r4,0(r9) /* set the systemcfg pointer */ + LOADADDR(r9,naca) - SET_REG_TO_CONST(r4, KERNELBASE) - addi r4,r4,0x4000 + SET_REG_TO_CONST(r4, NACA_VIRT_ADDR) std r4,0(r9) /* set the naca pointer */ /* Get the pointer to the segment table */ @@ -1285,13 +1315,18 @@ /* Relocate the TOC from a virt addr to a real addr */ sub r2,r2,r3 + /* setup the systemcfg pointer which is needed by prom_init */ + LOADADDR(r9,systemcfg) + sub r9,r9,r3 /* addr of the variable systemcfg */ + SET_REG_TO_CONST(r4, SYSTEMCFG_VIRT_ADDR) + sub r4,r4,r3 + std r4,0(r9) /* set the value of systemcfg */ + /* setup the naca pointer which is needed by prom_init */ LOADADDR(r9,naca) sub r9,r9,r3 /* addr of the variable naca */ - - SET_REG_TO_CONST(r4, KERNELBASE) + SET_REG_TO_CONST(r4, NACA_VIRT_ADDR) sub r4,r4,r3 - addi r4,r4,0x4000 std r4,0(r9) /* set the value of naca */ /* DRENG / PPPBBB Fix the following comment!!! -Peter */ @@ -1410,11 +1445,13 @@ copy_to_here: /* + * load_up_fpu(unused, unused, tsk) * Disable FP for the task which had the FPU previously, * and save its floating-point registers in its thread_struct. * Enables the FPU for use in the kernel on return. * On SMP we know the fpu is free, since we give it up every - * switch. -- Cort + * switch (ie, no lazy save of the FP registers). + * On entry: r13 == 'current' && last_task_used_math != 'current' */ _STATIC(load_up_fpu) mfmsr r5 /* grab the current MSR */ @@ -1432,27 +1469,30 @@ ld r4,last_task_used_math@l(r3) cmpi 0,r4,0 beq 1f - addi r4,r4,THREAD /* want THREAD of last_task_used_math */ + /* Save FP state to last_task_used_math's THREAD struct */ + addi r4,r4,THREAD SAVE_32FPRS(0, r4) mffs fr0 stfd fr0,THREAD_FPSCR(r4) + /* Disable FP for last_task_used_math */ ld r5,PT_REGS(r4) ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) li r20,MSR_FP|MSR_FE0|MSR_FE1 - andc r4,r4,r20 /* disable FP for previous task */ + andc r4,r4,r20 std r4,_MSR-STACK_FRAME_OVERHEAD(r5) 1: #endif /* CONFIG_SMP */ /* enable use of FP after return */ ld r4,PACACURRENT(r13) addi r5,r4,THREAD /* Get THREAD */ - lwz r4,THREAD_FPEXC_MODE(r5) + ld r4,THREAD_FPEXC_MODE(r5) ori r23,r23,MSR_FP or r23,r23,r4 lfd fr0,THREAD_FPSCR(r5) mtfsf 0xff,fr0 REST_32FPRS(0, r5) #ifndef CONFIG_SMP + /* Update last_task_used_math to 'current' */ subi r4,r5,THREAD /* Back to 'current' */ std r4,last_task_used_math@l(r3) #endif /* CONFIG_SMP */ @@ -1460,19 +1500,16 @@ b fast_exception_return /* - * FP unavailable trap from kernel - print a message, but let - * the task use FP in the kernel until it returns to user mode. + * disable_kernel_fp() + * Disable the FPU. */ -_GLOBAL(KernelFP) - ld r3,_MSR(r1) - ori r3,r3,MSR_FP - std r3,_MSR(r1) /* enable use of FP after return */ - LOADADDR(r3,86f) - ld r4,PACACURRENT(r13) /* current */ - ld r5,_NIP(r1) - b .ret_from_except -86: .string "floating point used in kernel (task=%p, pc=%x)\n" - .align 4 +_GLOBAL(disable_kernel_fp) + mfmsr r3 + rldicl r0,r3,(63-MSR_FP_LG),1 + rldicl r3,r0,(MSR_FP_LG+1),0 + mtmsrd r3 /* disable use of fpu now */ + isync + blr /* * giveup_fpu(tsk) @@ -1562,8 +1599,8 @@ sc /* HvCall_setASR */ #else /* set the ASR */ - addi r3,0,0x4000 /* r3 = ptr to naca */ - lhz r3,PLATFORM(r3) /* r3 = platform flags */ + li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */ + lwz r3,PLATFORM(r3) /* r3 = platform flags */ cmpldi r3,PLATFORM_PSERIES_LPAR bne 98f mfspr r3,PVR @@ -1642,10 +1679,20 @@ bl .reloc_offset mr r26,r3 + mfmsr r6 + ori r6,r6,MSR_RI + mtmsrd r6 /* RI on */ + + /* setup the systemcfg pointer which is needed by *tab_initialize */ + LOADADDR(r6,systemcfg) + sub r6,r6,r26 /* addr of the variable systemcfg */ + li r27,SYSTEMCFG_PHYS_ADDR + std r27,0(r6) /* set the value of systemcfg */ + /* setup the naca pointer which is needed by *tab_initialize */ LOADADDR(r6,naca) sub r6,r6,r26 /* addr of the variable naca */ - li r27,0x4000 + li r27,NACA_PHYS_ADDR std r27,0(r6) /* set the value of naca */ #ifdef CONFIG_HMT @@ -1709,15 +1756,12 @@ sub r13,r13,r26 /* convert to physical addr */ mtspr SPRG3,r13 /* PPPBBB: Temp... -Peter */ - li r3,0x5000 - std r3,PACASTABREAL(r13) - LOADADDR(r24, __start_stab) - std r24,PACASTABVIRT(r13) + ld r3,PACASTABREAL(r13) ori r4,r3,1 /* turn on valid bit */ /* set the ASR */ - addi r3,0,0x4000 /* r3 = ptr to naca */ - lhz r3,PLATFORM(r3) /* r3 = platform flags */ + li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */ + lwz r3,PLATFORM(r3) /* r3 = platform flags */ cmpldi r3,PLATFORM_PSERIES_LPAR bne 98f mfspr r3,PVR @@ -1741,8 +1785,8 @@ bl .stab_initialize bl .htab_initialize - addi r3,0,0x4000 /* r3 = ptr to naca */ - lhz r3,PLATFORM(r3) /* r3 = platform flags */ + li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */ + lwz r3,PLATFORM(r3) /* r3 = platform flags */ cmpldi r3,PLATFORM_PSERIES bne 98f LOADADDR(r6,_SDR1) /* Only if NOT LPAR */ @@ -1791,11 +1835,14 @@ addi r2,r2,0x4000 addi r2,r2,0x4000 - /* setup the naca pointer */ - LOADADDR(r9,naca) + /* setup the systemcfg pointer */ + LOADADDR(r9,systemcfg) + SET_REG_TO_CONST(r8, SYSTEMCFG_VIRT_ADDR) + std r8,0(r9) - SET_REG_TO_CONST(r8, KERNELBASE) - addi r8,r8,0x4000 + /* setup the naca pointer */ + LOADADDR(r9,naca) + SET_REG_TO_CONST(r8, NACA_VIRT_ADDR) std r8,0(r9) /* set the value of the naca ptr */ LOADADDR(r26, boot_cpuid) @@ -1946,7 +1993,7 @@ hardware_int_paca0: .space 8*4096 -/* 1 page segment table per cpu (max 48) */ +/* 1 page segment table per cpu (max 48, cpu0 allocated at STAB0_PHYS_ADDR) */ .globl stab_array stab_array: .space 4096 * 48 diff -Nru a/arch/ppc64/kernel/htab.c b/arch/ppc64/kernel/htab.c --- a/arch/ppc64/kernel/htab.c Thu May 15 15:24:40 2003 +++ b/arch/ppc64/kernel/htab.c Thu May 15 15:24:40 2003 @@ -101,7 +101,7 @@ hpteg = ((hash & htab_data.htab_hash_mask)*HPTES_PER_GROUP); - if (naca->platform == PLATFORM_PSERIES_LPAR) + if (systemcfg->platform == PLATFORM_PSERIES_LPAR) ret = pSeries_lpar_hpte_insert(hpteg, va, (unsigned long)__v2a(addr) >> PAGE_SHIFT, 0, mode, 1, large); @@ -140,7 +140,7 @@ htab_data.htab_num_ptegs = pteg_count; htab_data.htab_hash_mask = pteg_count - 1; - if (naca->platform == PLATFORM_PSERIES) { + if (systemcfg->platform == PLATFORM_PSERIES) { /* Find storage for the HPT. Must be contiguous in * the absolute address space. */ @@ -165,15 +165,15 @@ mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX; /* XXX we currently map kernel text rw, should fix this */ - if (cpu_has_largepage() && naca->physicalMemorySize > 256*MB) { + if (cpu_has_largepage() && systemcfg->physicalMemorySize > 256*MB) { create_pte_mapping((unsigned long)KERNELBASE, KERNELBASE + 256*MB, mode_rw, 0); create_pte_mapping((unsigned long)KERNELBASE + 256*MB, - KERNELBASE + (naca->physicalMemorySize), + KERNELBASE + (systemcfg->physicalMemorySize), mode_rw, 1); } else { create_pte_mapping((unsigned long)KERNELBASE, - KERNELBASE+(naca->physicalMemorySize), + KERNELBASE+(systemcfg->physicalMemorySize), mode_rw, 0); } } diff -Nru a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c --- a/arch/ppc64/kernel/iSeries_setup.c Thu May 15 15:24:41 2003 +++ b/arch/ppc64/kernel/iSeries_setup.c Thu May 15 15:24:41 2003 @@ -561,13 +561,13 @@ * which should be equal to * nextPhysChunk */ - naca->physicalMemorySize = chunk_to_addr(nextPhysChunk); + systemcfg->physicalMemorySize = chunk_to_addr(nextPhysChunk); /* Bolt kernel mappings for all of memory */ - iSeries_bolt_kernel( 0, naca->physicalMemorySize ); + iSeries_bolt_kernel( 0, systemcfg->physicalMemorySize ); lmb_init(); - lmb_add( 0, naca->physicalMemorySize ); + lmb_add( 0, systemcfg->physicalMemorySize ); lmb_analyze(); /* ?? */ lmb_reserve( 0, __pa(klimit)); @@ -584,29 +584,28 @@ static void __init setup_iSeries_cache_sizes(void) { - unsigned i,n; - unsigned procIx = get_paca()->xLpPaca.xDynHvPhysicalProcIndex; + unsigned int i, n; + unsigned int procIx = get_paca()->xLpPaca.xDynHvPhysicalProcIndex; + + systemcfg->iCacheL1Size = xIoHriProcessorVpd[procIx].xInstCacheSize * 1024; + systemcfg->iCacheL1LineSize = xIoHriProcessorVpd[procIx].xInstCacheOperandSize; + systemcfg->dCacheL1Size = xIoHriProcessorVpd[procIx].xDataL1CacheSizeKB * 1024; + systemcfg->dCacheL1LineSize = xIoHriProcessorVpd[procIx].xDataCacheOperandSize; + naca->iCacheL1LinesPerPage = PAGE_SIZE / systemcfg->iCacheL1LineSize; + naca->dCacheL1LinesPerPage = PAGE_SIZE / systemcfg->dCacheL1LineSize; - naca->iCacheL1LineSize = xIoHriProcessorVpd[procIx].xInstCacheOperandSize; - naca->dCacheL1LineSize = xIoHriProcessorVpd[procIx].xDataCacheOperandSize; - naca->iCacheL1LinesPerPage = PAGE_SIZE / naca->iCacheL1LineSize; - naca->dCacheL1LinesPerPage = PAGE_SIZE / naca->dCacheL1LineSize; - i = naca->iCacheL1LineSize; + i = systemcfg->iCacheL1LineSize; n = 0; while ((i=(i/2))) ++n; naca->iCacheL1LogLineSize = n; - i = naca->dCacheL1LineSize; + + i = systemcfg->dCacheL1LineSize; n = 0; while ((i=(i/2))) ++n; naca->dCacheL1LogLineSize = n; - printk( "D-cache line size = %d (log = %d)\n", - (unsigned)naca->dCacheL1LineSize, - (unsigned)naca->dCacheL1LogLineSize ); - printk( "I-cache line size = %d (log = %d)\n", - (unsigned)naca->iCacheL1LineSize, - (unsigned)naca->iCacheL1LogLineSize ); - + printk( "D-cache line size = %d\n", (unsigned int)systemcfg->dCacheL1LineSize); + printk( "I-cache line size = %d\n", (unsigned int)systemcfg->iCacheL1LineSize); } /* @@ -648,6 +647,11 @@ void * eventStack; unsigned procIx = get_paca()->xLpPaca.xDynHvPhysicalProcIndex; + /* Add an eye catcher and the systemcfg layout version number */ + strcpy(systemcfg->eye_catcher, "SYSTEMCFG:PPC64"); + systemcfg->version.major = SYSTEMCFG_MAJOR; + systemcfg->version.minor = SYSTEMCFG_MINOR; + /* Setup the Lp Event Queue */ /* Allocate a page for the Event Stack @@ -696,8 +700,8 @@ printk("Time base frequency = %lu.%02lu\n", tbFreqMhz, tbFreqMhzHundreths ); - printk("Processor version = %x\n", - xIoHriProcessorVpd[procIx].xPVR ); + systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR; + printk("Processor version = %x\n", systemcfg->processor); } @@ -726,9 +730,9 @@ seq_printf(m,"time base\t: %lu.%02luMHz\n", tbFreqMhz, tbFreqMhzHundreths ); seq_printf(m,"i-cache\t\t: %d\n", - naca->iCacheL1LineSize); + systemcfg->iCacheL1LineSize); seq_printf(m,"d-cache\t\t: %d\n", - naca->dCacheL1LineSize); + systemcfg->dCacheL1LineSize); } diff -Nru a/arch/ppc64/kernel/ioctl32.c b/arch/ppc64/kernel/ioctl32.c --- a/arch/ppc64/kernel/ioctl32.c Thu May 15 15:24:46 2003 +++ b/arch/ppc64/kernel/ioctl32.c Thu May 15 15:24:46 2003 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -577,6 +579,17 @@ len += sizeof(struct ethtool_regs); break; } + case ETHTOOL_GEEPROM: + case ETHTOOL_SEEPROM: { + struct ethtool_eeprom *promaddr = (struct ethtool_eeprom *)A(data); + /* darned variable size arguments */ + if (get_user(len, (u32 *)&promaddr->len)) { + err = -EFAULT; + goto out; + } + len += sizeof(struct ethtool_eeprom); + break; + } case ETHTOOL_GSET: case ETHTOOL_SSET: len = sizeof(struct ethtool_cmd); break; default: @@ -659,6 +672,47 @@ return err; } +static inline void *alloc_user_space(long len) +{ + struct pt_regs *regs = current->thread.regs; + unsigned long usp = regs->gpr[1]; + + /* + * We cant access below the stack pointer in the 32bit ABI and + * can access 288 bytes in the 64bit ABI + */ + if (!(test_thread_flag(TIF_32BIT))) + usp -= 288; + + return (void *) (usp - len); +} + +int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct ifreq *u_ifreq64; + struct ifreq32 *u_ifreq32 = (struct ifreq32 *) arg; + char tmp_buf[IFNAMSIZ]; + void __user *data64; + u32 data32; + + if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]), + IFNAMSIZ)) + return -EFAULT; + if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data)) + return -EFAULT; + data64 = A(data32); + + u_ifreq64 = alloc_user_space(sizeof(*u_ifreq64)); + + /* Don't check these user accesses, just let that get trapped + * in the ioctl handler instead. + */ + copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], IFNAMSIZ); + __put_user(data64, &u_ifreq64->ifr_ifru.ifru_data); + + return sys_ioctl(fd, cmd, (unsigned long) u_ifreq64); +} + static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg) { struct ifreq ifr; @@ -3643,670 +3697,32 @@ #define BNEPGETCONNLIST _IOR('B', 210, int) #define BNEPGETCONNINFO _IOR('B', 211, int) -struct ioctl_trans { - unsigned long cmd; - unsigned long handler; - unsigned long next; -}; - -#define COMPATIBLE_IOCTL(cmd) { cmd, (unsigned long)sys_ioctl, 0 }, +#define HANDLE_IOCTL(cmd,handler) { cmd, (ioctl_trans_handler_t)handler, 0 }, +#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd,sys_ioctl) -#define HANDLE_IOCTL(cmd,handler) { cmd, (unsigned long)handler, 0 }, +#define IOCTL_TABLE_START \ + struct ioctl_trans ioctl_start[] = { +#define IOCTL_TABLE_END \ + }; struct ioctl_trans ioctl_end[0]; #define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int) #define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, compat_uid_t) -static struct ioctl_trans ioctl_translations[] = { - /* List here explicitly which ioctl's need translation, - * all others default to calling sys_ioctl(). - */ -/* Big T */ -COMPATIBLE_IOCTL(TCGETA) -COMPATIBLE_IOCTL(TCSETA) -COMPATIBLE_IOCTL(TCSETAW) -COMPATIBLE_IOCTL(TCSETAF) -COMPATIBLE_IOCTL(TCSBRK) +IOCTL_TABLE_START +#include COMPATIBLE_IOCTL(TCSBRKP) -COMPATIBLE_IOCTL(TCXONC) -COMPATIBLE_IOCTL(TCFLSH) -COMPATIBLE_IOCTL(TCGETS) -COMPATIBLE_IOCTL(TCSETS) -COMPATIBLE_IOCTL(TCSETSW) -COMPATIBLE_IOCTL(TCSETSF) -COMPATIBLE_IOCTL(TIOCLINUX) COMPATIBLE_IOCTL(TIOCSTART) COMPATIBLE_IOCTL(TIOCSTOP) -/* Little t */ -COMPATIBLE_IOCTL(TIOCGETD) -COMPATIBLE_IOCTL(TIOCSETD) -COMPATIBLE_IOCTL(TIOCEXCL) -COMPATIBLE_IOCTL(TIOCNXCL) -COMPATIBLE_IOCTL(TIOCCONS) -COMPATIBLE_IOCTL(TIOCGSOFTCAR) -COMPATIBLE_IOCTL(TIOCSSOFTCAR) -COMPATIBLE_IOCTL(TIOCSWINSZ) -COMPATIBLE_IOCTL(TIOCGWINSZ) -COMPATIBLE_IOCTL(TIOCMGET) -COMPATIBLE_IOCTL(TIOCMBIC) -COMPATIBLE_IOCTL(TIOCMBIS) -COMPATIBLE_IOCTL(TIOCMSET) -COMPATIBLE_IOCTL(TIOCPKT) -COMPATIBLE_IOCTL(TIOCNOTTY) -COMPATIBLE_IOCTL(TIOCSTI) -COMPATIBLE_IOCTL(TIOCOUTQ) -COMPATIBLE_IOCTL(TIOCSPGRP) -COMPATIBLE_IOCTL(TIOCGPGRP) -COMPATIBLE_IOCTL(TIOCSCTTY) -COMPATIBLE_IOCTL(TIOCGPTN) -COMPATIBLE_IOCTL(TIOCSPTLCK) COMPATIBLE_IOCTL(TIOCGSERIAL) COMPATIBLE_IOCTL(TIOCSSERIAL) -COMPATIBLE_IOCTL(TIOCSERGETLSR) COMPATIBLE_IOCTL(TIOCSLTC) -/* Big F */ -COMPATIBLE_IOCTL(FBIOGET_VSCREENINFO) -COMPATIBLE_IOCTL(FBIOPUT_VSCREENINFO) -COMPATIBLE_IOCTL(FBIOPAN_DISPLAY) -COMPATIBLE_IOCTL(FBIOGET_CON2FBMAP) -COMPATIBLE_IOCTL(FBIOPUT_CON2FBMAP) #if 0 COMPATIBLE_IOCTL(FBIOBLANK) #endif -/* Little f */ -COMPATIBLE_IOCTL(FIOCLEX) -COMPATIBLE_IOCTL(FIONCLEX) -COMPATIBLE_IOCTL(FIOASYNC) -COMPATIBLE_IOCTL(FIONBIO) -COMPATIBLE_IOCTL(FIONREAD) /* This is also TIOCINQ */ -/* 0x00 */ -COMPATIBLE_IOCTL(FIBMAP) -COMPATIBLE_IOCTL(FIGETBSZ) -/* 0x03 -- HD/IDE ioctl's used by hdparm and friends. - * Some need translations, these do not. - */ -COMPATIBLE_IOCTL(HDIO_GET_IDENTITY) -COMPATIBLE_IOCTL(HDIO_SET_DMA) -COMPATIBLE_IOCTL(HDIO_SET_UNMASKINTR) -COMPATIBLE_IOCTL(HDIO_SET_NOWERR) -COMPATIBLE_IOCTL(HDIO_SET_32BIT) -COMPATIBLE_IOCTL(HDIO_SET_MULTCOUNT) -COMPATIBLE_IOCTL(HDIO_DRIVE_CMD) -COMPATIBLE_IOCTL(HDIO_SET_PIO_MODE) -COMPATIBLE_IOCTL(HDIO_SET_NICE) -/* 0x02 -- Floppy ioctls */ -COMPATIBLE_IOCTL(FDMSGON) -COMPATIBLE_IOCTL(FDMSGOFF) -COMPATIBLE_IOCTL(FDSETEMSGTRESH) -COMPATIBLE_IOCTL(FDFLUSH) -COMPATIBLE_IOCTL(FDWERRORCLR) -COMPATIBLE_IOCTL(FDSETMAXERRS) -COMPATIBLE_IOCTL(FDGETMAXERRS) -COMPATIBLE_IOCTL(FDGETDRVTYP) -COMPATIBLE_IOCTL(FDEJECT) -COMPATIBLE_IOCTL(FDCLRPRM) -COMPATIBLE_IOCTL(FDFMTBEG) -COMPATIBLE_IOCTL(FDFMTEND) -COMPATIBLE_IOCTL(FDRESET) -COMPATIBLE_IOCTL(FDTWADDLE) -COMPATIBLE_IOCTL(FDFMTTRK) -COMPATIBLE_IOCTL(FDRAWCMD) -/* 0x12 */ -COMPATIBLE_IOCTL(BLKROSET) -COMPATIBLE_IOCTL(BLKROGET) -COMPATIBLE_IOCTL(BLKRRPART) -COMPATIBLE_IOCTL(BLKFLSBUF) -COMPATIBLE_IOCTL(BLKSECTSET) -COMPATIBLE_IOCTL(BLKSSZGET) -COMPATIBLE_IOCTL(BLKRASET) -COMPATIBLE_IOCTL(BLKFRASET) -/* RAID */ -COMPATIBLE_IOCTL(RAID_VERSION) -COMPATIBLE_IOCTL(GET_ARRAY_INFO) -COMPATIBLE_IOCTL(GET_DISK_INFO) -COMPATIBLE_IOCTL(PRINT_RAID_DEBUG) -COMPATIBLE_IOCTL(CLEAR_ARRAY) -COMPATIBLE_IOCTL(ADD_NEW_DISK) -COMPATIBLE_IOCTL(HOT_REMOVE_DISK) -COMPATIBLE_IOCTL(SET_ARRAY_INFO) -COMPATIBLE_IOCTL(SET_DISK_INFO) -COMPATIBLE_IOCTL(WRITE_RAID_INFO) -COMPATIBLE_IOCTL(UNPROTECT_ARRAY) -COMPATIBLE_IOCTL(PROTECT_ARRAY) -COMPATIBLE_IOCTL(HOT_ADD_DISK) -COMPATIBLE_IOCTL(SET_DISK_FAULTY) -COMPATIBLE_IOCTL(RUN_ARRAY) -COMPATIBLE_IOCTL(START_ARRAY) -COMPATIBLE_IOCTL(STOP_ARRAY) -COMPATIBLE_IOCTL(STOP_ARRAY_RO) -COMPATIBLE_IOCTL(RESTART_ARRAY_RW) -/* Big K */ -COMPATIBLE_IOCTL(PIO_FONT) -COMPATIBLE_IOCTL(GIO_FONT) -COMPATIBLE_IOCTL(KDSIGACCEPT) -COMPATIBLE_IOCTL(KDGETKEYCODE) -COMPATIBLE_IOCTL(KDSETKEYCODE) -COMPATIBLE_IOCTL(KIOCSOUND) -COMPATIBLE_IOCTL(KDMKTONE) -COMPATIBLE_IOCTL(KDGKBTYPE) -COMPATIBLE_IOCTL(KDSETMODE) -COMPATIBLE_IOCTL(KDGETMODE) -COMPATIBLE_IOCTL(KDSKBMODE) -COMPATIBLE_IOCTL(KDGKBMODE) -COMPATIBLE_IOCTL(KDSKBMETA) -COMPATIBLE_IOCTL(KDGKBMETA) -COMPATIBLE_IOCTL(KDGKBENT) -COMPATIBLE_IOCTL(KDSKBENT) -COMPATIBLE_IOCTL(KDGKBSENT) -COMPATIBLE_IOCTL(KDSKBSENT) -COMPATIBLE_IOCTL(KDGKBDIACR) -COMPATIBLE_IOCTL(KDKBDREP) -COMPATIBLE_IOCTL(KDSKBDIACR) -COMPATIBLE_IOCTL(KDGKBLED) -COMPATIBLE_IOCTL(KDSKBLED) -COMPATIBLE_IOCTL(KDGETLED) -COMPATIBLE_IOCTL(KDSETLED) -COMPATIBLE_IOCTL(GIO_SCRNMAP) -COMPATIBLE_IOCTL(PIO_SCRNMAP) -COMPATIBLE_IOCTL(GIO_UNISCRNMAP) -COMPATIBLE_IOCTL(PIO_UNISCRNMAP) -COMPATIBLE_IOCTL(PIO_FONTRESET) -COMPATIBLE_IOCTL(PIO_UNIMAPCLR) -/* Big S */ -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN) -COMPATIBLE_IOCTL(SCSI_IOCTL_PROBE_HOST) -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_PCI) -COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK) -COMPATIBLE_IOCTL(SCSI_IOCTL_DOORUNLOCK) -COMPATIBLE_IOCTL(SCSI_IOCTL_TEST_UNIT_READY) -COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_ENABLE) -COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_DISABLE) -COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER) -COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND) -/* Big T */ -COMPATIBLE_IOCTL(TUNSETNOCSUM) -COMPATIBLE_IOCTL(TUNSETDEBUG) -COMPATIBLE_IOCTL(TUNSETIFF) -COMPATIBLE_IOCTL(TUNSETPERSIST) -COMPATIBLE_IOCTL(TUNSETOWNER) -/* Big V */ -COMPATIBLE_IOCTL(VT_SETMODE) -COMPATIBLE_IOCTL(VT_GETMODE) -COMPATIBLE_IOCTL(VT_GETSTATE) -COMPATIBLE_IOCTL(VT_OPENQRY) -COMPATIBLE_IOCTL(VT_ACTIVATE) -COMPATIBLE_IOCTL(VT_WAITACTIVE) -COMPATIBLE_IOCTL(VT_RELDISP) -COMPATIBLE_IOCTL(VT_DISALLOCATE) -COMPATIBLE_IOCTL(VT_RESIZE) -COMPATIBLE_IOCTL(VT_RESIZEX) -COMPATIBLE_IOCTL(VT_LOCKSWITCH) -COMPATIBLE_IOCTL(VT_UNLOCKSWITCH) -/* Little v, the video4linux ioctls */ -COMPATIBLE_IOCTL(VIDIOCGCAP) -COMPATIBLE_IOCTL(VIDIOCGCHAN) -COMPATIBLE_IOCTL(VIDIOCSCHAN) -COMPATIBLE_IOCTL(VIDIOCGPICT) -COMPATIBLE_IOCTL(VIDIOCSPICT) -COMPATIBLE_IOCTL(VIDIOCCAPTURE) -COMPATIBLE_IOCTL(VIDIOCKEY) -COMPATIBLE_IOCTL(VIDIOCGAUDIO) -COMPATIBLE_IOCTL(VIDIOCSAUDIO) -COMPATIBLE_IOCTL(VIDIOCSYNC) -COMPATIBLE_IOCTL(VIDIOCMCAPTURE) -COMPATIBLE_IOCTL(VIDIOCGMBUF) -COMPATIBLE_IOCTL(VIDIOCGUNIT) -COMPATIBLE_IOCTL(VIDIOCGCAPTURE) -COMPATIBLE_IOCTL(VIDIOCSCAPTURE) -/* BTTV specific... */ -COMPATIBLE_IOCTL(_IOW('v', BASE_VIDIOCPRIVATE+0, char [256])) -COMPATIBLE_IOCTL(_IOR('v', BASE_VIDIOCPRIVATE+1, char [256])) -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int)) -COMPATIBLE_IOCTL(_IOW('v' , BASE_VIDIOCPRIVATE+3, char [16])) /* struct bttv_pll_info */ -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+4, int)) -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+5, int)) -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+6, int)) -COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+7, int)) /* Little p (/dev/rtc, /dev/envctrl, etc.) */ COMPATIBLE_IOCTL(_IOR('p', 20, int[7])) /* RTCGET */ COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */ -COMPATIBLE_IOCTL(RTC_AIE_ON) -COMPATIBLE_IOCTL(RTC_AIE_OFF) -COMPATIBLE_IOCTL(RTC_UIE_ON) -COMPATIBLE_IOCTL(RTC_UIE_OFF) -COMPATIBLE_IOCTL(RTC_PIE_ON) -COMPATIBLE_IOCTL(RTC_PIE_OFF) -COMPATIBLE_IOCTL(RTC_WIE_ON) -COMPATIBLE_IOCTL(RTC_WIE_OFF) -COMPATIBLE_IOCTL(RTC_ALM_SET) -COMPATIBLE_IOCTL(RTC_ALM_READ) -COMPATIBLE_IOCTL(RTC_RD_TIME) -COMPATIBLE_IOCTL(RTC_SET_TIME) -COMPATIBLE_IOCTL(RTC_WKALM_SET) -COMPATIBLE_IOCTL(RTC_WKALM_RD) -/* Little m */ -COMPATIBLE_IOCTL(MTIOCTOP) -/* Socket level stuff */ -COMPATIBLE_IOCTL(FIOSETOWN) -COMPATIBLE_IOCTL(SIOCSPGRP) -COMPATIBLE_IOCTL(FIOGETOWN) -COMPATIBLE_IOCTL(SIOCGPGRP) -COMPATIBLE_IOCTL(SIOCATMARK) -COMPATIBLE_IOCTL(SIOCSIFLINK) -COMPATIBLE_IOCTL(SIOCSIFENCAP) -COMPATIBLE_IOCTL(SIOCGIFENCAP) -COMPATIBLE_IOCTL(SIOCSIFBR) -COMPATIBLE_IOCTL(SIOCGIFBR) -COMPATIBLE_IOCTL(SIOCSARP) -COMPATIBLE_IOCTL(SIOCGARP) -COMPATIBLE_IOCTL(SIOCDARP) -COMPATIBLE_IOCTL(SIOCSRARP) -COMPATIBLE_IOCTL(SIOCGRARP) -COMPATIBLE_IOCTL(SIOCDRARP) -COMPATIBLE_IOCTL(SIOCADDDLCI) -COMPATIBLE_IOCTL(SIOCDELDLCI) -COMPATIBLE_IOCTL(SIOCGMIIPHY) -COMPATIBLE_IOCTL(SIOCGMIIREG) -COMPATIBLE_IOCTL(SIOCSMIIREG) -COMPATIBLE_IOCTL(SIOCGIFVLAN) -COMPATIBLE_IOCTL(SIOCSIFVLAN) -/* SG stuff */ -COMPATIBLE_IOCTL(SG_SET_TIMEOUT) -COMPATIBLE_IOCTL(SG_GET_TIMEOUT) -COMPATIBLE_IOCTL(SG_EMULATED_HOST) -COMPATIBLE_IOCTL(SG_SET_TRANSFORM) -COMPATIBLE_IOCTL(SG_GET_TRANSFORM) -COMPATIBLE_IOCTL(SG_SET_RESERVED_SIZE) -COMPATIBLE_IOCTL(SG_GET_RESERVED_SIZE) -COMPATIBLE_IOCTL(SG_GET_SCSI_ID) -COMPATIBLE_IOCTL(SG_SET_FORCE_LOW_DMA) -COMPATIBLE_IOCTL(SG_GET_LOW_DMA) -COMPATIBLE_IOCTL(SG_SET_FORCE_PACK_ID) -COMPATIBLE_IOCTL(SG_GET_PACK_ID) -COMPATIBLE_IOCTL(SG_GET_NUM_WAITING) -COMPATIBLE_IOCTL(SG_SET_DEBUG) -COMPATIBLE_IOCTL(SG_GET_SG_TABLESIZE) -COMPATIBLE_IOCTL(SG_GET_COMMAND_Q) -COMPATIBLE_IOCTL(SG_SET_COMMAND_Q) -COMPATIBLE_IOCTL(SG_GET_VERSION_NUM) -COMPATIBLE_IOCTL(SG_NEXT_CMD_LEN) -COMPATIBLE_IOCTL(SG_SCSI_RESET) -COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE) -COMPATIBLE_IOCTL(SG_SET_KEEP_ORPHAN) -COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN) -/* PPP stuff */ -COMPATIBLE_IOCTL(PPPIOCGFLAGS) -COMPATIBLE_IOCTL(PPPIOCSFLAGS) -COMPATIBLE_IOCTL(PPPIOCGASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCSASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCGUNIT) -COMPATIBLE_IOCTL(PPPIOCGRASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCSRASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCGMRU) -COMPATIBLE_IOCTL(PPPIOCSMRU) -COMPATIBLE_IOCTL(PPPIOCSMAXCID) -COMPATIBLE_IOCTL(PPPIOCGXASYNCMAP) -COMPATIBLE_IOCTL(LPGETSTATUS) -COMPATIBLE_IOCTL(PPPIOCSXASYNCMAP) -COMPATIBLE_IOCTL(PPPIOCXFERUNIT) -COMPATIBLE_IOCTL(PPPIOCGNPMODE) -COMPATIBLE_IOCTL(PPPIOCSNPMODE) -COMPATIBLE_IOCTL(PPPIOCGDEBUG) -COMPATIBLE_IOCTL(PPPIOCSDEBUG) -COMPATIBLE_IOCTL(PPPIOCNEWUNIT) -COMPATIBLE_IOCTL(PPPIOCATTACH) -COMPATIBLE_IOCTL(PPPIOCDETACH) -COMPATIBLE_IOCTL(PPPIOCSMRRU) -COMPATIBLE_IOCTL(PPPIOCCONNECT) -COMPATIBLE_IOCTL(PPPIOCDISCONN) -COMPATIBLE_IOCTL(PPPIOCATTCHAN) -COMPATIBLE_IOCTL(PPPIOCGCHAN) -/* PPPOX */ -COMPATIBLE_IOCTL(PPPOEIOCSFWD) -COMPATIBLE_IOCTL(PPPOEIOCDFWD) -/* CDROM stuff */ -COMPATIBLE_IOCTL(CDROMPAUSE) -COMPATIBLE_IOCTL(CDROMRESUME) -COMPATIBLE_IOCTL(CDROMPLAYMSF) -COMPATIBLE_IOCTL(CDROMPLAYTRKIND) -COMPATIBLE_IOCTL(CDROMREADTOCHDR) -COMPATIBLE_IOCTL(CDROMREADTOCENTRY) -COMPATIBLE_IOCTL(CDROMSTOP) -COMPATIBLE_IOCTL(CDROMSTART) -COMPATIBLE_IOCTL(CDROMEJECT) -COMPATIBLE_IOCTL(CDROMVOLCTRL) -COMPATIBLE_IOCTL(CDROMSUBCHNL) -COMPATIBLE_IOCTL(CDROMEJECT_SW) -COMPATIBLE_IOCTL(CDROMMULTISESSION) -COMPATIBLE_IOCTL(CDROM_GET_MCN) -COMPATIBLE_IOCTL(CDROMRESET) -COMPATIBLE_IOCTL(CDROMVOLREAD) -COMPATIBLE_IOCTL(CDROMSEEK) -COMPATIBLE_IOCTL(CDROMPLAYBLK) -COMPATIBLE_IOCTL(CDROMCLOSETRAY) -COMPATIBLE_IOCTL(CDROM_SET_OPTIONS) -COMPATIBLE_IOCTL(CDROM_CLEAR_OPTIONS) -COMPATIBLE_IOCTL(CDROM_SELECT_SPEED) -COMPATIBLE_IOCTL(CDROM_SELECT_DISC) -COMPATIBLE_IOCTL(CDROM_MEDIA_CHANGED) -COMPATIBLE_IOCTL(CDROM_DRIVE_STATUS) -COMPATIBLE_IOCTL(CDROM_DISC_STATUS) -COMPATIBLE_IOCTL(CDROM_CHANGER_NSLOTS) -COMPATIBLE_IOCTL(CDROM_LOCKDOOR) -COMPATIBLE_IOCTL(CDROM_DEBUG) -COMPATIBLE_IOCTL(CDROM_GET_CAPABILITY) -/* DVD ioctls */ -COMPATIBLE_IOCTL(DVD_READ_STRUCT) -COMPATIBLE_IOCTL(DVD_WRITE_STRUCT) -COMPATIBLE_IOCTL(DVD_AUTH) -/* Big L */ -COMPATIBLE_IOCTL(LOOP_SET_FD) -COMPATIBLE_IOCTL(LOOP_CLR_FD) -/* Big Q for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_SEQ_RESET) -COMPATIBLE_IOCTL(SNDCTL_SEQ_SYNC) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_INFO) -COMPATIBLE_IOCTL(SNDCTL_SEQ_CTRLRATE) -COMPATIBLE_IOCTL(SNDCTL_SEQ_GETOUTCOUNT) -COMPATIBLE_IOCTL(SNDCTL_SEQ_GETINCOUNT) -COMPATIBLE_IOCTL(SNDCTL_SEQ_PERCMODE) -COMPATIBLE_IOCTL(SNDCTL_FM_LOAD_INSTR) -COMPATIBLE_IOCTL(SNDCTL_SEQ_TESTMIDI) -COMPATIBLE_IOCTL(SNDCTL_SEQ_RESETSAMPLES) -COMPATIBLE_IOCTL(SNDCTL_SEQ_NRSYNTHS) -COMPATIBLE_IOCTL(SNDCTL_SEQ_NRMIDIS) -COMPATIBLE_IOCTL(SNDCTL_MIDI_INFO) -COMPATIBLE_IOCTL(SNDCTL_SEQ_THRESHOLD) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_MEMAVL) -COMPATIBLE_IOCTL(SNDCTL_FM_4OP_ENABLE) -COMPATIBLE_IOCTL(SNDCTL_SEQ_PANIC) -COMPATIBLE_IOCTL(SNDCTL_SEQ_OUTOFBAND) -COMPATIBLE_IOCTL(SNDCTL_SEQ_GETTIME) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_ID) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_CONTROL) -COMPATIBLE_IOCTL(SNDCTL_SYNTH_REMOVESAMPLE) -/* Big T for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_TMR_TIMEBASE) -COMPATIBLE_IOCTL(SNDCTL_TMR_START) -COMPATIBLE_IOCTL(SNDCTL_TMR_STOP) -COMPATIBLE_IOCTL(SNDCTL_TMR_CONTINUE) -COMPATIBLE_IOCTL(SNDCTL_TMR_TEMPO) -COMPATIBLE_IOCTL(SNDCTL_TMR_SOURCE) -COMPATIBLE_IOCTL(SNDCTL_TMR_METRONOME) -COMPATIBLE_IOCTL(SNDCTL_TMR_SELECT) -/* Little m for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_MIDI_PRETIME) -COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUMODE) -COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUCMD) -/* Big P for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_DSP_RESET) -COMPATIBLE_IOCTL(SNDCTL_DSP_SYNC) -COMPATIBLE_IOCTL(SNDCTL_DSP_SPEED) -COMPATIBLE_IOCTL(SNDCTL_DSP_STEREO) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETBLKSIZE) -COMPATIBLE_IOCTL(SNDCTL_DSP_CHANNELS) -COMPATIBLE_IOCTL(SOUND_PCM_WRITE_FILTER) -COMPATIBLE_IOCTL(SNDCTL_DSP_POST) -COMPATIBLE_IOCTL(SNDCTL_DSP_SUBDIVIDE) -COMPATIBLE_IOCTL(SNDCTL_DSP_SETFRAGMENT) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETFMTS) -COMPATIBLE_IOCTL(SNDCTL_DSP_SETFMT) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETOSPACE) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETISPACE) -COMPATIBLE_IOCTL(SNDCTL_DSP_NONBLOCK) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETCAPS) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETTRIGGER) -COMPATIBLE_IOCTL(SNDCTL_DSP_SETTRIGGER) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETIPTR) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETOPTR) -/* SNDCTL_DSP_MAPINBUF, XXX needs translation */ -/* SNDCTL_DSP_MAPOUTBUF, XXX needs translation */ -COMPATIBLE_IOCTL(SNDCTL_DSP_SETSYNCRO) -COMPATIBLE_IOCTL(SNDCTL_DSP_SETDUPLEX) -COMPATIBLE_IOCTL(SNDCTL_DSP_GETODELAY) -COMPATIBLE_IOCTL(SNDCTL_DSP_PROFILE) -COMPATIBLE_IOCTL(SOUND_PCM_READ_RATE) -COMPATIBLE_IOCTL(SOUND_PCM_READ_CHANNELS) -COMPATIBLE_IOCTL(SOUND_PCM_READ_BITS) -COMPATIBLE_IOCTL(SOUND_PCM_READ_FILTER) -/* Big C for sound/OSS */ -COMPATIBLE_IOCTL(SNDCTL_COPR_RESET) -COMPATIBLE_IOCTL(SNDCTL_COPR_LOAD) -COMPATIBLE_IOCTL(SNDCTL_COPR_RDATA) -COMPATIBLE_IOCTL(SNDCTL_COPR_RCODE) -COMPATIBLE_IOCTL(SNDCTL_COPR_WDATA) -COMPATIBLE_IOCTL(SNDCTL_COPR_WCODE) -COMPATIBLE_IOCTL(SNDCTL_COPR_RUN) -COMPATIBLE_IOCTL(SNDCTL_COPR_HALT) -COMPATIBLE_IOCTL(SNDCTL_COPR_SENDMSG) -COMPATIBLE_IOCTL(SNDCTL_COPR_RCVMSG) -/* Big M for sound/OSS */ -COMPATIBLE_IOCTL(SOUND_MIXER_READ_VOLUME) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_BASS) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_TREBLE) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_SYNTH) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_PCM) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_SPEAKER) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_MIC) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_CD) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_IMIX) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_ALTPCM) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECLEV) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_IGAIN) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_OGAIN) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE1) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE2) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE3) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL1)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL2)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL3)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEIN)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEOUT)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_VIDEO)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_RADIO)) -COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_MONITOR)) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_MUTE) -/* SOUND_MIXER_READ_ENHANCE, same value as READ_MUTE */ -/* SOUND_MIXER_READ_LOUD, same value as READ_MUTE */ -COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECSRC) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_DEVMASK) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECMASK) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_STEREODEVS) -COMPATIBLE_IOCTL(SOUND_MIXER_READ_CAPS) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_VOLUME) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_BASS) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_TREBLE) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_SYNTH) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_PCM) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_SPEAKER) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MIC) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_CD) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_IMIX) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_ALTPCM) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_RECLEV) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_IGAIN) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_OGAIN) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE1) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE2) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE3) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL1)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL2)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL3)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEIN)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEOUT)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_VIDEO)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_RADIO)) -COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_MONITOR)) -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MUTE) -/* SOUND_MIXER_WRITE_ENHANCE, same value as WRITE_MUTE */ -/* SOUND_MIXER_WRITE_LOUD, same value as WRITE_MUTE */ -COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_RECSRC) -COMPATIBLE_IOCTL(SOUND_MIXER_INFO) -COMPATIBLE_IOCTL(SOUND_OLD_MIXER_INFO) -COMPATIBLE_IOCTL(SOUND_MIXER_ACCESS) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE1) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE2) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE3) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE4) -COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE5) -COMPATIBLE_IOCTL(SOUND_MIXER_GETLEVELS) -COMPATIBLE_IOCTL(SOUND_MIXER_SETLEVELS) -COMPATIBLE_IOCTL(OSS_GETVERSION) -/* AUTOFS */ -COMPATIBLE_IOCTL(AUTOFS_IOC_READY) -COMPATIBLE_IOCTL(AUTOFS_IOC_FAIL) -COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC) -COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER) -COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE) -/* DEVFS */ -COMPATIBLE_IOCTL(DEVFSDIOC_GET_PROTO_REV) -COMPATIBLE_IOCTL(DEVFSDIOC_SET_EVENT_MASK) -COMPATIBLE_IOCTL(DEVFSDIOC_RELEASE_EVENT_QUEUE) -COMPATIBLE_IOCTL(DEVFSDIOC_SET_DEBUG_MASK) -/* Raw devices */ -COMPATIBLE_IOCTL(RAW_SETBIND) -COMPATIBLE_IOCTL(RAW_GETBIND) -/* SMB ioctls which do not need any translations */ -COMPATIBLE_IOCTL(SMB_IOC_NEWCONN) -/* NCP ioctls which do not need any translations */ -COMPATIBLE_IOCTL(NCP_IOC_CONN_LOGGED_IN) -COMPATIBLE_IOCTL(NCP_IOC_SIGN_INIT) -COMPATIBLE_IOCTL(NCP_IOC_SIGN_WANTED) -COMPATIBLE_IOCTL(NCP_IOC_SET_SIGN_WANTED) -COMPATIBLE_IOCTL(NCP_IOC_LOCKUNLOCK) -COMPATIBLE_IOCTL(NCP_IOC_GETROOT) -COMPATIBLE_IOCTL(NCP_IOC_SETROOT) -COMPATIBLE_IOCTL(NCP_IOC_GETCHARSETS) -COMPATIBLE_IOCTL(NCP_IOC_SETCHARSETS) -COMPATIBLE_IOCTL(NCP_IOC_GETDENTRYTTL) -COMPATIBLE_IOCTL(NCP_IOC_SETDENTRYTTL) -/* Little a */ -COMPATIBLE_IOCTL(ATMSIGD_CTRL) -COMPATIBLE_IOCTL(ATMARPD_CTRL) -COMPATIBLE_IOCTL(ATMLEC_CTRL) -COMPATIBLE_IOCTL(ATMLEC_MCAST) -COMPATIBLE_IOCTL(ATMLEC_DATA) -COMPATIBLE_IOCTL(ATM_SETSC) -COMPATIBLE_IOCTL(SIOCSIFATMTCP) -COMPATIBLE_IOCTL(SIOCMKCLIP) -COMPATIBLE_IOCTL(ATMARP_MKIP) -COMPATIBLE_IOCTL(ATMARP_SETENTRY) -COMPATIBLE_IOCTL(ATMARP_ENCAP) -COMPATIBLE_IOCTL(ATMTCP_CREATE) -COMPATIBLE_IOCTL(ATMTCP_REMOVE) -COMPATIBLE_IOCTL(ATMMPC_CTRL) -COMPATIBLE_IOCTL(ATMMPC_DATA) -#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE) -COMPATIBLE_IOCTL(DRM_IOCTL_GET_MAGIC) -COMPATIBLE_IOCTL(DRM_IOCTL_IRQ_BUSID) -COMPATIBLE_IOCTL(DRM_IOCTL_AUTH_MAGIC) -COMPATIBLE_IOCTL(DRM_IOCTL_BLOCK) -COMPATIBLE_IOCTL(DRM_IOCTL_UNBLOCK) -COMPATIBLE_IOCTL(DRM_IOCTL_CONTROL) -COMPATIBLE_IOCTL(DRM_IOCTL_ADD_BUFS) -COMPATIBLE_IOCTL(DRM_IOCTL_MARK_BUFS) -COMPATIBLE_IOCTL(DRM_IOCTL_ADD_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_RM_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_MOD_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_GET_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_SWITCH_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_NEW_CTX) -COMPATIBLE_IOCTL(DRM_IOCTL_ADD_DRAW) -COMPATIBLE_IOCTL(DRM_IOCTL_RM_DRAW) -COMPATIBLE_IOCTL(DRM_IOCTL_LOCK) -COMPATIBLE_IOCTL(DRM_IOCTL_UNLOCK) -COMPATIBLE_IOCTL(DRM_IOCTL_FINISH) -#endif /* DRM */ -/* Big W */ -/* WIOC_GETSUPPORT not yet implemented -E */ -COMPATIBLE_IOCTL(WDIOC_GETSTATUS) -COMPATIBLE_IOCTL(WDIOC_GETBOOTSTATUS) -COMPATIBLE_IOCTL(WDIOC_GETTEMP) -COMPATIBLE_IOCTL(WDIOC_SETOPTIONS) -COMPATIBLE_IOCTL(WDIOC_KEEPALIVE) -/* Big R */ -COMPATIBLE_IOCTL(RNDGETENTCNT) -COMPATIBLE_IOCTL(RNDADDTOENTCNT) -COMPATIBLE_IOCTL(RNDGETPOOL) -COMPATIBLE_IOCTL(RNDADDENTROPY) -COMPATIBLE_IOCTL(RNDZAPENTCNT) -COMPATIBLE_IOCTL(RNDCLEARPOOL) -/* Bluetooth ioctls */ -COMPATIBLE_IOCTL(HCIDEVUP) -COMPATIBLE_IOCTL(HCIDEVDOWN) -COMPATIBLE_IOCTL(HCIDEVRESET) -COMPATIBLE_IOCTL(HCIDEVRESTAT) -COMPATIBLE_IOCTL(HCIGETDEVLIST) -COMPATIBLE_IOCTL(HCIGETDEVINFO) -COMPATIBLE_IOCTL(HCIGETCONNLIST) -COMPATIBLE_IOCTL(HCIGETCONNINFO) -COMPATIBLE_IOCTL(HCISETRAW) -COMPATIBLE_IOCTL(HCISETSCAN) -COMPATIBLE_IOCTL(HCISETAUTH) -COMPATIBLE_IOCTL(HCISETENCRYPT) -COMPATIBLE_IOCTL(HCISETPTYPE) -COMPATIBLE_IOCTL(HCISETLINKPOL) -COMPATIBLE_IOCTL(HCISETLINKMODE) -COMPATIBLE_IOCTL(HCISETACLMTU) -COMPATIBLE_IOCTL(HCISETSCOMTU) -COMPATIBLE_IOCTL(HCIINQUIRY) -COMPATIBLE_IOCTL(HCIUARTSETPROTO) -COMPATIBLE_IOCTL(HCIUARTGETPROTO) -COMPATIBLE_IOCTL(RFCOMMCREATEDEV) -COMPATIBLE_IOCTL(RFCOMMRELEASEDEV) -COMPATIBLE_IOCTL(RFCOMMGETDEVLIST) -COMPATIBLE_IOCTL(RFCOMMGETDEVINFO) -COMPATIBLE_IOCTL(RFCOMMSTEALDLC) -COMPATIBLE_IOCTL(BNEPCONNADD) -COMPATIBLE_IOCTL(BNEPCONNDEL) -COMPATIBLE_IOCTL(BNEPGETCONNLIST) -COMPATIBLE_IOCTL(BNEPGETCONNINFO) -COMPATIBLE_IOCTL(PCIIOC_CONTROLLER) -COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO) -COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM) -COMPATIBLE_IOCTL(PCIIOC_WRITE_COMBINE) -/* USB */ -COMPATIBLE_IOCTL(USBDEVFS_RESETEP) -COMPATIBLE_IOCTL(USBDEVFS_SETINTERFACE) -COMPATIBLE_IOCTL(USBDEVFS_SETCONFIGURATION) -COMPATIBLE_IOCTL(USBDEVFS_GETDRIVER) -COMPATIBLE_IOCTL(USBDEVFS_DISCARDURB) -COMPATIBLE_IOCTL(USBDEVFS_CLAIMINTERFACE) -COMPATIBLE_IOCTL(USBDEVFS_RELEASEINTERFACE) -COMPATIBLE_IOCTL(USBDEVFS_CONNECTINFO) -COMPATIBLE_IOCTL(USBDEVFS_HUB_PORTINFO) -COMPATIBLE_IOCTL(USBDEVFS_RESET) -COMPATIBLE_IOCTL(USBDEVFS_CLEAR_HALT) -/* MTD */ -COMPATIBLE_IOCTL(MEMGETINFO) -COMPATIBLE_IOCTL(MEMERASE) -COMPATIBLE_IOCTL(MEMLOCK) -COMPATIBLE_IOCTL(MEMUNLOCK) -COMPATIBLE_IOCTL(MEMGETREGIONCOUNT) -COMPATIBLE_IOCTL(MEMGETREGIONINFO) -/* NBD */ -COMPATIBLE_IOCTL(NBD_SET_SOCK) -COMPATIBLE_IOCTL(NBD_SET_BLKSIZE) -COMPATIBLE_IOCTL(NBD_SET_SIZE) -COMPATIBLE_IOCTL(NBD_DO_IT) -COMPATIBLE_IOCTL(NBD_CLEAR_SOCK) -COMPATIBLE_IOCTL(NBD_CLEAR_QUE) -COMPATIBLE_IOCTL(NBD_PRINT_DEBUG) -COMPATIBLE_IOCTL(NBD_SET_SIZE_BLOCKS) -COMPATIBLE_IOCTL(NBD_DISCONNECT) -/* device-mapper */ -COMPATIBLE_IOCTL(DM_VERSION) -COMPATIBLE_IOCTL(DM_REMOVE_ALL) -COMPATIBLE_IOCTL(DM_DEV_CREATE) -COMPATIBLE_IOCTL(DM_DEV_REMOVE) -COMPATIBLE_IOCTL(DM_DEV_RELOAD) -COMPATIBLE_IOCTL(DM_DEV_SUSPEND) -COMPATIBLE_IOCTL(DM_DEV_RENAME) -COMPATIBLE_IOCTL(DM_DEV_DEPS) -COMPATIBLE_IOCTL(DM_DEV_STATUS) -COMPATIBLE_IOCTL(DM_TARGET_STATUS) -COMPATIBLE_IOCTL(DM_TARGET_WAIT) + /* And these ioctls need translation */ HANDLE_IOCTL(MEMREADOOB32, mtd_rw_oob) HANDLE_IOCTL(MEMWRITEOOB32, mtd_rw_oob) @@ -4473,4 +3889,4 @@ HANDLE_IOCTL(BLKBSZGET_32, do_blkbszget) HANDLE_IOCTL(BLKBSZSET_32, do_blkbszset) HANDLE_IOCTL(BLKGETSIZE64_32, do_blkgetsize64) -}; +IOCTL_TABLE_END diff -Nru a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c --- a/arch/ppc64/kernel/irq.c Thu May 15 15:24:37 2003 +++ b/arch/ppc64/kernel/irq.c Thu May 15 15:24:37 2003 @@ -212,7 +212,8 @@ return -ENOENT; } -int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), +int request_irq(unsigned int irq, + irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long irqflags, const char * devname, void *dev_id) { struct irqaction *action; @@ -695,7 +696,7 @@ struct proc_dir_entry *entry; char name [MAX_NAMELEN]; - if (!root_irq_dir || (irq_desc[irq].handler == NULL)) + if (!root_irq_dir || (irq_desc[irq].handler == NULL) || irq_dir[irq]) return; memset(name, 0, MAX_NAMELEN); @@ -743,6 +744,7 @@ } } -void no_action(int irq, void *dev, struct pt_regs *regs) +irqreturn_t no_action(int irq, void *dev, struct pt_regs *regs) { + return IRQ_NONE; } diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S --- a/arch/ppc64/kernel/misc.S Thu May 15 15:24:43 2003 +++ b/arch/ppc64/kernel/misc.S Thu May 15 15:24:43 2003 @@ -170,12 +170,14 @@ */ LOADADDR(r10,naca) /* Get Naca address */ ld r10,0(r10) - lhz r7,DCACHEL1LINESIZE(r10) /* Get cache line size */ + LOADADDR(r11,systemcfg) /* Get systemcfg address */ + ld r11,0(r11) + lwz r7,DCACHEL1LINESIZE(r11)/* Get cache line size */ addi r5,r7,-1 andc r6,r3,r5 /* round low to line bdy */ subf r8,r6,r4 /* compute length */ add r8,r8,r5 /* ensure we get enough */ - lhz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of cache line size */ + lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of cache line size */ srw. r8,r8,r9 /* compute line count */ beqlr /* nothing to do? */ mtctr r8 @@ -186,12 +188,12 @@ /* Now invalidate the instruction cache */ - lhz r7,ICACHEL1LINESIZE(r10) /* Get Icache line size */ + lwz r7,ICACHEL1LINESIZE(r11) /* Get Icache line size */ addi r5,r7,-1 andc r6,r3,r5 /* round low to line bdy */ subf r8,r6,r4 /* compute length */ add r8,r8,r5 - lhz r9,ICACHEL1LOGLINESIZE(r10) /* Get log-2 of Icache line size */ + lwz r9,ICACHEL1LOGLINESIZE(r10) /* Get log-2 of Icache line size */ srw. r8,r8,r9 /* compute line count */ beqlr /* nothing to do? */ mtctr r8 @@ -217,12 +219,14 @@ */ LOADADDR(r10,naca) /* Get Naca address */ ld r10,0(r10) - lhz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */ + LOADADDR(r11,systemcfg) /* Get systemcfg address */ + ld r11,0(r11) + lwz r7,DCACHEL1LINESIZE(r11) /* Get dcache line size */ addi r5,r7,-1 andc r6,r3,r5 /* round low to line bdy */ subf r8,r6,r4 /* compute length */ add r8,r8,r5 /* ensure we get enough */ - lhz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */ + lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */ srw. r8,r8,r9 /* compute line count */ beqlr /* nothing to do? */ mtctr r8 @@ -249,9 +253,11 @@ /* Flush the dcache */ LOADADDR(r7,naca) ld r7,0(r7) + LOADADDR(r8,systemcfg) /* Get systemcfg address */ + ld r8,0(r8) clrrdi r3,r3,12 /* Page align */ - lhz r4,DCACHEL1LINESPERPAGE(r7) /* Get # dcache lines per page */ - lhz r5,DCACHEL1LINESIZE(r7) /* Get dcache line size */ + lwz r4,DCACHEL1LINESPERPAGE(r7) /* Get # dcache lines per page */ + lwz r5,DCACHEL1LINESIZE(r8) /* Get dcache line size */ mr r6,r3 mtctr r4 0: dcbst 0,r6 @@ -261,8 +267,8 @@ /* Now invalidate the icache */ - lhz r4,ICACHEL1LINESPERPAGE(r7) /* Get # icache lines per page */ - lhz r5,ICACHEL1LINESIZE(r7) /* Get icache line size */ + lwz r4,ICACHEL1LINESPERPAGE(r7) /* Get # icache lines per page */ + lwz r5,ICACHEL1LINESIZE(r8) /* Get icache line size */ mtctr r4 1: icbi 0,r3 add r3,r3,r5 @@ -574,7 +580,7 @@ .llong .sys32_ssetmask .llong .sys_setreuid /* 70 */ .llong .sys_setregid - .llong .sys_sigsuspend + .llong .sys32_sigsuspend .llong .compat_sys_sigpending .llong .sys32_sethostname .llong .compat_sys_setrlimit /* 75 */ @@ -737,7 +743,7 @@ .llong .sys_set_tid_address .llong .ppc32_fadvise64 .llong .sys_exit_group - .llong .ppc32_lookup_dcookie /* 245 */ + .llong .ppc32_lookup_dcookie /* 235 */ .llong .sys_epoll_create .llong .sys_epoll_ctl .llong .sys_epoll_wait @@ -812,13 +818,13 @@ .llong .sys_getppid .llong .sys_getpgrp /* 65 */ .llong .sys_setsid - .llong .sys_sigaction + .llong .sys_ni_syscall .llong .sys_sgetmask .llong .sys_ssetmask .llong .sys_setreuid /* 70 */ .llong .sys_setregid - .llong .sys_sigsuspend - .llong .sys_sigpending + .llong .sys_ni_syscall + .llong .sys_ni_syscall .llong .sys_sethostname .llong .sys_setrlimit /* 75 */ .llong .sys_ni_syscall /* old getrlimit syscall */ @@ -864,14 +870,14 @@ .llong .sys_sysinfo .llong .sys_ipc .llong .sys_fsync - .llong .ppc64_sigreturn + .llong .sys_ni_syscall .llong .sys_clone /* 120 */ .llong .sys_setdomainname .llong .ppc64_newuname .llong .sys_ni_syscall /* old modify_ldt syscall */ .llong .sys_adjtimex .llong .sys_mprotect /* 125 */ - .llong .sys_sigprocmask + .llong .sys_ni_syscall .llong .sys_ni_syscall /* old create_module syscall */ .llong .sys_init_module .llong .sys_delete_module diff -Nru a/arch/ppc64/kernel/module.c b/arch/ppc64/kernel/module.c --- a/arch/ppc64/kernel/module.c Thu May 15 15:24:45 2003 +++ b/arch/ppc64/kernel/module.c Thu May 15 15:24:45 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 Thu May 15 15:24:40 2003 +++ b/arch/ppc64/kernel/open_pic.c Thu May 15 15:24:40 2003 @@ -111,7 +111,6 @@ * data has probably been corrupted and we're going to panic or deadlock later * anyway --Troy */ -extern unsigned long* _get_SP(void); #define check_arg_irq(irq) \ if (irq < open_pic_irq_offset || irq >= (NumSources+open_pic_irq_offset)){ \ printk(KERN_ERR "open_pic.c:%d: illegal irq %d\n", __LINE__, irq); \ @@ -765,9 +764,11 @@ openpic_eoi(); } -static void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs) +static irqreturn_t openpic_ipi_action(int cpl, void *dev_id, + struct pt_regs *regs) { smp_message_recv(cpl-openpic_vec_ipi, regs); + return IRQ_HANDLED; } #endif /* CONFIG_SMP */ diff -Nru a/arch/ppc64/kernel/open_pic_defs.h b/arch/ppc64/kernel/open_pic_defs.h --- a/arch/ppc64/kernel/open_pic_defs.h Thu May 15 15:24:40 2003 +++ b/arch/ppc64/kernel/open_pic_defs.h Thu May 15 15:24:40 2003 @@ -298,7 +298,8 @@ #ifdef CONFIG_SMP /* Interprocessor Interrupts */ static void openpic_initipi(u_int ipi, u_int pri, u_int vector); -static void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs); +static irqreturn_t openpic_ipi_action(int cpl, void *dev_id, + struct pt_regs *regs); #endif /* Timer Interrupts */ diff -Nru a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c --- a/arch/ppc64/kernel/pSeries_lpar.c Thu May 15 15:24:46 2003 +++ b/arch/ppc64/kernel/pSeries_lpar.c Thu May 15 15:24:46 2003 @@ -110,29 +110,6 @@ lbuf[0], lbuf[1], &dummy, &dummy, &dummy); } -long plpar_eoi(unsigned long xirr) -{ - return plpar_hcall_norets(H_EOI, xirr); -} - -long plpar_cppr(unsigned long cppr) -{ - return plpar_hcall_norets(H_CPPR, cppr); -} - -long plpar_ipi(unsigned long servernum, - unsigned long mfrr) -{ - return plpar_hcall_norets(H_IPI, servernum, mfrr); -} - -long plpar_xirr(unsigned long *xirr_ret) -{ - unsigned long dummy; - return plpar_hcall(H_XIRR, 0, 0, 0, 0, - xirr_ret, &dummy, &dummy); -} - static void tce_build_pSeriesLP(struct TceTable *tbl, long tcenum, unsigned long uaddr, int direction ) { @@ -179,66 +156,6 @@ } } - -/* PowerPC Interrupts for lpar. */ -/* NOTE: this typedef is duplicated (for now) from xics.c! */ -typedef struct { - int (*xirr_info_get)(int cpu); - void (*xirr_info_set)(int cpu, int val); - void (*cppr_info)(int cpu, u8 val); - void (*qirr_info)(int cpu, u8 val); -} xics_ops; -static int pSeriesLP_xirr_info_get(int n_cpu) -{ - unsigned long lpar_rc; - unsigned long return_value; - - lpar_rc = plpar_xirr(&return_value); - if (lpar_rc != H_Success) { - panic(" bad return code xirr - rc = %lx \n", lpar_rc); - } - return ((int)(return_value)); -} - -static void pSeriesLP_xirr_info_set(int n_cpu, int value) -{ - unsigned long lpar_rc; - unsigned long val64 = value & 0xffffffff; - - lpar_rc = plpar_eoi(val64); - if (lpar_rc != H_Success) { - panic(" bad return code EOI - rc = %ld, value=%lx \n", lpar_rc, val64); - } -} - -static void pSeriesLP_cppr_info(int n_cpu, u8 value) -{ - unsigned long lpar_rc; - - lpar_rc = plpar_cppr(value); - if (lpar_rc != H_Success) { - panic(" bad return code cppr - rc = %lx \n", lpar_rc); - } -} - -static void pSeriesLP_qirr_info(int n_cpu , u8 value) -{ - unsigned long lpar_rc; - - lpar_rc = plpar_ipi(n_cpu, value); - if (lpar_rc != H_Success) { - panic(" bad return code qirr -ipi - rc = %lx \n", lpar_rc); - } -} - -xics_ops pSeriesLP_ops = { - pSeriesLP_xirr_info_get, - pSeriesLP_xirr_info_set, - pSeriesLP_cppr_info, - pSeriesLP_qirr_info -}; -/* end TAI-LPAR */ - int vtermno; /* virtual terminal# for udbg */ diff -Nru a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c --- a/arch/ppc64/kernel/pacaData.c Thu May 15 15:24:42 2003 +++ b/arch/ppc64/kernel/pacaData.c Thu May 15 15:24:42 2003 @@ -20,6 +20,7 @@ #include struct naca_struct *naca; +struct systemcfg *systemcfg; /* The Paca is an array with one entry per processor. Each contains an * ItLpPaca, which contains the information shared between the @@ -65,9 +66,9 @@ struct paca_struct paca[MAX_PACAS] __page_aligned = { #ifdef CONFIG_PPC_ISERIES - PACAINITDATA( 0, 1, &xItLpQueue, 0, 0xc000000000005000), + PACAINITDATA( 0, 1, &xItLpQueue, 0, STAB0_VIRT_ADDR), #else - PACAINITDATA( 0, 1, 0, 0x5000, 0xc000000000005000), + PACAINITDATA( 0, 1, 0, STAB0_PHYS_ADDR, STAB0_VIRT_ADDR), #endif PACAINITDATA( 1, 0, 0, 0, 0), PACAINITDATA( 2, 0, 0, 0, 0), diff -Nru a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c --- a/arch/ppc64/kernel/pci.c Thu May 15 15:24:43 2003 +++ b/arch/ppc64/kernel/pci.c Thu May 15 15:24:43 2003 @@ -21,6 +21,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/ppc64/kernel/pci_dma.c b/arch/ppc64/kernel/pci_dma.c --- a/arch/ppc64/kernel/pci_dma.c Thu May 15 15:24:40 2003 +++ b/arch/ppc64/kernel/pci_dma.c Thu May 15 15:24:40 2003 @@ -134,7 +134,7 @@ dev = ppc64_isabridge_dev; if (!dev) return NULL; - if (naca->platform == PLATFORM_ISERIES_LPAR) { + if (systemcfg->platform == PLATFORM_ISERIES_LPAR) { return ISERIES_DEVNODE(dev)->DevTceTable; } else { return PCI_GET_DN(dev)->tce_table; @@ -723,8 +723,8 @@ */ busdn->bussubno = bus->number; create_pci_bus_tce_table((unsigned long)busdn); - } else - create_tce_tables_for_busesLP(&bus->children); + } + create_tce_tables_for_busesLP(&bus->children); } } @@ -732,7 +732,7 @@ struct pci_dev *dev; struct device_node *dn, *mydn; - if (naca->platform == PLATFORM_PSERIES_LPAR) { + if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { create_tce_tables_for_busesLP(&pci_root_buses); } else { @@ -773,7 +773,7 @@ /* - Tce Table Share between buses, */ /* - Tce Table per logical slot. */ /*****************************************************************/ - if(naca->platform == PLATFORM_ISERIES_LPAR) { + if(systemcfg->platform == PLATFORM_ISERIES_LPAR) { struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)token; getTceTableParmsiSeries(DevNode,newTceTable); @@ -797,7 +797,7 @@ dn = (struct device_node *)token; phb = dn->phb; - if (naca->platform == PLATFORM_PSERIES) + if (systemcfg->platform == PLATFORM_PSERIES) getTceTableParmsPSeries(phb, dn, newTceTable); else getTceTableParmsPSeriesLP(phb, dn, newTceTable); @@ -1135,7 +1135,8 @@ /* Client asked for way to much space. This is checked later anyway */ /* It is easier to debug here for the drivers than in the tce tables.*/ if(order >= NUM_TCE_LEVELS) { - printk("PCI_DMA: pci_unmap_single 0x%lx size to large: 0x%lx \n",dma_handle,size); + printk("PCI_DMA: pci_unmap_single 0x%lx size too" + " large: 0x%lx \n", (long)dma_handle, (long)size); return; } diff -Nru a/arch/ppc64/kernel/proc_ppc64.c b/arch/ppc64/kernel/proc_ppc64.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ppc64/kernel/proc_ppc64.c Thu May 15 15:24:47 2003 @@ -0,0 +1,177 @@ +/* + * arch/ppc64/kernel/proc_ppc64.c + * + * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* + * Change Activity: + * 2001 : mikec : Created + * 2001/06/05 : engebret : Software event count support. + * 2003/02/13 : bergner : Move PMC code to pmc.c + * End Change Activity + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +struct proc_ppc64_t proc_ppc64; + +void proc_ppc64_create_paca(int num); + +static loff_t page_map_seek( struct file *file, loff_t off, int whence); +static ssize_t page_map_read( struct file *file, char *buf, size_t nbytes, loff_t *ppos); +static int page_map_mmap( struct file *file, struct vm_area_struct *vma ); + +static struct file_operations page_map_fops = { + llseek: page_map_seek, + read: page_map_read, + mmap: page_map_mmap +}; + + +static int __init proc_ppc64_init(void) +{ + + printk(KERN_INFO "proc_ppc64: Creating /proc/ppc64/\n"); + + proc_ppc64.root = proc_mkdir("ppc64", 0); + if (!proc_ppc64.root) + return 0; + + proc_ppc64.naca = create_proc_entry("naca", S_IRUSR, proc_ppc64.root); + if ( proc_ppc64.naca ) { + proc_ppc64.naca->nlink = 1; + proc_ppc64.naca->data = naca; + proc_ppc64.naca->size = 4096; + proc_ppc64.naca->proc_fops = &page_map_fops; + } + + proc_ppc64.systemcfg = create_proc_entry("systemcfg", S_IFREG|S_IRUGO, proc_ppc64.root); + if ( proc_ppc64.systemcfg ) { + proc_ppc64.systemcfg->nlink = 1; + proc_ppc64.systemcfg->data = systemcfg; + proc_ppc64.systemcfg->size = 4096; + proc_ppc64.systemcfg->proc_fops = &page_map_fops; + } + + /* /proc/ppc64/paca/XX -- raw paca contents. Only readable to root */ + proc_ppc64.paca = proc_mkdir("paca", proc_ppc64.root); + if (proc_ppc64.paca) { + unsigned long i; + + for (i = 0; i < NR_CPUS; i++) { + if (!cpu_online(i)) + continue; + proc_ppc64_create_paca(i); + } + } + + /* Placeholder for rtas interfaces. */ + proc_ppc64.rtas = proc_mkdir("rtas", proc_ppc64.root); + + return 0; +} + + +/* + * NOTE: since paca data is always in flux the values will never be a consistant set. + * In theory it could be made consistent if we made the corresponding cpu + * copy the page for us (via an IPI). Probably not worth it. + * + */ +void proc_ppc64_create_paca(int num) +{ + struct proc_dir_entry *ent; + struct paca_struct *lpaca = paca + num; + char buf[16]; + + sprintf(buf, "%02x", num); + ent = create_proc_entry(buf, S_IRUSR, proc_ppc64.paca); + if ( ent ) { + ent->nlink = 1; + ent->data = lpaca; + ent->size = 4096; + ent->proc_fops = &page_map_fops; + } +} + + +static loff_t page_map_seek( struct file *file, loff_t off, int whence) +{ + loff_t new; + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + + switch(whence) { + case 0: + new = off; + break; + case 1: + new = file->f_pos + off; + break; + case 2: + new = dp->size + off; + break; + default: + return -EINVAL; + } + if ( new < 0 || new > dp->size ) + return -EINVAL; + return (file->f_pos = new); +} + +static ssize_t page_map_read( struct file *file, char *buf, size_t nbytes, loff_t *ppos) +{ + unsigned pos = *ppos; + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + + if ( pos >= dp->size ) + return 0; + if ( nbytes >= dp->size ) + nbytes = dp->size; + if ( pos + nbytes > dp->size ) + nbytes = dp->size - pos; + + copy_to_user( buf, (char *)dp->data + pos, nbytes ); + *ppos = pos + nbytes; + return nbytes; +} + +static int page_map_mmap( struct file *file, struct vm_area_struct *vma ) +{ + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + + vma->vm_flags |= VM_SHM | VM_LOCKED; + + if ((vma->vm_end - vma->vm_start) > dp->size) + return -EINVAL; + + remap_page_range( vma, vma->vm_start, __pa(dp->data), dp->size, vma->vm_page_prot ); + return 0; +} + +fs_initcall(proc_ppc64_init); + diff -Nru a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c --- a/arch/ppc64/kernel/process.c Thu May 15 15:24:40 2003 +++ b/arch/ppc64/kernel/process.c Thu May 15 15:24:40 2003 @@ -533,8 +533,6 @@ } while (count++ < 32); } -extern unsigned long *_get_SP(void); - void dump_stack(void) { show_tsk_stack(current, (unsigned long)_get_SP()); diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c --- a/arch/ppc64/kernel/prom.c Thu May 15 15:24:41 2003 +++ b/arch/ppc64/kernel/prom.c Thu May 15 15:24:41 2003 @@ -118,7 +118,6 @@ #define FB_MAX 8 #endif -static int ppc64_is_smp; struct prom_t prom = { 0, /* entry */ @@ -301,7 +300,9 @@ unsigned long offset = reloc_offset(); struct prom_t *_prom = PTRRELOC(&prom); struct naca_struct *_naca = RELOC(naca); + struct systemcfg *_systemcfg = RELOC(systemcfg); + /* NOTE: _naca->debug_switch is already initialized. */ #ifdef DEBUG_PROM prom_print(RELOC("prom_initialize_naca: start...\n")); #endif @@ -320,25 +321,35 @@ * d-cache and i-cache sizes... -Peter */ if ( num_cpus == 1 ) { - u32 size; + u32 size, lsize; call_prom(RELOC("getprop"), 4, 1, node, - RELOC("d-cache-line-size"), + RELOC("d-cache-size"), &size, sizeof(size)); - _naca->dCacheL1LineSize = size; - _naca->dCacheL1LogLineSize = __ilog2(size); - _naca->dCacheL1LinesPerPage = PAGE_SIZE / size; + call_prom(RELOC("getprop"), 4, 1, node, + RELOC("d-cache-line-size"), + &lsize, sizeof(lsize)); + + _systemcfg->dCacheL1Size = size; + _systemcfg->dCacheL1LineSize = lsize; + _naca->dCacheL1LogLineSize = __ilog2(lsize); + _naca->dCacheL1LinesPerPage = PAGE_SIZE/lsize; call_prom(RELOC("getprop"), 4, 1, node, - RELOC("i-cache-line-size"), + RELOC("i-cache-size"), &size, sizeof(size)); - _naca->iCacheL1LineSize = size; - _naca->iCacheL1LogLineSize = __ilog2(size); - _naca->iCacheL1LinesPerPage = PAGE_SIZE / size; + call_prom(RELOC("getprop"), 4, 1, node, + RELOC("i-cache-line-size"), + &lsize, sizeof(lsize)); - if (_naca->platform == PLATFORM_PSERIES_LPAR) { + _systemcfg->iCacheL1Size = size; + _systemcfg->iCacheL1LineSize = lsize; + _naca->iCacheL1LogLineSize = __ilog2(lsize); + _naca->iCacheL1LinesPerPage = PAGE_SIZE/lsize; + + if (_systemcfg->platform == PLATFORM_PSERIES_LPAR) { u32 pft_size[2]; call_prom(RELOC("getprop"), 4, 1, node, RELOC("ibm,pft-size"), @@ -408,20 +419,17 @@ } /* We gotta have at least 1 cpu... */ - if (num_cpus < 1) + if ( (_systemcfg->processorCount = num_cpus) < 1 ) PROM_BUG(); - if (num_cpus > 1) - RELOC(ppc64_is_smp) = 1; - - _naca->physicalMemorySize = lmb_phys_mem_size(); + _systemcfg->physicalMemorySize = lmb_phys_mem_size(); - if (_naca->platform == PLATFORM_PSERIES) { + if (_systemcfg->platform == PLATFORM_PSERIES) { unsigned long rnd_mem_size, pteg_count; /* round mem_size up to next power of 2 */ - rnd_mem_size = 1UL << __ilog2(_naca->physicalMemorySize); - if (rnd_mem_size < _naca->physicalMemorySize) + rnd_mem_size = 1UL << __ilog2(_systemcfg->physicalMemorySize); + if (rnd_mem_size < _systemcfg->physicalMemorySize) rnd_mem_size <<= 1; /* # pages / 2 */ @@ -442,49 +450,43 @@ */ _naca->slb_size = 64; -#ifdef DEBUG_PROM - prom_print(RELOC("naca->physicalMemorySize = 0x")); - prom_print_hex(_naca->physicalMemorySize); - prom_print_nl(); - - prom_print(RELOC("naca->pftSize = 0x")); - prom_print_hex(_naca->pftSize); - prom_print_nl(); - - prom_print(RELOC("naca->dCacheL1LineSize = 0x")); - prom_print_hex(_naca->dCacheL1LineSize); - prom_print_nl(); + /* Add an eye catcher and the systemcfg layout version number */ + strcpy(_systemcfg->eye_catcher, RELOC("SYSTEMCFG:PPC64")); + _systemcfg->version.major = SYSTEMCFG_MAJOR; + _systemcfg->version.minor = SYSTEMCFG_MINOR; + _systemcfg->processor = _get_PVR(); - prom_print(RELOC("naca->dCacheL1LogLineSize = 0x")); - prom_print_hex(_naca->dCacheL1LogLineSize); +#ifdef DEBUG_PROM + prom_print(RELOC("systemcfg->processorCount = 0x")); + prom_print_hex(_systemcfg->processorCount); prom_print_nl(); - prom_print(RELOC("naca->dCacheL1LinesPerPage = 0x")); - prom_print_hex(_naca->dCacheL1LinesPerPage); + prom_print(RELOC("systemcfg->physicalMemorySize = 0x")); + prom_print_hex(_systemcfg->physicalMemorySize); prom_print_nl(); - prom_print(RELOC("naca->iCacheL1LineSize = 0x")); - prom_print_hex(_naca->iCacheL1LineSize); + prom_print(RELOC("naca->pftSize = 0x")); + prom_print_hex(_naca->pftSize); prom_print_nl(); - prom_print(RELOC("naca->iCacheL1LogLineSize = 0x")); - prom_print_hex(_naca->iCacheL1LogLineSize); + prom_print(RELOC("systemcfg->dCacheL1LineSize = 0x")); + prom_print_hex(_systemcfg->dCacheL1LineSize); prom_print_nl(); - prom_print(RELOC("naca->iCacheL1LinesPerPage = 0x")); - prom_print_hex(_naca->iCacheL1LinesPerPage); + prom_print(RELOC("systemcfg->iCacheL1LineSize = 0x")); + prom_print_hex(_systemcfg->iCacheL1LineSize); prom_print_nl(); - prom_print(RELOC("naca->serialPortAddr = 0x")); + prom_print(RELOC("naca->serialPortAddr = 0x")); prom_print_hex(_naca->serialPortAddr); prom_print_nl(); - prom_print(RELOC("naca->interrupt_controller = 0x")); + prom_print(RELOC("naca->interrupt_controller = 0x")); prom_print_hex(_naca->interrupt_controller); prom_print_nl(); - prom_print(RELOC("naca->platform = 0x")); - prom_print_hex(_naca->platform); + prom_print(RELOC("systemcfg->platform = 0x")); + prom_print_hex(_systemcfg->platform); prom_print_nl(); prom_print(RELOC("prom_initialize_naca: end...\n")); @@ -549,7 +551,7 @@ unsigned long offset = reloc_offset(); struct prom_t *_prom = PTRRELOC(&prom); struct rtas_t *_rtas = PTRRELOC(&rtas); - struct naca_struct *_naca = RELOC(naca); + struct systemcfg *_systemcfg = RELOC(systemcfg); ihandle prom_rtas; u32 getprop_rval; @@ -565,7 +567,7 @@ RELOC("ibm,hypertas-functions"), hypertas_funcs, sizeof(hypertas_funcs))) > 0) { - _naca->platform = PLATFORM_PSERIES_LPAR; + _systemcfg->platform = PLATFORM_PSERIES_LPAR; } call_prom(RELOC("getprop"), @@ -582,7 +584,7 @@ * of physical memory (or within the RMO region) because RTAS * runs in 32-bit mode and relocate off. */ - if ( _naca->platform == PLATFORM_PSERIES_LPAR ) { + if ( _systemcfg->platform == PLATFORM_PSERIES_LPAR ) { struct lmb *_lmb = PTRRELOC(&lmb); rtas_region = min(_lmb->rmo_size, RTAS_INSTANTIATE_MAX); } @@ -767,13 +769,21 @@ * By doing this, we avoid the pitfalls of trying to DMA to * MMIO space and the DMA alias hole. */ - minsize = 4UL << 20; + /* + * On POWER4, firmware sets the TCE region by assuming + * each TCE table is 8MB. Using this memory for anything + * else will impact performance, so we always allocate 8MB. + * Anton + * + * XXX FIXME use a cpu feature here + */ + minsize = 8UL << 20; /* Align to the greater of the align or size */ - align = (minalign < minsize) ? minsize : minalign; + align = max(minalign, minsize); /* Carve out storage for the TCE table. */ - base = lmb_alloc(8UL << 20, 8UL << 20); + base = lmb_alloc(minsize, align); if ( !base ) { prom_print(RELOC("ERROR, cannot find space for TCE table.\n")); @@ -875,7 +885,7 @@ prom_hold_cpus(unsigned long mem) { unsigned long i; - unsigned int reg; + unsigned int cpuid; phandle node; unsigned long offset = reloc_offset(); char type[64], *path; @@ -885,9 +895,13 @@ unsigned long *spinloop = __v2a(&__secondary_hold_spinloop); unsigned long *acknowledge = __v2a(&__secondary_hold_acknowledge); unsigned long secondary_hold = (unsigned long)__v2a(*PTRRELOC((unsigned long *)__secondary_hold)); + struct systemcfg *_systemcfg = RELOC(systemcfg); struct paca_struct *_xPaca = PTRRELOC(&paca[0]); struct prom_t *_prom = PTRRELOC(&prom); + /* Initially, we must have one active CPU. */ + _systemcfg->processorCount = 1; + #ifdef DEBUG_PROM prom_print(RELOC("prom_hold_cpus: start...\n")); prom_print(RELOC(" 1) spinloop = 0x")); @@ -933,12 +947,12 @@ if (strcmp(type, RELOC("okay")) != 0) continue; - reg = -1; + cpuid = -1; call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"), - ®, sizeof(reg)); + &cpuid, sizeof(cpuid)); /* Only need to start secondary procs, not ourself. */ - if ( reg == _prom->cpu ) + if ( cpuid == _prom->cpu ) continue; path = (char *) mem; @@ -950,7 +964,7 @@ #ifdef DEBUG_PROM prom_print_nl(); prom_print(RELOC("cpu hw idx = 0x")); - prom_print_hex(reg); + prom_print_hex(cpuid); prom_print_nl(); #endif prom_print(RELOC("starting cpu ")); @@ -978,9 +992,8 @@ prom_print(RELOC(" 3) secondary_hold = 0x")); prom_print_hex(secondary_hold); prom_print_nl(); - prom_print_nl(); #endif - call_prom(RELOC("start-cpu"), 3, 0, node, secondary_hold, reg); + call_prom(RELOC("start-cpu"), 3, 0, node, secondary_hold, cpuid); prom_print(RELOC("...")); for ( i = 0 ; (i < 100000000) && (*acknowledge == ((unsigned long)-1)); i++ ) ; @@ -992,10 +1005,11 @@ prom_print_nl(); } #endif - if (*acknowledge == reg) { + if (*acknowledge == cpuid) { prom_print(RELOC("ok\n")); /* Set the number of active processors. */ - _xPaca[reg].active = 1; + _systemcfg->processorCount++; + _xPaca[cpuid].active = 1; } else { prom_print(RELOC("failed: ")); prom_print_hex(*acknowledge); @@ -1024,8 +1038,8 @@ } } _xPaca[i+1].active = 1; - RELOC(hmt_thread_data)[i].threadid = i+1; } + _systemcfg->processorCount *= 2; } else { prom_print(RELOC("Processor is not HMT capable\n")); } @@ -1046,20 +1060,21 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp, unsigned long r6, unsigned long r7) { + int chrp = 0; unsigned long mem; - ihandle prom_root, prom_cpu; + ihandle prom_mmu, prom_op, prom_root, prom_cpu; phandle cpu_pkg; unsigned long offset = reloc_offset(); - long l; + long l, sz; char *p, *d; unsigned long phys; u32 getprop_rval; - struct naca_struct *_naca = RELOC(naca); + struct systemcfg *_systemcfg = RELOC(systemcfg); struct paca_struct *_xPaca = PTRRELOC(&paca[0]); struct prom_t *_prom = PTRRELOC(&prom); /* Default machine type. */ - _naca->platform = PLATFORM_PSERIES; + _systemcfg->platform = PLATFORM_PSERIES; #if 0 /* Reset klimit to take into account the embedded system map */ @@ -1149,6 +1164,8 @@ mem = prom_bi_rec_reserve(mem); + mem = check_display(mem); + prom_instantiate_rtas(); /* Initialize some system info into the Naca early... */ @@ -1158,11 +1175,9 @@ * following, regardless of whether we have an SMP * kernel or not. */ - if (RELOC(ppc64_is_smp)) + if (_systemcfg->processorCount > 1) prom_hold_cpus(mem); - mem = check_display(mem); - #ifdef DEBUG_PROM prom_print(RELOC("copying OF device tree...\n")); #endif @@ -1172,7 +1187,7 @@ lmb_reserve(0, __pa(RELOC(klimit))); - if (_naca->platform == PLATFORM_PSERIES) + if (_systemcfg->platform == PLATFORM_PSERIES) prom_initialize_tce_table(); prom_print(RELOC("Calling quiesce ...\n")); diff -Nru a/arch/ppc64/kernel/ras.c b/arch/ppc64/kernel/ras.c --- a/arch/ppc64/kernel/ras.c Thu May 15 15:24:36 2003 +++ b/arch/ppc64/kernel/ras.c Thu May 15 15:24:36 2003 @@ -54,8 +54,10 @@ #include #include -static void ras_epow_interrupt(int irq, void *dev_id, struct pt_regs * regs); -static void ras_error_interrupt(int irq, void *dev_id, struct pt_regs * regs); +static irqreturn_t ras_epow_interrupt(int irq, void *dev_id, + struct pt_regs * regs); +static irqreturn_t ras_error_interrupt(int irq, void *dev_id, + struct pt_regs * regs); void init_ras_IRQ(void); /* #define DEBUG */ @@ -73,7 +75,7 @@ &len))) { for(i=0; i<(len / sizeof(*ireg)); i++) { request_irq(virt_irq_create_mapping(*(ireg)) + NUM_8259_INTERRUPTS, - &ras_error_interrupt, 0, + ras_error_interrupt, 0, "RAS_ERROR", NULL); ireg++; } @@ -84,7 +86,7 @@ &len))) { for(i=0; i<(len / sizeof(*ireg)); i++) { request_irq(virt_irq_create_mapping(*(ireg)) + NUM_8259_INTERRUPTS, - &ras_epow_interrupt, 0, + ras_epow_interrupt, 0, "RAS_EPOW", NULL); ireg++; } @@ -98,7 +100,7 @@ * to examine the type of power failure and take appropriate action where * the time horizon permits something useful to be done. */ -static void +static irqreturn_t ras_epow_interrupt(int irq, void *dev_id, struct pt_regs * regs) { struct rtas_error_log log_entry; @@ -114,7 +116,8 @@ udbg_printf("EPOW <0x%lx 0x%lx>\n", *((unsigned long *)&log_entry), status); printk(KERN_WARNING - "EPOW <0x%lx 0x%lx>\n",*((unsigned long *)&log_entry), status); + "EPOW <0x%lx 0x%lx>\n",*((unsigned long *)&log_entry), status); + return IRQ_HANDLED; } /* @@ -125,7 +128,7 @@ * For nonrecoverable errors, an error is logged and we stop all processing * as quickly as possible in order to prevent propagation of the failure. */ -static void +static irqreturn_t ras_error_interrupt(int irq, void *dev_id, struct pt_regs * regs) { struct rtas_error_log log_entry; @@ -158,7 +161,6 @@ printk(KERN_WARNING "Warning: Recoverable hardware error <0x%lx 0x%lx>\n", *((unsigned long *)&log_entry), status); - - return; } + return IRQ_HANDLED; } diff -Nru a/arch/ppc64/kernel/rtas-proc.c b/arch/ppc64/kernel/rtas-proc.c --- a/arch/ppc64/kernel/rtas-proc.c Thu May 15 15:24:38 2003 +++ b/arch/ppc64/kernel/rtas-proc.c Thu May 15 15:24:38 2003 @@ -201,7 +201,7 @@ struct proc_dir_entry *entry; rtas_node = find_devices("rtas"); - if ((rtas_node == NULL) || (naca->platform == PLATFORM_ISERIES_LPAR)) { + if ((rtas_node == NULL) || (systemcfg->platform == PLATFORM_ISERIES_LPAR)) { return; } @@ -506,21 +506,27 @@ int error, char * buf) { /* Defined return vales */ - const char * key_switch[] = { "Off\t", "Normal\t", "Secure\t", "Mainenance" }; + const char * key_switch[] = { "Off\t", "Normal\t", "Secure\t", + "Maintenance" }; const char * enclosure_switch[] = { "Closed", "Open" }; const char * lid_status[] = { " ", "Open", "Closed" }; - const char * power_source[] = { "AC\t", "Battery", "AC & Battery" }; + const char * power_source[] = { "AC\t", "Battery", + "AC & Battery" }; const char * battery_remaining[] = { "Very Low", "Low", "Mid", "High" }; const char * epow_sensor[] = { "EPOW Reset", "Cooling warning", "Power warning", "System shutdown", "System halt", "EPOW main enclosure", "EPOW power off" }; - const char * battery_cyclestate[] = { "None", "In progress", "Requested" }; - const char * battery_charging[] = { "Charging", "Discharching", "No current flow" }; - const char * ibm_drconnector[] = { "Empty", "Present" }; + const char * battery_cyclestate[] = { "None", "In progress", + "Requested" }; + const char * battery_charging[] = { "Charging", "Discharching", + "No current flow" }; + const char * ibm_drconnector[] = { "Empty", "Present", "Unusable", + "Exchange" }; const char * ibm_intqueue[] = { "Disabled", "Enabled" }; int have_strings = 0; + int num_states = 0; int temperature = 0; int unknown = 0; int n = 0; @@ -530,13 +536,20 @@ switch (s.token) { case KEY_SWITCH: n += sprintf(buf+n, "Key switch:\t"); - n += sprintf(buf+n, "%s\t", key_switch[state]); - have_strings = 1; + num_states = sizeof(key_switch) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", key_switch[state]); + have_strings = 1; + } break; case ENCLOSURE_SWITCH: n += sprintf(buf+n, "Enclosure switch:\t"); - n += sprintf(buf+n, "%s\t", enclosure_switch[state]); - have_strings = 1; + num_states = sizeof(enclosure_switch) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", + enclosure_switch[state]); + have_strings = 1; + } break; case THERMAL_SENSOR: n += sprintf(buf+n, "Temp. (°C/°F):\t"); @@ -544,39 +557,63 @@ break; case LID_STATUS: n += sprintf(buf+n, "Lid status:\t"); - n += sprintf(buf+n, "%s\t", lid_status[state]); - have_strings = 1; + num_states = sizeof(lid_status) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", lid_status[state]); + have_strings = 1; + } break; case POWER_SOURCE: n += sprintf(buf+n, "Power source:\t"); - n += sprintf(buf+n, "%s\t", power_source[state]); - have_strings = 1; + num_states = sizeof(power_source) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", + power_source[state]); + have_strings = 1; + } break; case BATTERY_VOLTAGE: n += sprintf(buf+n, "Battery voltage:\t"); break; case BATTERY_REMAINING: n += sprintf(buf+n, "Battery remaining:\t"); - n += sprintf(buf+n, "%s\t", battery_remaining[state]); - have_strings = 1; + num_states = sizeof(battery_remaining) / sizeof(char *); + if (state < num_states) + { + n += sprintf(buf+n, "%s\t", + battery_remaining[state]); + have_strings = 1; + } break; case BATTERY_PERCENTAGE: n += sprintf(buf+n, "Battery percentage:\t"); break; case EPOW_SENSOR: n += sprintf(buf+n, "EPOW Sensor:\t"); - n += sprintf(buf+n, "%s\t", epow_sensor[state]); - have_strings = 1; + num_states = sizeof(epow_sensor) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", epow_sensor[state]); + have_strings = 1; + } break; case BATTERY_CYCLESTATE: n += sprintf(buf+n, "Battery cyclestate:\t"); - n += sprintf(buf+n, "%s\t", battery_cyclestate[state]); - have_strings = 1; + num_states = sizeof(battery_cyclestate) / + sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", + battery_cyclestate[state]); + have_strings = 1; + } break; case BATTERY_CHARGING: n += sprintf(buf+n, "Battery Charging:\t"); - n += sprintf(buf+n, "%s\t", battery_charging[state]); - have_strings = 1; + num_states = sizeof(battery_charging) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", + battery_charging[state]); + have_strings = 1; + } break; case IBM_SURVEILLANCE: n += sprintf(buf+n, "Surveillance:\t"); @@ -589,16 +626,24 @@ break; case IBM_DRCONNECTOR: n += sprintf(buf+n, "DR connector:\t"); - n += sprintf(buf+n, "%s\t", ibm_drconnector[state]); - have_strings = 1; + num_states = sizeof(ibm_drconnector) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", + ibm_drconnector[state]); + have_strings = 1; + } break; case IBM_POWERSUPPLY: n += sprintf(buf+n, "Powersupply:\t"); break; case IBM_INTQUEUE: n += sprintf(buf+n, "Interrupt queue:\t"); - n += sprintf(buf+n, "%s\t", ibm_intqueue[state]); - have_strings = 1; + num_states = sizeof(ibm_intqueue) / sizeof(char *); + if (state < num_states) { + n += sprintf(buf+n, "%s\t", + ibm_intqueue[state]); + have_strings = 1; + } break; default: n += sprintf(buf+n, "Unkown sensor (type %d), ignoring it\n", diff -Nru a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c --- a/arch/ppc64/kernel/rtas.c Thu May 15 15:24:34 2003 +++ b/arch/ppc64/kernel/rtas.c Thu May 15 15:24:34 2003 @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -27,7 +28,6 @@ #include #include -struct proc_dir_entry *rtas_proc_dir; /* /proc/ppc64/rtas dir */ struct flash_block_list_header rtas_firmware_flash_list = {0, 0}; /* @@ -216,7 +216,11 @@ image_size += f->blocks[i].length; } next = f->next; - f->next = (struct flash_block_list *)virt_to_absolute((unsigned long)f->next); + /* Don't translate NULL pointer for last entry */ + if(f->next) + f->next = (struct flash_block_list *)virt_to_absolute((unsigned long)f->next); + else + f->next = 0LL; /* make num_blocks into the version/length field */ f->num_blocks = (FLASH_BLOCK_LIST_VERSION << 56) | ((f->num_blocks+1)*16); } @@ -283,7 +287,7 @@ rtas_power_off(); } -EXPORT_SYMBOL(rtas_proc_dir); +EXPORT_SYMBOL(proc_ppc64); EXPORT_SYMBOL(rtas_firmware_flash_list); EXPORT_SYMBOL(rtas_token); EXPORT_SYMBOL(rtas_call); diff -Nru a/arch/ppc64/kernel/rtas_flash.c b/arch/ppc64/kernel/rtas_flash.c --- a/arch/ppc64/kernel/rtas_flash.c Thu May 15 15:24:44 2003 +++ b/arch/ppc64/kernel/rtas_flash.c Thu May 15 15:24:44 2003 @@ -210,7 +210,7 @@ { struct proc_dir_entry *ent = NULL; - if (!rtas_proc_dir) { + if (!proc_ppc64.rtas) { printk(KERN_WARNING "rtas proc dir does not already exist"); return -ENOENT; } @@ -218,7 +218,7 @@ if (rtas_token("ibm,update-flash-64-and-reboot") != RTAS_UNKNOWN_SERVICE) flash_possible = 1; - if ((ent = create_proc_entry(FIRMWARE_FLASH_NAME, S_IRUSR | S_IWUSR, rtas_proc_dir)) != NULL) { + if ((ent = create_proc_entry(FIRMWARE_FLASH_NAME, S_IRUSR | S_IWUSR, proc_ppc64.rtas)) != NULL) { ent->nlink = 1; ent->proc_fops = &rtas_flash_operations; ent->owner = THIS_MODULE; @@ -228,9 +228,9 @@ void __exit rtas_flash_cleanup(void) { - if (!rtas_proc_dir) + if (!proc_ppc64.rtas) return; - remove_proc_entry(FIRMWARE_FLASH_NAME, rtas_proc_dir); + remove_proc_entry(FIRMWARE_FLASH_NAME, proc_ppc64.rtas); } module_init(rtas_flash_init); diff -Nru a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c --- a/arch/ppc64/kernel/setup.c Thu May 15 15:24:38 2003 +++ b/arch/ppc64/kernel/setup.c Thu May 15 15:24:38 2003 @@ -142,9 +142,6 @@ void setup_system(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { - /* This should be fixed properly in kernel/resource.c */ - iomem_resource.end = MEM_SPACE_LIMIT; - #ifdef CONFIG_XMON_DEFAULT debugger = xmon; debugger_bpt = xmon_bpt; @@ -156,10 +153,10 @@ #ifdef CONFIG_PPC_ISERIES /* pSeries systems are identified in prom.c via OF. */ if ( itLpNaca.xLparInstalled == 1 ) - naca->platform = PLATFORM_ISERIES_LPAR; + systemcfg->platform = PLATFORM_ISERIES_LPAR; #endif - switch (naca->platform) { + switch (systemcfg->platform) { #ifdef CONFIG_PPC_ISERIES case PLATFORM_ISERIES_LPAR: iSeries_init_early(); @@ -185,7 +182,7 @@ #endif } - if (naca->platform & PLATFORM_PSERIES) { + if (systemcfg->platform & PLATFORM_PSERIES) { early_console_initialized = 1; register_console(&udbg_console); } @@ -193,32 +190,27 @@ printk("Starting Linux PPC64 %s\n", UTS_RELEASE); printk("-----------------------------------------------------\n"); - printk("naca = 0x%p\n", naca); -#if 0 - printk("naca->processorCount = 0x%x\n", naca->processorCount); -#endif - printk("naca->physicalMemorySize = 0x%lx\n", naca->physicalMemorySize); - printk("naca->dCacheL1LineSize = 0x%x\n", naca->dCacheL1LineSize); - printk("naca->dCacheL1LogLineSize = 0x%x\n", naca->dCacheL1LogLineSize); - printk("naca->dCacheL1LinesPerPage = 0x%x\n", naca->dCacheL1LinesPerPage); - printk("naca->iCacheL1LineSize = 0x%x\n", naca->iCacheL1LineSize); - printk("naca->iCacheL1LogLineSize = 0x%x\n", naca->iCacheL1LogLineSize); - printk("naca->iCacheL1LinesPerPage = 0x%x\n", naca->iCacheL1LinesPerPage); - printk("naca->pftSize = 0x%lx\n", naca->pftSize); - printk("naca->debug_switch = 0x%lx\n", naca->debug_switch); - printk("naca->interrupt_controller = 0x%d\n", naca->interrupt_controller); - printk("htab_data.htab = 0x%p\n", htab_data.htab); - printk("htab_data.num_ptegs = 0x%lx\n", htab_data.htab_num_ptegs); + printk("naca = 0x%p\n", naca); + printk("naca->pftSize = 0x%lx\n", naca->pftSize); + printk("naca->debug_switch = 0x%lx\n", naca->debug_switch); + printk("naca->interrupt_controller = 0x%d\n", naca->interrupt_controller); + printk("systemcf = 0x%p\n", systemcfg); + printk("systemcfg->processorCount = 0x%x\n", systemcfg->processorCount); + printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize); + printk("systemcfg->dCacheL1LineSize = 0x%x\n", systemcfg->dCacheL1LineSize); + printk("systemcfg->iCacheL1LineSize = 0x%x\n", systemcfg->iCacheL1LineSize); + printk("htab_data.htab = 0x%p\n", htab_data.htab); + printk("htab_data.num_ptegs = 0x%lx\n", htab_data.htab_num_ptegs); printk("-----------------------------------------------------\n"); - if (naca->platform & PLATFORM_PSERIES) { + if (systemcfg->platform & PLATFORM_PSERIES) { finish_device_tree(); chrp_init(r3, r4, r5, r6, r7); } mm_init_ppc64(); - switch (naca->platform) { + switch (systemcfg->platform) { #ifdef CONFIG_PPC_ISERIES case PLATFORM_ISERIES_LPAR: iSeries_init(); @@ -312,7 +304,7 @@ * Assume here that all clock rates are the same in a * smp system. -- Cort */ - if (naca->platform != PLATFORM_ISERIES_LPAR) { + if (systemcfg->platform != PLATFORM_ISERIES_LPAR) { struct device_node *cpu_node; int *fp; @@ -516,8 +508,8 @@ * Systems with OF can look in the properties on the cpu node(s) * for a possibly more accurate value. */ - dcache_bsize = naca->dCacheL1LineSize; - icache_bsize = naca->iCacheL1LineSize; + dcache_bsize = systemcfg->dCacheL1LineSize; + icache_bsize = systemcfg->iCacheL1LineSize; /* reboot on panic */ panic_timeout = 180; diff -Nru a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c --- a/arch/ppc64/kernel/signal.c Thu May 15 15:24:32 2003 +++ b/arch/ppc64/kernel/signal.c Thu May 15 15:24:32 2003 @@ -43,57 +43,29 @@ #endif #define GP_REGS_SIZE MIN(sizeof(elf_gregset_t), sizeof(struct pt_regs)) +#define FP_REGS_SIZE sizeof(elf_fpregset_t) -/* - * These are the flags in the MSR that the user is allowed to change - * by modifying the saved value of the MSR on the stack. SE and BE - * should not be in this list since gdb may want to change these. I.e, - * you should be able to step out of a signal handler to see what - * instruction executes next after the signal handler completes. - * Alternately, if you stepped into a signal handler, you should be - * able to continue 'til the next breakpoint from within the signal - * handler, even if the handler returns. - */ -#if 0 -#define MSR_USERCHANGE (MSR_FE0 | MSR_FE1) -#else -/* - * glibc tries to set FE0/FE1 via a signal handler. Since it only ever - * sets both bits and this is the default setting we now disable this - * behaviour. This is done to insure the new prctl which alters FE0/FE1 does - * not get overriden by glibc. Setting and clearing FE0/FE1 via signal - * handler has always been bogus since load_up_fpu used to set FE0/FE1 - * unconditionally. - */ -#define MSR_USERCHANGE 0 -#endif +#define TRAMP_TRACEBACK 3 +#define TRAMP_SIZE 6 /* - * When we have signals to deliver, we set up on the - * user stack, going down from the original stack pointer: - * a sigregs struct - * one or more sigcontext structs with - * a gap of __SIGNAL_FRAMESIZE bytes - * - * Each of these things must be a multiple of 16 bytes in size. - * + * When we have signals to deliver, we set up on the user stack, + * going down from the original stack pointer: + * 1) a rt_sigframe struct which contains the ucontext + * 2) a gap of __SIGNAL_FRAMESIZE bytes which acts as a dummy caller + * frame for the signal handler. */ -struct sigregs { - elf_gregset_t gp_regs; - double fp_regs[ELF_NFPREG]; - unsigned int tramp[2]; - /* 64 bit API allows for 288 bytes below sp before - decrementing it. */ - int abigap[72]; -}; -struct rt_sigframe -{ - unsigned long _unused[2]; +struct rt_sigframe { + /* sys_rt_sigreturn requires the ucontext be the first field */ + struct ucontext uc; + unsigned long _unused[2]; + unsigned int tramp[TRAMP_SIZE]; struct siginfo *pinfo; void *puc; struct siginfo info; - struct ucontext uc; + /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */ + char abigap[288]; }; @@ -102,37 +74,6 @@ /* * Atomically swap in the new signal mask, and wait for a signal. */ -long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7, - struct pt_regs *regs) -{ - sigset_t saveset; - - mask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - regs->result = -EINTR; - regs->gpr[3] = EINTR; - regs->ccr |= 0x10000000; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(&saveset, regs)) - /* - * If a signal handler needs to be called, - * do_signal() has set R3 to the signal number (the - * first argument of the signal handler), so don't - * overwrite that with EINTR ! - * In the other cases, do_signal() doesn't touch - * R3, so it's still set to -EINTR (see above). - */ - return regs->gpr[3]; - } -} - long sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, int p3, int p4, int p6, int p7, struct pt_regs *regs) { @@ -170,339 +111,232 @@ return do_sigaltstack(uss, uoss, regs->gpr[1]); } -long sys_sigaction(int sig, const struct old_sigaction *act, - struct old_sigaction *oact) + +/* + * Set up the sigcontext for the signal frame. + */ + +static int +setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, + int signr, sigset_t *set, unsigned long handler) { - struct k_sigaction new_ka, old_ka; - int ret; + int err = 0; - if (act) { - old_sigset_t mask; + if (regs->msr & MSR_FP) + giveup_fpu(current); - if (verify_area(VERIFY_READ, act, sizeof(*act)) || - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) - return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); - siginitset(&new_ka.sa.sa_mask, mask); - } + current->thread.saved_msr = regs->msr & ~(MSR_FP | MSR_FE0 | MSR_FE1); + regs->msr = current->thread.saved_msr | current->thread.fpexc_mode; + current->thread.saved_softe = regs->softe; + + err |= __put_user(&sc->gp_regs, &sc->regs); + err |= __copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE); + err |= __copy_to_user(&sc->fp_regs, ¤t->thread.fpr, FP_REGS_SIZE); + err |= __put_user(signr, &sc->signal); + err |= __put_user(handler, &sc->handler); + if (set != NULL) + err |= __put_user(set->sig[0], &sc->oldmask); - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - if (!ret && oact) { - if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) - return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); - } + regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1); + current->thread.fpscr = 0; - return ret; + return err; } /* - * When we have rt signals to deliver, we set up on the - * user stack, going down from the original stack pointer: - * a sigregs struct - * one rt_sigframe struct (siginfo + ucontext) - * a gap of __SIGNAL_FRAMESIZE bytes - * - * Each of these things must be a multiple of 16 bytes in size. - * + * Restore the sigcontext from the signal frame. */ -int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, unsigned long r8, - struct pt_regs *regs) +static int +restore_sigcontext(struct pt_regs *regs, sigset_t *set, struct sigcontext *sc) { - struct rt_sigframe *rt_sf; - struct sigcontext sigctx; - struct sigregs *sr; - elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */ - sigset_t set; - stack_t st; + unsigned int err = 0; - rt_sf = (struct rt_sigframe *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); - if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx)) - || copy_from_user(&set, &rt_sf->uc.uc_sigmask, sizeof(set)) - || copy_from_user(&st, &rt_sf->uc.uc_stack, sizeof(st))) - goto badframe; - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); if (regs->msr & MSR_FP) giveup_fpu(current); - /* restore registers - - * sigctx is initialized to point to the - * preamble frame (where registers are stored) - * see handle_signal() - */ - sr = (struct sigregs *)sigctx.regs; - if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs))) - goto badframe; - saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) - | (saved_regs[PT_MSR] & MSR_USERCHANGE); - saved_regs[PT_SOFTE] = regs->softe; - memcpy(regs, saved_regs, GP_REGS_SIZE); - if (copy_from_user(current->thread.fpr, &sr->fp_regs, - sizeof(sr->fp_regs))) - goto badframe; - /* This function sets back the stack flags into - the current task structure. */ - sys_sigaltstack(&st, NULL, 0, 0, 0, 0, regs); + err |= __copy_from_user(regs, &sc->gp_regs, GP_REGS_SIZE); + err |= __copy_from_user(¤t->thread.fpr, &sc->fp_regs, FP_REGS_SIZE); + current->thread.fpexc_mode = regs->msr & (MSR_FE0 | MSR_FE1); + if (set != NULL) + err |= __get_user(set->sig[0], &sc->oldmask); + + /* Don't allow the signal handler to change these modulo FE{0,1} */ + regs->msr = current->thread.saved_msr & ~(MSR_FP | MSR_FE0 | MSR_FE1); + regs->softe = current->thread.saved_softe; - return regs->result; - -badframe: - do_exit(SIGSEGV); + return err; } -static void setup_rt_frame(struct pt_regs *regs, struct sigregs *frame, - signed long newsp) +/* + * Allocate space for the signal frame + */ +static inline void * +get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) { - struct rt_sigframe *rt_sf = (struct rt_sigframe *)newsp; - /* Handler is *really* a pointer to the function descriptor for - * the signal routine. The first entry in the function - * descriptor is the entry address of signal and the second - * entry is the TOC value we need to use. - */ - struct funct_descr_entry { - unsigned long entry; - unsigned long toc; - }; - - struct funct_descr_entry * funct_desc_ptr; - unsigned long temp_ptr; + unsigned long newsp; - /* Set up preamble frame */ - if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) - goto badframe; - if (regs->msr & MSR_FP) - giveup_fpu(current); - if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE) - || __copy_to_user(&frame->fp_regs, current->thread.fpr, - ELF_NFPREG * sizeof(double)) - /* li r0, __NR_rt_sigreturn */ - || __put_user(0x38000000UL + __NR_rt_sigreturn, &frame->tramp[0]) - /* sc */ - || __put_user(0x44000002UL, &frame->tramp[1])) - goto badframe; - flush_icache_range((unsigned long)&frame->tramp[0], - (unsigned long)&frame->tramp[2]); - current->thread.fpscr = 0; /* turn off all fp exceptions */ - - /* Retrieve rt_sigframe from stack and - set up registers for signal handler - */ - newsp -= __SIGNAL_FRAMESIZE; + /* Default to using normal stack */ + newsp = regs->gpr[1]; - if (get_user(temp_ptr, &rt_sf->uc.uc_mcontext.handler)) { - goto badframe; + if (ka->sa.sa_flags & SA_ONSTACK) { + if (! on_sig_stack(regs->gpr[1])) + newsp = (current->sas_ss_sp + current->sas_ss_size); } - funct_desc_ptr = (struct funct_descr_entry *)temp_ptr; - - if (put_user(regs->gpr[1], (unsigned long *)newsp) - || get_user(regs->nip, &funct_desc_ptr->entry) - || get_user(regs->gpr[2], &funct_desc_ptr->toc) - || get_user(regs->gpr[3], &rt_sf->uc.uc_mcontext.signal) - || get_user(regs->gpr[4], (unsigned long *)&rt_sf->pinfo) - || get_user(regs->gpr[5], (unsigned long *)&rt_sf->puc)) - goto badframe; + return (void *)((newsp - frame_size) & -8ul); +} - regs->gpr[1] = newsp; - regs->gpr[6] = (unsigned long)rt_sf; - regs->link = (unsigned long)frame->tramp; +static int +setup_trampoline(unsigned int syscall, unsigned int *tramp) +{ + int i, err = 0; - return; + /* addi r1, r1, __SIGNAL_FRAMESIZE # Pop the dummy stackframe */ + err |= __put_user(0x38210000UL | (__SIGNAL_FRAMESIZE & 0xffff), &tramp[0]); + /* li r0, __NR_[rt_]sigreturn| */ + err |= __put_user(0x38000000UL | (syscall & 0xffff), &tramp[1]); + /* sc */ + err |= __put_user(0x44000002UL, &tramp[2]); + + /* Minimal traceback info */ + for (i=TRAMP_TRACEBACK; i < TRAMP_SIZE ;i++) + err |= __put_user(0, &tramp[i]); + + if (!err) + flush_icache_range((unsigned long) &tramp[0], + (unsigned long) &tramp[TRAMP_SIZE]); -badframe: -#if DEBUG_SIG - printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", - regs, frame, newsp); -#endif - do_exit(SIGSEGV); + return err; } /* * Do a signal return; undo the signal stack. */ -long sys_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, unsigned long r8, - struct pt_regs *regs) -{ - struct sigcontext *sc, sigctx; - struct sigregs *sr; - elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */ + +int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, unsigned long r8, + struct pt_regs *regs) +{ + struct ucontext *uc = (struct ucontext *)regs->gpr[1]; sigset_t set; + stack_t st; - sc = (struct sigcontext *)(regs->gpr[1] + __SIGNAL_FRAMESIZE); - if (copy_from_user(&sigctx, sc, sizeof(sigctx))) + if (verify_area(VERIFY_READ, uc, sizeof(*uc))) goto badframe; - set.sig[0] = sigctx.oldmask; -#if _NSIG_WORDS > 1 - set.sig[1] = sigctx._unused[3]; -#endif + if (__copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) + goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - if (regs->msr & MSR_FP) - giveup_fpu(current); - /* restore registers */ - sr = (struct sigregs *)sigctx.regs; - if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs))) + if (restore_sigcontext(regs, NULL, &uc->uc_mcontext)) goto badframe; - saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) - | (saved_regs[PT_MSR] & MSR_USERCHANGE); - saved_regs[PT_SOFTE] = regs->softe; - memcpy(regs, saved_regs, GP_REGS_SIZE); - if (copy_from_user(current->thread.fpr, &sr->fp_regs, - sizeof(sr->fp_regs))) + if (__copy_from_user(&st, &uc->uc_stack, sizeof(st))) goto badframe; + /* This function sets back the stack flags into + the current task structure. */ + sys_sigaltstack(&st, NULL, 0, 0, 0, 0, regs); return regs->result; badframe: +#if DEBUG_SIG + printk("badframe in sys_rt_sigreturn, regs=%p uc=%p &uc->uc_mcontext=%p\n", + regs, uc, &uc->uc_mcontext); +#endif do_exit(SIGSEGV); -} +} -/* - * Set up a signal frame. - */ -static void setup_frame(struct pt_regs *regs, struct sigregs *frame, - unsigned long newsp) +static void +setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs) { - /* Handler is *really* a pointer to the function descriptor for * the signal routine. The first entry in the function * descriptor is the entry address of signal and the second * entry is the TOC value we need to use. */ - struct funct_descr_entry { - unsigned long entry; - unsigned long toc; - }; - - struct funct_descr_entry * funct_desc_ptr; - unsigned long temp_ptr; + func_descr_t *funct_desc_ptr; + struct rt_sigframe *frame; + unsigned long newsp = 0; + int err = 0; - struct sigcontext *sc = (struct sigcontext *)newsp; - - if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) - goto badframe; - if (regs->msr & MSR_FP) - giveup_fpu(current); - if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE) - || __copy_to_user(&frame->fp_regs, current->thread.fpr, - ELF_NFPREG * sizeof(double)) - /* li r0, __NR_sigreturn */ - || __put_user(0x38000000UL + __NR_sigreturn, &frame->tramp[0]) - /* sc */ - || __put_user(0x44000002UL, &frame->tramp[1])) - goto badframe; - flush_icache_range((unsigned long)&frame->tramp[0], - (unsigned long)&frame->tramp[2]); - current->thread.fpscr = 0; /* turn off all fp exceptions */ + frame = get_sigframe(ka, regs, sizeof(*frame)); - newsp -= __SIGNAL_FRAMESIZE; - if (get_user(temp_ptr, &sc->handler)) + if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) goto badframe; - - funct_desc_ptr = (struct funct_descr_entry *)temp_ptr; - if (put_user(regs->gpr[1], (unsigned long *)newsp) - || get_user(regs->nip, &funct_desc_ptr ->entry) - || get_user(regs->gpr[2],&funct_desc_ptr->toc) - || get_user(regs->gpr[3], &sc->signal)) - goto badframe; + err |= __put_user(&frame->info, &frame->pinfo); + err |= __put_user(&frame->uc, &frame->puc); + err |= copy_siginfo_to_user(&frame->info, info); + if (err) + goto badframe; + + /* Create the ucontext. */ + err |= __put_user(0, &frame->uc.uc_flags); + err |= __put_user(0, &frame->uc.uc_link); + err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(regs->gpr[1]), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr, NULL, + (unsigned long)ka->sa.sa_handler); + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + if (err) + goto badframe; + + /* Set up to return from userspace. */ + err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); + if (err) + goto badframe; + + funct_desc_ptr = (func_descr_t *) ka->sa.sa_handler; + + /* Allocate a dummy caller frame for the signal handler. */ + newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE; + err |= put_user(0, (unsigned long *)newsp); + + /* Set up "regs" so we "return" to the signal handler. */ + err |= get_user(regs->nip, &funct_desc_ptr->entry); + regs->link = (unsigned long) &frame->tramp[0]; regs->gpr[1] = newsp; - regs->gpr[4] = (unsigned long)sc; - regs->link = (unsigned long)frame->tramp; + err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); + regs->gpr[3] = signr; + if (ka->sa.sa_flags & SA_SIGINFO) { + err |= get_user(regs->gpr[4], (unsigned long *)&frame->pinfo); + err |= get_user(regs->gpr[5], (unsigned long *)&frame->puc); + regs->gpr[6] = (unsigned long) frame; + } else { + regs->gpr[4] = (unsigned long)&frame->uc.uc_mcontext; + } + if (err) + goto badframe; return; badframe: #if DEBUG_SIG - printk("badframe in setup_frame, regs=%p frame=%p newsp=%lx\n", + printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif do_exit(SIGSEGV); } + /* * OK, we're invoking a handler */ -static void handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs, unsigned long *newspp, unsigned long frame) +static void +handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { - struct sigcontext *sc; - struct rt_sigframe *rt_sf; - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - - if (regs->trap == 0x0C00 /* System Call! */ - && ((int)regs->result == -ERESTARTNOHAND || - (int)regs->result == -ERESTART_RESTARTBLOCK || - ((int)regs->result == -ERESTARTSYS && - !(ka->sa.sa_flags & SA_RESTART)))) { - if ((int)regs->result == -ERESTART_RESTARTBLOCK) - current_thread_info()->restart_block.fn - = do_no_restart_syscall; - regs->result = -EINTR; - } - /* Set up Signal Frame */ - if (ka->sa.sa_flags & SA_SIGINFO) { - /* Put a Real Time Context onto stack */ - *newspp -= sizeof(*rt_sf); - rt_sf = (struct rt_sigframe *)*newspp; - if (verify_area(VERIFY_WRITE, rt_sf, sizeof(*rt_sf))) - goto badframe; - - if (__put_user((unsigned long)ka->sa.sa_handler, - &rt_sf->uc.uc_mcontext.handler) - || __put_user(&rt_sf->info, &rt_sf->pinfo) - || __put_user(&rt_sf->uc, &rt_sf->puc) - /* Put the siginfo */ - || copy_siginfo_to_user(&rt_sf->info, info) - /* Create the ucontext */ - || __put_user(0, &rt_sf->uc.uc_flags) - || __put_user(0, &rt_sf->uc.uc_link) - || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp) - || __put_user(sas_ss_flags(regs->gpr[1]), - &rt_sf->uc.uc_stack.ss_flags) - || __put_user(current->sas_ss_size, - &rt_sf->uc.uc_stack.ss_size) - || __copy_to_user(&rt_sf->uc.uc_sigmask, - oldset, sizeof(*oldset)) - /* mcontext.regs points to preamble register frame */ - || __put_user((struct pt_regs *)frame, &rt_sf->uc.uc_mcontext.regs) - || __put_user(sig, &rt_sf->uc.uc_mcontext.signal)) - goto badframe; - } else { - /* Put a sigcontext on the stack */ - *newspp -= sizeof(*sc); - sc = (struct sigcontext *)*newspp; - if (verify_area(VERIFY_WRITE, sc, sizeof(*sc))) - goto badframe; - - if (__put_user((unsigned long)ka->sa.sa_handler, &sc->handler) - || __put_user(oldset->sig[0], &sc->oldmask) -#if _NSIG_WORDS > 1 - || __put_user(oldset->sig[1], &sc->_unused[3]) -#endif - || __put_user((struct pt_regs *)frame, &sc->regs) - || __put_user(sig, &sc->signal)) - goto badframe; - } + setup_rt_frame(sig, ka, info, oldset, regs); if (ka->sa.sa_flags & SA_ONESHOT) ka->sa.sa_handler = SIG_DFL; @@ -515,14 +349,40 @@ spin_unlock_irq(¤t->sighand->siglock); } return; +} -badframe: -#if DEBUG_SIG - printk("badframe in handle_signal, regs=%p frame=%lx newsp=%lx\n", - regs, frame, *newspp); - printk("sc=%p sig=%d ka=%p info=%p oldset=%p\n", sc, sig, ka, info, oldset); -#endif - do_exit(SIGSEGV); +static inline void +syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) +{ + switch ((int)regs->result) { + case -ERESTART_RESTARTBLOCK: + current_thread_info()->restart_block.fn = do_no_restart_syscall; + /* fallthrough */ + case -ERESTARTNOHAND: + /* ERESTARTNOHAND means that the syscall should only be + * restarted if there was no handler for the signal, and since + * we only get here if there is a handler, we dont restart. + */ + regs->result = -EINTR; + break; + case -ERESTARTSYS: + /* ERESTARTSYS means to restart the syscall if there is no + * handler or the handler was registered with SA_RESTART + */ + if (!(ka->sa.sa_flags & SA_RESTART)) { + regs->result = -EINTR; + break; + } + /* fallthrough */ + case -ERESTARTNOINTR: + /* ERESTARTNOINTR means that the syscall should be + * called again after the signal handler returns. + */ + regs->gpr[3] = regs->orig_gpr3; + regs->nip -= 4; + regs->result = 0; + break; + } } /* @@ -535,8 +395,6 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) { siginfo_t info; - struct k_sigaction *ka; - unsigned long frame, newsp; int signr; /* @@ -549,20 +407,15 @@ if (!oldset) oldset = ¤t->blocked; - newsp = frame = 0; - signr = get_signal_to_deliver(&info, regs, NULL); if (signr > 0) { - ka = ¤t->sighand->action[signr-1]; - if ((ka->sa.sa_flags & SA_ONSTACK) - && (!on_sig_stack(regs->gpr[1]))) - newsp = (current->sas_ss_sp + current->sas_ss_size); - else - newsp = regs->gpr[1]; - newsp = frame = newsp - sizeof(struct sigregs); + struct k_sigaction *ka = ¤t->sighand->action[signr-1]; /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, oldset, regs, &newsp, frame); + if (regs->trap == 0x0C00) + syscall_restart(regs, ka); + handle_signal(signr, ka, &info, oldset, regs); + return 1; } if (regs->trap == 0x0C00) { /* System Call! */ @@ -579,13 +432,8 @@ } } - if (newsp == frame) - return 0; /* no signals delivered */ - - /* Invoke correct stack setup routine */ - if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame(regs, (struct sigregs *)frame, newsp); - else - setup_frame(regs, (struct sigregs *)frame, newsp); - return 1; + return 0; } + + + diff -Nru a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c --- a/arch/ppc64/kernel/signal32.c Thu May 15 15:24:44 2003 +++ b/arch/ppc64/kernel/signal32.c Thu May 15 15:24:44 2003 @@ -114,6 +114,40 @@ * setup_frame32 */ +/* + * Atomically swap in the new signal mask, and wait for a signal. + */ +long sys32_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7, + struct pt_regs *regs) +{ + sigset_t saveset; + + mask &= _BLOCKABLE; + spin_lock_irq(¤t->sighand->siglock); + saveset = current->blocked; + siginitset(¤t->blocked, mask); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + regs->result = -EINTR; + regs->gpr[3] = EINTR; + regs->ccr |= 0x10000000; + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (do_signal32(&saveset, regs)) + /* + * If a signal handler needs to be called, + * do_signal32() has set R3 to the signal number (the + * first argument of the signal handler), so don't + * overwrite that with EINTR ! + * In the other cases, do_signal32() doesn't touch + * R3, so it's still set to -EINTR (see above). + */ + return regs->gpr[3]; + } +} + long sys32_sigaction(int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact) { @@ -792,13 +826,13 @@ while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(&saveset, regs)) + if (do_signal32(&saveset, regs)) /* * If a signal handler needs to be called, - * do_signal() has set R3 to the signal number (the + * do_signal32() has set R3 to the signal number (the * first argument of the signal handler), so don't * overwrite that with EINTR ! - * In the other cases, do_signal() doesn't touch + * In the other cases, do_signal32() doesn't touch * R3, so it's still set to -EINTR (see above). */ return regs->gpr[3]; diff -Nru a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c --- a/arch/ppc64/kernel/smp.c Thu May 15 15:24:41 2003 +++ b/arch/ppc64/kernel/smp.c Thu May 15 15:24:41 2003 @@ -46,8 +46,9 @@ #include #include "open_pic.h" #include +#include -int smp_threads_ready = 0; +int smp_threads_ready; unsigned long cache_decay_ticks; /* initialised so it doesn't end up in bss */ @@ -63,18 +64,6 @@ void smp_call_function_interrupt(void); void smp_message_pass(int target, int msg, unsigned long data, int wait); -void xics_setup_cpu(void); -void xics_cause_IPI(int cpu); - -/* - * XICS only has a single IPI, so encode the messages per CPU - */ -struct xics_ipi_struct { - volatile unsigned long value; -} ____cacheline_aligned; - -struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; - #define smp_message_pass(t,m,d,w) smp_ops->message_pass((t),(m),(d),(w)) static inline void set_tb(unsigned int upper, unsigned int lower) @@ -189,7 +178,7 @@ smp_ops->kick_cpu = smp_iSeries_kick_cpu; smp_ops->setup_cpu = smp_iSeries_setup_cpu; #warning fix for iseries - naca->processorCount = smp_iSeries_numProcs(); + systemcfg->processorCount = smp_iSeries_numProcs(); } #endif @@ -353,7 +342,7 @@ smp_ops->probe = smp_xics_probe; } - if (naca->platform == PLATFORM_PSERIES) { + if (systemcfg->platform == PLATFORM_PSERIES) { smp_ops->give_timebase = pSeries_give_timebase; smp_ops->take_timebase = pSeries_take_timebase; } diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c --- a/arch/ppc64/kernel/sys_ppc32.c Thu May 15 15:24:41 2003 +++ b/arch/ppc64/kernel/sys_ppc32.c Thu May 15 15:24:41 2003 @@ -1801,7 +1801,7 @@ err = do_sys32_shmctl(first, second, (void *)AA(ptr)); break; default: - err = -EINVAL; + err = -ENOSYS; break; } return err; diff -Nru a/arch/ppc64/kernel/syscalls.c b/arch/ppc64/kernel/syscalls.c --- a/arch/ppc64/kernel/syscalls.c Thu May 15 15:24:41 2003 +++ b/arch/ppc64/kernel/syscalls.c Thu May 15 15:24:41 2003 @@ -68,7 +68,7 @@ version = call >> 16; /* hack for backward compatibility */ call &= 0xffff; - ret = -EINVAL; + ret = -ENOSYS; switch (call) { case SEMOP: ret = sys_semop (first, (struct sembuf *)ptr, second); diff -Nru a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c --- a/arch/ppc64/kernel/traps.c Thu May 15 15:24:39 2003 +++ b/arch/ppc64/kernel/traps.c Thu May 15 15:24:39 2003 @@ -55,14 +55,12 @@ * Trap & Exception support */ -/* Should we panic on bad kernel exceptions or try to recover */ -#undef PANIC_ON_ERROR - static spinlock_t die_lock = SPIN_LOCK_UNLOCKED; void die(const char *str, struct pt_regs *regs, long err) { static int die_counter; + console_verbose(); spin_lock_irq(&die_lock); bust_spinlocks(1); @@ -71,11 +69,16 @@ bust_spinlocks(0); spin_unlock_irq(&die_lock); -#ifdef PANIC_ON_ERROR - panic(str); -#else + if (in_interrupt()) + panic("Fatal exception in interrupt"); + + if (panic_on_oops) { + printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n"); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(5 * HZ); + panic("Fatal exception"); + } do_exit(SIGSEGV); -#endif } static void @@ -139,15 +142,13 @@ #ifdef CONFIG_DEBUG_KERNEL if (debugger) debugger(regs); + else #endif + panic("System Reset"); -#ifdef PANIC_ON_ERROR - panic("System Reset"); -#else /* Must die if the interrupt is not recoverable */ if (!(regs->msr & MSR_RI)) panic("Unrecoverable System Reset"); -#endif /* What should we do here? We could issue a shutdown or hard reset. */ } @@ -343,6 +344,14 @@ info.si_addr = (void *)regs->nip; _exception(SIGILL, &info, regs); } +} + + void +KernelFPUnavailableException(struct pt_regs *regs) +{ + printk("Illegal floating point used in kernel (task=0x%016lx, pc=0x%016lx, trap=0x%08x)\n", + current, regs->nip, regs->trap); + panic("Unrecoverable FP Unavailable Exception in Kernel"); } void diff -Nru a/arch/ppc64/kernel/udbg.c b/arch/ppc64/kernel/udbg.c --- a/arch/ppc64/kernel/udbg.c Thu May 15 15:24:33 2003 +++ b/arch/ppc64/kernel/udbg.c Thu May 15 15:24:33 2003 @@ -176,7 +176,7 @@ void udbg_printSP(const char *s) { - if (naca->platform == PLATFORM_PSERIES) { + if (systemcfg->platform == PLATFORM_PSERIES) { unsigned long sp; asm("mr %0,1" : "=r" (sp) :); if (s) diff -Nru a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c --- a/arch/ppc64/kernel/xics.c Thu May 15 15:24:39 2003 +++ b/arch/ppc64/kernel/xics.c Thu May 15 15:24:39 2003 @@ -1,5 +1,5 @@ /* - * arch/ppc/kernel/xics.c + * arch/ppc64/kernel/xics.c * * Copyright 2000 IBM Corporation. * @@ -22,10 +22,11 @@ #include #include #include -#include "i8259.h" #include #include -#include +#include + +#include "i8259.h" void xics_enable_irq(u_int irq); void xics_disable_irq(u_int irq); @@ -61,33 +62,39 @@ /* Want a priority other than 0. Various HW issues require this. */ #define DEFAULT_PRIORITY 5 +/* + * Mark IPIs as higher priority so we can take them inside interrupts that + * arent marked SA_INTERRUPT + */ +#define IPI_PRIORITY 4 + struct xics_ipl { union { - u32 word; - u8 bytes[4]; + u32 word; + u8 bytes[4]; } xirr_poll; union { u32 word; - u8 bytes[4]; + u8 bytes[4]; } xirr; - u32 dummy; + u32 dummy; union { - u32 word; - u8 bytes[4]; + u32 word; + u8 bytes[4]; } qirr; }; -struct xics_info { - volatile struct xics_ipl * per_cpu[NR_CPUS]; -}; +static struct xics_ipl *xics_per_cpu[NR_CPUS]; -struct xics_info xics_info; +static int xics_irq_8259_cascade = 0; +static int xics_irq_8259_cascade_real = 0; +static unsigned int default_server = 0xFF; +static unsigned int default_distrib_server = 0; -unsigned long long intr_base = 0; -int xics_irq_8259_cascade = 0; -int xics_irq_8259_cascade_real = 0; -unsigned int default_server = 0xFF; -unsigned int default_distrib_server = 0; +/* + * XICS only has a single IPI, so encode the messages per CPU + */ +struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; /* RTAS service tokens */ int ibm_get_xive; @@ -95,11 +102,6 @@ int ibm_int_on; int ibm_int_off; -struct xics_interrupt_node { - unsigned long long addr; - unsigned long long size; -} inodes[NR_CPUS*2]; - typedef struct { int (*xirr_info_get)(int cpu); void (*xirr_info_set)(int cpu, int val); @@ -108,24 +110,26 @@ } xics_ops; +/* SMP */ + static int pSeries_xirr_info_get(int n_cpu) { - return (xics_info.per_cpu[n_cpu]->xirr.word); + return xics_per_cpu[n_cpu]->xirr.word; } static void pSeries_xirr_info_set(int n_cpu, int value) { - xics_info.per_cpu[n_cpu]->xirr.word = value; + xics_per_cpu[n_cpu]->xirr.word = value; } static void pSeries_cppr_info(int n_cpu, u8 value) { - xics_info.per_cpu[n_cpu]->xirr.bytes[0] = value; + xics_per_cpu[n_cpu]->xirr.bytes[0] = value; } -static void pSeries_qirr_info(int n_cpu , u8 value) +static void pSeries_qirr_info(int n_cpu, u8 value) { - xics_info.per_cpu[n_cpu]->qirr.bytes[0] = value; + xics_per_cpu[n_cpu]->qirr.bytes[0] = value; } static xics_ops pSeries_ops = { @@ -136,113 +140,174 @@ }; static xics_ops *ops = &pSeries_ops; -extern xics_ops pSeriesLP_ops; -void -xics_enable_irq( - u_int virq - ) +/* LPAR */ + +static inline long plpar_eoi(unsigned long xirr) { - u_int irq; - unsigned long status; - long call_status; + return plpar_hcall_norets(H_EOI, xirr); +} + +static inline long plpar_cppr(unsigned long cppr) +{ + return plpar_hcall_norets(H_CPPR, cppr); +} + +static inline long plpar_ipi(unsigned long servernum, unsigned long mfrr) +{ + return plpar_hcall_norets(H_IPI, servernum, mfrr); +} + +static inline long plpar_xirr(unsigned long *xirr_ret) +{ + unsigned long dummy; + return plpar_hcall(H_XIRR, 0, 0, 0, 0, xirr_ret, &dummy, &dummy); +} + +static int pSeriesLP_xirr_info_get(int n_cpu) +{ + unsigned long lpar_rc; + unsigned long return_value; + + lpar_rc = plpar_xirr(&return_value); + if (lpar_rc != H_Success) + panic(" bad return code xirr - rc = %lx \n", lpar_rc); + return (int)return_value; +} + +static void pSeriesLP_xirr_info_set(int n_cpu, int value) +{ + unsigned long lpar_rc; + unsigned long val64 = value & 0xffffffff; + + lpar_rc = plpar_eoi(val64); + if (lpar_rc != H_Success) + panic("bad return code EOI - rc = %ld, value=%lx\n", lpar_rc, + val64); +} + +static void pSeriesLP_cppr_info(int n_cpu, u8 value) +{ + unsigned long lpar_rc; + + lpar_rc = plpar_cppr(value); + if (lpar_rc != H_Success) + panic("bad return code cppr - rc = %lx\n", lpar_rc); +} + +static void pSeriesLP_qirr_info(int n_cpu , u8 value) +{ + unsigned long lpar_rc; + + lpar_rc = plpar_ipi(n_cpu, value); + if (lpar_rc != H_Success) + panic("bad return code qirr - rc = %lx\n", lpar_rc); +} + +xics_ops pSeriesLP_ops = { + pSeriesLP_xirr_info_get, + pSeriesLP_xirr_info_set, + pSeriesLP_cppr_info, + pSeriesLP_qirr_info +}; + +void xics_enable_irq(u_int virq) +{ + u_int irq; + long call_status; + unsigned int server; virq -= XICS_IRQ_OFFSET; irq = virt_irq_to_real(virq); if (irq == XICS_IPI) return; + #ifdef CONFIG_IRQ_ALL_CPUS - call_status = rtas_call(ibm_set_xive, 3, 1, (unsigned long*)&status, - irq, smp_threads_ready ? default_distrib_server : default_server, DEFAULT_PRIORITY); + if (smp_threads_ready) + server = default_distrib_server; + else + server = default_server; #else - call_status = rtas_call(ibm_set_xive, 3, 1, (unsigned long*)&status, - irq, default_server, DEFAULT_PRIORITY); + server = default_server; #endif - if( call_status != 0 ) { - printk("xics_enable_irq: irq=%x: rtas_call failed; retn=%lx, status=%lx\n", - irq, call_status, status); + + call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, + DEFAULT_PRIORITY); + if (call_status != 0) { + printk("xics_enable_irq: irq=%x: ibm_set_xive returned %lx\n", + irq, call_status); return; } + /* Now unmask the interrupt (often a no-op) */ - call_status = rtas_call(ibm_int_on, 1, 1, (unsigned long*)&status, - irq); - if( call_status != 0 ) { - printk("xics_disable_irq on: irq=%x: rtas_call failed, retn=%lx\n", + call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq); + if (call_status != 0) { + printk("xics_enable_irq: irq=%x: ibm_int_on returned %lx\n", irq, call_status); return; } } -void -xics_disable_irq( - u_int virq - ) -{ - u_int irq; - unsigned long status; - long call_status; +void xics_disable_irq(u_int virq) +{ + u_int irq; + long call_status; virq -= XICS_IRQ_OFFSET; irq = virt_irq_to_real(virq); - call_status = rtas_call(ibm_int_off, 1, 1, (unsigned long*)&status, - irq); - if( call_status != 0 ) { - printk("xics_disable_irq: irq=%x: rtas_call failed, retn=%lx\n", + if (irq == XICS_IPI) + return; + + call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq); + if (call_status != 0) { + printk("xics_disable_irq: irq=%x: ibm_int_off returned %lx\n", irq, call_status); return; } } -void -xics_end_irq( - u_int irq - ) +void xics_end_irq(u_int irq) { int cpu = smp_processor_id(); - ops->cppr_info(cpu, 0); /* actually the value overwritten by ack */ - iosync(); - ops->xirr_info_set(cpu, ((0xff<<24) | (virt_irq_to_real(irq-XICS_IRQ_OFFSET)))); iosync(); + ops->xirr_info_set(cpu, ((0xff<<24) | + (virt_irq_to_real(irq-XICS_IRQ_OFFSET)))); } -void -xics_mask_and_ack_irq(u_int irq) +void xics_mask_and_ack_irq(u_int irq) { int cpu = smp_processor_id(); - if( irq < XICS_IRQ_OFFSET ) { + if (irq < XICS_IRQ_OFFSET) { i8259_pic.ack(irq); iosync(); - ops->xirr_info_set(cpu, ((0xff<<24) | xics_irq_8259_cascade_real)); - iosync(); - } - else { - ops->cppr_info(cpu, 0xff); + ops->xirr_info_set(cpu, ((0xff<<24) | + xics_irq_8259_cascade_real)); iosync(); } } -int -xics_get_irq(struct pt_regs *regs) +int xics_get_irq(struct pt_regs *regs) { - u_int cpu = smp_processor_id(); - u_int vec; + u_int cpu = smp_processor_id(); + u_int vec; int irq; vec = ops->xirr_info_get(cpu); /* (vec >> 24) == old priority */ vec &= 0x00ffffff; + /* for sanity, this had better be < NR_IRQS - 16 */ - if( vec == xics_irq_8259_cascade_real ) { + if (vec == xics_irq_8259_cascade_real) { irq = i8259_irq(cpu); - if(irq == -1) { + if (irq == -1) { /* Spurious cascaded interrupt. Still must ack xics */ xics_end_irq(XICS_IRQ_OFFSET + xics_irq_8259_cascade); irq = -1; } - } else if( vec == XICS_IRQ_SPURIOUS ) { + } else if (vec == XICS_IRQ_SPURIOUS) { irq = -1; } else { irq = real_irq_to_virt(vec) + XICS_IRQ_OFFSET; @@ -250,45 +315,49 @@ return irq; } -struct xics_ipi_struct { - volatile unsigned long value; -} ____cacheline_aligned; +#ifdef CONFIG_SMP extern struct xics_ipi_struct xics_ipi_message[NR_CPUS] __cacheline_aligned; -#ifdef CONFIG_SMP -void xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs) { int cpu = smp_processor_id(); + int handled = 0; ops->qirr_info(cpu, 0xff); while (xics_ipi_message[cpu].value) { - if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION, &xics_ipi_message[cpu].value)) { + handled = 1; + if (test_and_clear_bit(PPC_MSG_CALL_FUNCTION, + &xics_ipi_message[cpu].value)) { mb(); smp_message_recv(PPC_MSG_CALL_FUNCTION, regs); } - if (test_and_clear_bit(PPC_MSG_RESCHEDULE, &xics_ipi_message[cpu].value)) { + if (test_and_clear_bit(PPC_MSG_RESCHEDULE, + &xics_ipi_message[cpu].value)) { mb(); smp_message_recv(PPC_MSG_RESCHEDULE, regs); } #if 0 - if (test_and_clear_bit(PPC_MSG_MIGRATE_TASK, &xics_ipi_message[cpu].value)) { + if (test_and_clear_bit(PPC_MSG_MIGRATE_TASK, + &xics_ipi_message[cpu].value)) { mb(); smp_message_recv(PPC_MSG_MIGRATE_TASK, regs); } #endif #ifdef CONFIG_XMON - if (test_and_clear_bit(PPC_MSG_XMON_BREAK, &xics_ipi_message[cpu].value)) { + if (test_and_clear_bit(PPC_MSG_XMON_BREAK, + &xics_ipi_message[cpu].value)) { mb(); smp_message_recv(PPC_MSG_XMON_BREAK, regs); } #endif } + return IRQ_RETVAL(handled); } void xics_cause_IPI(int cpu) { - ops->qirr_info(cpu,0) ; + ops->qirr_info(cpu, IPI_PRIORITY); } void xics_setup_cpu(void) @@ -298,15 +367,20 @@ ops->cppr_info(cpu, 0xff); iosync(); } + #endif /* CONFIG_SMP */ -void -xics_init_IRQ( void ) +void xics_init_IRQ(void) { int i; unsigned long intr_size = 0; struct device_node *np; uint *ireg, ilen, indx=0; + unsigned long intr_base = 0; + struct xics_interrupt_node { + unsigned long long addr; + unsigned long long size; + } inodes[NR_CPUS*2]; ppc64_boot_msg(0x20, "XICS Init"); @@ -386,23 +460,24 @@ xics_irq_8259_cascade = virt_irq_create_mapping(xics_irq_8259_cascade_real); } - if (naca->platform == PLATFORM_PSERIES) { + if (systemcfg->platform == PLATFORM_PSERIES) { #ifdef CONFIG_SMP for (i = 0; i < NR_CPUS; ++i) { if (!cpu_possible(i)) continue; - xics_info.per_cpu[i] = - __ioremap((ulong)inodes[i].addr, - (ulong)inodes[i].size, _PAGE_NO_CACHE); + xics_per_cpu[i] = __ioremap((ulong)inodes[i].addr, + (ulong)inodes[i].size, + _PAGE_NO_CACHE); } #else - xics_info.per_cpu[0] = __ioremap((ulong)intr_base, intr_size, _PAGE_NO_CACHE); + xics_per_cpu[0] = __ioremap((ulong)intr_base, intr_size, + _PAGE_NO_CACHE); #endif /* CONFIG_SMP */ #ifdef CONFIG_PPC_PSERIES /* actually iSeries does not use any of xics...but it has link dependencies * for now, except this new one... */ - } else if (naca->platform == PLATFORM_PSERIES_LPAR) { + } else if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { ops = &pSeriesLP_ops; #endif } @@ -417,8 +492,8 @@ ops->cppr_info(boot_cpuid, 0xff); iosync(); if (xics_irq_8259_cascade != -1) { - if (request_irq(xics_irq_8259_cascade + XICS_IRQ_OFFSET, no_action, - 0, "8259 cascade", 0)) + if (request_irq(xics_irq_8259_cascade + XICS_IRQ_OFFSET, + no_action, 0, "8259 cascade", 0)) printk(KERN_ERR "xics_init_IRQ: couldn't get 8259 cascade\n"); i8259_init(); } diff -Nru a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c --- a/arch/ppc64/mm/fault.c Thu May 15 15:24:42 2003 +++ b/arch/ppc64/mm/fault.c Thu May 15 15:24:42 2003 @@ -75,8 +75,8 @@ } #endif - /* On an SLB miss we can only check for a valid exception entry */ - if (regs->trap == 0x380) { + /* On a kernel SLB miss we can only check for a valid exception entry */ + if (!user_mode(regs) && (regs->trap == 0x380)) { bad_page_fault(regs, address, SIGSEGV); return; } diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c --- a/arch/ppc64/mm/init.c Thu May 15 15:24:40 2003 +++ b/arch/ppc64/mm/init.c Thu May 15 15:24:40 2003 @@ -69,8 +69,6 @@ int mem_init_done; unsigned long ioremap_bot = IMALLOC_BASE; -static int boot_mapsize; - extern pgd_t swapper_pg_dir[]; extern char __init_begin, __init_end; extern char _start[], _end[]; @@ -454,6 +452,7 @@ unsigned long i; unsigned long start, bootmap_pages; unsigned long total_pages = lmb_end_of_DRAM() >> PAGE_SHIFT; + int boot_mapsize; /* * Find an area to use for the bootmem bitmap. Calculate the size of @@ -532,7 +531,7 @@ int nid; for (nid = 0; nid < numnodes; nid++) { - if (numa_node_exists[nid]) { + if (node_data[nid].node_size != 0) { printk("freeing bootmem node %x\n", nid); totalram_pages += free_all_bootmem_node(NODE_DATA(nid)); diff -Nru a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c --- a/arch/ppc64/mm/numa.c Thu May 15 15:24:41 2003 +++ b/arch/ppc64/mm/numa.c Thu May 15 15:24:41 2003 @@ -24,11 +24,18 @@ int numa_cpu_lookup_table[NR_CPUS] = { [ 0 ... (NR_CPUS - 1)] = -1}; int numa_memory_lookup_table[MAX_MEMORY >> MEMORY_INCREMENT_SHIFT] = { [ 0 ... ((MAX_MEMORY >> MEMORY_INCREMENT_SHIFT) - 1)] = -1}; -int numa_node_exists[MAX_NUMNODES]; +unsigned long numa_cpumask_lookup_table[MAX_NUMNODES]; struct pglist_data node_data[MAX_NUMNODES]; bootmem_data_t plat_node_bdata[MAX_NUMNODES]; +static inline void map_cpu_to_node(int cpu, int node) +{ + dbg("cpu %d maps to domain %d\n", cpu, node); + numa_cpu_lookup_table[cpu] = node; + numa_cpumask_lookup_table[node] |= 1UL << cpu; +} + static int __init parse_numa_properties(void) { struct device_node *cpu; @@ -88,9 +95,7 @@ if (max_domain < numa_domain) max_domain = numa_domain; - numa_cpu_lookup_table[cpu_nr] = numa_domain; - - dbg("cpu %d maps to domain %d\n", cpu_nr, numa_domain); + map_cpu_to_node(cpu_nr, numa_domain); } for (memory = find_type_devices("memory"); memory; @@ -135,7 +140,7 @@ /* FIXME */ if (numa_domain == 0xffff) { - dbg("cpu has no numa doman\n"); + dbg("memory has no numa doman\n"); numa_domain = 0; } @@ -145,7 +150,8 @@ if (max_domain < numa_domain) max_domain = numa_domain; - numa_node_exists[numa_domain] = 1; + node_data[numa_domain].node_start_pfn = start / PAGE_SIZE; + node_data[numa_domain].node_size = size / PAGE_SIZE; for (i = start ; i < (start+size); i += MEMORY_INCREMENT) numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = @@ -176,27 +182,17 @@ BUG(); for (nid = 0; nid < numnodes; nid++) { - unsigned long start, end; unsigned long start_paddr, end_paddr; int i; unsigned long bootmem_paddr; unsigned long bootmap_pages; - if (!numa_node_exists[nid]) + if (node_data[nid].node_size == 0) continue; - /* Find start and end of this zone */ - start = 0; - while (numa_memory_lookup_table[start] != nid) - start++; - - end = (MAX_MEMORY >> MEMORY_INCREMENT_SHIFT) - 1; - while (numa_memory_lookup_table[end] != nid) - end--; - end++; - - start_paddr = start << MEMORY_INCREMENT_SHIFT; - end_paddr = end << MEMORY_INCREMENT_SHIFT; + start_paddr = node_data[nid].node_start_pfn * PAGE_SIZE; + end_paddr = start_paddr + + (node_data[nid].node_size * PAGE_SIZE); dbg("node %d\n", nid); dbg("start_paddr = %lx\n", start_paddr); @@ -278,7 +274,7 @@ unsigned long start_pfn; unsigned long end_pfn; - if (!numa_node_exists[nid]) + if (node_data[nid].node_size == 0) continue; start_pfn = plat_node_bdata[nid].node_boot_start >> PAGE_SHIFT; diff -Nru a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c --- a/arch/ppc64/xmon/xmon.c Thu May 15 15:24:43 2003 +++ b/arch/ppc64/xmon/xmon.c Thu May 15 15:24:43 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 Thu May 15 15:24:43 2003 +++ b/arch/s390/kernel/compat_exec.c Thu May 15 15:24:43 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 Thu May 15 15:24:43 2003 +++ b/arch/s390/kernel/module.c Thu May 15 15:24:43 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 Thu May 15 15:24:40 2003 +++ b/arch/s390/kernel/s390_ksyms.c Thu May 15 15:24:40 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 Thu May 15 15:24:36 2003 +++ b/arch/s390/kernel/traps.c Thu May 15 15:24:36 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 Thu May 15 15:24:36 2003 +++ b/arch/s390/math-emu/math.c Thu May 15 15:24:36 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/kernel/module.c b/arch/sparc/kernel/module.c --- a/arch/sparc/kernel/module.c Thu May 15 15:24:32 2003 +++ b/arch/sparc/kernel/module.c Thu May 15 15:24:32 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 Thu May 15 15:24:34 2003 +++ b/arch/sparc/kernel/process.c Thu May 15 15:24:34 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) diff -Nru a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c --- a/arch/sparc/kernel/sparc_ksyms.c Thu May 15 15:24:33 2003 +++ b/arch/sparc/kernel/sparc_ksyms.c Thu May 15 15:24:33 2003 @@ -157,7 +157,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 +183,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 +198,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); diff -Nru a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c --- a/arch/sparc/mm/init.c Thu May 15 15:24:37 2003 +++ b/arch/sparc/mm/init.c Thu May 15 15:24:37 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 Thu May 15 15:24:39 2003 +++ b/arch/sparc/mm/srmmu.c Thu May 15 15:24:39 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 Thu May 15 15:24:36 2003 +++ b/arch/sparc64/defconfig Thu May 15 15:24:36 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/module.c b/arch/sparc64/kernel/module.c --- a/arch/sparc64/kernel/module.c Thu May 15 15:24:40 2003 +++ b/arch/sparc64/kernel/module.c Thu May 15 15:24:40 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 Thu May 15 15:24:43 2003 +++ b/arch/sparc64/kernel/power.c Thu May 15 15:24:43 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/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c --- a/arch/sparc64/kernel/sparc64_ksyms.c Thu May 15 15:24:43 2003 +++ b/arch/sparc64/kernel/sparc64_ksyms.c Thu May 15 15:24:43 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 Thu May 15 15:24:36 2003 +++ b/arch/sparc64/solaris/socksys.c Thu May 15 15:24:36 2003 @@ -191,10 +191,9 @@ printk ("Couldn't create socket\n"); return ret; } - devfs_register (NULL, "socksys", DEVFS_FL_DEFAULT, - 30, 0, - S_IFCHR | S_IRUSR | S_IWUSR, - &socksys_fops, NULL); + + devfs_mk_cdev(MKDEV(30, 0), S_IFCHR|S_IRUSR|S_IWUSR, "socksys"); + file = fcheck(ret); /* N.B. Is this valid? Suppose the f_ops are in a module ... */ socksys_file_ops = *file->f_op; diff -Nru a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c --- a/arch/um/drivers/mmapper_kern.c Thu May 15 15:24:34 2003 +++ b/arch/um/drivers/mmapper_kern.c Thu May 15 15:24:34 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 Thu May 15 15:24:42 2003 +++ b/arch/um/kernel/irq.c Thu May 15 15:24:42 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 Thu May 15 15:24:37 2003 +++ b/arch/um/kernel/mem.c Thu May 15 15:24:37 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 Thu May 15 15:24:43 2003 +++ b/arch/um/kernel/sys_call_table.c Thu May 15 15:24:43 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 Thu May 15 15:24:39 2003 +++ b/arch/v850/kernel/module.c Thu May 15 15:24:39 2003 @@ -230,3 +230,8 @@ return 0; } + +void +module_arch_cleanup(struct module *mod) +{ +} 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 Thu May 15 15:24:33 2003 +++ b/arch/x86_64/ia32/ia32_binfmt.c Thu May 15 15:24:33 2003 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -272,9 +273,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; @@ -319,7 +317,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; } diff -Nru a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c --- a/arch/x86_64/kernel/irq.c Thu May 15 15:24:37 2003 +++ b/arch/x86_64/kernel/irq.c Thu May 15 15:24:37 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)) @@ -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/module.c b/arch/x86_64/kernel/module.c --- a/arch/x86_64/kernel/module.c Thu May 15 15:24:43 2003 +++ b/arch/x86_64/kernel/module.c Thu May 15 15:24:43 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/reboot.c b/arch/x86_64/kernel/reboot.c --- a/arch/x86_64/kernel/reboot.c Thu May 15 15:24:43 2003 +++ b/arch/x86_64/kernel/reboot.c Thu May 15 15:24:43 2003 @@ -68,7 +68,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/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c --- a/arch/x86_64/kernel/traps.c Thu May 15 15:24:33 2003 +++ b/arch/x86_64/kernel/traps.c Thu May 15 15:24:33 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. diff -Nru a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c --- a/arch/x86_64/mm/ioremap.c Thu May 15 15:24:44 2003 +++ b/arch/x86_64/mm/ioremap.c Thu May 15 15:24:44 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/crypto/Kconfig b/crypto/Kconfig --- a/crypto/Kconfig Thu May 15 15:24:44 2003 +++ b/crypto/Kconfig Thu May 15 15:24:44 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). diff -Nru a/drivers/Makefile b/drivers/Makefile --- a/drivers/Makefile Thu May 15 15:24:42 2003 +++ b/drivers/Makefile Thu May 15 15:24:42 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/net/ether1.c b/drivers/acorn/net/ether1.c --- a/drivers/acorn/net/ether1.c Thu May 15 15:24:40 2003 +++ b/drivers/acorn/net/ether1.c Thu May 15 15:24:40 2003 @@ -68,7 +68,7 @@ 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 irqreturn_t 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); @@ -908,7 +908,7 @@ } while (1); } -static void +static irqreturn_t ether1_interrupt (int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *)dev_id; @@ -953,7 +953,9 @@ NORMALIRQS)); } } else - outb (CTRL_ACK, REG_CONTROL); + outb (CTRL_ACK, REG_CONTROL); + + return IRQ_HANDLED; } static int diff -Nru a/drivers/acorn/net/ether3.c b/drivers/acorn/net/ether3.c --- a/drivers/acorn/net/ether3.c Thu May 15 15:24:45 2003 +++ b/drivers/acorn/net/ether3.c Thu May 15 15:24:45 2003 @@ -82,7 +82,7 @@ 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 irqreturn_t 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); @@ -576,12 +576,12 @@ return 0; } -static void +static irqreturn_t 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; + unsigned int status, handled = IRQ_NONE; #if NET_DEBUG > 1 if(net_debug & DEBUG_INT) @@ -595,17 +595,20 @@ if (status & STAT_INTRX) { ether3_outw(CMD_ACKINTRX | priv->regs.command, REG_COMMAND); ether3_rx(dev, priv, 12); + handled = IRQ_HANDLED; } if (status & STAT_INTTX) { ether3_outw(CMD_ACKINTTX | priv->regs.command, REG_COMMAND); ether3_tx(dev, priv); + handled = IRQ_HANDLED; } #if NET_DEBUG > 1 if(net_debug & DEBUG_INT) printk("done\n"); #endif + return handled; } /* diff -Nru a/drivers/acorn/scsi/acornscsi.c b/drivers/acorn/scsi/acornscsi.c --- a/drivers/acorn/scsi/acornscsi.c Thu May 15 15:24:39 2003 +++ b/drivers/acorn/scsi/acornscsi.c Thu May 15 15:24:39 2003 @@ -2466,18 +2466,14 @@ * 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) +static irqreturn_t +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; @@ -2505,7 +2501,7 @@ in_irq = 1; } while (ret != INTR_IDLE); - host->scsi.interrupt = 0; + return IRQ_HANDLED; } /*============================================================================================= @@ -2935,37 +2931,6 @@ } } - 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); @@ -3110,7 +3075,6 @@ .remove = __devexit_p(acornscsi_remove), .id_table = acornscsi_cids, .drv = { - .devclass = &shost_devclass, .name = "acornscsi", }, }; diff -Nru a/drivers/acorn/scsi/arxescsi.c b/drivers/acorn/scsi/arxescsi.c --- a/drivers/acorn/scsi/arxescsi.c Thu May 15 15:24:39 2003 +++ b/drivers/acorn/scsi/arxescsi.c Thu May 15 15:24:39 2003 @@ -397,7 +397,6 @@ .remove = __devexit_p(arxescsi_remove), .id_table = arxescsi_cids, .drv = { - .devclass = &shost_devclass, .name = "arxescsi", }, }; diff -Nru a/drivers/acorn/scsi/cumana_1.c b/drivers/acorn/scsi/cumana_1.c --- a/drivers/acorn/scsi/cumana_1.c Thu May 15 15:24:33 2003 +++ b/drivers/acorn/scsi/cumana_1.c Thu May 15 15:24:33 2003 @@ -334,7 +334,6 @@ .remove = __devexit_p(cumanascsi1_remove), .id_table = cumanascsi1_cids, .drv = { - .devclass = &shost_devclass, .name = "cumanascsi1", }, }; diff -Nru a/drivers/acorn/scsi/cumana_2.c b/drivers/acorn/scsi/cumana_2.c --- a/drivers/acorn/scsi/cumana_2.c Thu May 15 15:24:41 2003 +++ b/drivers/acorn/scsi/cumana_2.c Thu May 15 15:24:41 2003 @@ -141,12 +141,12 @@ * dev_id - user-defined (Scsi_Host structure) * regs - processor registers at interrupt */ -static void +static irqreturn_t cumanascsi_2_intr(int irq, void *dev_id, struct pt_regs *regs) { struct cumanascsi2_info *info = dev_id; - fas216_intr(&info->info); + return fas216_intr(&info->info); } /* Prototype: fasdmatype_t cumanascsi_2_dma_setup(host, SCpnt, direction, min_type) @@ -380,26 +380,6 @@ 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) @@ -572,7 +552,6 @@ .remove = __devexit_p(cumanascsi2_remove), .id_table = cumanascsi2_cids, .drv = { - .devclass = &shost_devclass, .name = "cumanascsi2", }, }; diff -Nru a/drivers/acorn/scsi/eesox.c b/drivers/acorn/scsi/eesox.c --- a/drivers/acorn/scsi/eesox.c Thu May 15 15:24:45 2003 +++ b/drivers/acorn/scsi/eesox.c Thu May 15 15:24:45 2003 @@ -141,12 +141,12 @@ * dev_id - user-defined (Scsi_Host structure) * regs - processor registers at interrupt */ -static void +static irqreturn_t eesoxscsi_intr(int irq, void *dev_id, struct pt_regs *regs) { struct eesoxscsi_info *info = dev_id; - fas216_intr(&info->info); + return fas216_intr(&info->info); } /* Prototype: fasdmatype_t eesoxscsi_dma_setup(host, SCpnt, direction, min_type) @@ -452,25 +452,6 @@ 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) @@ -679,7 +660,6 @@ .remove = __devexit_p(eesoxscsi_remove), .id_table = eesoxscsi_cids, .drv = { - .devclass = &shost_devclass, .name = "eesoxscsi", }, }; diff -Nru a/drivers/acorn/scsi/fas216.c b/drivers/acorn/scsi/fas216.c --- a/drivers/acorn/scsi/fas216.c Thu May 15 15:24:37 2003 +++ b/drivers/acorn/scsi/fas216.c Thu May 15 15:24:37 2003 @@ -1824,9 +1824,10 @@ * * Handle interrupts from the interface to progress a command */ -void fas216_intr(FAS216_Info *info) +irqreturn_t fas216_intr(FAS216_Info *info) { unsigned char isr, ssr, stat; + int handled = IRQ_NONE; fas216_checkmagic(info); @@ -1857,7 +1858,9 @@ fas216_log(info, 0, "unknown interrupt received:" " phase %s isr %02X ssr %02X stat %02X", fas216_drv_phase(info), isr, ssr, stat); + handled = IRQ_HANDLED; } + return handled; } static void __fas216_start_command(FAS216_Info *info, Scsi_Cmnd *SCpnt) diff -Nru a/drivers/acorn/scsi/fas216.h b/drivers/acorn/scsi/fas216.h --- a/drivers/acorn/scsi/fas216.h Thu May 15 15:24:46 2003 +++ b/drivers/acorn/scsi/fas216.h Thu May 15 15:24:46 2003 @@ -351,11 +351,11 @@ */ extern int fas216_command (Scsi_Cmnd *); -/* Function: void fas216_intr (FAS216_Info *info) +/* Function: irqreturn_t 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 irqreturn_t fas216_intr (FAS216_Info *info); extern void fas216_remove (struct Scsi_Host *instance); diff -Nru a/drivers/acorn/scsi/oak.c b/drivers/acorn/scsi/oak.c --- a/drivers/acorn/scsi/oak.c Thu May 15 15:24:32 2003 +++ b/drivers/acorn/scsi/oak.c Thu May 15 15:24:32 2003 @@ -192,7 +192,6 @@ .remove = __devexit_p(oakscsi_remove), .id_table = oakscsi_cids, .drv = { - .devclass = &shost_devclass, .name = "oakscsi", }, }; diff -Nru a/drivers/acorn/scsi/powertec.c b/drivers/acorn/scsi/powertec.c --- a/drivers/acorn/scsi/powertec.c Thu May 15 15:24:40 2003 +++ b/drivers/acorn/scsi/powertec.c Thu May 15 15:24:40 2003 @@ -113,12 +113,12 @@ * dev_id - user-defined (Scsi_Host structure) * regs - processor registers at interrupt */ -static void +static irqreturn_t powertecscsi_intr(int irq, void *dev_id, struct pt_regs *regs) { struct powertec_info *info = dev_id; - fas216_intr(&info->info); + return fas216_intr(&info->info); } /* Prototype: fasdmatype_t powertecscsi_dma_setup(host, SCpnt, direction, min_type) @@ -475,7 +475,6 @@ .remove = __devexit_p(powertecscsi_remove), .id_table = powertecscsi_cids, .drv = { - .devclass = &shost_devclass, .name = "powertecscsi", }, }; diff -Nru a/drivers/acpi/acpi_ksyms.c b/drivers/acpi/acpi_ksyms.c --- a/drivers/acpi/acpi_ksyms.c Thu May 15 15:24:36 2003 +++ b/drivers/acpi/acpi_ksyms.c Thu May 15 15:24:36 2003 @@ -80,6 +80,7 @@ EXPORT_SYMBOL(acpi_get_possible_resources); EXPORT_SYMBOL(acpi_walk_resources); EXPORT_SYMBOL(acpi_set_current_resources); +EXPORT_SYMBOL(acpi_resource_to_address64); EXPORT_SYMBOL(acpi_enable_event); EXPORT_SYMBOL(acpi_disable_event); EXPORT_SYMBOL(acpi_clear_event); diff -Nru a/drivers/atm/Kconfig b/drivers/atm/Kconfig --- a/drivers/atm/Kconfig Thu May 15 15:24:38 2003 +++ b/drivers/atm/Kconfig Thu May 15 15:24:38 2003 @@ -440,5 +440,19 @@ default m if ATM_FORE200E_MAYBE!=y default y if ATM_FORE200E_MAYBE=y +config ATM_HE + tristate "ForeRunner HE Series" + depends on PCI && ATM + help + This is a driver for the Marconi ForeRunner HE-series ATM adapter + cards. It simultaneously supports the 155 and 622 versions. + +config ATM_HE_USE_SUNI + bool "Use S/UNI PHY driver" + depends on ATM_HE + help + Support for the S/UNI-Ultra and S/UNI-622 found in the ForeRunner + HE cards. This driver provides carrier detection some statistics. + endmenu diff -Nru a/drivers/atm/Makefile b/drivers/atm/Makefile --- a/drivers/atm/Makefile Thu May 15 15:24:33 2003 +++ b/drivers/atm/Makefile Thu May 15 15:24:33 2003 @@ -49,6 +49,10 @@ CONFIG_ATM_FORE200E_SBA_FW := $(obj)/sba200e_ecd.bin2 endif endif +obj-$(CONFIG_ATM_HE) += he.o +ifeq ($(CONFIG_ATM_HE_USE_SUNI),y) + obj-$(CONFIG_ATM_HE) += suni.o +endif # FORE Systems 200E-series firmware magic $(obj)/fore200e_pca_fw.c: $(patsubst "%", %, $(CONFIG_ATM_FORE200E_PCA_FW)) \ diff -Nru a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c --- a/drivers/atm/ambassador.c Thu May 15 15:24:33 2003 +++ b/drivers/atm/ambassador.c Thu May 15 15:24:33 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/eni.c b/drivers/atm/eni.c --- a/drivers/atm/eni.c Thu May 15 15:24:35 2003 +++ b/drivers/atm/eni.c Thu May 15 15:24:35 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)); diff -Nru a/drivers/atm/he.c b/drivers/atm/he.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/atm/he.c Thu May 15 15:24:47 2003 @@ -0,0 +1,3260 @@ +/* $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) +{ + struct atm_vcc *vcc; + short vpi; + int vci; + + vpi = cid >> he_dev->vcibits; + vci = cid & ((1<vcibits)-1); + + for (vcc = he_dev->atm_dev->vccs; vcc; vcc = vcc->next) + if (vcc->vci == vci && vcc->vpi == vpi + && vcc->qos.rxtp.traffic_class != ATM_NONE) return vcc; + + return NULL; +} + +static int __devinit +he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) +{ + struct atm_dev *atm_dev = 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 Thu May 15 15:24:47 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 Thu May 15 15:24:32 2003 +++ b/drivers/atm/horizon.c Thu May 15 15:24:32 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 Thu May 15 15:24:38 2003 +++ b/drivers/atm/idt77252.c Thu May 15 15:24:38 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); diff -Nru a/drivers/atm/iphase.c b/drivers/atm/iphase.c --- a/drivers/atm/iphase.c Thu May 15 15:24:45 2003 +++ b/drivers/atm/iphase.c Thu May 15 15:24:45 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 Thu May 15 15:24:35 2003 +++ b/drivers/atm/lanai.c Thu May 15 15:24:35 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 Thu May 15 15:24:34 2003 +++ b/drivers/atm/nicstar.c Thu May 15 15:24:34 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 Thu May 15 15:24:35 2003 +++ b/drivers/atm/nicstar.h Thu May 15 15:24:35 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 Thu May 15 15:24:35 2003 +++ b/drivers/atm/zatm.c Thu May 15 15:24:35 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/class.c b/drivers/base/class.c --- a/drivers/base/class.c Thu May 15 15:24:46 2003 +++ b/drivers/base/class.c Thu May 15 15:24:46 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/block/DAC960.c b/drivers/block/DAC960.c --- a/drivers/block/DAC960.c Thu May 15 15:24:42 2003 +++ b/drivers/block/DAC960.c Thu May 15 15:24:42 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) { @@ -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 Thu May 15 15:24:42 2003 +++ b/drivers/block/DAC960.h Thu May 15 15:24:42 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 Thu May 15 15:24:32 2003 +++ b/drivers/block/acsi_slm.c Thu May 15 15:24:32 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 Thu May 15 15:24:35 2003 +++ b/drivers/block/cciss_scsi.c Thu May 15 15:24:35 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 Thu May 15 15:24:39 2003 +++ b/drivers/block/cciss_scsi.h Thu May 15 15:24:39 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 Thu May 15 15:24:42 2003 +++ b/drivers/block/deadline-iosched.c Thu May 15 15:24:42 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) { @@ -353,6 +370,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 +692,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 +708,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 +724,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 +746,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 +931,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 Thu May 15 15:24:42 2003 +++ b/drivers/block/elevator.c Thu May 15 15:24:42 2003 @@ -408,6 +408,25 @@ 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) { request_queue_t *q = disk->queue; diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c --- a/drivers/block/ll_rw_blk.c Thu May 15 15:24:33 2003 +++ b/drivers/block/ll_rw_blk.c Thu May 15 15:24:33 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 Thu May 15 15:24:39 2003 +++ b/drivers/block/loop.c Thu May 15 15:24:39 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 Thu May 15 15:24:43 2003 +++ b/drivers/block/paride/pg.c Thu May 15 15:24:43 2003 @@ -652,11 +652,8 @@ devfs_mk_dir ("pg"); for (unit=0; unitsense_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 +297,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 +327,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 +371,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 Thu May 15 15:24:42 2003 +++ b/drivers/bluetooth/hci_ldisc.c Thu May 15 15:24:42 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 Thu May 15 15:24:44 2003 +++ b/drivers/bluetooth/hci_usb.c Thu May 15 15:24:44 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 Thu May 15 15:24:39 2003 +++ b/drivers/char/agp/Kconfig Thu May 15 15:24:39 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,54 +25,66 @@ 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 +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 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. + 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 + . - 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. + 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_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. + 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_VIA - tristate "VIA chipset support" - depends on AGP && !X86_64 +config AGP_AMD + 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 - XFree86 4.x on VIA MPV3/Apollo Pro chipsets. + 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_AMD - tristate "AMD Irongate, 761, and 762 support" - depends on AGP && !X86_64 +config AGP_AMD_8151 + tristate "AMD 8151 chipset support" + depends on AGP && X86 + default GART_IOMMU + help + Say Y here to support the AMD 8151 AGP bridge and the builtin + GART on the AMD Athlon64/Opteron ("Hammer") CPUs. + +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 the - XFree86 4.x on AMD Irongate, 761, and 762 chipsets. + 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_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 the + XFree86 4.x on the following NVIDIA chipsets. The supported chipsets + include nForce and nForce2 config AGP_SIS - tristate "Generic SiS support" - depends on AGP && !X86_64 + tristate "SiS chipset support" + depends on AGP && X86 && !X86_64 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] @@ -83,55 +95,39 @@ 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_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 - . - - 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_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 the + 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 diff -Nru a/drivers/char/agp/Makefile b/drivers/char/agp/Makefile --- a/drivers/char/agp/Makefile Thu May 15 15:24:36 2003 +++ b/drivers/char/agp/Makefile Thu May 15 15:24:36 2003 @@ -1,21 +1,15 @@ -# -# 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_VIA) += via-agp.o diff -Nru a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h --- a/drivers/char/agp/agp.h Thu May 15 15:24:37 2003 +++ b/drivers/char/agp/agp.h Thu May 15 15:24:37 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,41 @@ 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)(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); +}; + 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 +133,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 +157,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,11 +363,15 @@ 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); @@ -395,10 +388,40 @@ 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_0_enable(struct agp_bridge_data *bridge, u32 mode); +int agp_3_5_enable(struct agp_bridge_data *bridge, u32 mode); +void global_cache_flush(void); +void get_agp_version(struct agp_bridge_data *bridge); + +/* 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 Thu May 15 15:24:40 2003 +++ b/drivers/char/agp/ali-agp.c Thu May 15 15:24:40 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); @@ -118,47 +118,51 @@ { /* Memory type is ignored */ - return addr | agp_bridge->masks[0].mask; + return addr | agp_bridge->driver->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,17 +171,14 @@ 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[] = { @@ -195,170 +196,185 @@ {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, + .masks = ali_generic_masks, + .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 = ali_mask_memory, + .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, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; + +struct agp_bridge_driver ali_m1541_bridge = { + .owner = THIS_MODULE, + .masks = ali_generic_masks, + .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 = ali_mask_memory, + .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, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; + 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 = { @@ -379,22 +395,16 @@ .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 Thu May 15 15:24:40 2003 +++ b/drivers/char/agp/alpha-agp.c Thu May 15 15:24:40 2003 @@ -81,7 +81,7 @@ static unsigned long alpha_core_agp_mask_memory(unsigned long addr, int type) { /* Memory type is ignored */ - return addr | agp_bridge->masks[0].mask; + return addr | agp_bridge->driver->masks[0].mask; } static void alpha_core_agp_enable(u32 mode) @@ -109,7 +109,7 @@ status = agp->ops->bind(agp, pg_start, mem); mb(); - agp_bridge->tlb_flush(mem); + alpha_core_agp_tlbflush(mem); return status; } @@ -121,29 +121,57 @@ 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, + .masks = alpha_core_agp_masks, + .aperture_sizes = aper_size, + .current_size = aper_size, /* only one entry */ + .size_type = FIXED_APER_SIZE, + .num_aperture_sizes = 1, + .configure = alpha_core_agp_configure, + .fetch_size = alpha_core_agp_fetch_size, + .cleanup = alpha_core_agp_cleanup, + .tlb_flush = alpha_core_agp_tlbflush, + .mask_memory = alpha_core_agp_mask_memory, + .agp_enable = alpha_core_agp_enable, + .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, + .mode = agp->capability.lw, + .cant_use_aperture = 1, + .vm_ops = &alpha_core_agp_vm_ops, }; +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; + 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; @@ -151,63 +179,40 @@ /* * 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; - - /* - * 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; + 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->dev_private_data = agp; + alpha_bridge->dev = pdev; - 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 Thu May 15 15:24:46 2003 +++ b/drivers/char/agp/amd-k7-agp.c Thu May 15 15:24:46 2003 @@ -33,7 +33,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) { @@ -42,7 +42,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; @@ -75,6 +75,7 @@ } } kfree(tables); + amd_irongate_private.gatt_pages = NULL; } static int amd_create_gatt_pages(int nr_tables) @@ -184,8 +185,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); @@ -274,7 +275,7 @@ { /* Only type 0 is supported by the irongate */ - return addr | agp_bridge->masks[0].mask; + return addr | agp_bridge->driver->masks[0].mask; } static int amd_insert_memory(agp_memory * mem, @@ -297,14 +298,13 @@ 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,9 +312,9 @@ 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); + amd_irongate_mask_memory(mem->memory[i], mem->type); } - agp_bridge->tlb_flush(mem); + amd_irongate_tlbflush(mem); return 0; } @@ -335,7 +335,7 @@ (unsigned long) agp_bridge->scratch_page; } - agp_bridge->tlb_flush(mem); + amd_irongate_tlbflush(mem); return 0; } @@ -355,115 +355,104 @@ {.mask = 0x00000001, .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, + .masks = amd_irongate_masks, + .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 = amd_irongate_mask_memory, + .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, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; 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 = { @@ -484,22 +473,16 @@ .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 +491,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 Thu May 15 15:24:41 2003 +++ b/drivers/char/agp/amd-k8-agp.c Thu May 15 15:24:41 2003 @@ -29,6 +29,21 @@ 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. @@ -218,7 +214,7 @@ static unsigned long amd_8151_mask_memory(unsigned long addr, int type) { - return addr | agp_bridge->masks[0].mask; + return addr | agp_bridge->driver->masks[0].mask; } @@ -227,130 +223,110 @@ {.mask = 0x00000001, .type = 0} }; +struct agp_bridge_driver amd_8151_driver = { + .owner = THIS_MODULE, + .masks = amd_8151_masks, + .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 = amd_8151_mask_memory, + .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, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; -/* - * 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. - */ + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + if (!cap_ptr) + return -ENODEV; - /* 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); - } - } + printk(KERN_INFO PFX "Detected Opteron/Athlon64 on-CPU GART\n"); + + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; + + /* Assume here we have an 8151. (Later this assumption will be fixed). */ + 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; } - /* 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"); + 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; } + bridge->driver = &amd_8151_driver; + bridge->dev = pdev; + bridge->capndx = cap_ptr; - 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); -} - - -static int __init amd_8151_setup (struct pci_dev *pdev) -{ - struct pci_dev *dev; - int i=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; - + /* 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; + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); - printk (KERN_INFO PFX "Detected Opteron/Athlon64 on-CPU GART\n"); - - 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 = { @@ -371,25 +347,17 @@ .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 Thu May 15 15:24:41 2003 +++ b/drivers/char/agp/backend.c Thu May 15 15:24:41 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,62 @@ 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)); + 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; + } + + if (bridge->driver->agp_destroy_page && + bridge->driver->needs_scratch_page) + bridge->driver->agp_destroy_page( + phys_to_virt(bridge->scratch_page_real)); } static int agp_power(struct pm_dev *dev, pm_request_t rq, void *data) { - switch(rq) - { + switch(rq) { case PM_SUSPEND: - return agp_bridge->suspend(); + return agp_bridge->driver->suspend(); case PM_RESUME: - agp_bridge->resume(); + agp_bridge->driver->resume(); return 0; } return 0; } -extern int agp_frontend_initialize(void); -extern void agp_frontend_cleanup(void); static const drm_agp_t drm_agp = { &agp_free_memory, @@ -221,78 +234,81 @@ &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) { - printk (KERN_DEBUG PFX "Erk, registering with no pci_dev!\n"); + 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_DEBUG 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)) return -EINVAL; - ret_val = agp_backend_initialize(drv->dev); - if (ret_val) + bridge->type = SUPPORTED; + + error = agp_backend_initialize(agp_bridge); + if (error) goto err_out; - ret_val = agp_frontend_initialize(); - if (ret_val) + error = agp_frontend_initialize(); + if (error) 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); + pm_register(PM_PCI_DEV, PM_PCI_ID(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; +void agp_remove_bridge(struct agp_bridge_data *bridge) +{ + bridge->type = NOT_SUPPORTED; pm_unregister_all(agp_power); 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 +316,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 Thu May 15 15:24:34 2003 +++ b/drivers/char/agp/frontend.c Thu May 15 15:24:34 2003 @@ -53,11 +53,12 @@ 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) @@ -67,6 +68,7 @@ /* 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; } @@ -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; @@ -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,7 +381,7 @@ } } -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; @@ -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; + struct agp_client *client; + struct agp_file_private *priv = file->private_data; 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,9 +753,9 @@ 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; + struct agp_info userinfo; 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_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; + 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; + struct agp_bind bind_info; 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_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 Thu May 15 15:24:34 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 Thu May 15 15:24:36 2003 +++ b/drivers/char/agp/generic.c Thu May 15 15:24:36 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,6 +68,7 @@ return -1; } + agp_memory *agp_create_memory(int scratch_pages) { agp_memory *new; @@ -94,7 +95,16 @@ new->num_scratch_pages = scratch_pages; return new; } +EXPORT_SYMBOL(agp_create_memory); +/** + * 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(agp_memory * curr) { size_t i; @@ -106,21 +116,33 @@ 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_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. + */ agp_memory *agp_allocate_memory(size_t page_count, u32 type) { int scratch_pages; @@ -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,39 +256,61 @@ num_entries = 0; return num_entries; } +EXPORT_SYMBOL_GPL(agp_num_entries); -/* Routine to copy over information structure */ +/** + * 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(agp_kern_info * info) { memset(info, 0, sizeof(agp_kern_info)); - if (agp_bridge->type == NOT_SUPPORTED) { - info->chipset = agp_bridge->type; + 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. */ +/** + * 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(agp_memory * curr, off_t pg_start) { int ret_val; @@ -272,10 +320,10 @@ 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,7 +332,17 @@ curr->pg_start = pg_start; return 0; } +EXPORT_SYMBOL(agp_bind_memory); + +/** + * 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(agp_memory * curr) { int ret_val; @@ -295,7 +353,7 @@ if (curr->is_bound != TRUE) 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 +362,115 @@ 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; + + /* disable FW if it's not supported */ + if (!((*cmd & AGPSTAT_FW) && (*tmp & AGPSTAT_FW) && (*mode & AGPSTAT_FW))) + *cmd &= ~AGPSTAT_FW; -u32 agp_collect_device_status(u32 mode, u32 command) + /* 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; + + 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; + + /* disable FW if it's not supported */ + if (!((*cmd & AGPSTAT_FW) && (*tmp & AGPSTAT_FW) && (*mode & AGPSTAT_FW))) + *cmd &= ~AGPSTAT_FW; + + /* Set speed. */ + 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; - - /* disable FW if it's not supported */ - if (!((command & 0x00000010) && - (scratch & 0x00000010) && - (mode & 0x00000010))) - command &= ~0x00000010; - - 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; - } - - if (command & 4) - command &= ~3; /* 4X */ + cmd = ((cmd & ~AGPSTAT_RQ_DEPTH) | + min_t(u32, (mode & AGPSTAT_RQ_DEPTH), + min_t(u32, (cmd & AGPSTAT_RQ_DEPTH), (tmp & AGPSTAT_RQ_DEPTH)))); + + pci_read_config_dword(device, cap_ptr+AGPSTAT, &agp3); - if (command & 2) - command &= ~5; /* 2X (8X for AGP3.0) */ - - if (command & 1) - command &= ~6; /* 1X (4X for AGP3.0) */ - - return command; + /* Check to see if we are operating in 3.0 mode */ + if (agp3 & AGPSTAT_MODE_3_0) { + agp_v3_parse_one(&mode, &cmd, &tmp); + } else { + agp_v2_parse_one(&mode, &cmd, &tmp); + } + } + return cmd; } +EXPORT_SYMBOL(agp_collect_device_status); + void agp_device_command(u32 command, int agp_v3) { @@ -392,40 +491,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, mode); + 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 +566,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 +574,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 +607,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 +629,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 +647,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 +669,21 @@ return 0; } +EXPORT_SYMBOL(agp_generic_create_gatt_table); int agp_generic_suspend(void) { return 0; } +EXPORT_SYMBOL(agp_generic_suspend); + void agp_generic_resume(void) { return; } +EXPORT_SYMBOL(agp_generic_resume); + int agp_generic_free_gatt_table(void) { @@ -563,7 +694,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 +718,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,8 +728,16 @@ 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) { @@ -610,7 +748,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,24 +785,27 @@ 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) { @@ -681,14 +822,18 @@ (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) { return NULL; } +EXPORT_SYMBOL(agp_generic_alloc_by_type); + void agp_generic_free_by_type(agp_memory * curr) { @@ -698,13 +843,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 +868,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 +885,40 @@ 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); diff -Nru a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c --- a/drivers/char/agp/hp-agp.c Thu May 15 15:24:42 2003 +++ b/drivers/char/agp/hp-agp.c Thu May 15 15:24:42 2003 @@ -285,7 +285,7 @@ } if (mem->is_flushed == FALSE) { - CACHE_FLUSH(); + global_cache_flush(); mem->is_flushed = TRUE; } @@ -296,11 +296,11 @@ 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; } @@ -319,7 +319,7 @@ hp->gatt[i] = agp_bridge->scratch_page; } - agp_bridge->tlb_flush(mem); + agp_bridge->driver->tlb_flush(mem); return 0; } @@ -328,58 +328,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, + .masks = hp_zx1_masks, + .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, + .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 = { @@ -400,22 +404,16 @@ .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 Thu May 15 15:24:40 2003 +++ b/drivers/char/agp/i460-agp.c Thu May 15 15:24:40 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); @@ -294,7 +294,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,7 +306,7 @@ 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; @@ -417,7 +417,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); } @@ -439,7 +439,7 @@ 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 */ @@ -519,64 +519,71 @@ 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, + .masks = i460_masks, + .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, + .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, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, + .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 = { @@ -597,22 +604,16 @@ .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 Thu May 15 15:24:38 2003 +++ b/drivers/char/agp/intel-agp.c Thu May 15 15:24:38 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), @@ -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,15 +154,15 @@ } 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; } @@ -178,58 +177,61 @@ agp_bridge->scratch_page); } - CACHE_FLUSH(); - agp_bridge->tlb_flush(mem); + global_cache_flush(); + agp_bridge->driver->tlb_flush(mem); return 0; } +/* + * 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 agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type) +{ + 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 agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type) { 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; - - addr = agp_bridge->agp_alloc_page(); + if (type == AGP_PHYS_MEMORY) + return(alloc_agpphysmem_i8xx(pg_count, type)); - 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; } @@ -237,7 +239,7 @@ { 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); @@ -490,15 +461,15 @@ (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); } @@ -507,7 +478,7 @@ { 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 +488,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) { - 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 +511,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 +524,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,6 +542,25 @@ 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) { @@ -991,7 +905,7 @@ static unsigned long intel_mask_memory(unsigned long addr, int type) { /* Memory type is ignored */ - return addr | agp_bridge->masks[0].mask; + return addr | agp_bridge->driver->masks[0].mask; } static void intel_resume(void) @@ -1041,584 +955,485 @@ {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, + .masks = intel_generic_masks, + .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 = intel_mask_memory, + .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, + .suspend = agp_generic_suspend, + .resume = intel_resume, +}; -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, + .masks = intel_i810_masks, + .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, + .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, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; -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, + .masks = intel_generic_masks, + .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 = intel_mask_memory, + .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, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; -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, + .masks = intel_i810_masks, + .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, + .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, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; -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, + .masks = intel_generic_masks, + .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 = intel_mask_memory, + .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, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; -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, + .masks = intel_generic_masks, + .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 = intel_mask_memory, + .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, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; -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, + .masks = intel_generic_masks, + .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 = intel_mask_memory, + .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, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; -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, + .masks = intel_generic_masks, + .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 = intel_mask_memory, + .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, + .suspend = agp_generic_suspend, + .resume = intel_845_resume, +}; + +struct agp_bridge_driver intel_850_driver = { + .owner = THIS_MODULE, + .masks = intel_generic_masks, + .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 = intel_mask_memory, + .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, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, }; +struct agp_bridge_driver intel_860_driver = { + .owner = THIS_MODULE, + .masks = intel_generic_masks, + .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 = intel_mask_memory, + .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, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; -/* scan table above for supported devices */ -static int __init agp_lookup_host_bridge (struct pci_dev *pdev) +struct agp_bridge_driver intel_7505_driver = { + .owner = THIS_MODULE, + .masks = intel_generic_masks, + .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 = intel_mask_memory, + .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, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; + +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; - } - printk(KERN_INFO PFX "agpgart: Detected an Intel i815 Chipset.\n"); - agp_bridge->type = INTEL_I810; - return intel_i810_setup(i810_dev); - - 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; - } - printk(KERN_INFO PFX "Detected an Intel(R) 845G Chipset.\n"); - agp_bridge->type = INTEL_I810; - return intel_i830_setup(i810_dev); - + 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: - 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; + if (find_i830(PCI_DEVICE_ID_INTEL_82830_CGC)) { + bridge->driver = &intel_830_driver; + } else { + bridge->driver = &intel_830mp_driver; } - 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; + 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: + if (find_i830(PCI_DEVICE_ID_INTEL_82845G_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 = "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"; } - agp_bridge->type = INTEL_I810; - return intel_i830_setup(i810_dev); - + break; + case PCI_DEVICE_ID_INTEL_82860_HB: + bridge->driver = &intel_860_driver; + name = "i860"; + 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); - } - - 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; + if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG)) { + bridge->driver = &intel_830_driver; + } else { + bridge->driver = &intel_845_driver; } - printk(KERN_INFO PFX "Detected an Intel(R) 865G Chipset.\n"); - agp_bridge->type = INTEL_I810; - return intel_i830_setup(i810_dev); - + 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; + } + bridge->driver = &intel_generic_driver; break; - } + }; + + bridge->dev = pdev; + bridge->capndx = cap_ptr; - cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP); - if (cap_ptr == 0) - return -ENODEV; - agp_bridge->capndx = cap_ptr; + 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; + + printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n", name); /* Fill in the mode register */ - pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+PCI_AGP_STATUS, &agp_bridge->mode); + if (cap_ptr) { + pci_read_config_dword(pdev, + bridge->capndx+PCI_AGP_STATUS, + &bridge->mode); + } - /* probe for known chipsets */ - return agp_lookup_host_bridge(dev); + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); + fail: + agp_put_bridge(bridge); + return -ENODEV; } -static struct agp_driver intel_agp_driver = { - .owner = THIS_MODULE, -}; - -static int __init agp_intel_probe (struct pci_dev *dev, const struct pci_device_id *ent) +static void __devexit agp_intel_remove(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); + + agp_remove_bridge(bridge); + agp_put_bridge(bridge); } static struct pci_device_id agp_intel_pci_table[] __initdata = { @@ -1639,29 +1454,24 @@ .name = "agpgart-intel", .id_table = agp_intel_pci_table, .probe = agp_intel_probe, + .remove = agp_intel_remove, }; /* 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 Thu May 15 15:24:47 2003 @@ -0,0 +1,468 @@ +/* + * 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, u32 mode) +{ + 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"); + } + } + 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 Thu May 15 15:24:47 2003 @@ -0,0 +1,380 @@ +/* + * 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); +} + + +static unsigned long nvidia_mask_memory(unsigned long addr, int type) +{ + /* Memory type is ignored */ + return addr | agp_bridge->driver->masks[0].mask; +} + +#if 0 +extern int agp_memory_reserved; + +static int nvidia_insert_memory(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->tlb_flush(mem); + return 0; +} + +static int nvidia_remove_memory(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->tlb_flush(mem); + return 0; +} +#endif + + +static void nvidia_tlbflush(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[] = +{ + {0x00000001, 0} +}; + + +struct agp_bridge_driver nvidia_driver = { + .owner = THIS_MODULE, + .masks = nvidia_generic_masks, + .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 = nvidia_mask_memory, + .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, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; + +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 __initdata 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 Thu May 15 15:24:33 2003 +++ b/drivers/char/agp/sis-agp.c Thu May 15 15:24:33 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)))) { @@ -67,7 +67,7 @@ { /* Memory type is ignored */ - return addr | agp_bridge->masks[0].mask; + return addr | agp_bridge->driver->masks[0].mask; } static struct aper_size_info_8 sis_generic_sizes[7] = @@ -86,164 +86,144 @@ {.mask = 0x00000000, .type = 0} }; -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_bridge_driver sis_driver = { + .owner = THIS_MODULE, + .masks = sis_generic_masks, + .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 = sis_mask_memory, + .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, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; 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 = { @@ -264,22 +244,16 @@ .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 Thu May 15 15:24:37 2003 +++ b/drivers/char/agp/sworks-agp.c Thu May 15 15:24:37 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(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,43 +308,11 @@ 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; + return addr | agp_bridge->driver->masks[0].mask; } static int serverworks_insert_memory(agp_memory * mem, @@ -336,14 +335,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,9 +350,9 @@ 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; } @@ -368,8 +367,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,7 +377,7 @@ (unsigned long) agp_bridge->scratch_page; } - agp_bridge->tlb_flush(mem); + serverworks_tlbflush(mem); return 0; } @@ -420,123 +419,103 @@ agp_device_command(command, 0); } -static int __init serverworks_setup (struct pci_dev *pdev) +struct agp_bridge_driver sworks_driver = { + .owner = THIS_MODULE, + .masks = serverworks_masks, + .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 = serverworks_mask_memory, + .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, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; + +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 = { @@ -557,22 +536,16 @@ .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/via-agp.c b/drivers/char/agp/via-agp.c --- a/drivers/char/agp/via-agp.c Thu May 15 15:24:43 2003 +++ b/drivers/char/agp/via-agp.c Thu May 15 15:24:43 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); @@ -79,7 +79,7 @@ { /* Memory type is ignored */ - return addr | agp_bridge->masks[0].mask; + return addr | agp_bridge->driver->masks[0].mask; } @@ -107,11 +107,11 @@ 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 (temp == values[i].size_value) { agp_bridge->previous_size = agp_bridge->current_size = (void *) (values + i); @@ -174,99 +174,55 @@ { 2048, 524288, 9, 1<<11} /* 2GB <- Max supported */ }; +struct agp_bridge_driver via_agp3_driver = { + .owner = THIS_MODULE, + .masks = via_generic_masks, + .aperture_sizes = via_generic_agp3_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 10, + .configure = via_configure_agp3, + .fetch_size = via_fetch_size_agp3, + .cleanup = via_cleanup_agp3, + .tlb_flush = via_tlbflush_agp3, + .mask_memory = via_mask_memory, + .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, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; -static int __init via_generic_agp3_setup (struct pci_dev *pdev) -{ - agp_bridge->dev = pdev; - agp_bridge->type = VIA_GENERIC; - agp_bridge->masks = via_generic_masks; - agp_bridge->aperture_sizes = (void *) via_generic_agp3_sizes; - agp_bridge->size_type = U16_APER_SIZE; - agp_bridge->num_aperture_sizes = 10; - agp_bridge->dev_private_data = NULL; - agp_bridge->needs_scratch_page = FALSE; - agp_bridge->agp_enable = agp_generic_enable; - agp_bridge->configure = via_configure_agp3; - agp_bridge->fetch_size = via_fetch_size_agp3; - agp_bridge->cleanup = via_cleanup_agp3; - agp_bridge->tlb_flush = via_tlbflush_agp3; - agp_bridge->mask_memory = via_mask_memory; - 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 via_generic_setup (struct pci_dev *pdev) -{ - /* Garg, there are KT400s with KT266 IDs. */ - if (pdev->device == PCI_DEVICE_ID_VIA_8367_0) { - - /* Is there a KT400 subsystem ? */ - if (pdev->subsystem_device==PCI_DEVICE_ID_VIA_8377_0) { - u8 reg; - - printk (KERN_INFO PFX "Found KT400 in disguise as a KT266.\n"); - - /* Check AGP compatibility mode. */ - pci_read_config_byte(pdev, VIA_AGPSEL, ®); - if ((reg & (1<<1))==0) - return via_generic_agp3_setup(pdev); - - /* Its in 2.0 mode, drop through. */ - } - } - - agp_bridge->masks = via_generic_masks; - agp_bridge->aperture_sizes = (void *) via_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 = via_configure; - agp_bridge->fetch_size = via_fetch_size; - agp_bridge->cleanup = via_cleanup; - agp_bridge->tlb_flush = via_tlbflush; - agp_bridge->mask_memory = via_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; -} - - -/* The KT400 does magick to put the AGP bridge compliant with the same - * standards version as the graphics card. */ -static int __init via_kt400_setup(struct pci_dev *pdev) -{ - u8 reg; - pci_read_config_byte(pdev, VIA_AGPSEL, ®); - /* Check AGP 2.0 compatibility mode. */ - if ((reg & (1<<1))==0) - return via_generic_agp3_setup(pdev); - return via_generic_setup(pdev); -} - +struct agp_bridge_driver via_driver = { + .owner = THIS_MODULE, + .masks = via_generic_masks, + .aperture_sizes = via_generic_sizes, + .size_type = U8_APER_SIZE, + .num_aperture_sizes = 7, + .configure = via_configure, + .fetch_size = via_fetch_size, + .cleanup = via_cleanup, + .tlb_flush = via_tlbflush, + .mask_memory = via_mask_memory, + .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, + .suspend = agp_generic_suspend, + .resume = agp_generic_resume, +}; static struct agp_device_ids via_agp_device_ids[] __initdata = { @@ -310,7 +266,7 @@ /* VT8361 */ { - .device_id = PCI_DEVICE_ID_VIA_8361, // 0x3112 + .device_id = PCI_DEVICE_ID_VIA_8361, .chipset_name = "Apollo KLE133", }, @@ -353,7 +309,6 @@ { .device_id = PCI_DEVICE_ID_VIA_8377_0, .chipset_name = "Apollo Pro KT400", - .chipset_setup = via_kt400_setup, }, /* VT8604 / VT8605 / VT8603 / TwisterT @@ -402,74 +357,99 @@ /* P4M400 */ { .device_id = PCI_DEVICE_ID_VIA_P4M400, - .chipset_name = "PM400", + .chipset_name = "P4M400", }, { }, /* 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_via_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) { - int j=0; - struct agp_device_ids *devs; - - devs = via_agp_device_ids; + struct agp_device_ids *devs = via_agp_device_ids; + struct agp_bridge_data *bridge; + int j = 0; + u8 cap_ptr, reg; - while (devs[j].chipset_name != NULL) { - if (pdev->device == devs[j].device_id) { - printk (KERN_INFO PFX "Detected VIA %s chipset\n", devs[j].chipset_name); - agp_bridge->type = VIA_GENERIC; + 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 via_generic_setup(pdev); + /* probe for known chipsets */ + for (j = 0; devs[j].chipset_name; j++) { + if (pdev->device == devs[j].device_id) { + printk (KERN_INFO PFX "Detected VIA %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 VIA routines" - " for device id: %04x\n", pdev->device); - agp_bridge->type = VIA_GENERIC; - return via_generic_setup(pdev); + printk(KERN_ERR PFX + "Unsupported VIA chipset (device id: %04x)," + " you might want to try agp_try_unsupported=1.\n", + pdev->device); + return -ENODEV; } - printk(KERN_ERR PFX "Unsupported VIA chipset (device id: %04x)," - " you might want to try agp_try_unsupported=1.\n", pdev->device); - return -ENODEV; -} + printk(KERN_WARNING PFX "Trying generic VIA routines" + " for device id: %04x\n", pdev->device); - -static struct agp_driver via_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_VIA_8367_0: + /* + * Garg, there are KT400s with KT266 IDs. + */ + /* Is there a KT400 subsystem ? */ + if (pdev->subsystem_device != PCI_DEVICE_ID_VIA_8377_0) + break; + + printk(KERN_INFO PFX "Found KT400 in disguise as a KT266.\n"); + /*FALLTHROUGH*/ + case PCI_DEVICE_ID_VIA_8377_0: + /* + * The KT400 does magick to put the AGP bridge compliant + * with the same standards version as the graphics card. + */ + pci_read_config_byte(pdev, VIA_AGPSEL, ®); + /* Check AGP 2.0 compatibility mode. */ + if ((reg & (1<<1))==0) { + bridge->driver = &via_agp3_driver; + break; + } + /*FALLTHROUGH*/ + default: + bridge->driver = &via_driver; + break; + } -static int __init agp_via_probe (struct pci_dev *dev, const struct pci_device_id *ent) -{ - u8 cap_ptr = 0; + 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); - via_agp_driver.dev = dev; - agp_register_driver(&via_agp_driver); - return 0; - } - return -ENODEV; + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); } +static void __devexit agp_via_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_via_pci_table[] __initdata = { { @@ -490,27 +470,19 @@ .name = "agpgart-via", .id_table = agp_via_pci_table, .probe = agp_via_probe, + .remove = agp_via_remove, }; static int __init agp_via_init(void) { - int ret_val; - - ret_val = pci_module_init(&agp_via_pci_driver); - if (ret_val) - agp_bridge->type = NOT_SUPPORTED; - - return ret_val; + return pci_module_init(&agp_via_pci_driver); } - static void __exit agp_via_cleanup(void) { - agp_unregister_driver(&via_agp_driver); pci_unregister_driver(&agp_via_pci_driver); } - module_init(agp_via_init); module_exit(agp_via_cleanup); diff -Nru a/drivers/char/amiserial.c b/drivers/char/amiserial.c --- a/drivers/char/amiserial.c Thu May 15 15:24:46 2003 +++ b/drivers/char/amiserial.c Thu May 15 15:24:46 2003 @@ -1528,7 +1528,6 @@ if (tty_hung_up_p(filp)) { DBG_CNT("before DEC-hung"); - MOD_DEC_USE_COUNT; local_irq_restore(flags); return; } @@ -1555,7 +1554,6 @@ } if (state->count) { DBG_CNT("before DEC-2"); - MOD_DEC_USE_COUNT; local_irq_restore(flags); return; } @@ -1615,7 +1613,6 @@ info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE| ASYNC_CLOSING); wake_up_interruptible(&info->close_wait); - MOD_DEC_USE_COUNT; local_irq_restore(flags); } @@ -1894,15 +1891,12 @@ int retval, line; unsigned long page; - MOD_INC_USE_COUNT; line = tty->index; if ((line < 0) || (line >= NR_PORTS)) { - MOD_DEC_USE_COUNT; return -ENODEV; } retval = get_async_struct(line, &info); if (retval) { - MOD_DEC_USE_COUNT; return retval; } tty->driver_data = info; @@ -2116,6 +2110,7 @@ memset(&serial_driver, 0, sizeof(struct tty_driver)); serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.owner = THIS_MODULE; serial_driver.driver_name = "amiserial"; serial_driver.name = "ttyS"; serial_driver.major = TTY_MAJOR; diff -Nru a/drivers/char/cyclades.c b/drivers/char/cyclades.c --- a/drivers/char/cyclades.c Thu May 15 15:24:34 2003 +++ b/drivers/char/cyclades.c Thu May 15 15:24:34 2003 @@ -2579,15 +2579,12 @@ int retval, line; unsigned long page; - MOD_INC_USE_COUNT; line = tty->index; if ((line < 0) || (NR_PORTS <= line)){ - MOD_DEC_USE_COUNT; return -ENODEV; } info = &cy_port[line]; if (info->line < 0){ - MOD_DEC_USE_COUNT; return -ENODEV; } @@ -2607,7 +2604,6 @@ } else { printk("cyc:Cyclades-Z firmware not yet loaded\n"); } - MOD_DEC_USE_COUNT; return -ENODEV; } #ifdef CONFIG_CYZ_INTR @@ -2803,7 +2799,6 @@ CY_LOCK(info, flags); /* If the TTY is being hung up, nothing to do */ if (tty_hung_up_p(filp)) { - MOD_DEC_USE_COUNT; CY_UNLOCK(info, flags); return; } @@ -2834,7 +2829,6 @@ info->count = 0; } if (info->count) { - MOD_DEC_USE_COUNT; CY_UNLOCK(info, flags); return; } @@ -2931,7 +2925,6 @@ printk(" cyc:cy_close done\n"); #endif - MOD_DEC_USE_COUNT; CY_UNLOCK(info, flags); return; } /* cy_close */ @@ -5494,6 +5487,7 @@ memset(&cy_serial_driver, 0, sizeof(struct tty_driver)); cy_serial_driver.magic = TTY_DRIVER_MAGIC; + cy_serial_driver.owner = THIS_MODULE; cy_serial_driver.driver_name = "cyclades"; cy_serial_driver.name = "ttyC"; cy_serial_driver.major = CYCLADES_MAJOR; diff -Nru a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig --- a/drivers/char/drm/Kconfig Thu May 15 15:24:43 2003 +++ b/drivers/char/drm/Kconfig Thu May 15 15:24:43 2003 @@ -49,7 +49,7 @@ config DRM_I810 tristate "Intel I810" - depends on DRM && AGP + depends on DRM && AGP && AGP_INTEL help Choose this option if you have an Intel I810 graphics card. If M is selected, the module will be called i810. AGP support is required @@ -57,7 +57,7 @@ config DRM_I830 tristate "Intel 830M, 845G, 852GM, 855GM, 865G" - depends on DRM && AGP + depends on DRM && AGP && AGP_INTEL help Choose this option if you have a system that has Intel 830M, 845G, 852GM, 855GM or 865G integrated graphics. If M is selected, the diff -Nru a/drivers/char/drm/drm_drv.h b/drivers/char/drm/drm_drv.h --- a/drivers/char/drm/drm_drv.h Thu May 15 15:24:42 2003 +++ b/drivers/char/drm/drm_drv.h Thu May 15 15:24:42 2003 @@ -334,7 +334,6 @@ dev->last_context = 0; dev->last_switch = 0; dev->last_checked = 0; - init_timer( &dev->timer ); init_waitqueue_head( &dev->context_wait ); dev->ctx_start = 0; @@ -590,6 +589,7 @@ dev = &(DRM(device)[i]); memset( (void *)dev, 0, sizeof(*dev) ); dev->count_lock = SPIN_LOCK_UNLOCKED; + init_timer( &dev->timer ); sema_init( &dev->struct_sem, 1 ); if ((DRM(minor)[i] = DRM(stub_register)(DRIVER_NAME, &DRM(fops),dev)) < 0) diff -Nru a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c --- a/drivers/char/drm/radeon_cp.c Thu May 15 15:24:34 2003 +++ b/drivers/char/drm/radeon_cp.c Thu May 15 15:24:34 2003 @@ -903,8 +903,8 @@ RADEON_WRITE( RADEON_CP_RB_RPTR_ADDR, entry->busaddr[page_ofs]); - DRM_DEBUG( "ring rptr: offset=0x%08x handle=0x%08lx\n", - entry->busaddr[page_ofs], + DRM_DEBUG( "ring rptr: offset=0x%08lx handle=0x%08lx\n", + (unsigned long) entry->busaddr[page_ofs], entry->handle + tmp_ofs ); } diff -Nru a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c --- a/drivers/char/dsp56k.c Thu May 15 15:24:39 2003 +++ b/drivers/char/dsp56k.c Thu May 15 15:24:39 2003 @@ -512,10 +512,9 @@ printk("DSP56k driver: Unable to register driver\n"); return -ENODEV; } - devfs_register(NULL, "dsp56k", DEVFS_FL_DEFAULT, - DSP56K_MAJOR, 0, - S_IFCHR | S_IRUSR | S_IWUSR, - &dsp56k_fops, NULL); + + devfs_mk_cdev(MKDEV(DSP56K_MAJOR, 0), + S_IFCHR | S_IRUSR | S_IWUSR, "dsp56k"); printk(banner); return 0; diff -Nru a/drivers/char/dtlk.c b/drivers/char/dtlk.c --- a/drivers/char/dtlk.c Thu May 15 15:24:37 2003 +++ b/drivers/char/dtlk.c Thu May 15 15:24:37 2003 @@ -345,10 +345,9 @@ } if (dtlk_dev_probe() == 0) printk(", MAJOR %d\n", dtlk_major); - devfs_register(NULL, "dtlk", DEVFS_FL_DEFAULT, - dtlk_major, DTLK_MINOR, - S_IFCHR | S_IRUSR | S_IWUSR, - &dtlk_fops, NULL); + + devfs_mk_cdev(MKDEV(dtlk_major, DTLK_MINOR), + S_IFCHR | S_IRUSR | S_IWUSR, "dtlk"); init_timer(&dtlk_timer); dtlk_timer.function = dtlk_timer_tick; diff -Nru a/drivers/char/dz.c b/drivers/char/dz.c --- a/drivers/char/dz.c Thu May 15 15:24:33 2003 +++ b/drivers/char/dz.c Thu May 15 15:24:33 2003 @@ -1332,6 +1332,7 @@ memset(&serial_driver, 0, sizeof(struct tty_driver)); serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.owner = THIS_MODULE; #if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS)) serial_driver.name = "ttyS"; #else @@ -1425,8 +1426,8 @@ printk("ttyS%02d at 0x%08x (irq = %d)\n", info->line, info->port, SERIAL); - tty_register_device(&serial_driver, info->line); - tty_register_device(&callout_driver, info->line); + tty_register_device(&serial_driver, info->line, NULL); + tty_register_device(&callout_driver, info->line, NULL); } /* Reset the chip */ diff -Nru a/drivers/char/esp.c b/drivers/char/esp.c --- a/drivers/char/esp.c Thu May 15 15:24:32 2003 +++ b/drivers/char/esp.c Thu May 15 15:24:32 2003 @@ -643,9 +643,7 @@ #ifdef SERIAL_DEBUG_OPEN printk("scheduling hangup..."); #endif - MOD_INC_USE_COUNT; - if (schedule_task(&info->tqueue_hangup) == 0) - MOD_DEC_USE_COUNT; + schedule_task(&info->tqueue_hangup); } } } @@ -811,7 +809,6 @@ tty = info->tty; if (tty) tty_hangup(tty); - MOD_DEC_USE_COUNT; } /* @@ -2132,7 +2129,7 @@ info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE| ASYNC_CLOSING); wake_up_interruptible(&info->close_wait); -out: MOD_DEC_USE_COUNT; +out: restore_flags(flags); } @@ -2375,7 +2372,6 @@ #ifdef SERIAL_DEBUG_OPEN printk("esp_open %s, count = %d\n", tty->name, info->count); #endif - MOD_INC_USE_COUNT; info->count++; tty->driver_data = info; info->tty = tty; @@ -2551,6 +2547,7 @@ memset(&esp_driver, 0, sizeof(struct tty_driver)); esp_driver.magic = TTY_DRIVER_MAGIC; + esp_driver.owner = THIS_MODULE; esp_driver.name = "ttyP"; esp_driver.major = ESP_IN_MAJOR; esp_driver.minor_start = 0; diff -Nru a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c --- a/drivers/char/ftape/zftape/zftape-init.c Thu May 15 15:24:37 2003 +++ b/drivers/char/ftape/zftape/zftape-init.c Thu May 15 15:24:37 2003 @@ -342,38 +342,24 @@ TRACE_CATCH(register_chrdev(QIC117_TAPE_MAJOR, "zft", &zft_cdev),); for (i = 0; i < 4; i++) { - char devname[9]; - - sprintf (devname, "qft%i", i); - devfs_register (NULL, devname, DEVFS_FL_DEFAULT, - QIC117_TAPE_MAJOR, i, - S_IFCHR | S_IRUSR | S_IWUSR, - &zft_cdev, NULL); - sprintf (devname, "nqft%i", i); - devfs_register (NULL, devname, DEVFS_FL_DEFAULT, - QIC117_TAPE_MAJOR, i + 4, - S_IFCHR | S_IRUSR | S_IWUSR, - &zft_cdev, NULL); - sprintf (devname, "zqft%i", i); - devfs_register (NULL, devname, DEVFS_FL_DEFAULT, - QIC117_TAPE_MAJOR, i + 16, - S_IFCHR | S_IRUSR | S_IWUSR, - &zft_cdev, NULL); - sprintf (devname, "nzqft%i", i); - devfs_register (NULL, devname, DEVFS_FL_DEFAULT, - QIC117_TAPE_MAJOR, i + 20, - S_IFCHR | S_IRUSR | S_IWUSR, - &zft_cdev, NULL); - sprintf (devname, "rawqft%i", i); - devfs_register (NULL, devname, DEVFS_FL_DEFAULT, - QIC117_TAPE_MAJOR, i + 32, - S_IFCHR | S_IRUSR | S_IWUSR, - &zft_cdev, NULL); - sprintf (devname, "nrawqft%i", i); - devfs_register (NULL, devname, DEVFS_FL_DEFAULT, - QIC117_TAPE_MAJOR, i + 36, + devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i), S_IFCHR | S_IRUSR | S_IWUSR, - &zft_cdev, NULL); + "qft%i", i); + devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 4), + S_IFCHR | S_IRUSR | S_IWUSR, + "nqft%i", i); + devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 16), + S_IFCHR | S_IRUSR | S_IWUSR, + "zqft%i", i); + devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 20), + S_IFCHR | S_IRUSR | S_IWUSR, + "nzqft%i", i); + devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 32), + S_IFCHR | S_IRUSR | S_IWUSR, + "rawqft%i", i); + devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 36), + S_IFCHR | S_IRUSR | S_IWUSR, + "nrawqft%i", i); } #ifdef CONFIG_ZFT_COMPRESSOR diff -Nru a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c --- a/drivers/char/hvc_console.c Thu May 15 15:24:43 2003 +++ b/drivers/char/hvc_console.c Thu May 15 15:24:43 2003 @@ -227,7 +227,12 @@ spin_unlock_irqrestore(&hp->lock, flags); } +#if defined (CONFIG_XMON) extern unsigned long cpus_in_xmon; +#else +unsigned long cpus_in_xmon=0; +#endif + int khvcd(void *unused) { @@ -252,6 +257,7 @@ memset(&hvc_driver, 0, sizeof(struct tty_driver)); hvc_driver.magic = TTY_DRIVER_MAGIC; + hvc_driver.owner = THIS_MODULE; hvc_driver.driver_name = "hvc"; hvc_driver.name = "hvc/"; hvc_driver.major = HVC_MAJOR; @@ -277,7 +283,7 @@ for (i = 0; i < hvc_driver.num; i++) { hvc_struct[i].lock = SPIN_LOCK_UNLOCKED; hvc_struct[i].index = i; - tty_register_device(&hvc_driver, i); + tty_register_device(&hvc_driver, i, NULL); } if (tty_register_driver(&hvc_driver)) diff -Nru a/drivers/char/ip2main.c b/drivers/char/ip2main.c --- a/drivers/char/ip2main.c Thu May 15 15:24:46 2003 +++ b/drivers/char/ip2main.c Thu May 15 15:24:46 2003 @@ -793,6 +793,7 @@ /* Initialise the relevant fields. */ ip2_tty_driver.magic = TTY_DRIVER_MAGIC; + ip2_tty_driver.owner = THIS_MODULE; ip2_tty_driver.name = pcTty; #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0) ip2_tty_driver.driver_name = pcDriver_name; @@ -869,29 +870,19 @@ */ for( i = 0; i < IP2_MAX_BOARDS; ++i ) { -#ifdef CONFIG_DEVFS_FS - char name[16]; -#endif - if ( 0 == ip2config.addr[i] ) { continue; } #ifdef CONFIG_DEVFS_FS if ( NULL != ( pB = i2BoardPtrTable[i] ) ) { - sprintf( name, "ip2/ipl%d", i ); - devfs_register(NULL, name, - DEVFS_FL_DEFAULT, - IP2_IPL_MAJOR, 4 * i, + devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i), S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR, - &ip2_ipl, NULL); + "ip2/ipl%d", i); - sprintf( name, "ip2/stat%d", i ); - devfs_register(NULL, name, - DEVFS_FL_DEFAULT, - IP2_IPL_MAJOR, 4 * i + 1, + devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i + 1), S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR, - &ip2_ipl, NULL); + "ip2/stat%d", i); for ( box = 0; box < ABS_MAX_BOXES; ++box ) { @@ -901,10 +892,10 @@ { tty_register_device(&ip2_tty_driver, j + ABS_BIGGEST_BOX * - (box+i*ABS_MAX_BOXES)); + (box+i*ABS_MAX_BOXES), NULL); tty_register_device(&ip2_callout_driver, j + ABS_BIGGEST_BOX * - (box+i*ABS_MAX_BOXES)); + (box+i*ABS_MAX_BOXES), NULL); } } } @@ -1577,7 +1568,6 @@ /* Setup pointer links in device and tty structures */ pCh->pTTY = tty; tty->driver_data = pCh; - MOD_INC_USE_COUNT; #ifdef IP2DEBUG_OPEN printk(KERN_DEBUG \ @@ -1777,14 +1767,12 @@ #endif if ( tty_hung_up_p ( pFile ) ) { - MOD_DEC_USE_COUNT; ip2trace (CHANN, ITRC_CLOSE, 2, 1, 2 ); return; } if ( tty->count > 1 ) { /* not the last close */ - MOD_DEC_USE_COUNT; ip2trace (CHANN, ITRC_CLOSE, 2, 1, 3 ); @@ -1852,7 +1840,6 @@ DBG_CNT("ip2_close: after wakeups--"); #endif - MOD_DEC_USE_COUNT; ip2trace (CHANN, ITRC_CLOSE, ITRC_RETURN, 1, 1 ); diff -Nru a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c --- a/drivers/char/ipmi/ipmi_devintf.c Thu May 15 15:24:43 2003 +++ b/drivers/char/ipmi/ipmi_devintf.c Thu May 15 15:24:43 2003 @@ -441,24 +441,17 @@ static void ipmi_new_smi(int if_num) { - char name[10]; - - if (if_num > MAX_DEVICES) - return; - - snprintf(name, sizeof(name), "ipmidev/%d", if_num); - - devfs_register(NULL, name, 0, ipmi_major, if_num, - S_IFCHR | S_IRUSR | S_IWUSR, - &ipmi_fops, NULL); + if (if_num <= MAX_DEVICES) { + devfs_mk_cdev(MKDEV(ipmi_major, if_num), + S_IFCHR | S_IRUSR | S_IWUSR, + "ipmidev/%d", if_num); + } } static void ipmi_smi_gone(int if_num) { - if (if_num > MAX_DEVICES) - return; - - devfs_remove("ipmidev/%d", if_num); + if (if_num <= MAX_DEVICES) + devfs_remove("ipmidev/%d", if_num); } static struct ipmi_smi_watcher smi_watcher = diff -Nru a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c --- a/drivers/char/ipmi/ipmi_msghandler.c Thu May 15 15:24:39 2003 +++ b/drivers/char/ipmi/ipmi_msghandler.c Thu May 15 15:24:39 2003 @@ -174,7 +174,7 @@ int ipmi_register_all_cmd_rcvr(ipmi_user_t user) { - int flags; + unsigned long flags; int rv = -EBUSY; write_lock_irqsave(&(user->intf->users_lock), flags); @@ -193,7 +193,7 @@ int ipmi_unregister_all_cmd_rcvr(ipmi_user_t user) { - int flags; + unsigned long flags; int rv = -EINVAL; write_lock_irqsave(&(user->intf->users_lock), flags); @@ -1023,7 +1023,7 @@ int rv; ipmi_smi_t new_intf; struct list_head *entry; - unsigned int flags; + unsigned long flags; /* Make sure the driver is actually initialized, this handles @@ -1148,7 +1148,7 @@ int rv = -ENODEV; int i; struct list_head *entry; - unsigned int flags; + unsigned long flags; down_write(&interfaces_sem); if (list_empty(&(intf->users))) diff -Nru a/drivers/char/isicom.c b/drivers/char/isicom.c --- a/drivers/char/isicom.c Thu May 15 15:24:33 2003 +++ b/drivers/char/isicom.c Thu May 15 15:24:33 2003 @@ -590,9 +590,7 @@ port->status &= ~ISI_DCD; if (!((port->flags & ASYNC_CALLOUT_ACTIVE) && (port->flags & ASYNC_CALLOUT_NOHUP))) { - MOD_INC_USE_COUNT; - if (schedule_task(&port->hangup_tq) == 0) - MOD_DEC_USE_COUNT; + schedule_task(&port->hangup_tq); } } } @@ -846,7 +844,6 @@ #endif bp->status |= BOARD_ACTIVE; - MOD_INC_USE_COUNT; return; } @@ -1104,7 +1101,6 @@ for(channel = 0; channel < bp->port_count; channel++, port++) { drop_dtr_rts(port); } - MOD_DEC_USE_COUNT; } static void isicom_shutdown_port(struct isi_port * port) @@ -1644,7 +1640,6 @@ tty = port->tty; if (tty) tty_hangup(tty); /* FIXME: module removal race here - AKPM */ - MOD_DEC_USE_COUNT; } static void isicom_hangup(struct tty_struct * tty) @@ -1715,6 +1710,7 @@ /* tty driver structure initialization */ memset(&isicom_normal, 0, sizeof(struct tty_driver)); isicom_normal.magic = TTY_DRIVER_MAGIC; + isicom_normal.owner = THIS_MODULE; isicom_normal.name = "ttyM"; isicom_normal.major = ISICOM_NMAJOR; isicom_normal.minor_start = 0; diff -Nru a/drivers/char/istallion.c b/drivers/char/istallion.c --- a/drivers/char/istallion.c Thu May 15 15:24:40 2003 +++ b/drivers/char/istallion.c Thu May 15 15:24:40 2003 @@ -1054,7 +1054,6 @@ if (portp->devnr < 1) return(-ENODEV); - MOD_INC_USE_COUNT; /* * Check if this port is in the middle of closing. If so then wait @@ -1170,14 +1169,12 @@ save_flags(flags); cli(); if (tty_hung_up_p(filp)) { - MOD_DEC_USE_COUNT; restore_flags(flags); return; } if ((tty->count == 1) && (portp->refcount != 1)) portp->refcount = 1; if (portp->refcount-- > 1) { - MOD_DEC_USE_COUNT; restore_flags(flags); return; } @@ -1232,7 +1229,6 @@ portp->flags &= ~(ASYNC_CALLOUT_ACTIVE | ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); wake_up_interruptible(&portp->close_wait); - MOD_DEC_USE_COUNT; restore_flags(flags); } @@ -2369,7 +2365,6 @@ tty_hangup(portp->tty); } } - MOD_DEC_USE_COUNT; } /*****************************************************************************/ @@ -3004,9 +2999,7 @@ if (! ((portp->flags & ASYNC_CALLOUT_ACTIVE) && (portp->flags & ASYNC_CALLOUT_NOHUP))) { if (tty != (struct tty_struct *) NULL) { - MOD_INC_USE_COUNT; - if (schedule_task(&portp->tqhangup) == 0) - MOD_DEC_USE_COUNT; + schedule_task(&portp->tqhangup); } } } @@ -5336,12 +5329,9 @@ devfs_mk_dir("staliomem"); for (i = 0; i < 4; i++) { - char name[16]; - sprintf(name, "staliomem/%d", i); - devfs_register(NULL, name, DEVFS_FL_DEFAULT, - STL_SIOMEMMAJOR, i, + devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i), S_IFCHR | S_IRUSR | S_IWUSR, - &stli_fsiomem, NULL); + "staliomem/%d", i); } /* @@ -5350,6 +5340,7 @@ */ memset(&stli_serial, 0, sizeof(struct tty_driver)); stli_serial.magic = TTY_DRIVER_MAGIC; + stli_serial.owner = THIS_MODULE; stli_serial.driver_name = stli_drvname; stli_serial.name = stli_serialname; stli_serial.major = STL_SERIALMAJOR; diff -Nru a/drivers/char/keyboard.c b/drivers/char/keyboard.c --- a/drivers/char/keyboard.c Thu May 15 15:24:37 2003 +++ b/drivers/char/keyboard.c Thu May 15 15:24:37 2003 @@ -1047,8 +1047,8 @@ printk(KERN_WARNING "keyboard.c: can't emulate rawmode for keycode %d\n", keycode); #ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ - if (keycode == KEY_SYSRQ && !rep) { - sysrq_down = sysrq_alt && down; + if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) { + sysrq_down = down; return; } if (sysrq_down && down && !rep) { diff -Nru a/drivers/char/lp.c b/drivers/char/lp.c --- a/drivers/char/lp.c Thu May 15 15:24:33 2003 +++ b/drivers/char/lp.c Thu May 15 15:24:33 2003 @@ -784,8 +784,6 @@ static int lp_register(int nr, struct parport *port) { - char name[16]; - lp_table[nr].dev = parport_register_device(port, "lp", lp_preempt, NULL, NULL, 0, (void *) &lp_table[nr]); @@ -796,11 +794,8 @@ if (reset) lp_reset(nr); - sprintf (name, "printers/%d", nr); - devfs_register (NULL, name, - DEVFS_FL_DEFAULT, LP_MAJOR, nr, - S_IFCHR | S_IRUGO | S_IWUGO, - &lp_fops, NULL); + devfs_mk_cdev(MKDEV(LP_MAJOR, nr), S_IFCHR | S_IRUGO | S_IWUGO, + "printers/%d", nr); printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, (port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven"); diff -Nru a/drivers/char/mem.c b/drivers/char/mem.c --- a/drivers/char/mem.c Thu May 15 15:24:39 2003 +++ b/drivers/char/mem.c Thu May 15 15:24:39 2003 @@ -522,7 +522,7 @@ */ static loff_t memory_lseek(struct file * file, loff_t offset, int orig) { - int ret; + loff_t ret; lock_kernel(); switch (orig) { @@ -660,15 +660,16 @@ return 0; } -void __init memory_devfs_register (void) -{ - /* These are never unregistered */ - static const struct { - unsigned short minor; - char *name; - umode_t mode; - struct file_operations *fops; - } list[] = { /* list of minor devices */ +static struct file_operations memory_fops = { + .open = memory_open, /* just a selector for the real open */ +}; + +static const struct { + unsigned int minor; + char *name; + umode_t mode; + struct file_operations *fops; +} devlist[] = { /* list of minor devices */ {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, {3, "null", S_IRUGO | S_IWUGO, &null_fops}, @@ -680,25 +681,20 @@ {8, "random", S_IRUGO | S_IWUSR, &random_fops}, {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops}, {11,"kmsg", S_IRUGO | S_IWUSR, &kmsg_fops}, - }; - int i; - - for (i=0; i<(sizeof(list)/sizeof(*list)); i++) - devfs_register (NULL, list[i].name, DEVFS_FL_NONE, - MEM_MAJOR, list[i].minor, - list[i].mode | S_IFCHR, - list[i].fops, NULL); -} - -static struct file_operations memory_fops = { - .open = memory_open, /* just a selector for the real open */ }; -int __init chr_dev_init(void) +static int __init chr_dev_init(void) { + int i; + if (register_chrdev(MEM_MAJOR,"mem",&memory_fops)) printk("unable to get major %d for memory devs\n", MEM_MAJOR); - memory_devfs_register(); + + for (i = 0; i < ARRAY_SIZE(devlist); i++) { + devfs_mk_cdev(MKDEV(MEM_MAJOR, devlist[i].minor), + S_IFCHR | devlist[i].mode, devlist[i].name); + } + rand_initialize(); #if defined (CONFIG_FB) fbmem_init(); diff -Nru a/drivers/char/misc.c b/drivers/char/misc.c --- a/drivers/char/misc.c Thu May 15 15:24:44 2003 +++ b/drivers/char/misc.c Thu May 15 15:24:44 2003 @@ -200,8 +200,8 @@ "misc/%s", misc->name); } - devfs_register(NULL, misc->devfs_name, 0, MISC_MAJOR, misc->minor, - S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, misc->fops, NULL); + devfs_mk_cdev(MKDEV(MISC_MAJOR, misc->minor), + S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, misc->devfs_name); /* * Add it to the front, so that later devices can "override" diff -Nru a/drivers/char/moxa.c b/drivers/char/moxa.c --- a/drivers/char/moxa.c Thu May 15 15:24:44 2003 +++ b/drivers/char/moxa.c Thu May 15 15:24:44 2003 @@ -341,6 +341,7 @@ memset(&moxaDriver, 0, sizeof(struct tty_driver)); memset(&moxaCallout, 0, sizeof(struct tty_driver)); moxaDriver.magic = TTY_DRIVER_MAGIC; + moxaDriver.owner = THIS_MODULE; moxaDriver.name = "ttya"; moxaDriver.major = ttymajor; moxaDriver.minor_start = 0; @@ -544,7 +545,6 @@ ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE); } } - MOD_DEC_USE_COUNT; } static int moxa_open(struct tty_struct *tty, struct file *filp) @@ -556,7 +556,6 @@ port = PORTNO(tty); if (port == MAX_PORTS) { - MOD_INC_USE_COUNT; return (0); } if (!MoxaPortIsValid(port)) { @@ -579,7 +578,6 @@ } up(&moxaBuffSem); - MOD_INC_USE_COUNT; ch = &moxaChannels[port]; ch->count++; tty->driver_data = ch; @@ -619,7 +617,6 @@ port = PORTNO(tty); if (port == MAX_PORTS) { - MOD_DEC_USE_COUNT; return; } if (!MoxaPortIsValid(port)) { @@ -633,7 +630,6 @@ return; } if (tty_hung_up_p(filp)) { - MOD_DEC_USE_COUNT; return; } ch = (struct moxa_str *) tty->driver_data; @@ -649,7 +645,6 @@ ch->count = 0; } if (ch->count) { - MOD_DEC_USE_COUNT; return; } ch->asyncflags |= ASYNC_CLOSING; @@ -688,7 +683,6 @@ ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE | ASYNC_CLOSING); wake_up_interruptible(&ch->close_wait); - MOD_DEC_USE_COUNT; } static int moxa_write(struct tty_struct *tty, int from_user, @@ -1024,9 +1018,7 @@ wake_up_interruptible(&ch->open_wait); else { set_bit(MOXA_EVENT_HANGUP, &ch->event); - MOD_DEC_USE_COUNT; - if (schedule_work(&ch->tqueue) == 0) - MOD_INC_USE_COUNT; + schedule_work(&ch->tqueue); } } } diff -Nru a/drivers/char/mwave/mwavedd.h b/drivers/char/mwave/mwavedd.h --- a/drivers/char/mwave/mwavedd.h Thu May 15 15:24:39 2003 +++ b/drivers/char/mwave/mwavedd.h Thu May 15 15:24:39 2003 @@ -50,9 +50,11 @@ #define _LINUX_MWAVEDD_H #include "3780i.h" #include "tp3780i.h" +#include "smapi.h" #include "mwavepub.h" #include #include +#include extern int mwave_debug; extern int mwave_3780i_irq; diff -Nru a/drivers/char/mxser.c b/drivers/char/mxser.c --- a/drivers/char/mxser.c Thu May 15 15:24:41 2003 +++ b/drivers/char/mxser.c Thu May 15 15:24:41 2003 @@ -501,6 +501,7 @@ memset(&mxvar_sdriver, 0, sizeof(struct tty_driver)); mxvar_sdriver.magic = TTY_DRIVER_MAGIC; + mxvar_sdriver.owner = THIS_MODULE; mxvar_sdriver.name = "ttyM"; mxvar_sdriver.major = ttymajor; mxvar_sdriver.minor_start = 0; @@ -708,7 +709,6 @@ tty_hangup(tty); /* FIXME: module removal race here - AKPM */ } } - MOD_DEC_USE_COUNT; } /* @@ -767,8 +767,6 @@ info->session = current->session; info->pgrp = current->pgrp; - MOD_INC_USE_COUNT; - return (0); } @@ -795,7 +793,6 @@ if (tty_hung_up_p(filp)) { restore_flags(flags); - MOD_DEC_USE_COUNT; return; } if ((tty->count == 1) && (info->count != 1)) { @@ -817,7 +814,6 @@ } if (info->count) { restore_flags(flags); - MOD_DEC_USE_COUNT; return; } info->flags |= ASYNC_CLOSING; @@ -881,7 +877,6 @@ wake_up_interruptible(&info->close_wait); restore_flags(flags); - MOD_DEC_USE_COUNT; } static int mxser_write(struct tty_struct *tty, int from_user, @@ -1492,9 +1487,7 @@ if (info->xmit_cnt < WAKEUP_CHARS) { set_bit(MXSER_EVENT_TXLOW, &info->event); - MOD_INC_USE_COUNT; - if (schedule_work(&info->tqueue) == 0) - MOD_DEC_USE_COUNT; + schedule_work(&info->tqueue); } if (info->xmit_cnt <= 0) { info->IER &= ~UART_IER_THRI; @@ -1523,9 +1516,7 @@ else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) && (info->flags & ASYNC_CALLOUT_NOHUP))) set_bit(MXSER_EVENT_HANGUP, &info->event); - MOD_INC_USE_COUNT; - if (schedule_work(&info->tqueue) == 0) - MOD_DEC_USE_COUNT; + schedule_work(&info->tqueue); } if (info->flags & ASYNC_CTS_FLOW) { if (info->tty->hw_stopped) { @@ -1535,9 +1526,7 @@ outb(info->IER, info->base + UART_IER); set_bit(MXSER_EVENT_TXLOW, &info->event); - MOD_INC_USE_COUNT; - if (schedule_work(&info->tqueue) == 0) - MOD_DEC_USE_COUNT; + schedule_work(&info->tqueue); } } else { if (!(status & UART_MSR_CTS)) { diff -Nru a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c --- a/drivers/char/n_hdlc.c Thu May 15 15:24:35 2003 +++ b/drivers/char/n_hdlc.c Thu May 15 15:24:35 2003 @@ -9,7 +9,7 @@ * Al Longyear , Paul Mackerras * * Original release 01/11/99 - * $Id: n_hdlc.c,v 4.6 2003/04/21 19:14:07 paulkf Exp $ + * $Id: n_hdlc.c,v 4.8 2003/05/06 21:18:51 paulkf Exp $ * * This code is released under the GNU General Public License (GPL) * @@ -78,7 +78,7 @@ */ #define HDLC_MAGIC 0x239e -#define HDLC_VERSION "$Revision: 4.6 $" +#define HDLC_VERSION "$Revision: 4.8 $" #include #include @@ -215,6 +215,21 @@ /* Define this string only once for all macro invocations */ static char szVersion[] = HDLC_VERSION; +static struct tty_ldisc n_hdlc_ldisc = { + .owner = THIS_MODULE, + .magic = TTY_LDISC_MAGIC, + .name = "hdlc", + .open = n_hdlc_tty_open, + .close = n_hdlc_tty_close, + .read = n_hdlc_tty_read, + .write = n_hdlc_tty_write, + .ioctl = n_hdlc_tty_ioctl, + .poll = n_hdlc_tty_poll, + .receive_buf = n_hdlc_tty_receive, + .receive_room = n_hdlc_tty_room, + .write_wakeup = n_hdlc_tty_wakeup, +}; + /* n_hdlc_release() * * release an n_hdlc per device line discipline info structure @@ -968,25 +983,6 @@ static int __init n_hdlc_init(void) { - static struct tty_ldisc n_hdlc_ldisc = { - TTY_LDISC_MAGIC, /* magic */ - "hdlc", /* name */ - 0, /* num */ - 0, /* flags */ - n_hdlc_tty_open, /* open */ - n_hdlc_tty_close, /* close */ - 0, /* flush_buffer */ - 0, /* chars_in_buffer */ - n_hdlc_tty_read, /* read */ - n_hdlc_tty_write, /* write */ - n_hdlc_tty_ioctl, /* ioctl */ - 0, /* set_termios */ - n_hdlc_tty_poll, /* poll */ - n_hdlc_tty_receive, /* receive_buf */ - n_hdlc_tty_room, /* receive_room */ - n_hdlc_tty_wakeup, /* write_wakeup */ - THIS_MODULE /* owner */ - }; int status; /* range check maxframe arg */ diff -Nru a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c --- a/drivers/char/nwbutton.c Thu May 15 15:24:45 2003 +++ b/drivers/char/nwbutton.c Thu May 15 15:24:45 2003 @@ -146,7 +146,7 @@ * increments the counter. */ -static void button_handler (int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t button_handler (int irq, void *dev_id, struct pt_regs *regs) { if (button_press_count) { del_timer (&button_timer); @@ -156,6 +156,8 @@ button_timer.function = button_sequence_finished; button_timer.expires = (jiffies + bdelay); add_timer (&button_timer); + + return IRQ_HANDLED; } /* diff -Nru a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c --- a/drivers/char/pcmcia/synclink_cs.c Thu May 15 15:24:36 2003 +++ b/drivers/char/pcmcia/synclink_cs.c Thu May 15 15:24:36 2003 @@ -1,7 +1,7 @@ /* * linux/drivers/char/pcmcia/synclink_cs.c * - * $Id: synclink_cs.c,v 4.6 2003/04/21 17:46:55 paulkf Exp $ + * $Id: synclink_cs.c,v 4.10 2003/05/13 16:06:03 paulkf Exp $ * * Device driver for Microgate SyncLink PC Card * multiprotocol serial adapter. @@ -430,7 +430,7 @@ static int rx_alloc_buffers(MGSLPC_INFO *info); static void rx_free_buffers(MGSLPC_INFO *info); -static void mgslpc_isr(int irq, void *dev_id, struct pt_regs * regs); +static irqreturn_t mgslpc_isr(int irq, void *dev_id, struct pt_regs * regs); /* * Bottom half interrupt handlers @@ -476,6 +476,7 @@ static int debug_level = 0; static int maxframe[MAX_DEVICE_COUNT] = {0,}; +static int dosyncppp[MAX_DEVICE_COUNT] = {1,1,1,1}; /* The old way: bit map of interrupts to choose from */ /* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */ @@ -492,11 +493,12 @@ MODULE_PARM(cuamajor,"i"); MODULE_PARM(debug_level,"i"); MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_DEVICE_COUNT) "i"); +MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_DEVICE_COUNT) "i"); MODULE_LICENSE("GPL"); static char *driver_name = "SyncLink PC Card driver"; -static char *driver_version = "$Revision: 4.6 $"; +static char *driver_version = "$Revision: 4.10 $"; static struct tty_driver serial_driver, callout_driver; static int serial_refcount; @@ -574,9 +576,6 @@ link->priv = info; /* Initialize the dev_link_t structure */ - init_timer(&link->release); - link->release.function = &mgslpc_release; - link->release.data = (u_long)link; /* Interrupt setup */ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; @@ -813,7 +812,7 @@ link->state &= ~DEV_PRESENT; if (link->state & DEV_CONFIG) { ((MGSLPC_INFO *)link->priv)->stop = 1; - mod_timer(&link->release, jiffies + HZ/20); + mgslpc_release((u_long)link); } break; case CS_EVENT_CARD_INSERTION: @@ -1356,7 +1355,7 @@ * dev_id device ID supplied during interrupt registration * regs interrupted processor context */ -static void mgslpc_isr(int irq, void *dev_id, struct pt_regs * regs) +static irqreturn_t mgslpc_isr(int irq, void *dev_id, struct pt_regs * regs) { MGSLPC_INFO * info = (MGSLPC_INFO *)dev_id; unsigned short isr; @@ -1366,10 +1365,10 @@ if (debug_level >= DEBUG_LEVEL_ISR) printk("mgslpc_isr(%d) entry.\n", irq); if (!info) - return; + return IRQ_NONE; if (!(info->link.state & DEV_CONFIG)) - return; + return IRQ_HANDLED; spin_lock(&info->lock); @@ -1459,6 +1458,8 @@ if (debug_level >= DEBUG_LEVEL_ISR) printk("%s(%d):mgslpc_isr(%d)exit.\n", __FILE__,__LINE__,irq); + + return IRQ_HANDLED; } /* Initialize and start device. @@ -3113,8 +3114,7 @@ if (info->line < MAX_DEVICE_COUNT) { if (maxframe[info->line]) info->max_frame_size = maxframe[info->line]; -// info->dosyncppp = dosyncppp[info->line]; - info->dosyncppp = 1; + info->dosyncppp = dosyncppp[info->line]; } mgslpc_device_count++; @@ -3276,7 +3276,6 @@ unregister_pccard_driver(&dev_info); while (dev_list != NULL) { - del_timer(&dev_list->release); if (dev_list->state & DEV_CONFIG) mgslpc_release((u_long)dev_list); mgslpc_detach(dev_list); diff -Nru a/drivers/char/pcxx.c b/drivers/char/pcxx.c --- a/drivers/char/pcxx.c Thu May 15 15:24:40 2003 +++ b/drivers/char/pcxx.c Thu May 15 15:24:40 2003 @@ -431,8 +431,6 @@ return(-ENODEV); } - /* flag the kernel that there is somebody using this guy */ - MOD_INC_USE_COUNT; /* * If the device is in the middle of being closed, then block * until it's done, and then try again. @@ -576,7 +574,6 @@ if(tty_hung_up_p(filp)) { /* flag that somebody is done with this module */ - MOD_DEC_USE_COUNT; restore_flags(flags); return; } @@ -594,7 +591,6 @@ } if (info->count-- > 1) { restore_flags(flags); - MOD_DEC_USE_COUNT; return; } if (info->count < 0) { @@ -651,7 +647,6 @@ info->asyncflags &= ~(ASYNC_NORMAL_ACTIVE| ASYNC_CALLOUT_ACTIVE|ASYNC_CLOSING); wake_up_interruptible(&info->close_wait); - MOD_DEC_USE_COUNT; restore_flags(flags); } } @@ -1228,6 +1223,7 @@ memset(&pcxe_driver, 0, sizeof(struct tty_driver)); pcxe_driver.magic = TTY_DRIVER_MAGIC; + pcxe_driver.owner = THIS_MODULE; pcxe_driver.name = "ttyD"; pcxe_driver.major = DIGI_MAJOR; pcxe_driver.minor_start = 0; diff -Nru a/drivers/char/ppdev.c b/drivers/char/ppdev.c --- a/drivers/char/ppdev.c Thu May 15 15:24:45 2003 +++ b/drivers/char/ppdev.c Thu May 15 15:24:45 2003 @@ -760,10 +760,8 @@ } devfs_mk_dir("parports"); for (i = 0; i < PARPORT_MAX; i++) { - char name[16]; - sprintf(name, "parports/%d", i); - devfs_register(NULL, name, DEVFS_FL_DEFAULT, PP_MAJOR, i, - S_IFCHR | S_IRUGO | S_IWUGO, &pp_fops, NULL); + devfs_mk_cdev(MKDEV(PP_MAJOR, i), + S_IFCHR | S_IRUGO | S_IWUGO, "parports/%d", i); } printk (KERN_INFO PP_VERSION "\n"); diff -Nru a/drivers/char/random.c b/drivers/char/random.c --- a/drivers/char/random.c Thu May 15 15:24:33 2003 +++ b/drivers/char/random.c Thu May 15 15:24:33 2003 @@ -1527,7 +1527,7 @@ * If we gave the user some bytes, update the access time. */ if (count != 0) { - UPDATE_ATIME(file->f_dentry->d_inode); + update_atime(file->f_dentry->d_inode); } return (count ? count : retval); diff -Nru a/drivers/char/raw.c b/drivers/char/raw.c --- a/drivers/char/raw.c Thu May 15 15:24:40 2003 +++ b/drivers/char/raw.c Thu May 15 15:24:40 2003 @@ -181,7 +181,7 @@ } if (rawdev->binding) { bdput(rawdev->binding); - MOD_DEC_USE_COUNT; + module_put(THIS_MODULE); } if (rq.block_major == 0 && rq.block_minor == 0) { /* unbind */ @@ -191,7 +191,7 @@ if (rawdev->binding == NULL) err = -ENOMEM; else - try_module_get(THIS_MODULE); + __module_get(THIS_MODULE); } up(&raw_mutex); } else { diff -Nru a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c --- a/drivers/char/rio/rio_linux.c Thu May 15 15:24:40 2003 +++ b/drivers/char/rio/rio_linux.c Thu May 15 15:24:40 2003 @@ -389,29 +389,6 @@ udelay (usecs); } - -void rio_inc_mod_count (void) -{ -#ifdef MODULE - func_enter (); - rio_dprintk (RIO_DEBUG_MOD_COUNT, "rio_inc_mod_count\n"); - MOD_INC_USE_COUNT; - func_exit (); -#endif -} - - -void rio_dec_mod_count (void) -{ -#ifdef MODULE - func_enter (); - rio_dprintk (RIO_DEBUG_MOD_COUNT, "rio_dec_mod_count\n"); - MOD_DEC_USE_COUNT; - func_exit (); -#endif -} - - static int rio_set_real_termios (void *ptr) { int rv, modem; @@ -660,7 +637,6 @@ PortP = (struct Port *)ptr; PortP->gs.tty = NULL; - rio_dec_mod_count (); func_exit (); } @@ -686,7 +662,6 @@ } PortP->gs.tty = NULL; - rio_dec_mod_count (); func_exit (); } @@ -908,6 +883,7 @@ memset(&rio_driver, 0, sizeof(rio_driver)); rio_driver.magic = TTY_DRIVER_MAGIC; + rio_driver.owner = THIS_MODULE; rio_driver.driver_name = "specialix_rio"; rio_driver.name = "ttySR"; rio_driver.major = RIO_NORMAL_MAJOR0; diff -Nru a/drivers/char/rio/rio_linux.h b/drivers/char/rio/rio_linux.h --- a/drivers/char/rio/rio_linux.h Thu May 15 15:24:41 2003 +++ b/drivers/char/rio/rio_linux.h Thu May 15 15:24:41 2003 @@ -87,9 +87,6 @@ #endif -void rio_dec_mod_count (void); -void rio_inc_mod_count (void); - /* Allow us to debug "in the field" without requiring clients to recompile.... */ #if 1 diff -Nru a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c --- a/drivers/char/rio/riotty.c Thu May 15 15:24:37 2003 +++ b/drivers/char/rio/riotty.c Thu May 15 15:24:37 2003 @@ -139,7 +139,6 @@ extern struct rio_info *p; -extern void rio_inc_mod_count (void); int @@ -205,8 +204,6 @@ tty->driver_data = PortP; PortP->gs.tty = tty; - if (!PortP->gs.count) - rio_inc_mod_count (); PortP->gs.count++; rio_dprintk (RIO_DEBUG_TTY, "%d bytes in tx buffer\n", @@ -215,8 +212,6 @@ retval = gs_init_port (&PortP->gs); if (retval) { PortP->gs.count--; - if (PortP->gs.count) - rio_dec_mod_count (); return -ENXIO; } /* diff -Nru a/drivers/char/riscom8.c b/drivers/char/riscom8.c --- a/drivers/char/riscom8.c Thu May 15 15:24:38 2003 +++ b/drivers/char/riscom8.c Thu May 15 15:24:38 2003 @@ -552,9 +552,7 @@ wake_up_interruptible(&port->open_wait); else if (!((port->flags & ASYNC_CALLOUT_ACTIVE) && (port->flags & ASYNC_CALLOUT_NOHUP))) { - MOD_INC_USE_COUNT; - if (schedule_task(&port->tqueue_hangup) == 0) - MOD_DEC_USE_COUNT; + schedule_task(&port->tqueue_hangup); } } @@ -676,7 +674,6 @@ IRQ_to_board[bp->irq] = bp; bp->flags |= RC_BOARD_ACTIVE; - MOD_INC_USE_COUNT; return 0; } @@ -694,7 +691,6 @@ bp->DTR = ~0; rc_out(bp, RC_DTR, bp->DTR); /* Drop DTR on all ports */ - MOD_DEC_USE_COUNT; } /* @@ -1678,7 +1674,6 @@ tty = port->tty; if (tty) tty_hangup(tty); /* FIXME: module removal race still here */ - MOD_DEC_USE_COUNT; } static void rc_hangup(struct tty_struct * tty) @@ -1757,6 +1752,7 @@ memset(IRQ_to_board, 0, sizeof(IRQ_to_board)); memset(&riscom_driver, 0, sizeof(riscom_driver)); riscom_driver.magic = TTY_DRIVER_MAGIC; + riscom_driver.owner = THIS_MODULE; riscom_driver.name = "ttyL"; riscom_driver.major = RISCOM8_NORMAL_MAJOR; riscom_driver.num = RC_NBOARD * RC_NPORT; diff -Nru a/drivers/char/rocket.c b/drivers/char/rocket.c --- a/drivers/char/rocket.c Thu May 15 15:24:41 2003 +++ b/drivers/char/rocket.c Thu May 15 15:24:41 2003 @@ -874,9 +874,6 @@ } if (info->count++ == 0) { -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif rp_num_ports_open++; #ifdef ROCKET_DEBUG_OPEN printk("rocket mod++ = %d...", rp_num_ports_open); @@ -1071,9 +1068,6 @@ tty->closing = 0; wake_up_interruptible(&info->close_wait); -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif rp_num_ports_open--; #ifdef ROCKET_DEBUG_OPEN printk("rocket mod-- = %d...", rp_num_ports_open); @@ -1504,9 +1498,6 @@ return; } if (info->count) { -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif rp_num_ports_open--; } @@ -2012,6 +2003,7 @@ */ memset(&rocket_driver, 0, sizeof(struct tty_driver)); rocket_driver.magic = TTY_DRIVER_MAGIC; + rocket_driver.owner = THIS_MODULE; #ifdef CONFIG_DEVFS_FS rocket_driver.name = "tts/R"; #else diff -Nru a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c --- a/drivers/char/ser_a2232.c Thu May 15 15:24:35 2003 +++ b/drivers/char/ser_a2232.c Thu May 15 15:24:35 2003 @@ -272,7 +272,6 @@ not in "a2232_close()". See the comment in "sx.c", too. If you run into problems, compile this driver into the kernel instead of compiling it as a module. */ - MOD_DEC_USE_COUNT; } static int a2232_set_real_termios(void *ptr) @@ -414,7 +413,6 @@ a2232_disable_tx_interrupts(ptr); a2232_disable_rx_interrupts(ptr); /* see the comment in a2232_shutdown_port above. */ - /* MOD_DEC_USE_COUNT; */ } static void a2232_hungup(void *ptr) @@ -468,13 +466,9 @@ return retval; } port->gs.flags |= GS_ACTIVE; - if (port->gs.count == 1) { - MOD_INC_USE_COUNT; - } retval = gs_block_til_ready(port, filp); if (retval) { - MOD_DEC_USE_COUNT; port->gs.count--; return retval; } @@ -711,6 +705,7 @@ memset(&a2232_driver, 0, sizeof(a2232_driver)); a2232_driver.magic = TTY_DRIVER_MAGIC; + a2232_driver.owner = THIS_MODULE; a2232_driver.driver_name = "commodore_a2232"; a2232_driver.name = "ttyY"; a2232_driver.major = A2232_NORMAL_MAJOR; diff -Nru a/drivers/char/serial167.c b/drivers/char/serial167.c --- a/drivers/char/serial167.c Thu May 15 15:24:37 2003 +++ b/drivers/char/serial167.c Thu May 15 15:24:37 2003 @@ -2395,6 +2395,7 @@ memset(&cy_serial_driver, 0, sizeof(struct tty_driver)); cy_serial_driver.magic = TTY_DRIVER_MAGIC; + cy_serial_driver.owner = THIS_MODULE; #ifdef CONFIG_DEVFS_FS cy_serial_driver.name = "tts/"; #else diff -Nru a/drivers/char/serial_tx3912.c b/drivers/char/serial_tx3912.c --- a/drivers/char/serial_tx3912.c Thu May 15 15:24:39 2003 +++ b/drivers/char/serial_tx3912.c Thu May 15 15:24:39 2003 @@ -41,8 +41,6 @@ static void rs_shutdown_port (void * ptr); static int rs_set_real_termios (void *ptr); static int rs_chars_in_buffer (void * ptr); -static void rs_hungup (void *ptr); -static void rs_close (void *ptr); /* * Used by generic serial driver to access hardware @@ -56,8 +54,6 @@ .shutdown_port = rs_shutdown_port, .set_real_termios = rs_set_real_termios, .chars_in_buffer = rs_chars_in_buffer, - .close = rs_close, - .hungup = rs_hungup, }; /* @@ -579,9 +575,6 @@ rs_dprintk (TX3912_UART_DEBUG_OPEN, "before inc_use_count (count=%d.\n", port->gs.count); - if (port->gs.count == 1) { - MOD_INC_USE_COUNT; - } rs_dprintk (TX3912_UART_DEBUG_OPEN, "after inc_use_count\n"); /* Jim: Initialize port hardware here */ @@ -595,7 +588,6 @@ retval, port->gs.count); if (retval) { - MOD_DEC_USE_COUNT; port->gs.count--; return retval; } @@ -621,32 +613,6 @@ } - -static void rs_close (void *ptr) -{ - func_enter (); - - /* Anything to do here? */ - - MOD_DEC_USE_COUNT; - func_exit (); -} - - -/* I haven't the foggiest why the decrement use count has to happen - here. The whole linux serial drivers stuff needs to be redesigned. - My guess is that this is a hack to minimize the impact of a bug - elsewhere. Thinking about it some more. (try it sometime) Try - running minicom on a serial port that is driven by a modularized - driver. Have the modem hangup. Then remove the driver module. Then - exit minicom. I expect an "oops". -- REW */ -static void rs_hungup (void *ptr) -{ - func_enter (); - MOD_DEC_USE_COUNT; - func_exit (); -} - static int rs_ioctl (struct tty_struct * tty, struct file * filp, unsigned int cmd, unsigned long arg) { @@ -839,6 +805,7 @@ memset(&rs_driver, 0, sizeof(rs_driver)); rs_driver.magic = TTY_DRIVER_MAGIC; + rs_driver.owner = THIS_MODULE; rs_driver.driver_name = "serial"; rs_driver.name = "ttyS"; rs_driver.major = TTY_MAJOR; diff -Nru a/drivers/char/sh-sci.c b/drivers/char/sh-sci.c --- a/drivers/char/sh-sci.c Thu May 15 15:24:45 2003 +++ b/drivers/char/sh-sci.c Thu May 15 15:24:45 2003 @@ -71,8 +71,6 @@ static int sci_get_CD(void *ptr); static void sci_shutdown_port(void *ptr); static int sci_set_real_termios(void *ptr); -static void sci_hungup(void *ptr); -static void sci_close(void *ptr); static int sci_chars_in_buffer(void *ptr); static int sci_request_irq(struct sci_port *port); static void sci_free_irq(struct sci_port *port); @@ -216,8 +214,6 @@ sci_shutdown_port, sci_set_real_termios, sci_chars_in_buffer, - sci_close, - sci_hungup, NULL }; @@ -838,12 +834,7 @@ sci_setsignals(port, 1,1); if (port->gs.count == 1) { - MOD_INC_USE_COUNT; - retval = sci_request_irq(port); - if (retval) { - goto failed_2; - } } retval = gs_block_til_ready(port, filp); @@ -878,23 +869,11 @@ failed_3: sci_free_irq(port); -failed_2: - MOD_DEC_USE_COUNT; failed_1: port->gs.count--; return retval; } -static void sci_hungup(void *ptr) -{ - MOD_DEC_USE_COUNT; -} - -static void sci_close(void *ptr) -{ - MOD_DEC_USE_COUNT; -} - static int sci_ioctl(struct tty_struct * tty, struct file * filp, unsigned int cmd, unsigned long arg) { @@ -1019,6 +998,7 @@ memset(&sci_driver, 0, sizeof(sci_driver)); sci_driver.magic = TTY_DRIVER_MAGIC; + sci_driver.owner = THIS_MODULE; sci_driver.driver_name = "sci"; #ifdef CONFIG_DEVFS_FS sci_driver.name = "ttsc/"; diff -Nru a/drivers/char/specialix.c b/drivers/char/specialix.c --- a/drivers/char/specialix.c Thu May 15 15:24:43 2003 +++ b/drivers/char/specialix.c Thu May 15 15:24:43 2003 @@ -833,9 +833,7 @@ #ifdef SPECIALIX_DEBUG printk ( "Sending HUP.\n"); #endif - MOD_INC_USE_COUNT; - if (schedule_task(&port->tqueue_hangup) == 0) - MOD_DEC_USE_COUNT; + schedule_task(&port->tqueue_hangup); } else { #ifdef SPECIALIX_DEBUG printk ( "Don't need to send HUP.\n"); @@ -980,7 +978,6 @@ turn_ints_on (bp); bp->flags |= SX_BOARD_ACTIVE; - MOD_INC_USE_COUNT; return 0; } @@ -1000,7 +997,6 @@ turn_ints_off (bp); - MOD_DEC_USE_COUNT; } @@ -2150,7 +2146,6 @@ tty = port->tty; if (tty) tty_hangup(tty); /* FIXME: module removal race here */ - MOD_DEC_USE_COUNT; } @@ -2233,6 +2228,7 @@ init_bh(SPECIALIX_BH, do_specialix_bh); memset(&specialix_driver, 0, sizeof(specialix_driver)); specialix_driver.magic = TTY_DRIVER_MAGIC; + specialix_driver.owner = THIS_MODULE; specialix_driver.name = "ttyW"; specialix_driver.major = SPECIALIX_NORMAL_MAJOR; specialix_driver.num = SX_NBOARD * SX_NPORT; diff -Nru a/drivers/char/stallion.c b/drivers/char/stallion.c --- a/drivers/char/stallion.c Thu May 15 15:24:42 2003 +++ b/drivers/char/stallion.c Thu May 15 15:24:42 2003 @@ -1044,8 +1044,6 @@ if (portp == (stlport_t *) NULL) return(-ENODEV); - MOD_INC_USE_COUNT; - /* * On the first open of the device setup the port hardware, and * initialize the per port data structure. @@ -1207,14 +1205,12 @@ save_flags(flags); cli(); if (tty_hung_up_p(filp)) { - MOD_DEC_USE_COUNT; restore_flags(flags); return; } if ((tty->count == 1) && (portp->refcount != 1)) portp->refcount = 1; if (portp->refcount-- > 1) { - MOD_DEC_USE_COUNT; restore_flags(flags); return; } @@ -1267,7 +1263,6 @@ portp->flags &= ~(ASYNC_CALLOUT_ACTIVE | ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING); wake_up_interruptible(&portp->close_wait); - MOD_DEC_USE_COUNT; restore_flags(flags); } @@ -2241,11 +2236,11 @@ #endif if (portp == (stlport_t *) NULL) - goto out; + return; tty = portp->tty; if (tty == (struct tty_struct *) NULL) - goto out; + return; lock_kernel(); if (test_bit(ASYI_TXLOW, &portp->istate)) { @@ -2270,8 +2265,6 @@ } } unlock_kernel(); -out: - MOD_DEC_USE_COUNT; } /*****************************************************************************/ @@ -3216,13 +3209,11 @@ if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem)) printk("STALLION: failed to register serial board device\n"); devfs_mk_dir("staliomem"); + for (i = 0; i < 4; i++) { - char name[16]; - sprintf(name, "staliomem/%d", i); - devfs_register(NULL, name, DEVFS_FL_DEFAULT, - STL_SIOMEMMAJOR, i, - S_IFCHR | S_IRUSR | S_IWUSR, - &stl_fsiomem, NULL); + devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i), + S_IFCHR|S_IRUSR|S_IWUSR, + &stl_fsiomem, NULL, "staliomem/%d", i); } /* @@ -3231,6 +3222,7 @@ */ memset(&stl_serial, 0, sizeof(struct tty_driver)); stl_serial.magic = TTY_DRIVER_MAGIC; + stl_serial.owner = THIS_MODULE; stl_serial.driver_name = stl_drvname; stl_serial.name = stl_serialname; stl_serial.major = STL_SERIALMAJOR; @@ -4136,9 +4128,7 @@ if ((len == 0) || ((len < STL_TXBUFLOW) && (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { set_bit(ASYI_TXLOW, &portp->istate); - MOD_INC_USE_COUNT; - if (schedule_work(&portp->tqueue) == 0) - MOD_DEC_USE_COUNT; + schedule_work(&portp->tqueue); } if (len == 0) { @@ -4318,9 +4308,7 @@ misr = inb(ioaddr + EREG_DATA); if (misr & MISR_DCD) { set_bit(ASYI_DCDCHANGE, &portp->istate); - MOD_INC_USE_COUNT; - if (schedule_task(&portp->tqueue) == 0) - MOD_DEC_USE_COUNT; + schedule_task(&portp->tqueue); portp->stats.modem++; } @@ -5117,9 +5105,7 @@ if ((len == 0) || ((len < STL_TXBUFLOW) && (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { set_bit(ASYI_TXLOW, &portp->istate); - MOD_INC_USE_COUNT; - if (schedule_task(&portp->tqueue) == 0) - MOD_DEC_USE_COUNT; + schedule_task(&portp->tqueue); } if (len == 0) { @@ -5336,9 +5322,7 @@ ipr = stl_sc26198getreg(portp, IPR); if (ipr & IPR_DCDCHANGE) { set_bit(ASYI_DCDCHANGE, &portp->istate); - MOD_INC_USE_COUNT; - if (schedule_task(&portp->tqueue) == 0) - MOD_DEC_USE_COUNT; + schedule_task(&portp->tqueue); portp->stats.modem++; } break; diff -Nru a/drivers/char/sx.c b/drivers/char/sx.c --- a/drivers/char/sx.c Thu May 15 15:24:37 2003 +++ b/drivers/char/sx.c Thu May 15 15:24:37 2003 @@ -1739,8 +1739,10 @@ if (copy_from_user(tmp, (char *)data + i, (i + SX_CHUNK_SIZE > nbytes) ? nbytes - i : - SX_CHUNK_SIZE)) + SX_CHUNK_SIZE)) { + kfree (tmp); return -EFAULT; + } memcpy_toio ((char *) (board->base2 + offset + i), tmp, (i+SX_CHUNK_SIZE>nbytes)?nbytes-i:SX_CHUNK_SIZE); } diff -Nru a/drivers/char/synclink.c b/drivers/char/synclink.c --- a/drivers/char/synclink.c Thu May 15 15:24:37 2003 +++ b/drivers/char/synclink.c Thu May 15 15:24:37 2003 @@ -1,7 +1,7 @@ /* * linux/drivers/char/synclink.c * - * $Id: synclink.c,v 4.6 2003/04/21 17:46:54 paulkf Exp $ + * $Id: synclink.c,v 4.9 2003/05/06 21:18:51 paulkf Exp $ * * Device driver for Microgate SyncLink ISA and PCI * high speed multiprotocol serial adapters. @@ -193,6 +193,7 @@ int flags; int count; /* count of opens */ int line; + int hw_version; unsigned short close_delay; unsigned short closing_wait; /* time to wait before closing */ @@ -917,7 +918,7 @@ MODULE_PARM(txholdbufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i"); static char *driver_name = "SyncLink serial driver"; -static char *driver_version = "$Revision: 4.6 $"; +static char *driver_version = "$Revision: 4.9 $"; static int synclink_init_one (struct pci_dev *dev, const struct pci_device_id *ent); @@ -925,6 +926,7 @@ static struct pci_device_id synclink_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_MICROGATE, PCI_DEVICE_ID_MICROGATE_USC, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_MICROGATE, 0x0210, PCI_ANY_ID, PCI_ANY_ID, }, { 0, }, /* terminate list */ }; MODULE_DEVICE_TABLE(pci, synclink_pci_tbl); @@ -4216,9 +4218,7 @@ info->get_tx_holding_index=0; /* restart transmit timer */ - del_timer(&info->tx_timer); - info->tx_timer.expires = jiffies + jiffies_from_ms(5000); - add_timer(&info->tx_timer); + mod_timer(&info->tx_timer, jiffies + jiffies_from_ms(5000)); ret = 1; } @@ -4436,12 +4436,12 @@ info->max_frame_size = 65535; if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - printk( "SyncLink device %s added:PCI bus IO=%04X IRQ=%d Mem=%08X LCR=%08X MaxFrameSize=%u\n", - info->device_name, info->io_base, info->irq_level, + printk( "SyncLink PCI v%d %s: IO=%04X IRQ=%d Mem=%08X,%08X MaxFrameSize=%u\n", + info->hw_version + 1, info->device_name, info->io_base, info->irq_level, info->phys_memory_base, info->phys_lcr_base, info->max_frame_size ); } else { - printk( "SyncLink device %s added:ISA bus IO=%04X IRQ=%d DMA=%d MaxFrameSize=%u\n", + printk( "SyncLink ISA %s: IO=%04X IRQ=%d DMA=%d MaxFrameSize=%u\n", info->device_name, info->io_base, info->irq_level, info->dma_level, info->max_frame_size ); } @@ -5296,10 +5296,11 @@ info->mbre_bit = BIT8; outw( BIT8, info->io_base ); /* set Master Bus Enable (DCAR) */ - /* Enable DMAEN (Port 7, Bit 14) */ - /* This connects the DMA request signal to the ISA bus */ - /* on the ISA adapter. This has no effect for the PCI adapter */ - usc_OutReg( info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) & ~BIT14) ); + if (info->bus_type == MGSL_BUS_TYPE_ISA) { + /* Enable DMAEN (Port 7, Bit 14) */ + /* This connects the DMA request signal to the ISA bus */ + usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) & ~BIT14)); + } /* DMA Control Register (DCR) * @@ -6276,10 +6277,11 @@ usc_EnableMasterIrqBit( info ); - /* Enable INTEN (Port 6, Bit12) */ - /* This connects the IRQ request signal to the ISA bus */ - /* on the ISA adapter. This has no effect for the PCI adapter */ - usc_OutReg( info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12) ); + if (info->bus_type == MGSL_BUS_TYPE_ISA) { + /* Enable INTEN (Port 6, Bit12) */ + /* This connects the IRQ request signal to the ISA bus */ + usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12)); + } } /* end of usc_set_async_mode() */ @@ -6370,10 +6372,11 @@ usc_loopback_frame( info ); usc_set_sdlc_mode( info ); - /* Enable INTEN (Port 6, Bit12) */ - /* This connects the IRQ request signal to the ISA bus */ - /* on the ISA adapter. This has no effect for the PCI adapter */ - usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12)); + if (info->bus_type == MGSL_BUS_TYPE_ISA) { + /* Enable INTEN (Port 6, Bit12) */ + /* This connects the IRQ request signal to the ISA bus */ + usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12)); + } usc_enable_aux_clock(info, info->params.clock_speed); @@ -8115,17 +8118,20 @@ info->bus_type = MGSL_BUS_TYPE_PCI; info->io_addr_size = 8; info->irq_flags = SA_SHIRQ; - - /* Store the PCI9050 misc control register value because a flaw - * in the PCI9050 prevents LCR registers from being read if - * BIOS assigns an LCR base address with bit 7 set. - * - * Only the misc control register is accessed for which only - * write access is needed, so set an initial value and change - * bits to the device instance data as we write the value - * to the actual misc control register. - */ - info->misc_ctrl_value = 0x087e4546; + + if (dev->device == 0x0210) { + /* Version 1 PCI9030 based universal PCI adapter */ + info->misc_ctrl_value = 0x007c4080; + info->hw_version = 1; + } else { + /* Version 0 PCI9050 based 5V PCI adapter + * A PCI9050 bug prevents reading LCR registers if + * LCR base address bit 7 is set. Maintain shadow + * value so we can write to LCR misc control reg. + */ + info->misc_ctrl_value = 0x087e4546; + info->hw_version = 0; + } mgsl_add_device(info); diff -Nru a/drivers/char/sysrq.c b/drivers/char/sysrq.c --- a/drivers/char/sysrq.c Thu May 15 15:24:43 2003 +++ b/drivers/char/sysrq.c Thu May 15 15:24:43 2003 @@ -101,131 +101,19 @@ { machine_restart(NULL); } + static struct sysrq_key_op sysrq_reboot_op = { .handler = sysrq_handle_reboot, .help_msg = "reBoot", .action_msg = "Resetting", }; - - -/* SYNC SYSRQ HANDLERS BLOCK */ - -/* do_emergency_sync helper function */ -/* Guesses if the device is a local hard drive */ -static int is_local_disk(struct block_device *bdev) -{ - switch (MAJOR(bdev->bd_dev)) { - case IDE0_MAJOR: - case IDE1_MAJOR: - case IDE2_MAJOR: - case IDE3_MAJOR: - case IDE4_MAJOR: - case IDE5_MAJOR: - case IDE6_MAJOR: - case IDE7_MAJOR: - case IDE8_MAJOR: - case IDE9_MAJOR: - case SCSI_DISK0_MAJOR: - case SCSI_DISK1_MAJOR: - case SCSI_DISK2_MAJOR: - case SCSI_DISK3_MAJOR: - case SCSI_DISK4_MAJOR: - case SCSI_DISK5_MAJOR: - case SCSI_DISK6_MAJOR: - case SCSI_DISK7_MAJOR: - case XT_DISK_MAJOR: - return 1; - default: - return 0; - } -} - -/* do_emergency_sync helper function */ -static void go_sync(struct super_block *sb, int remount_flag) -{ - int orig_loglevel; - orig_loglevel = console_loglevel; - console_loglevel = 7; - printk(KERN_INFO "%sing device %s ... ", - remount_flag ? "Remount" : "Sync", - sb->s_id); - - if (remount_flag) { /* Remount R/O */ - int ret, flags; - struct file *file; - - if (sb->s_flags & MS_RDONLY) { - printk("R/O\n"); - return; - } - - file_list_lock(); - list_for_each_entry(file, &sb->s_files, f_list) { - if (file->f_dentry && file_count(file) - && S_ISREG(file->f_dentry->d_inode->i_mode)) - file->f_mode &= ~2; - } - file_list_unlock(); - DQUOT_OFF(sb); - fsync_bdev(sb->s_bdev); - flags = MS_RDONLY; - if (sb->s_op && sb->s_op->remount_fs) { - ret = sb->s_op->remount_fs(sb, &flags, NULL); - if (ret) - printk("error %d\n", ret); - else { - sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); - printk("OK\n"); - } - } else - printk("nothing to do\n"); - } else { /* Sync only */ - fsync_bdev(sb->s_bdev); - printk("OK\n"); - } - console_loglevel = orig_loglevel; -} -/* - * Emergency Sync or Unmount. We cannot do it directly, so we set a special - * flag and wake up the bdflush kernel thread which immediately calls this function. - * We process all mounted hard drives first to recover from crashed experimental - * block devices and malfunctional network filesystems. - */ - -int emergency_sync_scheduled; - -void do_emergency_sync(void) { - struct super_block *sb; - int remount_flag; - int orig_loglevel; - - lock_kernel(); - remount_flag = (emergency_sync_scheduled == EMERG_REMOUNT); - emergency_sync_scheduled = 0; - - list_for_each_entry(sb, &super_blocks, s_list) - if (sb->s_bdev && is_local_disk(sb->s_bdev)) - go_sync(sb, remount_flag); - - list_for_each_entry(sb, &super_blocks, s_list) - if (sb->s_bdev && !is_local_disk(sb->s_bdev)) - go_sync(sb, remount_flag); - - unlock_kernel(); - - orig_loglevel = console_loglevel; - console_loglevel = 7; - printk(KERN_INFO "Done.\n"); - console_loglevel = orig_loglevel; -} - static void sysrq_handle_sync(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { - emergency_sync_scheduled = EMERG_SYNC; - wakeup_bdflush(0); + emergency_sync(); } + static struct sysrq_key_op sysrq_sync_op = { .handler = sysrq_handle_sync, .help_msg = "Sync", @@ -235,9 +123,9 @@ static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { - emergency_sync_scheduled = EMERG_REMOUNT; - wakeup_bdflush(0); + emergency_remount(); } + static struct sysrq_key_op sysrq_mountro_op = { .handler = sysrq_handle_mountro, .help_msg = "Unmount", diff -Nru a/drivers/char/tipar.c b/drivers/char/tipar.c --- a/drivers/char/tipar.c Thu May 15 15:24:41 2003 +++ b/drivers/char/tipar.c Thu May 15 15:24:41 2003 @@ -421,8 +421,6 @@ static int tipar_register(int nr, struct parport *port) { - char name[32]; - /* Register our module into parport */ table[nr].dev = parport_register_device(port, "tipar", NULL, NULL, NULL, 0, @@ -432,13 +430,9 @@ return 1; /* Use devfs, tree: /dev/ticables/par/[0..2] */ - sprintf(name, "ticables/par/%d", nr); - printk - ("tipar: registering to devfs : major = %d, minor = %d, node = %s\n", - TISER_MAJOR, (TIPAR_MINOR + nr), name); - devfs_register(NULL, name, DEVFS_FL_DEFAULT, TIPAR_MAJOR, - TIPAR_MINOR + nr, S_IFCHR | S_IRUGO | S_IWUGO, - &tipar_fops, NULL); + devfs_mk_cdev(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr), + S_IFCHR | S_IRUGO | S_IWUGO, + "ticables/par/%d", nr); /* Display informations */ printk(KERN_INFO "tipar%d: using %s (%s).\n", nr, port->name, diff -Nru a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c --- a/drivers/char/tpqic02.c Thu May 15 15:24:38 2003 +++ b/drivers/char/tpqic02.c Thu May 15 15:24:38 2003 @@ -2694,38 +2694,27 @@ #endif return -ENODEV; } - devfs_register(NULL, "ntpqic11", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 2, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - devfs_register(NULL, "tpqic11", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 3, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - devfs_register(NULL, "ntpqic24", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 4, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - devfs_register(NULL, "tpqic24", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 5, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - devfs_register(NULL, "ntpqic120", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 6, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - devfs_register(NULL, "tpqic120", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 7, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - devfs_register(NULL, "ntpqic150", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 8, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); - devfs_register(NULL, "tpqic150", DEVFS_FL_DEFAULT, - QIC02_TAPE_MAJOR, 9, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, - &qic02_tape_fops, NULL); + + devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 2), + S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic11"); + devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 3), + S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic11"); + + devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 4), + S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic24"); + devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 5), + S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic24"); + + devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 6), + S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic120"); + devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 7), + S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic120"); + + devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 8), + S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic150"); + devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 9), + S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic150"); + init_waitqueue_head(&qic02_tape_transfer); /* prepare timer */ TIMEROFF; diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c --- a/drivers/char/tty_io.c Thu May 15 15:24:40 2003 +++ b/drivers/char/tty_io.c Thu May 15 15:24:40 2003 @@ -2088,22 +2088,6 @@ } #ifdef CONFIG_DEVFS_FS -static void tty_register_devfs(struct tty_driver *driver, unsigned index) -{ - dev_t dev = MKDEV(driver->major, driver->minor_start) + index; - char buf[32]; - - if (index >= driver->num) { - printk(KERN_ERR "Attempt to register invalid tty line number " - "with devfs (%d).\n", index); - return; - } - - tty_line_name(driver, index, buf); - devfs_register(NULL, buf, 0, MAJOR(dev), MINOR(dev), - S_IFCHR | S_IRUSR | S_IWUSR, &tty_fops, NULL); -} - static void tty_unregister_devfs(struct tty_driver *driver, int index) { char path[64]; @@ -2111,21 +2095,137 @@ devfs_remove(path); } #else -# define tty_register_devfs(driver, index) do { } while (0) # define tty_unregister_devfs(driver, index) do { } while (0) #endif /* CONFIG_DEVFS_FS */ -/* - * Register a tty device described by , with minor number . +static struct class tty_class = { + .name = "tty", +}; + +struct tty_dev { + struct list_head node; + dev_t dev; + struct class_device class_dev; +}; +#define to_tty_dev(d) container_of(d, struct tty_dev, class_dev) + +static LIST_HEAD(tty_dev_list); +static spinlock_t tty_dev_list_lock = SPIN_LOCK_UNLOCKED; + +static ssize_t show_dev(struct class_device *class_dev, char *buf) +{ + struct tty_dev *tty_dev = to_tty_dev(class_dev); + return sprintf(buf, "%04x\n", tty_dev->dev); +} +static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL); + +static void tty_add_class_device(char *name, dev_t dev, struct device *device) +{ + struct tty_dev *tty_dev = NULL; + char *temp; + int retval; + + tty_dev = kmalloc(sizeof(*tty_dev), GFP_KERNEL); + if (!tty_dev) + return; + memset(tty_dev, 0x00, sizeof(*tty_dev)); + + /* stupid '/' in tty name strings... */ + temp = strrchr(name, '/'); + if (temp && (temp[1] != 0x00)) + ++temp; + else + temp = name; + + tty_dev->class_dev.dev = device; + tty_dev->class_dev.class = &tty_class; + snprintf(tty_dev->class_dev.class_id, BUS_ID_SIZE, "%s", temp); + retval = class_device_register(&tty_dev->class_dev); + if (retval) + goto error; + class_device_create_file (&tty_dev->class_dev, &class_device_attr_dev); + tty_dev->dev = dev; + spin_lock(&tty_dev_list_lock); + list_add(&tty_dev->node, &tty_dev_list); + spin_unlock(&tty_dev_list_lock); + return; +error: + kfree(tty_dev); +} + +void tty_remove_class_device(dev_t dev) +{ + struct tty_dev *tty_dev = NULL; + struct list_head *tmp; + int found = 0; + + spin_lock(&tty_dev_list_lock); + list_for_each (tmp, &tty_dev_list) { + tty_dev = list_entry(tmp, struct tty_dev, node); + if ((MAJOR(tty_dev->dev) == MAJOR(dev)) && + (MINOR(tty_dev->dev) == MINOR(dev))) { + found = 1; + break; + } + } + if (found) { + list_del(&tty_dev->node); + spin_unlock(&tty_dev_list_lock); + class_device_unregister(&tty_dev->class_dev); + kfree(tty_dev); + } else { + spin_unlock(&tty_dev_list_lock); + } +} + +/** + * tty_register_device - register a tty device + * @driver: the tty driver that describes the tty device + * @index: the index in the tty driver for this tty device + * @device: a struct device that is associated with this tty device. + * This field is optional, if there is no known struct device for this + * tty device it can be set to NULL safely. + * + * This call is required to be made to register an individual tty device if + * the tty driver's flags have the TTY_DRIVER_NO_DEVFS bit set. If that + * bit is not set, this function should not be called. */ -void tty_register_device(struct tty_driver *driver, unsigned index) +void tty_register_device(struct tty_driver *driver, unsigned index, + struct device *device) { - tty_register_devfs(driver, index); + dev_t dev = MKDEV(driver->major, driver->minor_start) + index; + char name[64]; + + if (index >= driver->num) { + printk(KERN_ERR "Attempt to register invalid tty line number " + " (%d).\n", index); + return; + } + + tty_line_name(driver, index, name); + devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR, name); + + /* stupid console driver devfs names... change vc/X into ttyX */ + if (driver->type == TTY_DRIVER_TYPE_CONSOLE) + sprintf(name, "tty%d", MINOR(dev)); + + /* we don't care about the ptys */ + if (driver->type != TTY_DRIVER_TYPE_PTY) + tty_add_class_device (name, dev, device); } +/** + * tty_unregister_device - unregister a tty device + * @driver: the tty driver that describes the tty device + * @index: the index in the tty driver for this tty device + * + * If a tty device is registered with a call to tty_register_device() then + * this function must be made when the tty device is gone. + */ void tty_unregister_device(struct tty_driver *driver, unsigned index) { tty_unregister_devfs(driver, index); + tty_remove_class_device(MKDEV(driver->major, driver->minor_start) + index); } EXPORT_SYMBOL(tty_register_device); @@ -2207,7 +2307,7 @@ if ( !(driver->flags & TTY_DRIVER_NO_DEVFS) ) { for(i = 0; i < driver->num; i++) - tty_register_device(driver, i); + tty_register_device(driver, i, NULL); } proc_tty_register_driver(driver); return error; @@ -2288,10 +2388,6 @@ extern int vty_init(void); #endif -static struct class tty_class = { - .name = "tty", -}; - static int __init tty_class_init(void) { return class_register(&tty_class); @@ -2308,33 +2404,29 @@ if (register_chrdev_region(TTYAUX_MAJOR, 0, 1, "/dev/tty", &tty_fops) < 0) panic("Couldn't register /dev/tty driver\n"); - - devfs_register (NULL, "tty", 0, TTYAUX_MAJOR, 0, - S_IFCHR | S_IRUGO | S_IWUGO, &tty_fops, NULL); + devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty"); + tty_add_class_device ("tty", MKDEV(TTYAUX_MAJOR, 0), NULL); if (register_chrdev_region(TTYAUX_MAJOR, 1, 1, "/dev/console", &tty_fops) < 0) panic("Couldn't register /dev/console driver\n"); - - devfs_register (NULL, "console", 0, TTYAUX_MAJOR, 1, - S_IFCHR | S_IRUSR | S_IWUSR, &tty_fops, NULL); + devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console"); + tty_add_class_device ("console", MKDEV(TTYAUX_MAJOR, 1), NULL); #ifdef CONFIG_UNIX98_PTYS if (register_chrdev_region(TTYAUX_MAJOR, 2, 1, "/dev/ptmx", &tty_fops) < 0) panic("Couldn't register /dev/ptmx driver\n"); - - devfs_register (NULL, "ptmx", 0, TTYAUX_MAJOR, 2, - S_IFCHR | S_IRUGO | S_IWUGO, &tty_fops, NULL); + devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx"); + tty_add_class_device ("ptmx", MKDEV(TTYAUX_MAJOR, 2), NULL); #endif #ifdef CONFIG_VT if (register_chrdev_region(TTY_MAJOR, 0, 1, "/dev/vc/0", &tty_fops) < 0) panic("Couldn't register /dev/tty0 driver\n"); - - devfs_register (NULL, "vc/0", 0, TTY_MAJOR, 0, - S_IFCHR | S_IRUSR | S_IWUSR, &tty_fops, NULL); + devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0"); + tty_add_class_device ("tty0", MKDEV(TTY_MAJOR, 0), NULL); vty_init(); #endif diff -Nru a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c --- a/drivers/char/tty_ioctl.c Thu May 15 15:24:46 2003 +++ b/drivers/char/tty_ioctl.c Thu May 15 15:24:46 2003 @@ -394,7 +394,7 @@ return -EFAULT; return 0; case TCSETSF: - return set_termios(real_tty, arg, TERMIOS_FLUSH); + return set_termios(real_tty, arg, TERMIOS_FLUSH | TERMIOS_WAIT); case TCSETSW: return set_termios(real_tty, arg, TERMIOS_WAIT); case TCSETS: @@ -402,7 +402,7 @@ case TCGETA: return get_termio(real_tty,(struct termio *) arg); case TCSETAF: - return set_termios(real_tty, arg, TERMIOS_FLUSH | TERMIOS_TERMIO); + return set_termios(real_tty, arg, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO); case TCSETAW: return set_termios(real_tty, arg, TERMIOS_WAIT | TERMIOS_TERMIO); case TCSETA: diff -Nru a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c --- a/drivers/char/vc_screen.c Thu May 15 15:24:35 2003 +++ b/drivers/char/vc_screen.c Thu May 15 15:24:35 2003 @@ -469,40 +469,27 @@ .open = vcs_open, }; -void vcs_make_devfs (unsigned int index, int unregister) +void vcs_make_devfs(struct tty_struct *tty) { -#ifdef CONFIG_DEVFS_FS - - if (unregister) { - devfs_remove("vcc/%u", index + 1); - devfs_remove("vcc/a%u", index + 1); - } else { - char name[16]; - sprintf(name, "vcc/%u", index + 1); - devfs_register(NULL, name, DEVFS_FL_DEFAULT, - VCS_MAJOR, index + 1, - S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL); - sprintf(name, "vcc/a%u", index + 1); - devfs_register(NULL, name, DEVFS_FL_DEFAULT, - VCS_MAJOR, index + 129, - S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL); - } -#endif /* CONFIG_DEVFS_FS */ + devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 1), + S_IFCHR|S_IRUSR|S_IWUSR, + "vcc/%u", tty->index + 1); + devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 129), + S_IFCHR|S_IRUSR|S_IWUSR, + "vcc/a%u", tty->index + 1); +} +void vcs_remove_devfs(struct tty_struct *tty) +{ + devfs_remove("vcc/%u", tty->index + 1); + devfs_remove("vcc/a%u", tty->index + 1); } int __init vcs_init(void) { - int error; - - error = register_chrdev(VCS_MAJOR, "vcs", &vcs_fops); - - if (error) - printk("unable to get major %d for vcs device", VCS_MAJOR); - - devfs_register(NULL, "vcc/0", DEVFS_FL_DEFAULT, VCS_MAJOR, 0, - S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL); - devfs_register(NULL, "vcc/a", DEVFS_FL_DEFAULT, VCS_MAJOR, 128, - S_IFCHR | S_IRUSR | S_IWUSR, &vcs_fops, NULL); + if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops)) + panic("unable to get major %d for vcs device", VCS_MAJOR); - return error; + devfs_mk_cdev(MKDEV(VCS_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/0"); + devfs_mk_cdev(MKDEV(VCS_MAJOR, 128), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/a0"); + return 0; } diff -Nru a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c --- a/drivers/char/vme_scc.c Thu May 15 15:24:33 2003 +++ b/drivers/char/vme_scc.c Thu May 15 15:24:33 2003 @@ -129,6 +129,7 @@ memset(&scc_driver, 0, sizeof(scc_driver)); scc_driver.magic = TTY_DRIVER_MAGIC; + scc_driver.owner = THIS_MODULE; scc_driver.driver_name = "scc"; #ifdef CONFIG_DEVFS_FS scc_driver.name = "tts/"; @@ -795,7 +796,6 @@ { scc_disable_tx_interrupts(ptr); scc_disable_rx_interrupts(ptr); - MOD_DEC_USE_COUNT; } @@ -803,7 +803,6 @@ { scc_disable_tx_interrupts(ptr); scc_disable_rx_interrupts(ptr); - MOD_DEC_USE_COUNT; } @@ -938,13 +937,9 @@ return retval; } port->gs.flags |= GS_ACTIVE; - if (port->gs.count == 1) { - MOD_INC_USE_COUNT; - } retval = gs_block_til_ready(port, filp); if (retval) { - MOD_DEC_USE_COUNT; port->gs.count--; return retval; } diff -Nru a/drivers/char/vt.c b/drivers/char/vt.c --- a/drivers/char/vt.c Thu May 15 15:24:43 2003 +++ b/drivers/char/vt.c Thu May 15 15:24:43 2003 @@ -124,7 +124,9 @@ #define DEFAULT_BELL_PITCH 750 #define DEFAULT_BELL_DURATION (HZ/8) -extern void vcs_make_devfs (unsigned int index, int unregister); +extern void vcs_make_devfs(struct tty_struct *tty); +extern void vcs_remove_devfs(struct tty_struct *tty); + extern void console_map_init(void); #ifdef CONFIG_PROM_CONSOLE extern void prom_con_init(void); @@ -158,7 +160,6 @@ static void hide_cursor(int currcons); static void unblank_screen_t(unsigned long dummy); static void console_callback(void *ignored); -static void __init con_init_devfs (void); static int printable; /* Is console ready for printing? */ @@ -2410,7 +2411,7 @@ tty->winsize.ws_col = video_num_columns; } if (tty->count == 1) - vcs_make_devfs (currcons, 0); + vcs_make_devfs(tty); return 0; } @@ -2418,10 +2419,10 @@ { struct vt_struct *vt; - if (!tty) + if (!tty || tty->count != 1) return; - if (tty->count != 1) return; - vcs_make_devfs (tty->index, 1); + + vcs_remove_devfs(tty); vt = (struct vt_struct*)tty->driver_data; if (vt) vc_cons[vt->vc_num].d->vc_tty = NULL; @@ -2525,11 +2526,6 @@ console_driver.type = TTY_DRIVER_TYPE_CONSOLE; console_driver.init_termios = tty_std_termios; console_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS; - /* Tell tty_register_driver() to skip consoles because they are - * registered before kmalloc() is ready. We'll patch them in later. - * See comments at console_init(); see also con_init_devfs(). - */ - console_driver.flags |= TTY_DRIVER_NO_DEVFS; console_driver.refcount = &console_refcount; console_driver.table = console_table; console_driver.termios = console_termios; @@ -2562,7 +2558,6 @@ #ifdef CONFIG_FRAMEBUFFER_CONSOLE fb_console_init(); #endif - con_init_devfs(); vcs_init(); return 0; } @@ -2655,18 +2650,6 @@ unsigned int mode; get_user(mode, argp); vesa_blank_mode = (mode < 4) ? mode : 0; -} - -/* We can't register the console with devfs during con_init(), because it - * is called before kmalloc() works. This function is called later to - * do the registration. - */ -static void __init con_init_devfs (void) -{ - int i; - - for (i = 0; i < console_driver.num; i++) - tty_register_device (&console_driver, i); } /* diff -Nru a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c --- a/drivers/char/vt_ioctl.c Thu May 15 15:24:41 2003 +++ b/drivers/char/vt_ioctl.c Thu May 15 15:24:41 2003 @@ -869,13 +869,13 @@ if (clin > 32) return -EINVAL; - if (vlin) - vc->vc_scan_lines = vlin; - if (clin) - vc->vc_font.height = clin; - - for (i = 0; i < MAX_NR_CONSOLES; i++) + for (i = 0; i < MAX_NR_CONSOLES; i++) { + if (vlin) + vc_cons[i].d->vc_scan_lines = vlin; + if (clin) + vc_cons[i].d->vc_font.height = clin; vc_resize(i, cc, ll); + } return 0; } diff -Nru a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c --- a/drivers/char/watchdog/pcwd.c Thu May 15 15:24:33 2003 +++ b/drivers/char/watchdog/pcwd.c Thu May 15 15:24:33 2003 @@ -594,6 +594,7 @@ static int __init pcwatchdog_init(void) { + char *firmware; int i, found = 0; pcwd_validate_timeout(); spin_lock_init(&io_lock); @@ -633,10 +634,12 @@ if (revision == PCWD_REVISION_A) printk(KERN_INFO "pcwd: PC Watchdog (REV.A) detected at port 0x%03x\n", current_readport); - else if (revision == PCWD_REVISION_C) + else if (revision == PCWD_REVISION_C) { + firmware = get_firmware(); printk(KERN_INFO "pcwd: PC Watchdog (REV.C) detected at port 0x%03x (Firmware version: %s)\n", - current_readport, get_firmware()); - else { + current_readport, firmware); + kfree(firmware); + } else { /* Should NEVER happen, unless get_revision() fails. */ printk("pcwd: Unable to get revision.\n"); return -1; diff -Nru a/drivers/cpufreq/proc_intf.c b/drivers/cpufreq/proc_intf.c --- a/drivers/cpufreq/proc_intf.c Thu May 15 15:24:34 2003 +++ b/drivers/cpufreq/proc_intf.c Thu May 15 15:24:34 2003 @@ -209,6 +209,9 @@ { struct proc_dir_entry *entry = NULL; + if (!cpufreq_driver) + return -ENODEV; + /* are these acceptable values? */ entry = create_proc_entry("cpufreq", S_IFREG|S_IRUGO|S_IWUSR, &proc_root); diff -Nru a/drivers/hotplug/Kconfig b/drivers/hotplug/Kconfig --- a/drivers/hotplug/Kconfig Thu May 15 15:24:37 2003 +++ b/drivers/hotplug/Kconfig Thu May 15 15:24:37 2003 @@ -61,7 +61,7 @@ config HOTPLUG_PCI_ACPI tristate "ACPI PCI Hotplug driver" - depends on ACPI && HOTPLUG_PCI + depends on ACPI_BUS && HOTPLUG_PCI help Say Y here if you have a system that supports PCI Hotplug using ACPI. diff -Nru a/drivers/hotplug/acpiphp_glue.c b/drivers/hotplug/acpiphp_glue.c --- a/drivers/hotplug/acpiphp_glue.c Thu May 15 15:24:36 2003 +++ b/drivers/hotplug/acpiphp_glue.c Thu May 15 15:24:36 2003 @@ -203,6 +203,7 @@ if (ACPI_FAILURE(status)) { err("failed to register interrupt notify handler\n"); + kfree(newfunc); return status; } @@ -806,6 +807,7 @@ struct list_head *l; struct acpiphp_func *func; int retval = 0; + int num; if (slot->flags & SLOT_ENABLED) goto err_exit; @@ -825,7 +827,10 @@ goto err_exit; /* returned `dev' is the *first function* only! */ - dev = pci_scan_slot(slot->bridge->pci_bus, PCI_DEVFN(slot->device, 0)); + num = pci_scan_slot(slot->bridge->pci_bus, PCI_DEVFN(slot->device, 0)); + if (num) + pci_bus_add_devices(slot->bridge->pci_bus); + dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0)); if (!dev) { err("No new device found\n"); diff -Nru a/drivers/hotplug/cpqphp.h b/drivers/hotplug/cpqphp.h --- a/drivers/hotplug/cpqphp.h Thu May 15 15:24:43 2003 +++ b/drivers/hotplug/cpqphp.h Thu May 15 15:24:43 2003 @@ -31,7 +31,7 @@ #include "pci_hotplug.h" #include #include /* for read? and write? functions */ - +#include /* for delays */ #if !defined(CONFIG_HOTPLUG_PCI_COMPAQ_MODULE) #define MY_NAME "cpqphp.o" @@ -146,6 +146,10 @@ u8 reserved11; /* 0x2b */ u8 slot_SERR; /* 0x2c */ u8 slot_power; /* 0x2d */ + u8 reserved12; /* 0x2e */ + u8 reserved13; /* 0x2f */ + u8 next_curr_freq; /* 0x30 */ + u8 reset_freq_mode; /* 0x31 */ } __attribute__ ((packed)); /* offsets to the controller registers based on the above structure layout */ @@ -173,6 +177,8 @@ CTRL_RESERVED11 = offsetof(struct ctrl_reg, reserved11), SLOT_SERR = offsetof(struct ctrl_reg, slot_SERR), SLOT_POWER = offsetof(struct ctrl_reg, slot_power), + NEXT_CURR_FREQ = offsetof(struct ctrl_reg, next_curr_freq), + RESET_FREQ_MODE = offsetof(struct ctrl_reg, reset_freq_mode), }; struct hrt { @@ -294,12 +300,11 @@ struct pci_resource *bus_head; struct pci_dev *pci_dev; struct pci_bus *pci_bus; - struct proc_dir_entry* proc_entry; - struct proc_dir_entry* proc_entry2; struct event_info event_queue[10]; struct slot *slot; u8 next_event; u8 interrupt; + u8 cfgspc_irq; u8 bus; /* bus number for the pci hotplug controller */ u8 rev; u8 slot_device_offset; @@ -316,8 +321,6 @@ u8 pcix_speed_capability; /* PCI-X */ u8 pcix_support; /* PCI-X */ u16 vendor_id; - char proc_name[20]; - char proc_name2[20]; struct work_struct int_task_event; wait_queue_head_t queue; /* sleep & wake process */ }; @@ -344,6 +347,7 @@ #define PCI_SUB_HPC_ID2 0xA2F8 #define PCI_SUB_HPC_ID3 0xA2F9 #define PCI_SUB_HPC_ID_INTC 0xA2FA +#define PCI_SUB_HPC_ID4 0xA2FD #define INT_BUTTON_IGNORE 0 #define INT_PRESENCE_ON 1 @@ -436,7 +440,7 @@ extern void cpqhp_destroy_resource_list (struct resource_lists * resources); extern int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func); extern int cpqhp_unconfigure_device (struct pci_func* func); - +extern struct slot *cpqhp_find_slot (struct controller *ctrl, u8 device); /* Global variables */ extern int cpqhp_debug; @@ -564,6 +568,7 @@ u32 led_control; led_control = readl(ctrl->hpc_reg + LED_CONTROL); + led_control &= ~(0x0101L << slot); led_control |= (0x0001L << slot); writel(led_control, ctrl->hpc_reg + LED_CONTROL); } @@ -605,14 +610,63 @@ } +/* + * get_controller_speed - find the current frequency/mode of controller. + * + * @ctrl: controller to get frequency/mode for. + * + * Returns controller speed. + * + */ static inline u8 get_controller_speed (struct controller *ctrl) { - u16 misc; - - misc = readw(ctrl->hpc_reg + MISC); - return (misc & 0x0800) ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; + u8 curr_freq; + u16 misc; + + if (ctrl->pcix_support) { + curr_freq = readb(ctrl->hpc_reg + NEXT_CURR_FREQ); + if ((curr_freq & 0xB0) == 0xB0) + return PCI_SPEED_133MHz_PCIX; + if ((curr_freq & 0xA0) == 0xA0) + return PCI_SPEED_100MHz_PCIX; + if ((curr_freq & 0x90) == 0x90) + return PCI_SPEED_66MHz_PCIX; + if (curr_freq & 0x10) + return PCI_SPEED_66MHz; + + return PCI_SPEED_33MHz; + } + + misc = readw(ctrl->hpc_reg + MISC); + return (misc & 0x0800) ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; } + + +/* + * get_adapter_speed - find the max supported frequency/mode of adapter. + * + * @ctrl: hotplug controller. + * @hp_slot: hotplug slot where adapter is installed. + * + * Returns adapter speed. + * + */ +static inline u8 get_adapter_speed (struct controller *ctrl, u8 hp_slot) +{ + u32 temp_dword = readl(ctrl->hpc_reg + NON_INT_INPUT); + dbg("slot: %d, PCIXCAP: %8x\n", hp_slot, temp_dword); + if (ctrl->pcix_support) { + if (temp_dword & (0x10000 << hp_slot)) + return PCI_SPEED_133MHz_PCIX; + if (temp_dword & (0x100 << hp_slot)) + return PCI_SPEED_66MHz_PCIX; + } + if (temp_dword & (0x01 << hp_slot)) + return PCI_SPEED_66MHz; + + return PCI_SPEED_33MHz; +} static inline void enable_slot_power (struct controller *ctrl, u8 slot) { @@ -719,6 +773,139 @@ dbg("%s - end\n", __FUNCTION__); return retval; +} + + +/** + * set_controller_speed - set the frequency and/or mode of a specific + * controller segment. + * + * @ctrl: controller to change frequency/mode for. + * @adapter_speed: the speed of the adapter we want to match. + * @hp_slot: the slot number where the adapter is installed. + * + * Returns 0 if we successfully change frequency and/or mode to match the + * adapter speed. + * + */ +static inline u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot) +{ + struct slot *slot; + u8 reg; + u8 slot_power = readb(ctrl->hpc_reg + SLOT_POWER); + u16 reg16; + u32 leds = readl(ctrl->hpc_reg + LED_CONTROL); + + if (ctrl->speed == adapter_speed) + return 0; + + /* We don't allow freq/mode changes if we find another adapter running + * in another slot on this controller */ + for(slot = ctrl->slot; slot; slot = slot->next) { + if (slot->device == (hp_slot + ctrl->slot_device_offset)) + continue; + if (!slot->hotplug_slot && !slot->hotplug_slot->info) + continue; + if (slot->hotplug_slot->info->adapter_status == 0) + continue; + /* If another adapter is running on the same segment but at a + * lower speed/mode, we allow the new adapter to function at + * this rate if supported */ + if (ctrl->speed < adapter_speed) + return 0; + + return 1; + } + + /* If the controller doesn't support freq/mode changes and the + * controller is running at a higher mode, we bail */ + if ((ctrl->speed > adapter_speed) && (!ctrl->pcix_speed_capability)) + return 1; + + /* But we allow the adapter to run at a lower rate if possible */ + if ((ctrl->speed < adapter_speed) && (!ctrl->pcix_speed_capability)) + return 0; + + /* We try to set the max speed supported by both the adapter and + * controller */ + if (ctrl->speed_capability < adapter_speed) { + if (ctrl->speed == ctrl->speed_capability) + return 0; + adapter_speed = ctrl->speed_capability; + } + + writel(0x0L, ctrl->hpc_reg + LED_CONTROL); + writeb(0x00, ctrl->hpc_reg + SLOT_ENABLE); + + set_SOGO(ctrl); + wait_for_ctrl_irq(ctrl); + + if (adapter_speed != PCI_SPEED_133MHz_PCIX) + reg = 0xF5; + else + reg = 0xF4; + pci_write_config_byte(ctrl->pci_dev, 0x41, reg); + + reg16 = readw(ctrl->hpc_reg + NEXT_CURR_FREQ); + reg16 &= ~0x000F; + switch(adapter_speed) { + case(PCI_SPEED_133MHz_PCIX): + reg = 0x75; + reg16 |= 0xB; + break; + case(PCI_SPEED_100MHz_PCIX): + reg = 0x74; + reg16 |= 0xA; + break; + case(PCI_SPEED_66MHz_PCIX): + reg = 0x73; + reg16 |= 0x9; + break; + case(PCI_SPEED_66MHz): + reg = 0x73; + reg16 |= 0x1; + break; + default: /* 33MHz PCI 2.2 */ + reg = 0x71; + break; + + } + reg16 |= 0xB << 12; + writew(reg16, ctrl->hpc_reg + NEXT_CURR_FREQ); + + mdelay(5); + + /* Reenable interrupts */ + writel(0, ctrl->hpc_reg + INT_MASK); + + pci_write_config_byte(ctrl->pci_dev, 0x41, reg); + + /* Restart state machine */ + reg = ~0xF; + pci_read_config_byte(ctrl->pci_dev, 0x43, ®); + pci_write_config_byte(ctrl->pci_dev, 0x43, reg); + + /* Only if mode change...*/ + if (((ctrl->speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) || + ((ctrl->speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz))) + set_SOGO(ctrl); + + wait_for_ctrl_irq(ctrl); + mdelay(1100); + + /* Restore LED/Slot state */ + writel(leds, ctrl->hpc_reg + LED_CONTROL); + writeb(slot_power, ctrl->hpc_reg + SLOT_ENABLE); + + set_SOGO(ctrl); + wait_for_ctrl_irq(ctrl); + + ctrl->speed = adapter_speed; + slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + + info("Successfully changed frequency/mode for adapter in slot %d\n", + slot->number); + return 0; } #endif diff -Nru a/drivers/hotplug/cpqphp_core.c b/drivers/hotplug/cpqphp_core.c --- a/drivers/hotplug/cpqphp_core.c Thu May 15 15:24:32 2003 +++ b/drivers/hotplug/cpqphp_core.c Thu May 15 15:24:32 2003 @@ -24,6 +24,9 @@ * * Send feedback to * + * Jan 12, 2003 - Added 66/100/133MHz PCI-X support, + * Torben Mathiasen + * */ #include @@ -57,7 +60,7 @@ static u8 power_mode; static int debug; -#define DRIVER_VERSION "0.9.6" +#define DRIVER_VERSION "0.9.7" #define DRIVER_AUTHOR "Dan Zink , Greg Kroah-Hartman " #define DRIVER_DESC "Compaq Hot Plug PCI Controller Driver" @@ -835,6 +838,7 @@ u8 hp_slot = 0; u8 device; u8 rev; + u8 bus_cap; u16 temp_word; u16 vendor_id; u16 subsystem_vid; @@ -896,6 +900,39 @@ switch (subsystem_vid) { case PCI_VENDOR_ID_COMPAQ: + if (rev >= 0x13) { /* CIOBX */ + ctrl->push_flag = 1; + ctrl->slot_switch_type = 1; // Switch is present + ctrl->push_button = 1; // Pushbutton is present + ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported + ctrl->defeature_PHP = 1; // PHP is supported + ctrl->pcix_support = 1; // PCI-X supported + ctrl->pcix_speed_capability = 1; + pci_read_config_byte(pdev, 0x41, &bus_cap); + if (bus_cap & 0x80) { + dbg("bus max supports 133MHz PCI-X\n"); + ctrl->speed_capability = PCI_SPEED_133MHz_PCIX; + break; + } + if (bus_cap & 0x40) { + dbg("bus max supports 100MHz PCI-X\n"); + ctrl->speed_capability = PCI_SPEED_100MHz_PCIX; + break; + } + if (bus_cap & 20) { + dbg("bus max supports 66MHz PCI-X\n"); + ctrl->speed_capability = PCI_SPEED_66MHz_PCIX; + break; + } + if (bus_cap & 10) { + dbg("bus max supports 66MHz PCI\n"); + ctrl->speed_capability = PCI_SPEED_66MHz; + break; + } + + break; + } + switch (subsystem_deviceid) { case PCI_SUB_HPC_ID: /* Original 6500/7000 implementation */ @@ -939,8 +976,18 @@ ctrl->pcix_support = 0; // PCI-X not supported ctrl->pcix_speed_capability = 0; // N/A since PCI-X not supported break; + case PCI_SUB_HPC_ID4: + /* First PCI-X implementation, 100MHz */ + ctrl->push_flag = 1; + ctrl->slot_switch_type = 1; // Switch is present + ctrl->speed_capability = PCI_SPEED_100MHz_PCIX; + ctrl->push_button = 1; // Pushbutton is present + ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported + ctrl->defeature_PHP = 1; // PHP is supported + ctrl->pcix_support = 1; // PCI-X supported + ctrl->pcix_speed_capability = 0; + break; default: - // TODO: Add SSIDs for CPQ systems that support PCI-X err(msg_HPC_not_supported); rc = -ENODEV; goto err_free_ctrl; @@ -1029,7 +1076,7 @@ info("Initializing the PCI hot plug controller residing on PCI bus %d\n", pdev->bus->number); dbg ("Hotplug controller capabilities:\n"); - dbg (" speed_capability %s\n", ctrl->speed_capability == PCI_SPEED_33MHz ? "33MHz" : "66Mhz"); + dbg (" speed_capability %d\n", ctrl->speed_capability); dbg (" slot_switch_type %s\n", ctrl->slot_switch_type == 0 ? "no switch" : "switch present"); dbg (" defeature_PHP %s\n", ctrl->defeature_PHP == 0 ? "PHP not supported" : "PHP supported"); dbg (" alternate_base_address %s\n", ctrl->alternate_base_address == 0 ? "not supported" : "supported"); @@ -1082,7 +1129,6 @@ } // Check for 66Mhz operation - // TODO: Add PCI-X support ctrl->speed = get_controller_speed(ctrl); @@ -1118,6 +1164,9 @@ */ // The next line is required for cpqhp_find_available_resources ctrl->interrupt = pdev->irq; + + ctrl->cfgspc_irq = 0; + pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &ctrl->cfgspc_irq); rc = cpqhp_find_available_resources(ctrl, cpqhp_rom_start); ctrl->add_support = !rc; diff -Nru a/drivers/hotplug/cpqphp_ctrl.c b/drivers/hotplug/cpqphp_ctrl.c --- a/drivers/hotplug/cpqphp_ctrl.c Thu May 15 15:24:36 2003 +++ b/drivers/hotplug/cpqphp_ctrl.c Thu May 15 15:24:36 2003 @@ -136,9 +136,9 @@ /* - * find_slot + * cpqhp_find_slot */ -static inline struct slot *find_slot (struct controller * ctrl, u8 device) +struct slot *cpqhp_find_slot (struct controller * ctrl, u8 device) { struct slot *slot; @@ -187,7 +187,7 @@ rc++; - p_slot = find_slot(ctrl, hp_slot + (readb(ctrl->hpc_reg + SLOT_MASK) >> 4)); + p_slot = cpqhp_find_slot(ctrl, hp_slot + (readb(ctrl->hpc_reg + SLOT_MASK) >> 4)); if (!p_slot) return 0; @@ -920,6 +920,7 @@ { struct controller *ctrl = data; u8 schedule_flag = 0; + u8 reset; u16 misc; u32 Diff; u32 temp_dword; @@ -971,6 +972,15 @@ schedule_flag += handle_power_fault((u8)((Diff & 0xFF00L) >> 8), ctrl); } + reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE); + if (reset & 0x40) { + /* Bus reset has completed */ + reset &= 0xCF; + writeb(reset, ctrl->hpc_reg + RESET_FREQ_MODE); + reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE); + wake_up_interruptible(&ctrl->queue); + } + if (schedule_flag) { up(&event_semaphore); dbg("Signal event_semaphore\n"); @@ -1172,6 +1182,7 @@ { u8 hp_slot; u8 temp_byte; + u8 adapter_speed; u32 index; u32 rc = 0; u32 src = 8; @@ -1189,46 +1200,46 @@ //********************************* rc = CARD_FUNCTIONING; } else { - if (ctrl->speed == PCI_SPEED_66MHz) { - // Wait for exclusive access to hardware - down(&ctrl->crit_sect); - - // turn on board without attaching to the bus - enable_slot_power (ctrl, hp_slot); + // Wait for exclusive access to hardware + down(&ctrl->crit_sect); - set_SOGO(ctrl); + // turn on board without attaching to the bus + enable_slot_power (ctrl, hp_slot); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + set_SOGO(ctrl); - // Change bits in slot power register to force another shift out - // NOTE: this is to work around the timer bug - temp_byte = readb(ctrl->hpc_reg + SLOT_POWER); - writeb(0x00, ctrl->hpc_reg + SLOT_POWER); - writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER); + // Wait for SOBS to be unset + wait_for_ctrl_irq (ctrl); - set_SOGO(ctrl); + // Change bits in slot power register to force another shift out + // NOTE: this is to work around the timer bug + temp_byte = readb(ctrl->hpc_reg + SLOT_POWER); + writeb(0x00, ctrl->hpc_reg + SLOT_POWER); + writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + set_SOGO(ctrl); - if (!(readl(ctrl->hpc_reg + NON_INT_INPUT) & (0x01 << hp_slot))) { + // Wait for SOBS to be unset + wait_for_ctrl_irq (ctrl); + + adapter_speed = get_adapter_speed(ctrl, hp_slot); + if (ctrl->speed != adapter_speed) + if (set_controller_speed(ctrl, adapter_speed, hp_slot)) rc = WRONG_BUS_FREQUENCY; - } - // turn off board without attaching to the bus - disable_slot_power (ctrl, hp_slot); - set_SOGO(ctrl); + // turn off board without attaching to the bus + disable_slot_power (ctrl, hp_slot); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + set_SOGO(ctrl); - // Done with exclusive hardware access - up(&ctrl->crit_sect); + // Wait for SOBS to be unset + wait_for_ctrl_irq (ctrl); - if (rc) - return(rc); - } + // Done with exclusive hardware access + up(&ctrl->crit_sect); + + if (rc) + return(rc); // Wait for exclusive access to hardware down(&ctrl->crit_sect); @@ -1376,6 +1387,7 @@ { u8 hp_slot; u8 temp_byte; + u8 adapter_speed; int index; u32 temp_register = 0xFFFFFFFF; u32 rc = 0; @@ -1387,47 +1399,48 @@ dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot); - if (ctrl->speed == PCI_SPEED_66MHz) { - // Wait for exclusive access to hardware - down(&ctrl->crit_sect); - - // turn on board without attaching to the bus - enable_slot_power (ctrl, hp_slot); + // Wait for exclusive access to hardware + down(&ctrl->crit_sect); - set_SOGO(ctrl); + // turn on board without attaching to the bus + enable_slot_power (ctrl, hp_slot); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + set_SOGO(ctrl); - // Change bits in slot power register to force another shift out - // NOTE: this is to work around the timer bug - temp_byte = readb(ctrl->hpc_reg + SLOT_POWER); - writeb(0x00, ctrl->hpc_reg + SLOT_POWER); - writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER); + // Wait for SOBS to be unset + wait_for_ctrl_irq (ctrl); - set_SOGO(ctrl); + // Change bits in slot power register to force another shift out + // NOTE: this is to work around the timer bug + temp_byte = readb(ctrl->hpc_reg + SLOT_POWER); + writeb(0x00, ctrl->hpc_reg + SLOT_POWER); + writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + set_SOGO(ctrl); - if (!(readl(ctrl->hpc_reg + NON_INT_INPUT) & (0x01 << hp_slot))) { + // Wait for SOBS to be unset + wait_for_ctrl_irq (ctrl); + + adapter_speed = get_adapter_speed(ctrl, hp_slot); + if (ctrl->speed != adapter_speed) + if (set_controller_speed(ctrl, adapter_speed, hp_slot)) rc = WRONG_BUS_FREQUENCY; - } - // turn off board without attaching to the bus - disable_slot_power (ctrl, hp_slot); + + // turn off board without attaching to the bus + disable_slot_power (ctrl, hp_slot); - set_SOGO(ctrl); + set_SOGO(ctrl); - // Wait for SOBS to be unset - wait_for_ctrl_irq (ctrl); + // Wait for SOBS to be unset + wait_for_ctrl_irq (ctrl); - // Done with exclusive hardware access - up(&ctrl->crit_sect); + // Done with exclusive hardware access + up(&ctrl->crit_sect); - if (rc) - return(rc); - } - p_slot = find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + if (rc) + return(rc); + + p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); // turn on board and blink green LED @@ -1800,7 +1813,7 @@ if (!func) return; - p_slot = find_slot(ctrl, hp_slot + ctrl->slot_device_offset); + p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); if (!p_slot) return; @@ -1860,11 +1873,12 @@ } // Wait for exclusive access to hardware down(&ctrl->crit_sect); - + dbg("blink green LED and turn off amber\n"); + amber_LED_off (ctrl, hp_slot); green_LED_blink (ctrl, hp_slot); - + set_SOGO(ctrl); // Wait for SOBS to be unset @@ -1992,7 +2006,7 @@ device = func->device; hp_slot = device - ctrl->slot_device_offset; - p_slot = find_slot(ctrl, device); + p_slot = cpqhp_find_slot(ctrl, device); if (p_slot) { physical_slot = p_slot->number; } @@ -2091,7 +2105,7 @@ device = func->device; func = cpqhp_slot_find(ctrl->bus, device, index++); - p_slot = find_slot(ctrl, device); + p_slot = cpqhp_find_slot(ctrl, device); if (p_slot) { physical_slot = p_slot->number; } diff -Nru a/drivers/hotplug/cpqphp_pci.c b/drivers/hotplug/cpqphp_pci.c --- a/drivers/hotplug/cpqphp_pci.c Thu May 15 15:24:44 2003 +++ b/drivers/hotplug/cpqphp_pci.c Thu May 15 15:24:44 2003 @@ -85,18 +85,20 @@ { unsigned char bus; struct pci_bus *child; - int rc = 0; + int num; if (func->pci_dev == NULL) - func->pci_dev = pci_find_slot(func->bus, (func->device << 3) | (func->function & 0x7)); + func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function)); - //Still NULL ? Well then scan for it ! + /* No pci device, we need to create it then */ if (func->pci_dev == NULL) { dbg("INFO: pci_dev still null\n"); - //this will generate pci_dev structures for all functions, but we will only call this case when lookup fails - func->pci_dev = pci_scan_slot(ctrl->pci_dev->bus, - (func->device << 3) + (func->function & 0x7)); + num = pci_scan_slot(ctrl->pci_dev->bus, PCI_DEVFN(func->device, func->function)); + if (num) + pci_bus_add_devices(ctrl->pci_dev->bus); + + func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function)); if (func->pci_dev == NULL) { dbg("ERROR: pci_dev still null\n"); return 0; @@ -107,10 +109,9 @@ pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus); child = (struct pci_bus*) pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus); pci_do_scan_bus(child); - } - return rc; + return 0; } @@ -1209,11 +1210,11 @@ temp = 0; if (!cpqhp_nic_irq) { - cpqhp_nic_irq = ctrl->interrupt; + cpqhp_nic_irq = ctrl->cfgspc_irq; } if (!cpqhp_disk_irq) { - cpqhp_disk_irq = ctrl->interrupt; + cpqhp_disk_irq = ctrl->cfgspc_irq; } dbg("cpqhp_disk_irq, cpqhp_nic_irq= %d, %d\n", cpqhp_disk_irq, cpqhp_nic_irq); diff -Nru a/drivers/hotplug/ibmphp_core.c b/drivers/hotplug/ibmphp_core.c --- a/drivers/hotplug/ibmphp_core.c Thu May 15 15:24:46 2003 +++ b/drivers/hotplug/ibmphp_core.c Thu May 15 15:24:46 2003 @@ -846,22 +846,24 @@ { unsigned char bus; struct pci_bus *child; - int rc = 0; + int num; int flag = 0; /* this is to make sure we don't double scan the bus, for bridged devices primarily */ if (!(bus_structure_fixup (func->busno))) flag = 1; if (func->dev == NULL) - func->dev = pci_find_slot (func->busno, (func->device << 3) | (func->function & 0x7)); + func->dev = pci_find_slot (func->busno, PCI_DEVFN(func->device, func->function)); if (func->dev == NULL) { struct pci_bus *bus = ibmphp_find_bus (func->busno); if (!bus) return 0; - func->dev = pci_scan_slot(bus, - (func->device << 3) + (func->function & 0x7)); + num = pci_scan_slot(bus, PCI_DEVFN(func->device, func->function)); + if (num) + pci_bus_add_devices(bus); + func->dev = pci_find_slot(func->busno, PCI_DEVFN(func->device, func->function)); if (func->dev == NULL) { err ("ERROR... : pci_dev still NULL \n"); return 0; @@ -873,7 +875,7 @@ pci_do_scan_bus (child); } - return rc; + return 0; } /******************************************************* @@ -1415,7 +1417,7 @@ /* lock ourselves into memory with a module * count of -1 so that no one can unload us. */ - MOD_DEC_USE_COUNT; + module_put(THIS_MODULE); exit: return rc; diff -Nru a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c --- a/drivers/i2c/busses/i2c-ali15x3.c Thu May 15 15:24:39 2003 +++ b/drivers/i2c/busses/i2c-ali15x3.c Thu May 15 15:24:39 2003 @@ -475,6 +475,7 @@ static struct i2c_adapter ali15x3_adapter = { .owner = THIS_MODULE, .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI15X3, + .class = I2C_ADAP_CLASS_SMBUS, .algo = &smbus_algorithm, .dev = { .name = "unset", diff -Nru a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c --- a/drivers/i2c/busses/i2c-amd756.c Thu May 15 15:24:43 2003 +++ b/drivers/i2c/busses/i2c-amd756.c Thu May 15 15:24:43 2003 @@ -313,6 +313,7 @@ static struct i2c_adapter amd756_adapter = { .owner = THIS_MODULE, .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD756, + .class = I2C_ADAP_CLASS_SMBUS, .algo = &smbus_algorithm, .dev = { .name = "unset", diff -Nru a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c --- a/drivers/i2c/busses/i2c-amd8111.c Thu May 15 15:24:43 2003 +++ b/drivers/i2c/busses/i2c-amd8111.c Thu May 15 15:24:43 2003 @@ -360,6 +360,7 @@ snprintf(smbus->adapter.dev.name, DEVICE_NAME_SIZE, "SMBus2 AMD8111 adapter at %04x", smbus->base); smbus->adapter.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD8111; + smbus->adapter.class = I2C_ADAP_CLASS_SMBUS; smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo_data = smbus; diff -Nru a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c --- a/drivers/i2c/busses/i2c-i801.c Thu May 15 15:24:38 2003 +++ b/drivers/i2c/busses/i2c-i801.c Thu May 15 15:24:38 2003 @@ -547,6 +547,7 @@ static struct i2c_adapter i801_adapter = { .owner = THIS_MODULE, .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_I801, + .class = I2C_ADAP_CLASS_SMBUS, .algo = &smbus_algorithm, .dev = { .name = "unset", diff -Nru a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c --- a/drivers/i2c/busses/i2c-isa.c Thu May 15 15:24:39 2003 +++ b/drivers/i2c/busses/i2c-isa.c Thu May 15 15:24:39 2003 @@ -40,6 +40,7 @@ static struct i2c_adapter isa_adapter = { .owner = THIS_MODULE, .id = I2C_ALGO_ISA | I2C_HW_ISA, + .class = I2C_ADAP_CLASS_SMBUS, .algo = &isa_algorithm, .dev = { .name = "ISA main adapter", diff -Nru a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c --- a/drivers/i2c/busses/i2c-piix4.c Thu May 15 15:24:36 2003 +++ b/drivers/i2c/busses/i2c-piix4.c Thu May 15 15:24:36 2003 @@ -395,6 +395,7 @@ static struct i2c_adapter piix4_adapter = { .owner = THIS_MODULE, .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_PIIX4, + .class = I2C_ADAP_CLASS_SMBUS, .algo = &smbus_algorithm, .dev = { .name = "unset", diff -Nru a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c --- a/drivers/i2c/busses/i2c-viapro.c Thu May 15 15:24:41 2003 +++ b/drivers/i2c/busses/i2c-viapro.c Thu May 15 15:24:41 2003 @@ -295,6 +295,7 @@ static struct i2c_adapter vt596_adapter = { .owner = THIS_MODULE, .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_VIA2, + .class = I2C_ADAP_CLASS_SMBUS, .algo = &smbus_algorithm, .dev = { .name = "unset", diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c --- a/drivers/i2c/chips/adm1021.c Thu May 15 15:24:33 2003 +++ b/drivers/i2c/chips/adm1021.c Thu May 15 15:24:33 2003 @@ -203,6 +203,8 @@ static int adm1021_attach_adapter(struct i2c_adapter *adapter) { + if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + return 0; return i2c_detect(adapter, &addr_data, adm1021_detect); } diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c --- a/drivers/i2c/chips/it87.c Thu May 15 15:24:42 2003 +++ b/drivers/i2c/chips/it87.c Thu May 15 15:24:42 2003 @@ -3,7 +3,7 @@ monitoring. Supports: IT8705F Super I/O chip w/LPC interface - IT8712F Super I/O chup w/LPC interface & SMbus + IT8712F Super I/O chip w/LPC interface & SMbus Sis950 A clone of the IT8705F Copyright (c) 2001 Chris Gauthron @@ -80,17 +80,17 @@ /* Monitors: 9 voltage (0 to 7, battery), 3 temp (1 to 3), 3 fan (1 to 3) */ -#define IT87_REG_FAN(nr) (0x0c + (nr)) -#define IT87_REG_FAN_MIN(nr) (0x0f + (nr)) +#define IT87_REG_FAN(nr) (0x0d + (nr)) +#define IT87_REG_FAN_MIN(nr) (0x10 + (nr)) #define IT87_REG_FAN_CTRL 0x13 #define IT87_REG_VIN(nr) (0x20 + (nr)) -#define IT87_REG_TEMP(nr) (0x28 + (nr)) +#define IT87_REG_TEMP(nr) (0x29 + (nr)) #define IT87_REG_VIN_MAX(nr) (0x30 + (nr) * 2) #define IT87_REG_VIN_MIN(nr) (0x31 + (nr) * 2) -#define IT87_REG_TEMP_HIGH(nr) (0x3e + (nr) * 2) -#define IT87_REG_TEMP_LOW(nr) (0x3f + (nr) * 2) +#define IT87_REG_TEMP_HIGH(nr) (0x40 + ((nr) * 2)) +#define IT87_REG_TEMP_LOW(nr) (0x41 + ((nr) * 2)) #define IT87_REG_I2C_ADDR 0x48 @@ -99,46 +99,8 @@ #define IT87_REG_CHIPID 0x58 -static inline u8 IN_TO_REG(long val, int inNum) -{ - /* to avoid floating point, we multiply everything by 100. - val is guaranteed to be positive, so we can achieve the effect of - rounding by (...*10+5)/10. Note that the *10 is hidden in the - /250 (which should really be /2500). - At the end, we need to /100 because we *100 everything and we need - to /10 because of the rounding thing, so we /1000. */ - if (inNum <= 1) - return (u8) - SENSORS_LIMIT(((val * 210240 - 13300) / 250 + 5) / 1000, - 0, 255); - else if (inNum == 2) - return (u8) - SENSORS_LIMIT(((val * 157370 - 13300) / 250 + 5) / 1000, - 0, 255); - else if (inNum == 3) - return (u8) - SENSORS_LIMIT(((val * 101080 - 13300) / 250 + 5) / 1000, - 0, 255); - else - return (u8) SENSORS_LIMIT(((val * 41714 - 13300) / 250 + 5) - / 1000, 0, 255); -} - -static inline long IN_FROM_REG(u8 val, int inNum) -{ - /* to avoid floating point, we multiply everything by 100. - val is guaranteed to be positive, so we can achieve the effect of - rounding by adding 0.5. Or, to avoid fp math, we do (...*10+5)/10. - We need to scale with *100 anyway, so no need to /100 at the end. */ - if (inNum <= 1) - return (long) (((250000 * val + 13300) / 210240 * 10 + 5) /10); - else if (inNum == 2) - return (long) (((250000 * val + 13300) / 157370 * 10 + 5) /10); - else if (inNum == 3) - return (long) (((250000 * val + 13300) / 101080 * 10 + 5) /10); - else - return (long) (((250000 * val + 13300) / 41714 * 10 + 5) /10); -} +#define IN_TO_REG(val) (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255)) +#define IN_FROM_REG(val) (((val) * 16) / 10) static inline u8 FAN_TO_REG(long rpm, int div) { @@ -159,7 +121,14 @@ 205-(val)*5) #define ALARMS_FROM_REG(val) (val) -#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1) +static int log2(int val) +{ + int answer = 0; + while ((val >>= 1)) + answer++; + return answer; +} +#define DIV_TO_REG(val) log2(val) #define DIV_FROM_REG(val) (1 << (val)) /* Initial limits. Use the config file to set better limits. */ @@ -238,6 +207,7 @@ u8 temp[3]; /* Register value */ u8 temp_high[3]; /* Register value */ u8 temp_low[3]; /* Register value */ + u8 sensor; /* Register value */ u8 fan_div[3]; /* Register encoding, shifted right */ u8 vid; /* Register encoding, combined */ u32 alarms; /* Register encoding, combined */ @@ -252,7 +222,7 @@ static int it87_write_value(struct i2c_client *client, u8 register, u8 value); static void it87_update_client(struct i2c_client *client); -static void it87_init_client(struct i2c_client *client); +static void it87_init_client(struct i2c_client *client, struct it87_data *data); static struct i2c_driver it87_driver = { @@ -271,7 +241,7 @@ struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); it87_update_client(client); - return sprintf(buf, "%ld\n", IN_FROM_REG(data->in[nr], nr)*10 ); + return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr])*10 ); } static ssize_t show_in_min(struct device *dev, char *buf, int nr) @@ -279,7 +249,7 @@ struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); it87_update_client(client); - return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_min[nr], nr)*10 ); + return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr])*10 ); } static ssize_t show_in_max(struct device *dev, char *buf, int nr) @@ -287,7 +257,7 @@ struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); it87_update_client(client); - return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_max[nr], nr)*10 ); + return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr])*10 ); } static ssize_t set_in_min(struct device *dev, const char *buf, @@ -296,7 +266,7 @@ struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10)/10; - data->in_min[nr] = IN_TO_REG(val,nr); + data->in_min[nr] = IN_TO_REG(val); it87_write_value(client, IT87_REG_VIN_MIN(nr), data->in_min[nr]); return count; @@ -307,7 +277,7 @@ struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); unsigned long val = simple_strtoul(buf, NULL, 10)/10; - data->in_max[nr] = IN_TO_REG(val,nr); + data->in_max[nr] = IN_TO_REG(val); it87_write_value(client, IT87_REG_VIN_MAX(nr), data->in_max[nr]); return count; @@ -319,6 +289,9 @@ { \ return show_in(dev, buf, 0x##offset); \ } \ +static DEVICE_ATTR(in_input##offset, S_IRUGO, show_in##offset, NULL) + +#define limit_in_offset(offset) \ static ssize_t \ show_in##offset##_min (struct device *dev, char *buf) \ { \ @@ -339,17 +312,28 @@ { \ return set_in_max(dev, buf, count, 0x##offset); \ } \ -static DEVICE_ATTR(in_input##offset, S_IRUGO, show_in##offset, NULL) \ static DEVICE_ATTR(in_min##offset, S_IRUGO | S_IWUSR, \ show_in##offset##_min, set_in##offset##_min) \ static DEVICE_ATTR(in_max##offset, S_IRUGO | S_IWUSR, \ show_in##offset##_max, set_in##offset##_max) show_in_offset(0); +limit_in_offset(0); show_in_offset(1); +limit_in_offset(1); show_in_offset(2); +limit_in_offset(2); show_in_offset(3); +limit_in_offset(3); show_in_offset(4); +limit_in_offset(4); +show_in_offset(5); +limit_in_offset(5); +show_in_offset(6); +limit_in_offset(6); +show_in_offset(7); +limit_in_offset(7); +show_in_offset(8); /* 3 temperatures */ static ssize_t show_temp(struct device *dev, char *buf, int nr) @@ -357,7 +341,7 @@ struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); it87_update_client(client); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])*10 ); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])*100 ); } /* more like overshoot temperature */ static ssize_t show_temp_max(struct device *dev, char *buf, int nr) @@ -365,7 +349,7 @@ struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); it87_update_client(client); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[nr])*10); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[nr])*100); } /* more like hysteresis temperature */ static ssize_t show_temp_min(struct device *dev, char *buf, int nr) @@ -373,14 +357,14 @@ struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); it87_update_client(client); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_low[nr])*10); + return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_low[nr])*100); } static ssize_t set_temp_max(struct device *dev, const char *buf, size_t count, int nr) { struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10)/10; + int val = simple_strtol(buf, NULL, 10)/100; data->temp_high[nr] = TEMP_TO_REG(val); it87_write_value(client, IT87_REG_TEMP_HIGH(nr), data->temp_high[nr]); return count; @@ -390,7 +374,7 @@ { struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); - int val = simple_strtol(buf, NULL, 10)/10; + int val = simple_strtol(buf, NULL, 10)/100; data->temp_low[nr] = TEMP_TO_REG(val); it87_write_value(client, IT87_REG_TEMP_LOW(nr), data->temp_low[nr]); return count; @@ -430,7 +414,52 @@ show_temp_offset(2); show_temp_offset(3); -/* 2 Fans */ +/* more like overshoot temperature */ +static ssize_t show_sensor(struct device *dev, char *buf, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + struct it87_data *data = i2c_get_clientdata(client); + it87_update_client(client); + if (data->sensor & (1 << nr)) + return sprintf(buf, "1\n"); + if (data->sensor & (8 << nr)) + return sprintf(buf, "2\n"); + return sprintf(buf, "0\n"); +} +static ssize_t set_sensor(struct device *dev, const char *buf, + size_t count, int nr) +{ + struct i2c_client *client = to_i2c_client(dev); + struct it87_data *data = i2c_get_clientdata(client); + int val = simple_strtol(buf, NULL, 10); + + data->sensor &= ~(1 << nr); + data->sensor &= ~(8 << nr); + if (val == 1) + data->sensor |= 1 << nr; + else if (val == 2) + data->sensor |= 8 << nr; + it87_write_value(client, IT87_REG_TEMP_ENABLE, data->sensor); + return count; +} +#define show_sensor_offset(offset) \ +static ssize_t show_sensor_##offset (struct device *dev, char *buf) \ +{ \ + return show_sensor(dev, buf, 0x##offset - 1); \ +} \ +static ssize_t set_sensor_##offset (struct device *dev, \ + const char *buf, size_t count) \ +{ \ + return set_sensor(dev, buf, count, 0x##offset - 1); \ +} \ +static DEVICE_ATTR(sensor##offset, S_IRUGO | S_IWUSR, \ + show_sensor_##offset, set_sensor_##offset) + +show_sensor_offset(1); +show_sensor_offset(2); +show_sensor_offset(3); + +/* 3 Fans */ static ssize_t show_fan(struct device *dev, char *buf, int nr) { struct i2c_client *client = to_i2c_client(dev); @@ -461,7 +490,7 @@ struct it87_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - it87_write_value(client, IT87_REG_FAN_MIN(nr+1), data->fan_min[nr]); + it87_write_value(client, IT87_REG_FAN_MIN(nr), data->fan_min[nr]); return count; } static ssize_t set_fan_div(struct device *dev, const char *buf, @@ -470,10 +499,34 @@ struct i2c_client *client = to_i2c_client(dev); struct it87_data *data = i2c_get_clientdata(client); int val = simple_strtol(buf, NULL, 10); - int old = it87_read_value(client, IT87_REG_FAN_DIV); - data->fan_div[nr] = DIV_TO_REG(val); - old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4); - it87_write_value(client, IT87_REG_FAN_DIV, old); + int i, min[3]; + u8 old = it87_read_value(client, IT87_REG_FAN_DIV); + + for (i = 0; i < 3; i++) + min[i] = FAN_FROM_REG(data->fan_min[i], DIV_FROM_REG(data->fan_div[i])); + + switch (nr) { + case 0: + case 1: + data->fan_div[nr] = DIV_TO_REG(val); + break; + case 2: + if (val < 8) + data->fan_div[nr] = 1; + else + data->fan_div[nr] = 3; + } + val = old & 0x100; + val |= (data->fan_div[0] & 0x07); + val |= (data->fan_div[1] & 0x07) << 3; + if (data->fan_div[2] == 3) + val |= 0x1 << 6; + it87_write_value(client, IT87_REG_FAN_DIV, val); + + for (i = 0; i < 3; i++) { + data->fan_min[i]=FAN_TO_REG(min[i], DIV_FROM_REG(data->fan_div[i])); + it87_write_value(client, IT87_REG_FAN_MIN(i), data->fan_min[i]); + } return count; } @@ -508,6 +561,7 @@ show_fan_offset(1); show_fan_offset(2); +show_fan_offset(3); /* Alarm */ static ssize_t show_alarm(struct device *dev, char *buf) @@ -525,6 +579,8 @@ * when a new adapter is inserted (and it87_driver is still present) */ static int it87_attach_adapter(struct i2c_adapter *adapter) { + if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + return 0; return i2c_detect(adapter, &addr_data, it87_detect); } @@ -574,6 +630,7 @@ } } } + memset (new_client, 0x00, sizeof(struct i2c_client) + sizeof(struct it87_data)); /* OK. For now, we presume we have a valid client. We now create the client structure, even though we cannot fill it completely yet. @@ -585,6 +642,8 @@ err = -ENOMEM; goto ERROR1; } + memset(new_client, 0x00, sizeof(struct i2c_client) + + sizeof(struct it87_data)); data = (struct it87_data *) (new_client + 1); if (is_isa) @@ -652,16 +711,26 @@ device_create_file(&new_client->dev, &dev_attr_in_input2); device_create_file(&new_client->dev, &dev_attr_in_input3); device_create_file(&new_client->dev, &dev_attr_in_input4); + device_create_file(&new_client->dev, &dev_attr_in_input5); + device_create_file(&new_client->dev, &dev_attr_in_input6); + device_create_file(&new_client->dev, &dev_attr_in_input7); + device_create_file(&new_client->dev, &dev_attr_in_input8); device_create_file(&new_client->dev, &dev_attr_in_min0); device_create_file(&new_client->dev, &dev_attr_in_min1); device_create_file(&new_client->dev, &dev_attr_in_min2); device_create_file(&new_client->dev, &dev_attr_in_min3); device_create_file(&new_client->dev, &dev_attr_in_min4); + device_create_file(&new_client->dev, &dev_attr_in_min5); + device_create_file(&new_client->dev, &dev_attr_in_min6); + device_create_file(&new_client->dev, &dev_attr_in_min7); device_create_file(&new_client->dev, &dev_attr_in_max0); device_create_file(&new_client->dev, &dev_attr_in_max1); device_create_file(&new_client->dev, &dev_attr_in_max2); device_create_file(&new_client->dev, &dev_attr_in_max3); device_create_file(&new_client->dev, &dev_attr_in_max4); + device_create_file(&new_client->dev, &dev_attr_in_max5); + device_create_file(&new_client->dev, &dev_attr_in_max6); + device_create_file(&new_client->dev, &dev_attr_in_max7); device_create_file(&new_client->dev, &dev_attr_temp_input1); device_create_file(&new_client->dev, &dev_attr_temp_input2); device_create_file(&new_client->dev, &dev_attr_temp_input3); @@ -671,16 +740,22 @@ device_create_file(&new_client->dev, &dev_attr_temp_min1); device_create_file(&new_client->dev, &dev_attr_temp_min2); device_create_file(&new_client->dev, &dev_attr_temp_min3); + device_create_file(&new_client->dev, &dev_attr_sensor1); + device_create_file(&new_client->dev, &dev_attr_sensor2); + device_create_file(&new_client->dev, &dev_attr_sensor3); device_create_file(&new_client->dev, &dev_attr_fan_input1); device_create_file(&new_client->dev, &dev_attr_fan_input2); + device_create_file(&new_client->dev, &dev_attr_fan_input3); device_create_file(&new_client->dev, &dev_attr_fan_min1); device_create_file(&new_client->dev, &dev_attr_fan_min2); + device_create_file(&new_client->dev, &dev_attr_fan_min3); device_create_file(&new_client->dev, &dev_attr_fan_div1); device_create_file(&new_client->dev, &dev_attr_fan_div2); + device_create_file(&new_client->dev, &dev_attr_fan_div3); device_create_file(&new_client->dev, &dev_attr_alarm); /* Initialize the IT87 chip */ - it87_init_client(new_client); + it87_init_client(new_client, data); return 0; ERROR1: @@ -753,70 +828,70 @@ } /* Called when we have found a new IT87. It should set limits, etc. */ -static void it87_init_client(struct i2c_client *client) +static void it87_init_client(struct i2c_client *client, struct it87_data *data) { /* Reset all except Watchdog values and last conversion values This sets fan-divs to 2, among others */ it87_write_value(client, IT87_REG_CONFIG, 0x80); it87_write_value(client, IT87_REG_VIN_MIN(0), - IN_TO_REG(IT87_INIT_IN_MIN_0, 0)); + IN_TO_REG(IT87_INIT_IN_MIN_0)); it87_write_value(client, IT87_REG_VIN_MAX(0), - IN_TO_REG(IT87_INIT_IN_MAX_0, 0)); + IN_TO_REG(IT87_INIT_IN_MAX_0)); it87_write_value(client, IT87_REG_VIN_MIN(1), - IN_TO_REG(IT87_INIT_IN_MIN_1, 1)); + IN_TO_REG(IT87_INIT_IN_MIN_1)); it87_write_value(client, IT87_REG_VIN_MAX(1), - IN_TO_REG(IT87_INIT_IN_MAX_1, 1)); + IN_TO_REG(IT87_INIT_IN_MAX_1)); it87_write_value(client, IT87_REG_VIN_MIN(2), - IN_TO_REG(IT87_INIT_IN_MIN_2, 2)); + IN_TO_REG(IT87_INIT_IN_MIN_2)); it87_write_value(client, IT87_REG_VIN_MAX(2), - IN_TO_REG(IT87_INIT_IN_MAX_2, 2)); + IN_TO_REG(IT87_INIT_IN_MAX_2)); it87_write_value(client, IT87_REG_VIN_MIN(3), - IN_TO_REG(IT87_INIT_IN_MIN_3, 3)); + IN_TO_REG(IT87_INIT_IN_MIN_3)); it87_write_value(client, IT87_REG_VIN_MAX(3), - IN_TO_REG(IT87_INIT_IN_MAX_3, 3)); + IN_TO_REG(IT87_INIT_IN_MAX_3)); it87_write_value(client, IT87_REG_VIN_MIN(4), - IN_TO_REG(IT87_INIT_IN_MIN_4, 4)); + IN_TO_REG(IT87_INIT_IN_MIN_4)); it87_write_value(client, IT87_REG_VIN_MAX(4), - IN_TO_REG(IT87_INIT_IN_MAX_4, 4)); + IN_TO_REG(IT87_INIT_IN_MAX_4)); it87_write_value(client, IT87_REG_VIN_MIN(5), - IN_TO_REG(IT87_INIT_IN_MIN_5, 5)); + IN_TO_REG(IT87_INIT_IN_MIN_5)); it87_write_value(client, IT87_REG_VIN_MAX(5), - IN_TO_REG(IT87_INIT_IN_MAX_5, 5)); + IN_TO_REG(IT87_INIT_IN_MAX_5)); it87_write_value(client, IT87_REG_VIN_MIN(6), - IN_TO_REG(IT87_INIT_IN_MIN_6, 6)); + IN_TO_REG(IT87_INIT_IN_MIN_6)); it87_write_value(client, IT87_REG_VIN_MAX(6), - IN_TO_REG(IT87_INIT_IN_MAX_6, 6)); + IN_TO_REG(IT87_INIT_IN_MAX_6)); it87_write_value(client, IT87_REG_VIN_MIN(7), - IN_TO_REG(IT87_INIT_IN_MIN_7, 7)); + IN_TO_REG(IT87_INIT_IN_MIN_7)); it87_write_value(client, IT87_REG_VIN_MAX(7), - IN_TO_REG(IT87_INIT_IN_MAX_7, 7)); + IN_TO_REG(IT87_INIT_IN_MAX_7)); /* Note: Battery voltage does not have limit registers */ - it87_write_value(client, IT87_REG_FAN_MIN(1), + it87_write_value(client, IT87_REG_FAN_MIN(0), FAN_TO_REG(IT87_INIT_FAN_MIN_1, 2)); - it87_write_value(client, IT87_REG_FAN_MIN(2), + it87_write_value(client, IT87_REG_FAN_MIN(1), FAN_TO_REG(IT87_INIT_FAN_MIN_2, 2)); - it87_write_value(client, IT87_REG_FAN_MIN(3), + it87_write_value(client, IT87_REG_FAN_MIN(2), FAN_TO_REG(IT87_INIT_FAN_MIN_3, 2)); - it87_write_value(client, IT87_REG_TEMP_HIGH(1), + it87_write_value(client, IT87_REG_TEMP_HIGH(0), TEMP_TO_REG(IT87_INIT_TEMP_HIGH_1)); - it87_write_value(client, IT87_REG_TEMP_LOW(1), + it87_write_value(client, IT87_REG_TEMP_LOW(0), TEMP_TO_REG(IT87_INIT_TEMP_LOW_1)); - it87_write_value(client, IT87_REG_TEMP_HIGH(2), + it87_write_value(client, IT87_REG_TEMP_HIGH(1), TEMP_TO_REG(IT87_INIT_TEMP_HIGH_2)); - it87_write_value(client, IT87_REG_TEMP_LOW(2), + it87_write_value(client, IT87_REG_TEMP_LOW(1), TEMP_TO_REG(IT87_INIT_TEMP_LOW_2)); - it87_write_value(client, IT87_REG_TEMP_HIGH(3), + it87_write_value(client, IT87_REG_TEMP_HIGH(2), TEMP_TO_REG(IT87_INIT_TEMP_HIGH_3)); - it87_write_value(client, IT87_REG_TEMP_LOW(3), + it87_write_value(client, IT87_REG_TEMP_LOW(2), TEMP_TO_REG(IT87_INIT_TEMP_LOW_3)); /* Enable voltage monitors */ it87_write_value(client, IT87_REG_VIN_ENABLE, 0xff); /* Enable Temp1-Temp3 */ - it87_write_value(client, IT87_REG_TEMP_ENABLE, - (it87_read_value(client, IT87_REG_TEMP_ENABLE) & 0xc0) - | (temp_type & 0x3f)); + data->sensor = (it87_read_value(client, IT87_REG_TEMP_ENABLE) & 0xc0); + data->sensor |= temp_type & 0x3f; + it87_write_value(client, IT87_REG_TEMP_ENABLE, data->sensor); /* Enable fans */ it87_write_value(client, IT87_REG_FAN_CTRL, @@ -860,18 +935,18 @@ data->in_min[8] = 0; data->in_max[8] = 255; - for (i = 1; i <= 3; i++) { - data->fan[i - 1] = + for (i = 0; i < 3; i++) { + data->fan[i] = it87_read_value(client, IT87_REG_FAN(i)); - data->fan_min[i - 1] = + data->fan_min[i] = it87_read_value(client, IT87_REG_FAN_MIN(i)); } - for (i = 1; i <= 3; i++) { - data->temp[i - 1] = + for (i = 0; i < 3; i++) { + data->temp[i] = it87_read_value(client, IT87_REG_TEMP(i)); - data->temp_high[i - 1] = + data->temp_high[i] = it87_read_value(client, IT87_REG_TEMP_HIGH(i)); - data->temp_low[i - 1] = + data->temp_low[i] = it87_read_value(client, IT87_REG_TEMP_LOW(i)); } @@ -887,7 +962,7 @@ i = it87_read_value(client, IT87_REG_FAN_DIV); data->fan_div[0] = i & 0x07; data->fan_div[1] = (i >> 3) & 0x07; - data->fan_div[2] = 1; + data->fan_div[2] = (i & 0x40) ? 3 : 1; data->alarms = it87_read_value(client, IT87_REG_ALARM1) | diff -Nru a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c --- a/drivers/i2c/chips/lm75.c Thu May 15 15:24:32 2003 +++ b/drivers/i2c/chips/lm75.c Thu May 15 15:24:32 2003 @@ -121,6 +121,8 @@ static int lm75_attach_adapter(struct i2c_adapter *adapter) { + if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + return 0; return i2c_detect(adapter, &addr_data, lm75_detect); } diff -Nru a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c --- a/drivers/i2c/chips/via686a.c Thu May 15 15:24:33 2003 +++ b/drivers/i2c/chips/via686a.c Thu May 15 15:24:33 2003 @@ -661,6 +661,8 @@ /* This is called when the module is loaded */ static int via686a_attach_adapter(struct i2c_adapter *adapter) { + if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + return 0; return i2c_detect(adapter, &addr_data, via686a_detect); } diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c --- a/drivers/i2c/chips/w83781d.c Thu May 15 15:24:32 2003 +++ b/drivers/i2c/chips/w83781d.c Thu May 15 15:24:32 2003 @@ -1026,6 +1026,8 @@ static int w83781d_attach_adapter(struct i2c_adapter *adapter) { + if (!(adapter->class & I2C_ADAP_CLASS_SMBUS)) + return 0; return i2c_detect(adapter, &addr_data, w83781d_detect); } diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c --- a/drivers/i2c/i2c-core.c Thu May 15 15:24:34 2003 +++ b/drivers/i2c/i2c-core.c Thu May 15 15:24:34 2003 @@ -38,8 +38,8 @@ #define DEB(x) if (i2c_debug>=1) x; #define DEB2(x) if (i2c_debug>=2) x; -static struct i2c_adapter *adapters[I2C_ADAP_MAX]; -static struct i2c_driver *drivers[I2C_DRIVER_MAX]; +static LIST_HEAD(adapters); +static LIST_HEAD(drivers); static DECLARE_MUTEX(core_lists); /**** debug level */ @@ -55,13 +55,17 @@ return 0; } -static struct device_driver i2c_generic_driver = { - .name = "i2c", +static struct device_driver i2c_adapter_driver = { + .name = "i2c_adapter", .bus = &i2c_bus_type, .probe = i2c_device_probe, .remove = i2c_device_remove, }; +static struct class i2c_adapter_class = { + .name = "i2c-adapter" +}; + /* --------------------------------------------------- * registering functions @@ -75,23 +79,17 @@ */ int i2c_add_adapter(struct i2c_adapter *adap) { - int res = 0, i, j; + static int nr = 0; + struct list_head *item; + struct i2c_driver *driver; down(&core_lists); - for (i = 0; i < I2C_ADAP_MAX; i++) - if (NULL == adapters[i]) - break; - if (I2C_ADAP_MAX == i) { - dev_warn(&adap->dev, - "register_adapter - enlarge I2C_ADAP_MAX.\n"); - res = -ENOMEM; - goto out_unlock; - } - - adapters[i] = adap; - init_MUTEX(&adap->bus); - init_MUTEX(&adap->list); + adap->nr = nr++; + init_MUTEX(&adap->bus_lock); + init_MUTEX(&adap->clist_lock); + list_add_tail(&adap->list,&adapters); + INIT_LIST_HEAD(&adap->clients); /* Add the adapter to the driver core. * If the parent pointer is not set up, @@ -99,77 +97,73 @@ */ if (adap->dev.parent == NULL) adap->dev.parent = &legacy_bus; - sprintf(adap->dev.bus_id, "i2c-%d", i); - adap->dev.driver = &i2c_generic_driver; + sprintf(adap->dev.bus_id, "i2c-%d", adap->nr); + adap->dev.driver = &i2c_adapter_driver; device_register(&adap->dev); + /* Add this adapter to the i2c_adapter class */ + memset(&adap->class_dev, 0x00, sizeof(struct class_device)); + adap->class_dev.dev = &adap->dev; + adap->class_dev.class = &i2c_adapter_class; + strncpy(adap->class_dev.class_id, adap->dev.bus_id, BUS_ID_SIZE); + class_device_register(&adap->class_dev); + /* inform drivers of new adapters */ - for (j=0;jflags&(I2C_DF_NOTIFY|I2C_DF_DUMMY))) + list_for_each(item,&drivers) { + driver = list_entry(item, struct i2c_driver, list); + if (driver->flags & I2C_DF_NOTIFY) /* We ignore the return code; if it fails, too bad */ - drivers[j]->attach_adapter(adap); + driver->attach_adapter(adap); + } up(&core_lists); - - DEB(dev_dbg(&adap->dev, "registered as adapter %d.\n", i)); - out_unlock: - up(&core_lists); - return res;; + DEB(dev_dbg(&adap->dev, "registered as adapter #%d\n", adap->nr)); + return 0; } int i2c_del_adapter(struct i2c_adapter *adap) { - int res = 0, i, j; + struct list_head *item; + struct i2c_driver *driver; + struct i2c_client *client; + int res = 0; down(&core_lists); - for (i = 0; i < I2C_ADAP_MAX; i++) - if (adap == adapters[i]) - break; - if (I2C_ADAP_MAX == i) { - dev_warn(&adap->dev, "unregister_adapter adap not found.\n"); - res = -ENODEV; - goto out_unlock; - } - /* DUMMY drivers do not register their clients, so we have to - * use a trick here: we call driver->attach_adapter to - * *detach* it! Of course, each dummy driver should know about - * this or hell will break loose... - */ - for (j = 0; j < I2C_DRIVER_MAX; j++) - if (drivers[j] && (drivers[j]->flags & I2C_DF_DUMMY)) - if ((res = drivers[j]->attach_adapter(adap))) { + list_for_each(item,&drivers) { + driver = list_entry(item, struct i2c_driver, list); + if (driver->detach_adapter) + if ((res = driver->detach_adapter(adap))) { dev_warn(&adap->dev, "can't detach adapter" - "while detaching driver %s: driver not " - "detached!", drivers[j]->name); + "while detaching driver %s: driver not " + "detached!", driver->name); goto out_unlock; } + } /* detach any active clients. This must be done first, because * it can fail; in which case we give upp. */ - for (j=0;jclients[j]; - if (client!=NULL) { - /* detaching devices is unconditional of the set notify - * flag, as _all_ clients that reside on the adapter - * must be deleted, as this would cause invalid states. - */ - if ((res=client->driver->detach_client(client))) { - dev_err(&adap->dev, "adapter not " - "unregistered, because client at " - "address %02x can't be detached. ", - client->addr); - goto out_unlock; - } + list_for_each(item,&adap->clients) { + client = list_entry(item, struct i2c_client, list); + + /* detaching devices is unconditional of the set notify + * flag, as _all_ clients that reside on the adapter + * must be deleted, as this would cause invalid states. + */ + if ((res=client->driver->detach_client(client))) { + dev_err(&adap->dev, "adapter not " + "unregistered, because client at " + "address %02x can't be detached. ", + client->addr); + goto out_unlock; } } /* clean up the sysfs representation */ + class_device_unregister(&adap->class_dev); device_unregister(&adap->dev); - - adapters[i] = NULL; + list_del(&adap->list); DEB(dev_dbg(&adap->dev, "adapter unregistered\n")); @@ -187,24 +181,11 @@ int i2c_add_driver(struct i2c_driver *driver) { - int res = 0, i; + struct list_head *item; + struct i2c_adapter *adapter; + int res = 0; down(&core_lists); - for (i = 0; i < I2C_DRIVER_MAX; i++) - if (NULL == drivers[i]) - break; - if (I2C_DRIVER_MAX == i) { - printk(KERN_WARNING - " i2c-core.o: register_driver(%s) " - "- enlarge I2C_DRIVER_MAX.\n", - driver->name); - res = -ENOMEM; - goto out_unlock; - } - - drivers[i] = driver; - - DEB(printk(KERN_DEBUG "i2c-core.o: driver %s registered.\n",driver->name)); /* add the driver to the list of i2c drivers in the driver core */ driver->driver.name = driver->name; @@ -216,13 +197,14 @@ if (res) goto out_unlock; - /* now look for instances of driver on our adapters - */ - if (driver->flags& (I2C_DF_NOTIFY|I2C_DF_DUMMY)) { - for (i=0;iattach_adapter(adapters[i]); + list_add_tail(&driver->list,&drivers); + DEB(printk(KERN_DEBUG "i2c-core.o: driver %s registered.\n",driver->name)); + + /* now look for instances of driver on our adapters */ + if (driver->flags & I2C_DF_NOTIFY) { + list_for_each(item,&adapters) { + adapter = list_entry(item, struct i2c_adapter, list); + driver->attach_adapter(adapter); } } @@ -233,44 +215,29 @@ int i2c_del_driver(struct i2c_driver *driver) { - int res = 0, i, j, k; + struct list_head *item1; + struct list_head *item2; + struct i2c_client *client; + struct i2c_adapter *adap; + + int res = 0; down(&core_lists); - for (i = 0; i < I2C_DRIVER_MAX; i++) - if (driver == drivers[i]) - break; - if (I2C_DRIVER_MAX == i) { - printk(KERN_WARNING " i2c-core.o: unregister_driver: " - "[%s] not found\n", - driver->name); - res = -ENODEV; - goto out_unlock; - } - - driver_unregister(&driver->driver); /* Have a look at each adapter, if clients of this driver are still * attached. If so, detach them to be able to kill the driver * afterwards. */ DEB2(printk(KERN_DEBUG "i2c-core.o: unregister_driver - looking for clients.\n")); - /* removing clients does not depend on the notify flag, else * invalid operation might (will!) result, when using stale client * pointers. */ - for (k=0;kdev, "examining adapter\n")); - if (driver->flags & I2C_DF_DUMMY) { - /* DUMMY drivers do not register their clients, so we have to - * use a trick here: we call driver->attach_adapter to - * *detach* it! Of course, each dummy driver should know about - * this or hell will break loose... - */ - if ((res = driver->attach_adapter(adap))) { + if (driver->detach_adapter) { + if ((res = driver->detach_adapter(adap))) { dev_warn(&adap->dev, "while unregistering " "dummy driver %s, adapter could " "not be detached properly; driver " @@ -278,31 +245,31 @@ goto out_unlock; } } else { - for (j=0;jclients[j]; - if (client != NULL && - client->driver == driver) { - DEB2(printk(KERN_DEBUG "i2c-core.o: " - "detaching client %s:\n", - client->dev.name)); - if ((res = driver->detach_client(client))) { - dev_err(&adap->dev, "while " - "unregistering driver " - "`%s', the client at " - "address %02x of " - "adapter could not " - "be detached; driver " - "not unloaded!", - driver->name, - client->addr); - goto out_unlock; - } + list_for_each(item2,&adap->clients) { + client = list_entry(item2, struct i2c_client, list); + if (client->driver != driver) + continue; + DEB2(printk(KERN_DEBUG "i2c-core.o: " + "detaching client %s:\n", + client->dev.name)); + if ((res = driver->detach_client(client))) { + dev_err(&adap->dev, "while " + "unregistering driver " + "`%s', the client at " + "address %02x of " + "adapter could not " + "be detached; driver " + "not unloaded!", + driver->name, + client->addr); + goto out_unlock; } } } } - drivers[i] = NULL; - + + driver_unregister(&driver->driver); + list_del(&driver->list); DEB(printk(KERN_DEBUG "i2c-core.o: driver unregistered: %s\n",driver->name)); out_unlock: @@ -310,14 +277,16 @@ return 0; } -static int __i2c_check_addr(struct i2c_adapter *adapter, int addr) +static int __i2c_check_addr(struct i2c_adapter *adapter, unsigned int addr) { - int i; + struct list_head *item; + struct i2c_client *client; - for (i = 0; i < I2C_CLIENT_MAX ; i++) - if (adapter->clients[i] && (adapter->clients[i]->addr == addr)) + list_for_each(item,&adapter->clients) { + client = list_entry(item, struct i2c_client, list); + if (client->addr == addr) return -EBUSY; - + } return 0; } @@ -325,9 +294,9 @@ { int rval; - down(&adapter->list); + down(&adapter->clist_lock); rval = __i2c_check_addr(adapter, addr); - up(&adapter->list); + up(&adapter->clist_lock); return rval; } @@ -335,28 +304,14 @@ int i2c_attach_client(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; - int i; - - down(&adapter->list); - if (__i2c_check_addr(client->adapter, client->addr)) - goto out_unlock_list; - for (i = 0; i < I2C_CLIENT_MAX; i++) { - if (!adapter->clients[i]) - goto free_slot; + down(&adapter->clist_lock); + if (__i2c_check_addr(client->adapter, client->addr)) { + up(&adapter->clist_lock); + return -EBUSY; } - - printk(KERN_WARNING - " i2c-core.o: attach_client(%s) - enlarge I2C_CLIENT_MAX.\n", - client->dev.name); - - out_unlock_list: - up(&adapter->list); - return -EBUSY; - - free_slot: - adapter->clients[i] = client; - up(&adapter->list); + list_add_tail(&client->list,&adapter->clients); + up(&adapter->clist_lock); if (adapter->client_register) { if (adapter->client_register(client)) { @@ -366,8 +321,8 @@ } } - DEB(dev_dbg(&adapter->dev, "client [%s] registered to adapter " - "(pos. %d).\n", client->dev.name, i)); + DEB(dev_dbg(&adapter->dev, "client [%s] registered to adapter\n", + client->dev.name)); if (client->flags & I2C_CLIENT_ALLOW_USE) client->usage_count = 0; @@ -388,7 +343,7 @@ int i2c_detach_client(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; - int res = 0, i; + int res = 0; if ((client->flags & I2C_CLIENT_ALLOW_USE) && (client->usage_count > 0)) return -EBUSY; @@ -403,22 +358,11 @@ } } - down(&adapter->list); - for (i = 0; i < I2C_CLIENT_MAX; i++) { - if (client == adapter->clients[i]) { - adapter->clients[i] = NULL; - goto out_unlock; - } - } - - printk(KERN_WARNING - " i2c-core.o: unregister_client [%s] not found\n", - client->dev.name); - res = -ENODEV; - - out_unlock: + down(&adapter->clist_lock); + list_del(&client->list); device_unregister(&client->dev); - up(&adapter->list); + up(&adapter->clist_lock); + out: return res; } @@ -479,6 +423,27 @@ return 0; } +void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg) +{ + struct list_head *item; + struct i2c_client *client; + + down(&adap->clist_lock); + list_for_each(item,&adap->clients) { + client = list_entry(item, struct i2c_client, list); + if (!try_module_get(client->driver->owner)) + continue; + if (NULL != client->driver->command) { + up(&adap->clist_lock); + client->driver->command(client,cmd,arg); + down(&adap->clist_lock); + } + module_put(client->driver->owner); + } + up(&adap->clist_lock); +} + + /* match always succeeds, as we want the probe() to tell if we really accept this match */ static int i2c_device_match(struct device *dev, struct device_driver *drv) { @@ -490,14 +455,23 @@ .match = i2c_device_match, }; - static int __init i2c_init(void) { - return bus_register(&i2c_bus_type); + int retval; + + retval = bus_register(&i2c_bus_type); + if (retval) + return retval; + retval = driver_register(&i2c_adapter_driver); + if (retval) + return retval; + return class_register(&i2c_adapter_class); } static void __exit i2c_exit(void) { + class_unregister(&i2c_adapter_class); + driver_unregister(&i2c_adapter_driver); bus_unregister(&i2c_bus_type); } @@ -516,13 +490,13 @@ if (adap->algo->master_xfer) { DEB2(dev_dbg(&adap->dev, "master_xfer: with %d msgs.\n", num)); - down(&adap->bus); + down(&adap->bus_lock); ret = adap->algo->master_xfer(adap,msgs,num); - up(&adap->bus); + up(&adap->bus_lock); return ret; } else { - dev_err(&adap->dev, "I2C level transfers not supported\n"); + DEB2(dev_dbg(&adap->dev, "I2C level transfers not supported\n")); return -ENOSYS; } } @@ -542,9 +516,9 @@ DEB2(dev_dbg(&client->adapter->dev, "master_send: writing %d bytes.\n", count)); - down(&adap->bus); + down(&adap->bus_lock); ret = adap->algo->master_xfer(adap,&msg,1); - up(&adap->bus); + up(&adap->bus_lock); /* if everything went ok (i.e. 1 msg transmitted), return #bytes * transmitted, else error code. @@ -572,9 +546,9 @@ DEB2(dev_dbg(&client->adapter->dev, "master_recv: reading %d bytes.\n", count)); - down(&adap->bus); + down(&adap->bus_lock); ret = adap->algo->master_xfer(adap,&msg,1); - up(&adap->bus); + up(&adap->bus_lock); DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: return:%d (count:%d, addr:0x%02x)\n", ret, count, client->addr)); @@ -743,11 +717,30 @@ */ int i2c_adapter_id(struct i2c_adapter *adap) { - int i; - for (i = 0; i < I2C_ADAP_MAX; i++) - if (adap == adapters[i]) - return i; - return -1; + return adap->nr; +} + +struct i2c_adapter* i2c_get_adapter(int id) +{ + struct list_head *item; + struct i2c_adapter *adapter; + + down(&core_lists); + list_for_each(item,&adapters) { + adapter = list_entry(item, struct i2c_adapter, list); + if (id == adapter->nr && + try_module_get(adapter->owner)) { + up(&core_lists); + return adapter; + } + } + up(&core_lists); + return NULL; +} + +void i2c_put_adapter(struct i2c_adapter *adap) +{ + module_put(adap->owner); } /* The SMBus parts */ @@ -1189,10 +1182,10 @@ } if (adapter->algo->smbus_xfer) { - down(&adapter->bus); + down(&adapter->bus_lock); res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, command,size,data); - up(&adapter->bus); + up(&adapter->bus_lock); } else res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, command,size,data); @@ -1232,6 +1225,7 @@ EXPORT_SYMBOL(i2c_detach_client); EXPORT_SYMBOL(i2c_use_client); EXPORT_SYMBOL(i2c_release_client); +EXPORT_SYMBOL(i2c_clients_command); EXPORT_SYMBOL(i2c_check_addr); EXPORT_SYMBOL(i2c_master_send); @@ -1239,6 +1233,8 @@ EXPORT_SYMBOL(i2c_control); EXPORT_SYMBOL(i2c_transfer); EXPORT_SYMBOL(i2c_adapter_id); +EXPORT_SYMBOL(i2c_get_adapter); +EXPORT_SYMBOL(i2c_put_adapter); EXPORT_SYMBOL(i2c_probe); EXPORT_SYMBOL(i2c_smbus_xfer); diff -Nru a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c --- a/drivers/i2c/i2c-dev.c Thu May 15 15:24:42 2003 +++ b/drivers/i2c/i2c-dev.c Thu May 15 15:24:42 2003 @@ -58,6 +58,7 @@ static int i2cdev_release (struct inode *inode, struct file *file); static int i2cdev_attach_adapter(struct i2c_adapter *adap); +static int i2cdev_detach_adapter(struct i2c_adapter *adap); static int i2cdev_detach_client(struct i2c_client *client); static int i2cdev_command(struct i2c_client *client, unsigned int cmd, void *arg); @@ -72,15 +73,13 @@ .release = i2cdev_release, }; -#define I2CDEV_ADAPS_MAX I2C_ADAP_MAX -static struct i2c_adapter *i2cdev_adaps[I2CDEV_ADAPS_MAX]; - static struct i2c_driver i2cdev_driver = { .owner = THIS_MODULE, .name = "dev driver", .id = I2C_DRIVERID_I2CDEV, - .flags = I2C_DF_DUMMY, + .flags = I2C_DF_NOTIFY, .attach_adapter = i2cdev_attach_adapter, + .detach_adapter = i2cdev_detach_adapter, .detach_client = i2cdev_detach_client, .command = i2cdev_command, }; @@ -340,35 +339,31 @@ { unsigned int minor = minor(inode->i_rdev); struct i2c_client *client; + struct i2c_adapter *adap; - if ((minor >= I2CDEV_ADAPS_MAX) || !(i2cdev_adaps[minor])) + adap = i2c_get_adapter(minor); + if (NULL == adap) return -ENODEV; client = kmalloc(sizeof(*client), GFP_KERNEL); - if (!client) + if (!client) { + i2c_put_adapter(adap); return -ENOMEM; + } memcpy(client, &i2cdev_client_template, sizeof(*client)); /* registered with adapter, passed as client to user */ - client->adapter = i2cdev_adaps[minor]; + client->adapter = adap; file->private_data = client; - /* use adapter module, i2c-dev handled with fops */ - if (!try_module_get(client->adapter->owner)) - goto out_kfree; - return 0; - -out_kfree: - kfree(client); - return -ENODEV; } static int i2cdev_release(struct inode *inode, struct file *file) { struct i2c_client *client = file->private_data; - module_put(client->adapter->owner); + i2c_put_adapter(client->adapter); kfree(client); file->private_data = NULL; @@ -378,32 +373,22 @@ int i2cdev_attach_adapter(struct i2c_adapter *adap) { int i; - char name[12]; - if ((i = i2c_adapter_id(adap)) < 0) { - dev_dbg(&adap->dev, "Unknown adapter ?!?\n"); - return -ENODEV; - } - if (i >= I2CDEV_ADAPS_MAX) { - dev_dbg(&adap->dev, "Adapter number too large?!? (%d)\n",i); - return -ENODEV; - } + i = i2c_adapter_id(adap); + devfs_mk_cdev(MKDEV(I2C_MAJOR, i), + S_IFCHR|S_IRUSR|S_IWUSR, "i2c/%d", i); + dev_dbg(&adap->dev, "Registered as minor %d\n", i); + return 0; +} - sprintf (name, "i2c/%d", i); - if (! i2cdev_adaps[i]) { - i2cdev_adaps[i] = adap; - devfs_register (NULL, name, - DEVFS_FL_DEFAULT, I2C_MAJOR, i, - S_IFCHR | S_IRUSR | S_IWUSR, - &i2cdev_fops, NULL); - dev_dbg(&adap->dev, "Registered as minor %d\n", i); - } else { - /* This is actually a detach_adapter call! */ - devfs_remove("i2c/%d", i); - i2cdev_adaps[i] = NULL; - dev_dbg(&adap->dev, "Adapter unregistered\n"); - } +int i2cdev_detach_adapter(struct i2c_adapter *adap) +{ + int i; + + i = i2c_adapter_id(adap); + devfs_remove("i2c/%d", i); + dev_dbg(&adap->dev, "Adapter unregistered\n"); return 0; } diff -Nru a/drivers/i2c/i2c-keywest.c b/drivers/i2c/i2c-keywest.c --- a/drivers/i2c/i2c-keywest.c Thu May 15 15:24:41 2003 +++ b/drivers/i2c/i2c-keywest.c Thu May 15 15:24:41 2003 @@ -212,7 +212,7 @@ #ifndef POLLED_MODE /* Interrupt handler */ -static void +static irqreturn_t keywest_irq(int irq, void *dev_id, struct pt_regs *regs) { struct keywest_iface *iface = (struct keywest_iface *)dev_id; @@ -225,6 +225,7 @@ add_timer(&iface->timeout_timer); } spin_unlock(&iface->lock); + return IRQ_HANDLED; } static void diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c --- a/drivers/ide/ide-cd.c Thu May 15 15:24:37 2003 +++ b/drivers/ide/ide-cd.c Thu May 15 15:24:38 2003 @@ -2070,6 +2070,7 @@ req.sense = sense; req.cmd[0] = GPCMD_TEST_UNIT_READY; + req.flags |= REQ_QUIET; #if ! STANDARD_ATAPI /* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to @@ -2871,6 +2872,11 @@ struct atapi_capabilities_page cap; int nslots = 1; + if (drive->media == ide_optical) { + printk("%s: ATAPI magneto-optical drive\n", drive->name); + return nslots; + } + if (CDROM_CONFIG_FLAGS(drive)->nec260) { CDROM_CONFIG_FLAGS(drive)->no_eject = 0; CDROM_CONFIG_FLAGS(drive)->audio_play = 1; @@ -3337,7 +3343,7 @@ goto failed; if (!drive->present) goto failed; - if (drive->media != ide_cdrom) + if (drive->media != ide_cdrom && drive->media != ide_optical) goto failed; /* skip drives that we were told to ignore */ if (ignore != NULL) { diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c --- a/drivers/ide/ide-disk.c Thu May 15 15:24:37 2003 +++ b/drivers/ide/ide-disk.c Thu May 15 15:24:37 2003 @@ -1479,7 +1479,7 @@ static int set_lba_addressing (ide_drive_t *drive, int arg) { - return (probe_lba_addressing(drive, arg)); + return probe_lba_addressing(drive, arg); } static void idedisk_add_settings(ide_drive_t *drive) @@ -1565,6 +1565,18 @@ } (void) probe_lba_addressing(drive, 1); + + if (drive->addressing == 1) { + ide_hwif_t *hwif = HWIF(drive); + int max_s = 2048; + + if (max_s > hwif->rqsize) + max_s = hwif->rqsize; + + blk_queue_max_sectors(&drive->queue, max_s); + } + + printk("%s: max request size: %dKiB\n", drive->name, drive->queue.max_sectors / 2); /* Extract geometry if we did not already have one for the drive */ if (!drive->cyl || !drive->head || !drive->sect) { diff -Nru a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c --- a/drivers/ide/ide-io.c Thu May 15 15:24:42 2003 +++ b/drivers/ide/ide-io.c Thu May 15 15:24:42 2003 @@ -850,14 +850,14 @@ * happens anyway when any interrupt comes in, IDE or otherwise * -- the kernel masks the IRQ while it is being handled. */ - if (hwif->irq != masked_irq) + if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq) disable_irq_nosync(hwif->irq); spin_unlock(&ide_lock); local_irq_enable(); /* allow other IRQs while we start this request */ startstop = start_request(drive, rq); spin_lock_irq(&ide_lock); - if (hwif->irq != masked_irq) + if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq) enable_irq(hwif->irq); if (startstop == ide_released) goto queue_next; diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c --- a/drivers/ide/ide-probe.c Thu May 15 15:24:40 2003 +++ b/drivers/ide/ide-probe.c Thu May 15 15:24:40 2003 @@ -803,7 +803,7 @@ return; if ((hwif->chipset != ide_4drives || !hwif->mate || !hwif->mate->present) && -#if CONFIG_BLK_DEV_PDC4030 +#ifdef CONFIG_BLK_DEV_PDC4030 (hwif->chipset != ide_pdc4030 || hwif->channel == 0) && #endif /* CONFIG_BLK_DEV_PDC4030 */ (hwif_check_regions(hwif))) { @@ -998,6 +998,7 @@ static void ide_init_queue(ide_drive_t *drive) { request_queue_t *q = &drive->queue; + ide_hwif_t *hwif = HWIF(drive); int max_sectors = 256; /* @@ -1013,8 +1014,10 @@ drive->queue_setup = 1; blk_queue_segment_boundary(q, 0xffff); - if (HWIF(drive)->rqsize) - max_sectors = HWIF(drive)->rqsize; + if (!hwif->rqsize) + hwif->rqsize = hwif->addressing ? 256 : 65536; + if (hwif->rqsize < max_sectors) + max_sectors = hwif->rqsize; blk_queue_max_sectors(q, max_sectors); /* IDE DMA can do PRD_ENTRIES number of segments. */ @@ -1235,7 +1238,7 @@ (void) request_module("ide-disk"); if (drive->scsi) (void) request_module("ide-scsi"); - if (drive->media == ide_cdrom) + if (drive->media == ide_cdrom || drive->media == ide_optical) (void) request_module("ide-cd"); if (drive->media == ide_tape) (void) request_module("ide-tape"); diff -Nru a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c --- a/drivers/ide/ide-tape.c Thu May 15 15:24:36 2003 +++ b/drivers/ide/ide-tape.c Thu May 15 15:24:36 2003 @@ -6292,11 +6292,9 @@ devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor) S_IFCHR | S_IRUGO | S_IWUGO, - &idetape_fops, NULL, "%s/mt", drive->devfs_name); devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor + 128), S_IFCHR | S_IRUGO | S_IWUGO, - &idetape_fops, NULL, "%s/mtn", drive->devfs_name); drive->disk->number = devfs_register_tape(drive->devfs_name); diff -Nru a/drivers/ide/ide-tcq.c b/drivers/ide/ide-tcq.c --- a/drivers/ide/ide-tcq.c Thu May 15 15:24:46 2003 +++ b/drivers/ide/ide-tcq.c Thu May 15 15:24:46 2003 @@ -51,9 +51,58 @@ */ #undef IDE_TCQ_FIDDLE_SI +/* + * bad drive blacklist, for drives that raport tcq capability but don't + * work reliably with the default config. initially from freebsd table. + */ +struct ide_tcq_blacklist { + char *model; + char works; + unsigned int max_sectors; +}; + +static struct ide_tcq_blacklist ide_tcq_blacklist[] = { + { + .model = "IBM-DTTA", + .works = 1, + .max_sectors = 128, + }, + { + .model = "IBM-DJNA", + .works = 0, + }, + { + .model = "WDC AC", + .works = 0, + }, + { + .model = NULL, + }, +}; + ide_startstop_t ide_dmaq_intr(ide_drive_t *drive); ide_startstop_t ide_service(ide_drive_t *drive); +static struct ide_tcq_blacklist *ide_find_drive_blacklist(ide_drive_t *drive) +{ + struct ide_tcq_blacklist *itb; + int i = 0; + + do { + itb = &ide_tcq_blacklist[i]; + + if (!itb->model) + break; + + if (!strncmp(drive->id->model, itb->model, strlen(itb->model))) + return itb; + + i++; + } while (1); + + return NULL; +} + static inline void drive_ctl_nien(ide_drive_t *drive, int set) { #ifdef IDE_TCQ_NIEN @@ -502,7 +551,7 @@ return 0; err: kfree(args); - return 1; + return -EIO; } /* @@ -511,6 +560,7 @@ */ static int ide_enable_queued(ide_drive_t *drive, int on) { + struct ide_tcq_blacklist *itb; int depth = drive->using_tcq ? drive->queue_depth : 0; /* @@ -530,6 +580,17 @@ } /* + * some drives need limited transfer size in tcq + */ + itb = ide_find_drive_blacklist(drive); + if (itb && itb->max_sectors) { + if (itb->max_sectors > HWIF(drive)->rqsize) + itb->max_sectors = HWIF(drive)->rqsize; + + blk_queue_max_sectors(&drive->queue, itb->max_sectors); + } + + /* * enable block tagging */ if (!blk_queue_tagged(&drive->queue)) @@ -582,13 +643,36 @@ return 0; } +static int ide_tcq_check_blacklist(ide_drive_t *drive) +{ + struct ide_tcq_blacklist *itb = ide_find_drive_blacklist(drive); + + if (!itb) + return 0; + + return !itb->works; +} + int __ide_dma_queued_on(ide_drive_t *drive) { if (!drive->using_dma) return 1; + if (HWIF(drive)->chipset == ide_pdc4030) + return 1; + if (ide_tcq_check_blacklist(drive)) { + printk(KERN_WARNING "%s: tcq forbidden by blacklist\n", + drive->name); + return 1; + } + if (drive->next != drive) { + printk(KERN_WARNING "%s: only one drive on a channel supported" + " for tcq\n", drive->name); + return 1; + } if (ata_pending_commands(drive)) { - printk(KERN_WARNING "ide-tcq; can't toggle tcq feature on busy drive\n"); + printk(KERN_WARNING "ide-tcq; can't toggle tcq feature on " + "busy drive\n"); return 1; } diff -Nru a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c --- a/drivers/ieee1394/amdtp.c Thu May 15 15:24:40 2003 +++ b/drivers/ieee1394/amdtp.c Thu May 15 15:24:40 2003 @@ -1205,7 +1205,6 @@ { struct amdtp_host *ah; int minor; - char name[16]; if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME) != 0) return; @@ -1223,13 +1222,11 @@ minor = IEEE1394_MINOR_BLOCK_AMDTP * 16 + ah->ohci->id; - sprintf(name, "amdtp/%d", ah->ohci->id); - INIT_LIST_HEAD(&ah->stream_list); spin_lock_init(&ah->stream_list_lock); - devfs_register(NULL, name, 0, IEEE1394_MAJOR, minor, - S_IFCHR | S_IRUSR | S_IWUSR, &amdtp_fops, NULL); + devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor), + S_IFCHR|S_IRUSR|S_IWUSR, "amdtp/%d", ah->ohci->id); } static void amdtp_remove_host(struct hpsb_host *host) diff -Nru a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c --- a/drivers/ieee1394/dv1394.c Thu May 15 15:24:41 2003 +++ b/drivers/ieee1394/dv1394.c Thu May 15 15:24:41 2003 @@ -2420,24 +2420,6 @@ }; -#ifdef CONFIG_DEVFS_FS -static int dv1394_devfs_add_entry(struct video_card *video) -{ - char buf[64]; - - snprintf(buf, sizeof(buf), "ieee1394/dv/host%d/%s/%s", - (video->id>>2), - (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"), - (video->mode == MODE_RECEIVE ? "in" : "out")); - - devfs_register(NULL, buf, 0, IEEE1394_MAJOR, - IEEE1394_MINOR_BLOCK_DV1394*16 + video->id, - S_IFCHR | S_IRUGO | S_IWUGO, &dv1394_fops, video); - return 0; -} -#endif /* CONFIG_DEVFS_FS */ - - /*** HOTPLUG STUFF **********************************************************/ /* * Export information about protocols/devices supported by this driver. @@ -2536,10 +2518,14 @@ list_add_tail(&video->list, &dv1394_cards); spin_unlock_irqrestore(&dv1394_cards_lock, flags); -#ifdef CONFIG_DEVFS_FS - if (dv1394_devfs_add_entry(video) < 0) + if (devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, + IEEE1394_MINOR_BLOCK_DV1394*16 + video->id), + S_IFCHR|S_IRUGO|S_IWUGO, + "ieee1394/dv/host%d/%s/%s", + (video->id>>2), + (video->pal_or_ntsc == DV1394_NTSC ? "NTSC" : "PAL"), + (video->mode == MODE_RECEIVE ? "in" : "out")) < 0) goto err_free; -#endif debug_printk("dv1394: dv1394_init() OK on ID %d\n", video->id); @@ -2562,9 +2548,7 @@ (video->mode == MODE_RECEIVE ? "in" : "out") ); -#ifdef CONFIG_DEVFS_FS devfs_remove("ieee1394/%s", buf); -#endif #ifdef CONFIG_PROC_FS dv1394_procfs_del(buf); #endif @@ -2602,11 +2586,9 @@ n = (video->id >> 2); -#ifdef CONFIG_DEVFS_FS devfs_remove("ieee1394/dv/host%d/NTSC", n); devfs_remove("ieee1394/dv/host%d/PAL", n); devfs_remove("ieee1394/dv/host%d", n); -#endif #ifdef CONFIG_PROC_FS snprintf(buf, sizeof(buf), "dv/host%d/NTSC", n); @@ -2642,11 +2624,9 @@ } #endif -#ifdef CONFIG_DEVFS_FS devfs_mk_dir("ieee1394/dv/host%d", ohci->id); devfs_mk_dir("ieee1394/dv/host%d/NTSC", ohci->id); devfs_mk_dir("ieee1394/dv/host%d/PAL", ohci->id); -#endif dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE); dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT); @@ -2901,9 +2881,7 @@ hpsb_unregister_highlevel(&dv1394_highlevel); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394); -#ifdef CONFIG_DEVFS_FS devfs_remove("ieee1394/dv"); -#endif #ifdef CONFIG_PROC_FS dv1394_procfs_del("dv"); #endif @@ -2920,18 +2898,14 @@ return -EIO; } -#ifdef CONFIG_DEVFS_FS devfs_mk_dir("ieee1394/dv"); -#endif #ifdef CONFIG_PROC_FS ret = dv1394_procfs_add_dir("dv",NULL,NULL); if (ret < 0) { printk(KERN_ERR "dv1394: unable to create /proc/bus/ieee1394/dv\n"); ieee1394_unregister_chardev(IEEE1394_MINOR_BLOCK_DV1394); -#ifdef CONFIG_DEVFS_FS devfs_remove("ieee1394/dv"); -#endif return -ENOMEM; } #endif diff -Nru a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c --- a/drivers/ieee1394/raw1394.c Thu May 15 15:24:33 2003 +++ b/drivers/ieee1394/raw1394.c Thu May 15 15:24:33 2003 @@ -2531,9 +2531,8 @@ { hpsb_register_highlevel(&raw1394_highlevel); - devfs_register(NULL, RAW1394_DEVICE_NAME, 0, - IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16, - S_IFCHR | S_IRUSR | S_IWUSR, &file_ops, NULL); + devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), + S_IFCHR | S_IRUSR | S_IWUSR, RAW1394_DEVICE_NAME); if (ieee1394_register_chardev(IEEE1394_MINOR_BLOCK_RAW1394, THIS_MODULE, &file_ops)) { diff -Nru a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c --- a/drivers/ieee1394/video1394.c Thu May 15 15:24:34 2003 +++ b/drivers/ieee1394/video1394.c Thu May 15 15:24:34 2003 @@ -1257,7 +1257,6 @@ static void video1394_add_host (struct hpsb_host *host) { struct ti_ohci *ohci; - char name[16]; int minor; /* We only work with the OHCI-1394 driver */ @@ -1274,12 +1273,10 @@ hpsb_set_hostinfo(&video1394_highlevel, host, ohci); hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->id); - sprintf(name, "%s/%d", VIDEO1394_DRIVER_NAME, ohci->id); - minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->id; - devfs_register(NULL, name, 0, IEEE1394_MAJOR, minor, - S_IFCHR | S_IRUSR | S_IWUSR, &video1394_fops, NULL); - - return; + minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->id; + devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor), + S_IFCHR | S_IRUSR | S_IWUSR, + "%s/%d", VIDEO1394_DRIVER_NAME, ohci->id); } diff -Nru a/drivers/input/evdev.c b/drivers/input/evdev.c --- a/drivers/input/evdev.c Thu May 15 15:24:41 2003 +++ b/drivers/input/evdev.c Thu May 15 15:24:41 2003 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -400,7 +401,9 @@ sprintf(evdev->name, "event%d", minor); evdev_table[minor] = evdev; - input_register_minor("input/event%d", minor, EVDEV_MINOR_BASE); + + devfs_mk_cdev(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor), + S_IFCHR|S_IRUGO|S_IWUSR, "input/event%d", minor); return &evdev->handle; } diff -Nru a/drivers/input/input.c b/drivers/input/input.c --- a/drivers/input/input.c Thu May 15 15:24:39 2003 +++ b/drivers/input/input.c Thu May 15 15:24:39 2003 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -32,7 +33,6 @@ EXPORT_SYMBOL(input_unregister_device); EXPORT_SYMBOL(input_register_handler); EXPORT_SYMBOL(input_unregister_handler); -EXPORT_SYMBOL(input_register_minor); EXPORT_SYMBOL(input_open_device); EXPORT_SYMBOL(input_close_device); EXPORT_SYMBOL(input_accept_process); @@ -40,7 +40,6 @@ EXPORT_SYMBOL(input_event); EXPORT_SYMBOL(input_class); -#define INPUT_MAJOR 13 #define INPUT_DEVICES 256 static LIST_HEAD(input_dev_list); @@ -540,15 +539,6 @@ .owner = THIS_MODULE, .open = input_open_file, }; - -void input_register_minor(char *name, int minor, int minor_base) -{ - char devfs_name[16]; - - sprintf(devfs_name, name, minor); - devfs_register(NULL, devfs_name, 0, INPUT_MAJOR, minor_base + minor, - S_IFCHR|S_IRUGO|S_IWUSR, &input_fops, NULL); -} #ifdef CONFIG_PROC_FS diff -Nru a/drivers/input/joydev.c b/drivers/input/joydev.c --- a/drivers/input/joydev.c Thu May 15 15:24:38 2003 +++ b/drivers/input/joydev.c Thu May 15 15:24:38 2003 @@ -445,7 +445,9 @@ } joydev_table[minor] = joydev; - input_register_minor("js%d", minor, JOYDEV_MINOR_BASE); + + devfs_mk_cdev(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor), + S_IFCHR|S_IRUGO|S_IWUSR, "js%d", minor); return &joydev->handle; } diff -Nru a/drivers/input/mouse/rpcmouse.c b/drivers/input/mouse/rpcmouse.c --- a/drivers/input/mouse/rpcmouse.c Thu May 15 15:24:37 2003 +++ b/drivers/input/mouse/rpcmouse.c Thu May 15 15:24:37 2003 @@ -49,7 +49,7 @@ }, }; -static void rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs) { struct input_dev *dev = dev_id; short x, y, dx, dy, b; @@ -74,6 +74,8 @@ input_report_key(dev, BTN_RIGHT, b & 0x10); input_sync(dev); + + return IRQ_HANDLED; } static int __init rpcmouse_init(void) diff -Nru a/drivers/input/mousedev.c b/drivers/input/mousedev.c --- a/drivers/input/mousedev.c Thu May 15 15:24:44 2003 +++ b/drivers/input/mousedev.c Thu May 15 15:24:44 2003 @@ -432,7 +432,9 @@ input_open_device(&mousedev->handle); mousedev_table[minor] = mousedev; - input_register_minor("input/mouse%d", minor, MOUSEDEV_MINOR_BASE); + + devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor), + S_IFCHR|S_IRUGO|S_IWUSR, "input/mouse%d", minor); return &mousedev->handle; } @@ -502,7 +504,10 @@ mousedev_table[MOUSEDEV_MIX] = &mousedev_mix; mousedev_mix.exist = 1; mousedev_mix.minor = MOUSEDEV_MIX; - input_register_minor("input/mice", MOUSEDEV_MIX, MOUSEDEV_MINOR_BASE); + + devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), + S_IFCHR|S_IRUGO|S_IWUSR, "input/mice"); + #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX if (!(mousedev_mix.misc = !misc_register(&psaux_mouse))) diff -Nru a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c --- a/drivers/input/serio/ambakmi.c Thu May 15 15:24:41 2003 +++ b/drivers/input/serio/ambakmi.c Thu May 15 15:24:41 2003 @@ -28,22 +28,27 @@ struct amba_kmi_port { struct serio io; struct amba_kmi_port *next; - unsigned long base; + void *base; unsigned int irq; unsigned int divisor; char name[32]; char phys[16]; + struct resource *res; }; -static void amba_kmi_int(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t amba_kmi_int(int irq, void *dev_id, struct pt_regs *regs) { struct amba_kmi_port *kmi = dev_id; - unsigned int status = __raw_readb(KMIIR); + unsigned int status = readb(KMIIR); + int handled = IRQ_NONE; while (status & KMIIR_RXINTR) { - serio_interrupt(&kmi->io, __raw_readb(KMIDATA), 0, regs); - status = __raw_readb(KMIIR); + serio_interrupt(&kmi->io, readb(KMIDATA), 0, regs); + status = readb(KMIIR); + handled = IRQ_HANDLED; } + + return handled; } static int amba_kmi_write(struct serio *io, unsigned char val) @@ -51,11 +56,11 @@ struct amba_kmi_port *kmi = io->driver; unsigned int timeleft = 10000; /* timeout in 100ms */ - while ((__raw_readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && timeleft--) + while ((readb(KMISTAT) & KMISTAT_TXEMPTY) == 0 && timeleft--) udelay(10); if (timeleft) - __raw_writeb(val, KMIDATA); + writeb(val, KMIDATA); return timeleft ? 0 : SERIO_TIMEOUT; } @@ -65,17 +70,17 @@ struct amba_kmi_port *kmi = io->driver; int ret; - __raw_writeb(kmi->divisor, KMICLKDIV); - __raw_writeb(KMICR_EN, KMICR); + writeb(kmi->divisor, KMICLKDIV); + writeb(KMICR_EN, KMICR); ret = request_irq(kmi->irq, amba_kmi_int, 0, kmi->phys, kmi); if (ret) { printk(KERN_ERR "kmi: failed to claim IRQ%d\n", kmi->irq); - __raw_writeb(0, KMICR); + writeb(0, KMICR); return ret; } - __raw_writeb(KMICR_EN | KMICR_RXINTREN, KMICR); + writeb(KMICR_EN | KMICR_RXINTREN, KMICR); return 0; } @@ -84,9 +89,9 @@ { struct amba_kmi_port *kmi = io->driver; - free_irq(kmi->irq, kmi); + writeb(0, KMICR); - __raw_writeb(0, KMICR); + free_irq(kmi->irq, kmi); } static struct amba_kmi_port *list; @@ -109,24 +114,36 @@ kmi->io.phys = kmi->phys; kmi->io.driver = kmi; - kmi->base = base; + snprintf(kmi->name, sizeof(kmi->name), "AMBA KMI PS/2 %s port", type); + snprintf(kmi->phys, sizeof(kmi->phys), "amba/serio%d", nr); + + kmi->res = request_mem_region(base, KMI_SIZE, kmi->phys); + if (!kmi->res) { + kfree(kmi); + return -EBUSY; + } + + kmi->base = ioremap(base, KMI_SIZE); + if (!kmi->base) { + release_resource(kmi->res); + kfree(kmi); + return -ENOMEM; + } + kmi->irq = irq; kmi->divisor = 24 / 8 - 1; kmi->next = list; list = kmi; - snprintf(kmi->name, sizeof(kmi->name), "AMBA KMI PS/2 %s port", type); - snprintf(kmi->phys, sizeof(kmi->phys), "amba/serio%d", nr); - serio_register_port(&kmi->io); return 0; } static int __init amba_kmi_init(void) { - amba_kmi_init_one("keyboard", IO_ADDRESS(KMI0_BASE), IRQ_KMIINT0, 0); - amba_kmi_init_one("mouse", IO_ADDRESS(KMI1_BASE), IRQ_KMIINT1, 1); + amba_kmi_init_one("keyboard", KMI0_BASE, IRQ_KMIINT0, 0); + amba_kmi_init_one("mouse", KMI1_BASE, IRQ_KMIINT1, 1); return 0; } @@ -139,6 +156,8 @@ next = kmi->next; serio_unregister_port(&kmi->io); + iounmap(kmi->base); + release_resource(kmi->res); kfree(kmi); kmi = next; diff -Nru a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c --- a/drivers/input/serio/i8042.c Thu May 15 15:24:33 2003 +++ b/drivers/input/serio/i8042.c Thu May 15 15:24:33 2003 @@ -62,6 +62,12 @@ static unsigned char i8042_mux_open; struct timer_list i8042_timer; +/* + * Shared IRQ's require a device pointer, but this driver doesn't support + * multiple devices + */ +#define i8042_request_irq_cookie (&i8042_timer) + static unsigned long i8042_unxlate_seen[256 / BITS_PER_LONG]; static unsigned char i8042_unxlate_table[128] = { 0,118, 22, 30, 38, 37, 46, 54, 61, 62, 70, 69, 78, 85,102, 13, @@ -235,7 +241,8 @@ if (i8042_mux_open++) return 0; - if (request_irq(values->irq, i8042_interrupt, 0, "i8042", NULL)) { + if (request_irq(values->irq, i8042_interrupt, + SA_SHIRQ, "i8042", i8042_request_irq_cookie)) { printk(KERN_ERR "i8042.c: Can't get irq %d for %s, unregistering the port.\n", values->irq, values->name); values->exists = 0; serio_unregister_port(port); @@ -275,7 +282,7 @@ return; } - free_irq(values->irq, NULL); + free_irq(values->irq, i8042_request_irq_cookie); i8042_flush(); } @@ -572,9 +579,10 @@ * Check if AUX irq is available. */ - if (request_irq(values->irq, i8042_interrupt, 0, "i8042", NULL)) + if (request_irq(values->irq, i8042_interrupt, SA_SHIRQ, + "i8042", i8042_request_irq_cookie)) return -1; - free_irq(values->irq, NULL); + free_irq(values->irq, i8042_request_irq_cookie); /* * Get rid of bytes in the queue. @@ -643,9 +651,10 @@ * in trying to detect AUX presence. */ - if (request_irq(values->irq, i8042_interrupt, 0, "i8042", NULL)) + if (request_irq(values->irq, i8042_interrupt, SA_SHIRQ, + "i8042", i8042_request_irq_cookie)) return -1; - free_irq(values->irq, NULL); + free_irq(values->irq, i8042_request_irq_cookie); /* * Get rid of bytes in the queue. diff -Nru a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c --- a/drivers/input/serio/rpckbd.c Thu May 15 15:24:33 2003 +++ b/drivers/input/serio/rpckbd.c Thu May 15 15:24:33 2003 @@ -54,20 +54,24 @@ return 0; } -static void rpckbd_rx(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t rpckbd_rx(int irq, void *dev_id, struct pt_regs *regs) { struct serio *port = dev_id; unsigned int byte; + int handled = IRQ_NONE; while (iomd_readb(IOMD_KCTRL) & (1 << 5)) { byte = iomd_readb(IOMD_KARTRX); serio_interrupt(port, byte, 0, regs); + handled = IRQ_HANDLED; } + return handled; } -static void rpckbd_tx(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t rpckbd_tx(int irq, void *dev_id, struct pt_regs *regs) { + return IRQ_HANDLED; } static int rpckbd_open(struct serio *port) diff -Nru a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c --- a/drivers/input/serio/sa1111ps2.c Thu May 15 15:24:38 2003 +++ b/drivers/input/serio/sa1111ps2.c Thu May 15 15:24:38 2003 @@ -41,10 +41,11 @@ * at the most one, but we loop for safety. If there was a * framing error, we have to manually clear the status. */ -static void ps2_rxint(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t ps2_rxint(int irq, void *dev_id, struct pt_regs *regs) { struct ps2if *ps2if = dev_id; unsigned int scancode, flag, status; + int handled = IRQ_NONE; status = sa1111_readl(ps2if->base + SA1111_PS2STAT); while (status & PS2STAT_RXF) { @@ -62,13 +63,17 @@ serio_interrupt(&ps2if->io, scancode, flag, regs); status = sa1111_readl(ps2if->base + SA1111_PS2STAT); + + handled = IRQ_HANDLED; } + + return handled; } /* * Completion of ps2 write */ -static void ps2_txint(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t ps2_txint(int irq, void *dev_id, struct pt_regs *regs) { struct ps2if *ps2if = dev_id; unsigned int status; @@ -83,6 +88,8 @@ ps2if->tail = (ps2if->tail + 1) & (sizeof(ps2if->buf) - 1); } spin_unlock(&ps2if->lock); + + return IRQ_HANDLED; } /* diff -Nru a/drivers/input/tsdev.c b/drivers/input/tsdev.c --- a/drivers/input/tsdev.c Thu May 15 15:24:45 2003 +++ b/drivers/input/tsdev.c Thu May 15 15:24:45 2003 @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -329,8 +330,9 @@ tsdev->handle.private = tsdev; tsdev_table[minor] = tsdev; - input_register_minor("input/ts%d", minor, TSDEV_MINOR_BASE); - + + devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor), + S_IFCHR|S_IRUGO|S_IWUSR, "input/ts%d", minor); return &tsdev->handle; } diff -Nru a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c --- a/drivers/isdn/capi/capi.c Thu May 15 15:24:45 2003 +++ b/drivers/isdn/capi/capi.c Thu May 15 15:24:45 2003 @@ -200,10 +200,8 @@ unsigned int minor = 0; unsigned long flags; - MOD_INC_USE_COUNT; mp = kmalloc(sizeof(*mp), GFP_ATOMIC); if (!mp) { - MOD_DEC_USE_COUNT; printk(KERN_ERR "capi: can't alloc capiminor\n"); return 0; } @@ -249,7 +247,6 @@ skb_queue_purge(&mp->outqueue); capiminor_del_all_ack(mp); kfree(mp); - MOD_DEC_USE_COUNT; } struct capiminor *capiminor_find(unsigned int minor) @@ -1280,6 +1277,7 @@ memset(drv, 0, sizeof(struct tty_driver)); drv->magic = TTY_DRIVER_MAGIC; + drv->owner = THIS_MODULE; drv->driver_name = "capi_nc"; drv->name = "capi/"; drv->major = capi_ttymajor; @@ -1460,7 +1458,6 @@ char *p; char *compileinfo; - MOD_INC_USE_COUNT; if ((p = strchr(revision, ':')) != 0 && p[1]) { strncpy(rev, p + 2, sizeof(rev)); @@ -1472,19 +1469,17 @@ if (register_chrdev(capi_major, "capi20", &capi_fops)) { printk(KERN_ERR "capi20: unable to get major %d\n", capi_major); - MOD_DEC_USE_COUNT; return -EIO; } - devfs_register (NULL, "isdn/capi20", DEVFS_FL_DEFAULT, - capi_major, 0, S_IFCHR | S_IRUSR | S_IWUSR, - &capi_fops, NULL); + devfs_mk_cdev(MKDEV(capi_major, 0), S_IFCHR | S_IRUSR | S_IWUSR, + "isdn/capi20"); + printk(KERN_NOTICE "capi20: started up with major %d\n", capi_major); #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE if (capinc_tty_init() < 0) { unregister_chrdev(capi_major, "capi20"); - MOD_DEC_USE_COUNT; return -ENOMEM; } #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ @@ -1503,7 +1498,6 @@ printk(KERN_NOTICE "capi20: Rev %s: started up with major %d%s\n", rev, capi_major, compileinfo); - MOD_DEC_USE_COUNT; return 0; } diff -Nru a/drivers/isdn/eicon/eicon_mod.c b/drivers/isdn/eicon/eicon_mod.c --- a/drivers/isdn/eicon/eicon_mod.c Thu May 15 15:24:33 2003 +++ b/drivers/isdn/eicon/eicon_mod.c Thu May 15 15:24:33 2003 @@ -245,7 +245,7 @@ card->hwif.isa.shmem = (eicon_isa_shmem *)a; return 0; case EICON_BUS_MCA: -#if CONFIG_MCA +#ifdef CONFIG_MCA if (eicon_mca_find_card( 0, a, card->hwif.isa.irq, @@ -853,7 +853,7 @@ card->type = Type; switch (Type) { #ifdef CONFIG_ISDN_DRV_EICON_ISA -#if CONFIG_MCA /* only needed for MCA */ +#ifdef CONFIG_MCA /* only needed for MCA */ case EICON_CTYPE_S: case EICON_CTYPE_SX: case EICON_CTYPE_SCOM: @@ -1342,7 +1342,7 @@ static void __exit eicon_exit(void) { -#if CONFIG_PCI +#ifdef CONFIG_PCI #ifdef CONFIG_ISDN_DRV_EICON_PCI card_t *pCard; word wCardIndex; @@ -1374,7 +1374,7 @@ eicon_freecard(last); } -#if CONFIG_PCI +#ifdef CONFIG_PCI #ifdef CONFIG_ISDN_DRV_EICON_PCI pCard = DivasCards; for (wCardIndex = 0; wCardIndex < MAX_CARDS; wCardIndex++) diff -Nru a/drivers/isdn/eicon/eicon_pci.c b/drivers/isdn/eicon/eicon_pci.c --- a/drivers/isdn/eicon/eicon_pci.c Thu May 15 15:24:44 2003 +++ b/drivers/isdn/eicon/eicon_pci.c Thu May 15 15:24:44 2003 @@ -26,7 +26,7 @@ char *eicon_pci_revision = "$Revision: 1.1.4.1.2.3 $"; -#if CONFIG_PCI /* intire stuff is only for PCI */ +#ifdef CONFIG_PCI /* entire stuff is only for PCI */ #ifdef CONFIG_ISDN_DRV_EICON_PCI int eicon_pci_find_card(char *ID) diff -Nru a/drivers/isdn/hardware/eicon/divamnt.c b/drivers/isdn/hardware/eicon/divamnt.c --- a/drivers/isdn/hardware/eicon/divamnt.c Thu May 15 15:24:39 2003 +++ b/drivers/isdn/hardware/eicon/divamnt.c Thu May 15 15:24:39 2003 @@ -420,10 +420,8 @@ DRIVERLNAME); return (0); } - devfs_register(NULL, "DivasMAINT", DEVFS_FL_DEFAULT, major, 0, - S_IFCHR | S_IRUSR | S_IWUSR, &divas_maint_fops, - NULL); + devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, DivasMAINT); return (1); } diff -Nru a/drivers/isdn/hardware/eicon/divasi.c b/drivers/isdn/hardware/eicon/divasi.c --- a/drivers/isdn/hardware/eicon/divasi.c Thu May 15 15:24:37 2003 +++ b/drivers/isdn/hardware/eicon/divasi.c Thu May 15 15:24:37 2003 @@ -179,10 +179,8 @@ DRIVERLNAME); return (0); } - devfs_register(NULL, "DivasIDI", DEVFS_FL_DEFAULT, major, 0, - S_IFCHR | S_IRUSR | S_IWUSR, &divas_idi_fops, - NULL); + devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, "DivasIDI"); return (1); } diff -Nru a/drivers/isdn/hardware/eicon/divasmain.c b/drivers/isdn/hardware/eicon/divasmain.c --- a/drivers/isdn/hardware/eicon/divasmain.c Thu May 15 15:24:34 2003 +++ b/drivers/isdn/hardware/eicon/divasmain.c Thu May 15 15:24:34 2003 @@ -788,9 +788,8 @@ DRIVERLNAME); return (0); } - devfs_register(NULL, "Divas", DEVFS_FL_DEFAULT, major, 0, - S_IFCHR | S_IRUSR | S_IWUSR, &divas_fops, NULL); + devfs_mk_cdev(MKDEV(major, 0), S_IFCHR|S_IRUSR|S_IWUSR, "Divas"); return (1); } diff -Nru a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c --- a/drivers/isdn/hisax/avm_pci.c Thu May 15 15:24:36 2003 +++ b/drivers/isdn/hisax/avm_pci.c Thu May 15 15:24:36 2003 @@ -730,7 +730,7 @@ } } #endif -#if CONFIG_PCI +#ifdef CONFIG_PCI if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, dev_avm))) { if (avm_pci_probe(card->cs, dev_avm)) diff -Nru a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c --- a/drivers/isdn/hisax/diva.c Thu May 15 15:24:44 2003 +++ b/drivers/isdn/hisax/diva.c Thu May 15 15:24:44 2003 @@ -772,7 +772,7 @@ } } #endif -#if CONFIG_PCI +#ifdef CONFIG_PCI if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) { diff -Nru a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c --- a/drivers/isdn/hisax/elsa.c Thu May 15 15:24:34 2003 +++ b/drivers/isdn/hisax/elsa.c Thu May 15 15:24:34 2003 @@ -1098,7 +1098,7 @@ return 0; return 1; } else if (card->typ == ISDN_CTYPE_ELSA_PCI) { -#if CONFIG_PCI +#ifdef CONFIG_PCI if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) { if (elsa_qs_pci_probe(card->cs, dev_qs1000, diff -Nru a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c --- a/drivers/isdn/hisax/niccy.c Thu May 15 15:24:37 2003 +++ b/drivers/isdn/hisax/niccy.c Thu May 15 15:24:37 2003 @@ -319,7 +319,7 @@ return 0; return 1; } else { -#if CONFIG_PCI +#ifdef CONFIG_PCI if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM, PCI_DEVICE_ID_SATSAGEM_NICCY, niccy_dev))) { if (niccy_pci_probe(card->cs, niccy_dev) < 0) diff -Nru a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c --- a/drivers/isdn/hisax/sedlbauer.c Thu May 15 15:24:45 2003 +++ b/drivers/isdn/hisax/sedlbauer.c Thu May 15 15:24:45 2003 @@ -789,7 +789,7 @@ } #endif /* Probe for Sedlbauer speed pci */ -#if CONFIG_PCI +#ifdef CONFIG_PCI dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100, dev_sedl); if (dev_sedl) { diff -Nru a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c --- a/drivers/isdn/i4l/isdn_common.c Thu May 15 15:24:36 2003 +++ b/drivers/isdn/i4l/isdn_common.c Thu May 15 15:24:36 2003 @@ -37,9 +37,6 @@ static void isdn_lock_driver(struct isdn_driver *drv); static void isdn_unlock_driver(struct isdn_driver *drv); -static void isdn_register_devfs(int); -static void isdn_unregister_devfs(int); - /* ====================================================================== */ /* Description of hardware-level-driver */ @@ -2157,85 +2154,37 @@ return max; } -/* - ***************************************************************************** - * And now the modules code. - ***************************************************************************** - */ - -#ifdef CONFIG_DEVFS_FS - -static void isdn_register_devfs(int k) -{ - char buf[16]; - - sprintf (buf, "isdn/isdnctrl%d", k); - devfs_register(NULL, buf, DEVFS_FL_DEFAULT, - ISDN_MAJOR, ISDN_MINOR_CTRL + k, 0600 | S_IFCHR, - &isdn_fops, NULL); -} - -static void isdn_unregister_devfs(int k) +static void isdn_init_devfs(void) { - devfs_remove("isdn/isdnctrl%d", k); -} + devfs_mk_dir("isdn"); -static void isdn_init_devfs(void) +#ifdef CONFIG_ISDN_PPP { -# ifdef CONFIG_ISDN_PPP int i; -# endif - devfs_mk_dir("isdn"); -# ifdef CONFIG_ISDN_PPP - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - char buf[16]; + for (i = 0; i < ISDN_MAX_CHANNELS; i++) + devfs_mk_cdev(MKDEV(ISDN_MAJOR, ISDN_MINOR_PPP + i), + 0600 | S_IFCHR, "isdn/ippp%d", i); +} +#endif - sprintf (buf, "isdn/ippp%d", i); - devfs_register(NULL, buf, DEVFS_FL_DEFAULT, - ISDN_MAJOR, ISDN_MINOR_PPP + i, - 0600 | S_IFCHR, &isdn_fops, NULL); - } -# endif - - devfs_register(NULL, "isdn/isdninfo", DEVFS_FL_DEFAULT, - ISDN_MAJOR, ISDN_MINOR_STATUS, 0600 | S_IFCHR, - &isdn_fops, NULL); - devfs_register(NULL, "isdn/isdnctrl", DEVFS_FL_DEFAULT, - ISDN_MAJOR, ISDN_MINOR_CTRL, 0600 | S_IFCHR, - &isdn_fops, NULL); + devfs_mk_cdev(MKDEV(ISDN_MAJOR, ISDN_MINOR_STATUS), + 0600 | S_IFCHR, "isdn/isdninfo"); + devfs_mk_cdev(MKDEV(ISDN_MAJOR, ISDN_MINOR_CTRL), + 0600 | S_IFCHR, "isdn/isdnctrl"); } static void isdn_cleanup_devfs(void) { -# ifdef CONFIG_ISDN_PPP +#ifdef CONFIG_ISDN_PPP int i; for (i = 0; i < ISDN_MAX_CHANNELS; i++) devfs_remove("isdn/ippp%d", i); -# endif +#endif devfs_remove("isdn/isdninfo"); devfs_remove("isdn/isdnctrl"); devfs_remove("isdn"); } - -#else /* CONFIG_DEVFS_FS */ -static void isdn_register_devfs(int dummy) -{ -} - -static void isdn_unregister_devfs(int dummy) -{ -} - -static void isdn_init_devfs(void) -{ -} - -static void isdn_cleanup_devfs(void) -{ -} - -#endif /* CONFIG_DEVFS_FS */ /* * Allocate and initialize all data, register modem-devices diff -Nru a/drivers/isdn/i4l/isdn_net_lib.c b/drivers/isdn/i4l/isdn_net_lib.c --- a/drivers/isdn/i4l/isdn_net_lib.c Thu May 15 15:24:33 2003 +++ b/drivers/isdn/i4l/isdn_net_lib.c Thu May 15 15:24:33 2003 @@ -1777,6 +1777,7 @@ printk(KERN_INFO "%s: disconnected\n", idev->name); fsm_change_state(fi, ST_WAIT_DHUP); + return 0; } static int @@ -1898,7 +1899,7 @@ static int isdn_net_handle_event(isdn_net_dev *idev, int pr, void *arg) { - fsm_event(&idev->fi, pr, arg); + return fsm_event(&idev->fi, pr, arg); } static int diff -Nru a/drivers/isdn/i4l/isdn_x25iface.c b/drivers/isdn/i4l/isdn_x25iface.c --- a/drivers/isdn/i4l/isdn_x25iface.c Thu May 15 15:24:37 2003 +++ b/drivers/isdn/i4l/isdn_x25iface.c Thu May 15 15:24:37 2003 @@ -222,6 +222,8 @@ printk(KERN_WARNING "isdn_x25iface_connect_ind while unconfigured %s\n" , MY_DEVNAME(cprot->net_dev) ); + if (skb) + dev_kfree_skb(skb); return -1; } *state_p = WAN_CONNECTED; diff -Nru a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c --- a/drivers/isdn/pcbit/drv.c Thu May 15 15:24:41 2003 +++ b/drivers/isdn/pcbit/drv.c Thu May 15 15:24:41 2003 @@ -1071,6 +1071,7 @@ ptr->msn = kmalloc(len, GFP_ATOMIC); if (!ptr->msn) { printk(KERN_WARNING "kmalloc failed\n"); + kfree(ptr); return; } diff -Nru a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c --- a/drivers/macintosh/adb.c Thu May 15 15:24:46 2003 +++ b/drivers/macintosh/adb.c Thu May 15 15:24:46 2003 @@ -896,8 +896,6 @@ if (register_chrdev(ADB_MAJOR, "adb", &adb_fops)) printk(KERN_ERR "adb: unable to get major %d\n", ADB_MAJOR); else - devfs_register (NULL, "adb", DEVFS_FL_DEFAULT, - ADB_MAJOR, 0, - S_IFCHR | S_IRUSR | S_IWUSR, - &adb_fops, NULL); + devfs_mk_cdev(MKDEV(ADB_MAJOR, 0), + S_IFCHR | S_IRUSR | S_IWUSR, "adb"); } diff -Nru a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c --- a/drivers/macintosh/macserial.c Thu May 15 15:24:45 2003 +++ b/drivers/macintosh/macserial.c Thu May 15 15:24:45 2003 @@ -1932,7 +1932,6 @@ spin_lock_irqsave(&info->lock, flags); if (tty_hung_up_p(filp)) { - MOD_DEC_USE_COUNT; spin_unlock_irqrestore(&info->lock, flags); return; } @@ -1956,7 +1955,6 @@ info->count = 0; } if (info->count) { - MOD_DEC_USE_COUNT; spin_unlock_irqrestore(&info->lock, flags); return; } @@ -2026,7 +2024,6 @@ info->flags &= ~(ZILOG_NORMAL_ACTIVE|ZILOG_CALLOUT_ACTIVE| ZILOG_CLOSING); wake_up_interruptible(&info->close_wait); - MOD_DEC_USE_COUNT; } /* @@ -2233,17 +2230,14 @@ int retval, line; unsigned long page; - MOD_INC_USE_COUNT; line = tty->index; if ((line < 0) || (line >= zs_channels_found)) { - MOD_DEC_USE_COUNT; return -ENODEV; } info = zs_soft + line; #ifdef CONFIG_KGDB if (info->kgdb_channel) { - MOD_DEC_USE_COUNT; return -ENODEV; } #endif @@ -2610,6 +2604,7 @@ memset(&serial_driver, 0, sizeof(struct tty_driver)); serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.owner = THIS_MODULE; serial_driver.driver_name = "macserial"; #ifdef CONFIG_DEVFS_FS serial_driver.name = "tts/"; diff -Nru a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c --- a/drivers/md/dm-ioctl.c Thu May 15 15:24:35 2003 +++ b/drivers/md/dm-ioctl.c Thu May 15 15:24:35 2003 @@ -278,6 +278,7 @@ DMWARN("asked to rename to an already existing name %s -> %s", old, new); up_write(&_hash_lock); + kfree(new_name); return -EBUSY; } @@ -289,6 +290,7 @@ DMWARN("asked to rename a non existent device %s -> %s", old, new); up_write(&_hash_lock); + kfree(new_name); return -ENXIO; } diff -Nru a/drivers/md/dm-target.c b/drivers/md/dm-target.c --- a/drivers/md/dm-target.c Thu May 15 15:24:45 2003 +++ b/drivers/md/dm-target.c Thu May 15 15:24:45 2003 @@ -122,6 +122,8 @@ list_add(&ti->list, &_targets); up_write(&_lock); + if (rv) + kfree(ti); return rv; } diff -Nru a/drivers/md/md.c b/drivers/md/md.c --- a/drivers/md/md.c Thu May 15 15:24:35 2003 +++ b/drivers/md/md.c Thu May 15 15:24:35 2003 @@ -1111,8 +1111,10 @@ static void print_desc(mdp_disk_t *desc) { + char b[BDEVNAME_SIZE]; + printk(" DISK\n", desc->number, - partition_name(MKDEV(desc->major,desc->minor)), + __bdevname(MKDEV(desc->major, desc->minor), b), desc->major,desc->minor,desc->raid_disk,desc->state); } @@ -1294,6 +1296,7 @@ */ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_minor) { + char b[BDEVNAME_SIZE]; int err; mdk_rdev_t *rdev; sector_t size; @@ -1301,7 +1304,7 @@ rdev = (mdk_rdev_t *) kmalloc(sizeof(*rdev), GFP_KERNEL); if (!rdev) { printk(KERN_ERR "md: could not alloc mem for %s!\n", - partition_name(newdev)); + __bdevname(newdev, b)); return ERR_PTR(-ENOMEM); } memset(rdev, 0, sizeof(*rdev)); @@ -1312,7 +1315,7 @@ err = lock_rdev(rdev, newdev); if (err) { printk(KERN_ERR "md: could not lock %s.\n", - partition_name(newdev)); + __bdevname(newdev, b)); goto abort_free; } rdev->desc_nr = -1; @@ -1840,6 +1843,7 @@ static int autostart_array(dev_t startdev) { + char b[BDEVNAME_SIZE]; int err = -EINVAL, i; mdp_super_t *sb = NULL; mdk_rdev_t *start_rdev = NULL, *rdev; @@ -1847,7 +1851,7 @@ start_rdev = md_import_device(startdev, 0, 0); if (IS_ERR(start_rdev)) { printk(KERN_WARNING "md: could not import %s!\n", - partition_name(startdev)); + __bdevname(startdev, b)); return err; } @@ -1884,7 +1888,7 @@ if (IS_ERR(rdev)) { printk(KERN_WARNING "md: could not import %s," " trying to run array nevertheless.\n", - partition_name(dev)); + __bdevname(dev, b)); continue; } list_add(&rdev->same_set, &pending_raid_disks); @@ -2116,6 +2120,7 @@ static int hot_generate_error(mddev_t * mddev, dev_t dev) { + char b[BDEVNAME_SIZE]; struct request_queue *q; mdk_rdev_t *rdev; @@ -2123,7 +2128,7 @@ return -ENODEV; printk(KERN_INFO "md: trying to generate %s error in md%d ... \n", - partition_name(dev), mdidx(mddev)); + __bdevname(dev, b), mdidx(mddev)); rdev = find_rdev(mddev, dev); if (!rdev) { @@ -2151,13 +2156,14 @@ static int hot_remove_disk(mddev_t * mddev, dev_t dev) { + char b[BDEVNAME_SIZE]; mdk_rdev_t *rdev; if (!mddev->pers) return -ENODEV; printk(KERN_INFO "md: trying to remove %s from md%d ... \n", - partition_name(dev), mdidx(mddev)); + __bdevname(dev, b), mdidx(mddev)); rdev = find_rdev(mddev, dev); if (!rdev) @@ -2178,6 +2184,7 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) { + char b[BDEVNAME_SIZE]; int err; unsigned int size; mdk_rdev_t *rdev; @@ -2186,7 +2193,7 @@ return -ENODEV; printk(KERN_INFO "md: trying to hot-add %s to md%d ... \n", - partition_name(dev), mdidx(mddev)); + __bdevname(dev, b), mdidx(mddev)); if (mddev->major_version != 0) { printk(KERN_WARNING "md%d: HOT_ADD may only be used with" @@ -2344,6 +2351,7 @@ static int md_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + char b[BDEVNAME_SIZE]; unsigned int minor; int err = 0; struct hd_geometry *loc = (struct hd_geometry *) arg; @@ -2403,7 +2411,7 @@ err = autostart_array(arg); if (err) { printk(KERN_WARNING "md: autostart %s failed!\n", - partition_name(arg)); + __bdevname(arg, b)); goto abort; } goto done; @@ -3516,6 +3524,7 @@ static void autostart_arrays(void) { + char b[BDEVNAME_SIZE]; mdk_rdev_t *rdev; int i; @@ -3527,7 +3536,7 @@ rdev = md_import_device(dev,0, 0); if (IS_ERR(rdev)) { printk(KERN_ALERT "md: could not import %s!\n", - partition_name(dev)); + __bdevname(dev, b)); continue; } if (rdev->faulty) { diff -Nru a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c --- a/drivers/media/dvb/dvb-core/dvbdev.c Thu May 15 15:24:34 2003 +++ b/drivers/media/dvb/dvb-core/dvbdev.c Thu May 15 15:24:34 2003 @@ -189,7 +189,6 @@ const struct dvb_device *template, void *priv, int type) { u32 id; - char name [20]; struct dvb_device *dvbdev; if (down_interruptible (&dvbdev_register_lock)) @@ -219,12 +218,12 @@ list_add_tail (&dvbdev->list_head, &adap->device_list); - sprintf(name, "dvb/adapter%d%s%d", adap->num, dnames[type], id); - devfs_register(NULL, name, 0, DVB_MAJOR, nums2minor(adap->num, type, id), - S_IFCHR | S_IRUSR | S_IWUSR, dvbdev->fops, dvbdev); + devfs_mk_cdev(MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)), + S_IFCHR | S_IRUSR | S_IWUSR, + "dvb/adapter%d/%s%d", adap->num, dnames[type], id); - dprintk("DVB: register adapter%d/%s @ minor: %i (0x%02x)\n", - adap->num, name, nums2minor(adap->num, type, id), + dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", + adap->num, dnames[type], id, nums2minor(adap->num, type, id), nums2minor(adap->num, type, id)); return 0; @@ -234,7 +233,7 @@ void dvb_unregister_device(struct dvb_device *dvbdev) { if (dvbdev) { - devfs_remove("dvb/adapter%d%s%d", dvbdev->adapter->num, + devfs_remove("dvb/adapter%d/%s%d", dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id); list_del(&dvbdev->list_head); kfree(dvbdev); @@ -322,12 +321,12 @@ int __init init_dvbdev(void) { devfs_mk_dir("dvb"); -#ifndef CONFIG_DVB_DEVFS_ONLY + if(register_chrdev(DVB_MAJOR,"DVB", &dvb_device_fops)) { printk("video_dev: unable to get major %d\n", DVB_MAJOR); return -EIO; } -#endif + return 0; } @@ -335,9 +334,7 @@ static void __exit exit_dvbdev(void) { -#ifndef CONFIG_DVB_DEVFS_ONLY unregister_chrdev(DVB_MAJOR, "DVB"); -#endif devfs_remove("dvb"); } diff -Nru a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c --- a/drivers/media/radio/miropcm20-rds.c Thu May 15 15:24:33 2003 +++ b/drivers/media/radio/miropcm20-rds.c Thu May 15 15:24:33 2003 @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include "miropcm20-rds-core.h" diff -Nru a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c --- a/drivers/media/video/bt819.c Thu May 15 15:24:33 2003 +++ b/drivers/media/video/bt819.c Thu May 15 15:24:33 2003 @@ -167,6 +167,7 @@ decoder = kmalloc(sizeof(struct bt819), GFP_KERNEL); if (decoder == NULL) { MOD_DEC_USE_COUNT; + kfree(client); return -ENOMEM; } diff -Nru a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c --- a/drivers/media/video/bt832.c Thu May 15 15:24:41 2003 +++ b/drivers/media/video/bt832.c Thu May 15 15:24:41 2003 @@ -198,25 +198,9 @@ static int bt832_probe(struct i2c_adapter *adap) { - int rc; - - printk("bt832_probe\n"); - - switch (adap->id) { - case I2C_ALGO_BIT | I2C_HW_B_BT848: - case I2C_ALGO_BIT | I2C_HW_B_RIVA: - case I2C_ALGO_SAA7134: - printk("bt832: probing %s i2c adapter [id=0x%x]\n", - adap->name,adap->id); - rc = i2c_probe(adap, &addr_data, bt832_attach); - break; - default: - printk("bt832: ignoring %s i2c adapter [id=0x%x]\n", - adap->name,adap->id); - rc = 0; - /* nothing */ - } - return rc; + if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) + return i2c_probe(adap, &addr_data, bt832_attach); + return 0; } static int bt832_detach(struct i2c_client *client) diff -Nru a/drivers/media/video/bttv-if.c b/drivers/media/video/bttv-if.c --- a/drivers/media/video/bttv-if.c Thu May 15 15:24:33 2003 +++ b/drivers/media/video/bttv-if.c Thu May 15 15:24:33 2003 @@ -7,7 +7,7 @@ Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) & Marcus Metzler (mocm@thp.uni-koeln.de) - (c) 1999,2000 Gerd Knorr + (c) 1999-2003 Gerd Knorr This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -195,51 +195,21 @@ static int attach_inform(struct i2c_client *client) { struct bttv *btv = i2c_get_adapdata(client->adapter); - int i; - for (i = 0; i < I2C_CLIENTS_MAX; i++) { - if (btv->i2c_clients[i] == NULL) { - btv->i2c_clients[i] = client; - break; - } - } - if (btv->tuner_type != -1) + if (btv->tuner_type != UNSET) bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type); - if (bttv_verbose) - printk("bttv%d: i2c attach [client=%s,%s]\n",btv->nr, - client->dev.name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed"); - return 0; -} - -static int detach_inform(struct i2c_client *client) -{ - struct bttv *btv = i2c_get_adapdata(client->adapter); - int i; - for (i = 0; i < I2C_CLIENTS_MAX; i++) { - if (btv->i2c_clients[i] == client) { - btv->i2c_clients[i] = NULL; - break; - } - } - if (bttv_verbose) - printk("bttv%d: i2c detach [client=%s,%s]\n",btv->nr, - client->dev.name, (i < I2C_CLIENTS_MAX) ? "ok" : "failed"); + if (bttv_debug) + printk("bttv%d: i2c attach [client=%s]\n", + btv->nr, i2c_clientname(client)); return 0; } void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg) { - int i; - - for (i = 0; i < I2C_CLIENTS_MAX; i++) { - if (NULL == btv->i2c_clients[i]) - continue; - if (NULL == btv->i2c_clients[i]->driver->command) - continue; - btv->i2c_clients[i]->driver->command( - btv->i2c_clients[i],cmd,arg); - } + if (0 != btv->i2c_rc) + return; + i2c_clients_command(&btv->i2c_adap, cmd, arg); } void bttv_i2c_call(unsigned int card, unsigned int cmd, void *arg) @@ -260,20 +230,16 @@ }; static struct i2c_adapter bttv_i2c_adap_template = { - .owner = THIS_MODULE, + .owner = THIS_MODULE, + I2C_DEVNAME("bt848"), .id = I2C_HW_B_BT848, + .class = I2C_ADAP_CLASS_TV_ANALOG, .client_register = attach_inform, - .client_unregister = detach_inform, - .dev = { - .name = "bt848", - }, }; static struct i2c_client bttv_i2c_client_template = { - .id = -1, - .dev = { - .name = "bttv internal", - }, + I2C_DEVNAME("bttv internal"), + .id = -1, }; @@ -347,8 +313,8 @@ memcpy(&btv->i2c_client, &bttv_i2c_client_template, sizeof(struct i2c_client)); - sprintf(btv->i2c_adap.dev.name+strlen(btv->i2c_adap.dev.name), - " #%d", btv->nr); + sprintf(btv->i2c_adap.dev.name, "bt848 #%d", btv->nr); + btv->i2c_algo.data = btv; i2c_set_adapdata(&btv->i2c_adap, btv); btv->i2c_adap.algo_data = &btv->i2c_algo; diff -Nru a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h --- a/drivers/media/video/bttv.h Thu May 15 15:24:33 2003 +++ b/drivers/media/video/bttv.h Thu May 15 15:24:33 2003 @@ -243,7 +243,6 @@ /* i2c */ -#define I2C_CLIENTS_MAX 16 extern void bttv_bit_setscl(void *data, int state); extern void bttv_bit_setsda(void *data, int state); extern void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg); diff -Nru a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h --- a/drivers/media/video/bttvp.h Thu May 15 15:24:37 2003 +++ b/drivers/media/video/bttvp.h Thu May 15 15:24:37 2003 @@ -62,6 +62,8 @@ #define RAW_LINES 640 #define RAW_BPL 1024 +#define UNSET (-1U) + /* ---------------------------------------------------------- */ struct bttv_tvnorm @@ -276,7 +278,6 @@ struct i2c_algo_bit_data i2c_algo; struct i2c_client i2c_client; int i2c_state, i2c_rc; - struct i2c_client *i2c_clients[I2C_CLIENTS_MAX]; /* video4linux (1) */ struct video_device video_dev; diff -Nru a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c --- a/drivers/media/video/cpia.c Thu May 15 15:24:41 2003 +++ b/drivers/media/video/cpia.c Thu May 15 15:24:41 2003 @@ -1409,12 +1409,10 @@ LOG("Unable to initialise /proc/cpia\n"); } -#ifdef MODULE -static void proc_cpia_destroy(void) +static void __exit proc_cpia_destroy(void) { remove_proc_entry("cpia", 0); } -#endif /*MODULE*/ #endif /* CONFIG_PROC_FS */ /* ----------------------- debug functions ---------------------- */ diff -Nru a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c --- a/drivers/media/video/dpc7146.c Thu May 15 15:24:37 2003 +++ b/drivers/media/video/dpc7146.c Thu May 15 15:24:37 2003 @@ -96,7 +96,8 @@ static int dpc_probe(struct saa7146_dev* dev) { struct dpc* dpc = 0; - int i = 0; + struct i2c_client *client; + struct list_head *item; dpc = (struct dpc*)kmalloc(sizeof(struct dpc), GFP_KERNEL); if( NULL == dpc ) { @@ -117,12 +118,10 @@ } /* loop through all i2c-devices on the bus and look who is there */ - for(i = 0; i < I2C_CLIENT_MAX; i++) { - if( NULL == dpc->i2c_adapter.clients[i] ) { - continue; - } - if( I2C_SAA7111A == dpc->i2c_adapter.clients[i]->addr ) - dpc->saa7111a = dpc->i2c_adapter.clients[i]; + list_for_each(item,&dpc->i2c_adapter.clients) { + client = list_entry(item, struct i2c_client, list); + if( I2C_SAA7111A == client->addr ) + dpc->saa7111a = client; } /* check if all devices are present */ diff -Nru a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c --- a/drivers/media/video/msp3400.c Thu May 15 15:24:40 2003 +++ b/drivers/media/video/msp3400.c Thu May 15 15:24:40 2003 @@ -1372,7 +1372,7 @@ static int msp_probe(struct i2c_adapter *adap) { - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) + if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, msp_attach); return 0; } diff -Nru a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c --- a/drivers/media/video/mxb.c Thu May 15 15:24:33 2003 +++ b/drivers/media/video/mxb.c Thu May 15 15:24:33 2003 @@ -208,7 +208,8 @@ static int mxb_probe(struct saa7146_dev* dev) { struct mxb* mxb = 0; - int i = 0; + struct i2c_client *client; + struct list_head *item; request_module("tuner"); request_module("tea6420"); @@ -235,22 +236,20 @@ } /* loop through all i2c-devices on the bus and look who is there */ - for(i = 0; i < I2C_CLIENT_MAX; i++) { - if( NULL == mxb->i2c_adapter.clients[i] ) { - continue; - } - if( I2C_TEA6420_1 == mxb->i2c_adapter.clients[i]->addr ) - mxb->tea6420_1 = mxb->i2c_adapter.clients[i]; - if( I2C_TEA6420_2 == mxb->i2c_adapter.clients[i]->addr ) - mxb->tea6420_2 = mxb->i2c_adapter.clients[i]; - if( I2C_TEA6415C_2 == mxb->i2c_adapter.clients[i]->addr ) - mxb->tea6415c = mxb->i2c_adapter.clients[i]; - if( I2C_TDA9840 == mxb->i2c_adapter.clients[i]->addr ) - mxb->tda9840 = mxb->i2c_adapter.clients[i]; - if( I2C_SAA7111A == mxb->i2c_adapter.clients[i]->addr ) - mxb->saa7111a = mxb->i2c_adapter.clients[i]; - if( 0x60 == mxb->i2c_adapter.clients[i]->addr ) - mxb->tuner = mxb->i2c_adapter.clients[i]; + list_for_each(item,&mxb->i2c_adapter.clients) { + client = list_entry(item, struct i2c_client, list); + if( I2C_TEA6420_1 == client->addr ) + mxb->tea6420_1 = client; + if( I2C_TEA6420_2 == client->addr ) + mxb->tea6420_2 = client; + if( I2C_TEA6415C_2 == client->addr ) + mxb->tea6415c = client; + if( I2C_TDA9840 == client->addr ) + mxb->tda9840 = client; + if( I2C_SAA7111A == client->addr ) + mxb->saa7111a = client; + if( 0x60 == client->addr ) + mxb->tuner = client; } /* check if all devices are present */ diff -Nru a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c --- a/drivers/media/video/saa5249.c Thu May 15 15:24:42 2003 +++ b/drivers/media/video/saa5249.c Thu May 15 15:24:42 2003 @@ -224,12 +224,8 @@ static int saa5249_probe(struct i2c_adapter *adap) { - /* Only attach these chips to the BT848 bus for now */ - - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) - { + if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, saa5249_attach); - } return 0; } diff -Nru a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c --- a/drivers/media/video/saa7134/saa7134-i2c.c Thu May 15 15:24:34 2003 +++ b/drivers/media/video/saa7134/saa7134-i2c.c Thu May 15 15:24:34 2003 @@ -334,19 +334,16 @@ static struct i2c_adapter saa7134_adap_template = { .owner = THIS_MODULE, + I2C_DEVNAME("saa7134"), .id = I2C_ALGO_SAA7134, + .class = I2C_ADAP_CLASS_TV_ANALOG, .algo = &saa7134_algo, .client_register = attach_inform, - .dev = { - .name = "saa7134", - }, }; static struct i2c_client saa7134_client_template = { - .id = -1, - .dev = { - .name = "saa7134 internal", - }, + I2C_DEVNAME("saa7134 internal"), + .id = -1, }; /* ----------------------------------------------------------- */ @@ -399,22 +396,13 @@ void saa7134_i2c_call_clients(struct saa7134_dev *dev, unsigned int cmd, void *arg) { - int i; - - for (i = 0; i < I2C_CLIENT_MAX; i++) { - if (NULL == dev->i2c_adap.clients[i]) - continue; - if (NULL == dev->i2c_adap.clients[i]->driver->command) - continue; - dev->i2c_adap.clients[i]->driver->command - (dev->i2c_adap.clients[i],cmd,arg); - } + i2c_clients_command(&dev->i2c_adap, cmd, arg); } int saa7134_i2c_register(struct saa7134_dev *dev) { dev->i2c_adap = saa7134_adap_template; - strncpy(dev->i2c_adap.dev.name, dev->name, DEVICE_NAME_SIZE); + strcpy(dev->i2c_adap.dev.name,dev->name); dev->i2c_adap.algo_data = dev; i2c_add_adapter(&dev->i2c_adap); diff -Nru a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c --- a/drivers/media/video/tda7432.c Thu May 15 15:24:41 2003 +++ b/drivers/media/video/tda7432.c Thu May 15 15:24:41 2003 @@ -340,7 +340,7 @@ static int tda7432_probe(struct i2c_adapter *adap) { - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) + if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, tda7432_attach); return 0; } diff -Nru a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c --- a/drivers/media/video/tda9875.c Thu May 15 15:24:37 2003 +++ b/drivers/media/video/tda9875.c Thu May 15 15:24:37 2003 @@ -273,7 +273,7 @@ static int tda9875_probe(struct i2c_adapter *adap) { - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) + if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, tda9875_attach); return 0; } diff -Nru a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c --- a/drivers/media/video/tda9887.c Thu May 15 15:24:32 2003 +++ b/drivers/media/video/tda9887.c Thu May 15 15:24:32 2003 @@ -368,23 +368,9 @@ static int tda9887_probe(struct i2c_adapter *adap) { - int rc; - - switch (adap->id) { - case I2C_ALGO_BIT | I2C_HW_B_BT848: - case I2C_ALGO_BIT | I2C_HW_B_RIVA: - case I2C_ALGO_SAA7134: - printk("tda9887: probing %s i2c adapter [id=0x%x]\n", - adap->dev.name,adap->id); - rc = i2c_probe(adap, &addr_data, tda9887_attach); - break; - default: - printk("tda9887: ignoring %s i2c adapter [id=0x%x]\n", - adap->dev.name,adap->id); - rc = 0; - /* nothing */ - } - return rc; + if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) + return i2c_probe(adap, &addr_data, tda9887_attach); + return 0; } static int tda9887_detach(struct i2c_client *client) diff -Nru a/drivers/media/video/tuner.c b/drivers/media/video/tuner.c --- a/drivers/media/video/tuner.c Thu May 15 15:24:43 2003 +++ b/drivers/media/video/tuner.c Thu May 15 15:24:43 2003 @@ -817,29 +817,15 @@ static int tuner_probe(struct i2c_adapter *adap) { - int rc; - if (0 != addr) { normal_i2c_range[0] = addr; normal_i2c_range[1] = addr; } this_adap = 0; - switch (adap->id) { - case I2C_ALGO_BIT | I2C_HW_B_BT848: - case I2C_ALGO_BIT | I2C_HW_B_RIVA: - case I2C_ALGO_SAA7134: - case I2C_ALGO_SAA7146: - printk("tuner: probing %s i2c adapter [id=0x%x]\n", - adap->dev.name,adap->id); - rc = i2c_probe(adap, &addr_data, tuner_attach); - break; - default: - printk("tuner: ignoring %s i2c adapter [id=0x%x]\n", - adap->dev.name,adap->id); - rc = 0; - /* nothing */ - } - return rc; + + if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) + return i2c_probe(adap, &addr_data, tuner_attach); + return 0; } static int tuner_detach(struct i2c_client *client) diff -Nru a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c --- a/drivers/media/video/tvaudio.c Thu May 15 15:24:36 2003 +++ b/drivers/media/video/tvaudio.c Thu May 15 15:24:36 2003 @@ -1408,14 +1408,9 @@ static int chip_probe(struct i2c_adapter *adap) { - switch (adap->id) { - case I2C_ALGO_BIT | I2C_HW_B_BT848: - case I2C_ALGO_BIT | I2C_HW_B_RIVA: + if (adap->class & I2C_ADAP_CLASS_TV_ANALOG) return i2c_probe(adap, &addr_data, chip_attach); - default: - /* ignore this i2c bus */ - return 0; - } + return 0; } static int chip_detach(struct i2c_client *client) diff -Nru a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c --- a/drivers/media/video/tvmixer.c Thu May 15 15:24:43 2003 +++ b/drivers/media/video/tvmixer.c Thu May 15 15:24:43 2003 @@ -217,8 +217,9 @@ .owner = THIS_MODULE, .name = "tv card mixer driver", .id = I2C_DRIVERID_TVMIXER, - .flags = I2C_DF_DUMMY, + .flags = I2C_DF_NOTIFY, .attach_adapter = tvmixer_adapters, + .detach_adapter = tvmixer_adapters, .detach_client = tvmixer_clients, }; @@ -234,14 +235,15 @@ static int tvmixer_adapters(struct i2c_adapter *adap) { - int i; + struct list_head *item; + struct i2c_client *client; if (debug) printk("tvmixer: adapter %s\n",adap->dev.name); - for (i=0; iclients[i]) - continue; - tvmixer_clients(adap->clients[i]); + + list_for_each(item,&adap->clients) { + client = list_entry(item, struct i2c_client, list); + tvmixer_clients(client); } return 0; } @@ -252,19 +254,15 @@ int i,minor; /* TV card ??? */ - switch (client->adapter->id) { - case I2C_ALGO_BIT | I2C_HW_B_BT848: - case I2C_ALGO_BIT | I2C_HW_B_RIVA: - /* ok, have a look ... */ - break; - default: + if (!(client->adapter->class & I2C_ADAP_CLASS_TV_ANALOG)) { /* ignore that one */ if (debug) printk("tvmixer: %s is not a tv card\n", client->adapter->dev.name); return -1; } - printk("tvmixer: debug: %s\n",client->dev.name); + if (debug) + printk("tvmixer: debug: %s\n",client->dev.name); /* unregister ?? */ for (i = 0; i < DEV_MAX; i++) { diff -Nru a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c --- a/drivers/media/video/videodev.c Thu May 15 15:24:33 2003 +++ b/drivers/media/video/videodev.c Thu May 15 15:24:33 2003 @@ -311,8 +311,10 @@ return; p = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, video_dev_proc_entry); - if (!p) + if (!p) { + kfree(d); return; + } p->data = vfd; p->read_proc = videodev_proc_read; @@ -427,8 +429,8 @@ up(&videodev_lock); sprintf(vfd->devfs_name, "v4l/%s%d", name_base, i - base); - devfs_register(NULL, vfd->devfs_name, 0, VIDEO_MAJOR, vfd->minor, - S_IFCHR | S_IRUSR | S_IWUSR, &video_fops, NULL); + devfs_mk_cdev(MKDEV(VIDEO_MAJOR, vfd->minor), + S_IFCHR | S_IRUSR | S_IWUSR, vfd->devfs_name); init_MUTEX(&vfd->lock); #ifdef CONFIG_VIDEO_PROC_FS diff -Nru a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c --- a/drivers/message/fusion/mptscsih.c Thu May 15 15:24:37 2003 +++ b/drivers/message/fusion/mptscsih.c Thu May 15 15:24:37 2003 @@ -3631,8 +3631,30 @@ /* see mptscsih.h */ #ifdef MPT_SCSIHOST_NEED_ENTRY_EXIT_HOOKUPS - static Scsi_Host_Template driver_template = MPT_SCSIHOST; -# include "../../scsi/scsi_module.c" +static Scsi_Host_Template driver_template = { + .proc_name = "mptscsih", + .proc_info = x_scsi_proc_info, + .name = "MPT SCSI Host", + .detect = x_scsi_detect, + .release = x_scsi_release, + .info = x_scsi_info, + .queuecommand = x_scsi_queuecommand, + .slave_alloc = x_scsi_slave_alloc, + .slave_configure = x_scsi_slave_configure, + .slave_destroy = x_scsi_slave_destroy, + .eh_abort_handler = x_scsi_abort, + .eh_device_reset_handler = x_scsi_dev_reset, + .eh_bus_reset_handler = x_scsi_bus_reset, + .eh_host_reset_handler = x_scsi_host_reset, + .bios_param = x_scsi_bios_param, + .can_queue = MPT_SCSI_CAN_QUEUE, + .this_id = -1, + .sg_tablesize = MPT_SCSI_SG_DEPTH, + .max_sectors = MPT_SCSI_MAX_SECTORS, + .cmd_per_lun = MPT_SCSI_CMD_PER_LUN, + .use_clustering = ENABLE_CLUSTERING, +}; +#include "../../scsi/scsi_module.c" #endif /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff -Nru a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h --- a/drivers/message/fusion/mptscsih.h Thu May 15 15:24:46 2003 +++ b/drivers/message/fusion/mptscsih.h Thu May 15 15:24:46 2003 @@ -201,36 +201,6 @@ extern void x_scsi_slave_destroy(Scsi_Device *); extern int x_scsi_proc_info(char *, char **, off_t, int, int, int); -#define PROC_SCSI_DECL .proc_name = "mptscsih", - -#define MPT_SCSIHOST { \ - PROC_SCSI_DECL \ - .proc_info = x_scsi_proc_info, \ - .name = "MPT SCSI Host", \ - .detect = x_scsi_detect, \ - .release = x_scsi_release, \ - .info = x_scsi_info, \ - .command = NULL, \ - .queuecommand = x_scsi_queuecommand, \ - .slave_alloc = x_scsi_slave_alloc, \ - .slave_configure = x_scsi_slave_configure, \ - .slave_destroy = x_scsi_slave_destroy, \ - .eh_strategy_handler = NULL, \ - .eh_abort_handler = x_scsi_abort, \ - .eh_device_reset_handler = x_scsi_dev_reset, \ - .eh_bus_reset_handler = x_scsi_bus_reset, \ - .eh_host_reset_handler = x_scsi_host_reset, \ - .bios_param = x_scsi_bios_param, \ - .can_queue = MPT_SCSI_CAN_QUEUE, \ - .this_id = -1, \ - .sg_tablesize = MPT_SCSI_SG_DEPTH, \ - .max_sectors = MPT_SCSI_MAX_SECTORS, \ - .cmd_per_lun = MPT_SCSI_CMD_PER_LUN, \ - .unchecked_isa_dma = 0, \ - .use_clustering = ENABLE_CLUSTERING, \ -} - - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* include/scsi/scsi.h may not be quite complete... */ diff -Nru a/drivers/message/i2o/i2o_core.c b/drivers/message/i2o/i2o_core.c --- a/drivers/message/i2o/i2o_core.c Thu May 15 15:24:40 2003 +++ b/drivers/message/i2o/i2o_core.c Thu May 15 15:24:40 2003 @@ -2018,15 +2018,14 @@ { printk(KERN_ERR "%s: Unable to set SysTab (status=%#x).\n", iop->name, -ret); - kfree(privbuf); } else { dprintk(KERN_INFO "%s: SysTab set.\n", iop->name); - kfree(privbuf); } i2o_status_get(iop); // Entered READY state + kfree(privbuf); return ret; } diff -Nru a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c --- a/drivers/mtd/chips/cfi_cmdset_0001.c Thu May 15 15:24:35 2003 +++ b/drivers/mtd/chips/cfi_cmdset_0001.c Thu May 15 15:24:35 2003 @@ -203,6 +203,7 @@ if (!mtd->eraseregions) { printk(KERN_ERR "Failed to allocate memory for MTD erase region info\n"); kfree(cfi->cmdset_priv); + kfree(mtd); return NULL; } @@ -227,6 +228,7 @@ printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize); kfree(mtd->eraseregions); kfree(cfi->cmdset_priv); + kfree(mtd); return NULL; } diff -Nru a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c --- a/drivers/mtd/chips/cfi_cmdset_0002.c Thu May 15 15:24:37 2003 +++ b/drivers/mtd/chips/cfi_cmdset_0002.c Thu May 15 15:24:37 2003 @@ -174,6 +174,7 @@ if (!mtd->eraseregions) { printk(KERN_WARNING "Failed to allocate memory for MTD erase region info\n"); kfree(cfi->cmdset_priv); + kfree(mtd); return NULL; } @@ -197,6 +198,7 @@ printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize); kfree(mtd->eraseregions); kfree(cfi->cmdset_priv); + kfree(mtd); return NULL; } #if 0 diff -Nru a/drivers/mtd/chips/sharp.c b/drivers/mtd/chips/sharp.c --- a/drivers/mtd/chips/sharp.c Thu May 15 15:24:39 2003 +++ b/drivers/mtd/chips/sharp.c Thu May 15 15:24:39 2003 @@ -116,8 +116,10 @@ return NULL; sharp = kmalloc(sizeof(*sharp), GFP_KERNEL); - if(!sharp) + if(!sharp) { + kfree(mtd); return NULL; + } memset(mtd, 0, sizeof(*mtd)); diff -Nru a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c --- a/drivers/mtd/maps/sa1100-flash.c Thu May 15 15:24:35 2003 +++ b/drivers/mtd/maps/sa1100-flash.c Thu May 15 15:24:35 2003 @@ -337,7 +337,7 @@ #ifdef CONFIG_SA1100_FREEBIRD static struct mtd_partition freebird_partitions[] = { -#if CONFIG_SA1100_FREEBIRD_NEW +#ifdef CONFIG_SA1100_FREEBIRD_NEW { .name = "firmware", .size = 0x00040000, diff -Nru a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c --- a/drivers/mtd/mtdchar.c Thu May 15 15:24:41 2003 +++ b/drivers/mtd/mtdchar.c Thu May 15 15:24:41 2003 @@ -461,22 +461,12 @@ static void mtd_notify_add(struct mtd_info* mtd) { - char name[16]; - if (!mtd) return; - - sprintf(name, "mtd/%d", mtd->index); - devfs_register(NULL, name, - DEVFS_FL_DEFAULT, MTD_CHAR_MAJOR, mtd->index*2, - S_IFCHR | S_IRUGO | S_IWUGO, - &mtd_fops, NULL); - - sprintf(name, "mtd/%dro", mtd->index); - devfs_register(NULL, name, - DEVFS_FL_DEFAULT, MTD_CHAR_MAJOR, mtd->index*2+1, - S_IFCHR | S_IRUGO | S_IWUGO, - &mtd_fops, NULL); + devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2), + S_IFCHR | S_IRUGO | S_IWUGO, "mtd/%d", mtd->index); + devfs_mk_cdev(MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1), + S_IFCHR | S_IRUGO | S_IWUGO, "mtd/%dro", mtd->index); } static void mtd_notify_remove(struct mtd_info* mtd) diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig --- a/drivers/net/Kconfig Thu May 15 15:24:43 2003 +++ b/drivers/net/Kconfig Thu May 15 15:24:43 2003 @@ -158,7 +158,7 @@ config NET_SB1000 tristate "General Instruments Surfboard 1000" - depends on NETDEVICES && ISAPNP + depends on NETDEVICES && PNP ---help--- This is a driver for the General Instrument (also known as NextLevel) SURFboard 1000 internal diff -Nru a/drivers/net/acenic.c b/drivers/net/acenic.c --- a/drivers/net/acenic.c Thu May 15 15:24:38 2003 +++ b/drivers/net/acenic.c Thu May 15 15:24:38 2003 @@ -1871,7 +1871,9 @@ } else { printk(KERN_DEBUG "%s: BUG... transmitter died. Kicking it.\n", dev->name); +#if 0 netif_wake_queue(dev); +#endif } } diff -Nru a/drivers/net/bmac.c b/drivers/net/bmac.c --- a/drivers/net/bmac.c Thu May 15 15:24:33 2003 +++ b/drivers/net/bmac.c Thu May 15 15:24:33 2003 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -82,6 +83,7 @@ int opened; unsigned short hash_use_count[64]; unsigned short hash_table_mask[4]; + spinlock_t lock; struct net_device *next_bmac; }; @@ -159,9 +161,9 @@ static void bmac_init_registers(struct net_device *dev); static void bmac_enable_and_reset_chip(struct net_device *dev); static int bmac_set_address(struct net_device *dev, void *addr); -static void bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs); -static void bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs); -static void bmac_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t bmac_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs); static void bmac_set_timeout(struct net_device *dev); static void bmac_tx_timeout(unsigned long data); static int bmac_proc_info ( char *buffer, char **start, off_t offset, int length); @@ -485,7 +487,7 @@ case PBOOK_SLEEP_NOW: netif_device_detach(dev); /* prolly should wait for dma to finish & turn off the chip */ - save_flags(flags); cli(); + spin_lock_irqsave(&bp->lock, flags); if (bp->timeout_active) { del_timer(&bp->tx_timeout); bp->timeout_active = 0; @@ -494,7 +496,7 @@ disable_irq(bp->tx_dma_intr); disable_irq(bp->rx_dma_intr); bp->sleeping = 1; - restore_flags(flags); + spin_unlock_irqrestore(&bp->lock, flags); if (bp->opened) { volatile struct dbdma_regs *rd = bp->rx_dma; volatile struct dbdma_regs *td = bp->tx_dma; @@ -539,13 +541,14 @@ static int bmac_set_address(struct net_device *dev, void *addr) { + struct bmac_data *bp = (struct bmac_data *) dev->priv; unsigned char *p = addr; unsigned short *pWord16; unsigned long flags; int i; XXDEBUG(("bmac: enter set_address\n")); - save_flags(flags); cli(); + spin_lock_irqsave(&bp->lock, flags); for (i = 0; i < 6; ++i) { dev->dev_addr[i] = p[i]; @@ -556,7 +559,7 @@ bmwrite(dev, MADD1, *pWord16++); bmwrite(dev, MADD2, *pWord16); - restore_flags(flags); + spin_unlock_irqrestore(&bp->lock, flags); XXDEBUG(("bmac: exit set_address\n")); return 0; } @@ -566,8 +569,7 @@ struct bmac_data *bp = (struct bmac_data *) dev->priv; unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&bp->lock, flags); if (bp->timeout_active) del_timer(&bp->tx_timeout); bp->tx_timeout.expires = jiffies + TX_TIMEOUT; @@ -575,7 +577,7 @@ bp->tx_timeout.data = (unsigned long) dev; add_timer(&bp->tx_timeout); bp->timeout_active = 1; - restore_flags(flags); + spin_unlock_irqrestore(&bp->lock, flags); } static void @@ -703,7 +705,7 @@ static int rxintcount; -static void bmac_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t bmac_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; struct bmac_data *bp = (struct bmac_data *) dev->priv; @@ -715,7 +717,7 @@ int last; unsigned long flags; - save_flags(flags); cli(); + spin_lock_irqsave(&bp->lock, flags); if (++rxintcount < 10) { XXDEBUG(("bmac_rxdma_intr\n")); @@ -769,18 +771,18 @@ bp->rx_empty = i; } - restore_flags(flags); - dbdma_continue(rd); + spin_unlock_irqrestore(&bp->lock, flags); if (rxintcount < 10) { XXDEBUG(("bmac_rxdma_intr done\n")); } + return IRQ_HANDLED; } static int txintcount; -static void bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; struct bmac_data *bp = (struct bmac_data *) dev->priv; @@ -788,7 +790,7 @@ int stat; unsigned long flags; - save_flags(flags); cli(); + spin_lock_irqsave(&bp->lock, flags); if (txintcount++ < 10) { XXDEBUG(("bmac_txdma_intr\n")); @@ -824,13 +826,14 @@ break; } - restore_flags(flags); + spin_unlock_irqrestore(&bp->lock, flags); if (txintcount < 10) { XXDEBUG(("bmac_txdma_intr done->bmac_start\n")); } bmac_start(dev); + return IRQ_HANDLED; } static struct net_device_stats *bmac_stats(struct net_device *dev) @@ -1096,7 +1099,7 @@ static int miscintcount; -static void bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; struct bmac_data *bp = (struct bmac_data *)dev->priv; @@ -1117,6 +1120,7 @@ if (status & TxErrorMask) bp->stats.tx_errors++; if (status & TxUnderrun) bp->stats.tx_fifo_errors++; if (status & TxNormalCollExp) bp->stats.collisions++; + return IRQ_HANDLED; } /* @@ -1249,7 +1253,7 @@ struct sk_buff *skb; unsigned char *data; - save_flags(flags); cli(); + spin_lock_irqsave(&bp->lock, flags); bmac_enable_and_reset_chip(dev); bmac_init_tx_ring(bp); bmac_init_rx_ring(bp); @@ -1270,7 +1274,7 @@ memcpy(data+6, dev->dev_addr, 6); bmac_transmit_packet(skb, dev); } - restore_flags(flags); + spin_unlock_irqrestore(&bp->lock, flags); } static int __init bmac_probe(void) @@ -1336,6 +1340,7 @@ bp = (struct bmac_data *) dev->priv; SET_MODULE_OWNER(dev); bp->node = bmac; + spin_lock_init(&bp->lock); if (!request_OF_resource(bmac, 0, " (bmac)")) { printk(KERN_ERR "BMAC: can't request IO resource !\n"); @@ -1522,7 +1527,7 @@ if (bp->sleeping) return; - save_flags(flags); cli(); + spin_lock_irqsave(&bp->lock, flags); while (1) { i = bp->tx_fill + 1; if (i >= N_TX_RING) @@ -1534,7 +1539,7 @@ break; bmac_transmit_packet(skb, dev); } - restore_flags(flags); + spin_unlock_irqrestore(&bp->lock, flags); } static int @@ -1558,7 +1563,7 @@ int i; XXDEBUG(("bmac: tx_timeout called\n")); - save_flags(flags); cli(); + spin_lock_irqsave(&bp->lock, flags); bp->timeout_active = 0; /* update various counters */ @@ -1614,7 +1619,7 @@ oldConfig = bmread(dev, TXCFG); bmwrite(dev, TXCFG, oldConfig | TxMACEnable ); - restore_flags(flags); + spin_unlock_irqrestore(&bp->lock, flags); } #if 0 diff -Nru a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c --- a/drivers/net/cs89x0.c Thu May 15 15:24:42 2003 +++ b/drivers/net/cs89x0.c Thu May 15 15:24:42 2003 @@ -1630,16 +1630,21 @@ } -static int set_mac_address(struct net_device *dev, void *addr) +static int set_mac_address(struct net_device *dev, void *p) { int i; + struct sockaddr *addr = p; + if (netif_running(dev)) return -EBUSY; + + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + if (net_debug) { printk("%s: Setting MAC address to ", dev->name); - for (i = 0; i < 6; i++) - printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]); + for (i = 0; i < dev->addr_len; i++) + printk(" %2.2x", dev->dev_addr[i]); printk(".\n"); } /* set the Ethernet address */ diff -Nru a/drivers/net/depca.c b/drivers/net/depca.c --- a/drivers/net/depca.c Thu May 15 15:24:39 2003 +++ b/drivers/net/depca.c Thu May 15 15:24:39 2003 @@ -230,6 +230,7 @@ by acme@conectiva.com.br 0.54 08-Nov-01 use library crc32 functions by Matt_Domsch@dell.com + 0.55 01-Mar-03 Use EISA/sysfs framework ========================================================================= */ @@ -263,6 +264,11 @@ #include #endif +#ifdef CONFIG_EISA +#include +#include +#endif + #include "depca.h" static char version[] __initdata = "depca.c:v0.53 2001/1/12 davies@maniac.ultranet.com\n"; @@ -328,6 +334,25 @@ DEPCA, de100, de101, de200, de201, de202, de210, de212, de422, unknown } adapter; +#ifdef CONFIG_EISA +struct eisa_device_id depca_eisa_ids[] = { + { "DEC4220" }, + { "" } +}; + +static int depca_eisa_probe (struct device *device); +static int depca_eisa_remove (struct device *device); + +struct eisa_driver depca_eisa_driver = { + .id_table = depca_eisa_ids, + .driver = { + .name = "depca", + .probe = depca_eisa_probe, + .remove = __devexit_p (depca_eisa_remove) + } +}; +#endif + /* ** Miscellaneous info... */ @@ -388,6 +413,8 @@ void *rx_buff[NUM_RX_DESC]; /* CPU virt address of sh'd memory buffs */ void *tx_buff[NUM_TX_DESC]; /* CPU virt address of sh'd memory buffs */ void *sh_mem; /* CPU mapped virt address of device RAM */ + u_long mem_start; /* Bus address of device RAM (before remap) */ + u_long mem_len; /* device memory size */ /* Device address space fields */ u_long device_ram_start; /* Start of RAM in device addr space */ /* Offsets used in both address spaces */ @@ -450,10 +477,8 @@ static void DepcaSignature(char *name, u_long paddr); static int DevicePresent(u_long ioaddr); static int get_hw_addr(struct net_device *dev); -static int EISA_signature(char *name, s32 eisa_id); static void SetMulticastFilter(struct net_device *dev); static void isa_probe(struct net_device *dev, u_long iobase); -static void eisa_probe(struct net_device *dev, u_long iobase); #ifdef CONFIG_MCA static void mca_probe(struct net_device *dev, u_long iobase); #endif @@ -503,7 +528,9 @@ mca_probe(dev, iobase); #endif isa_probe(dev, iobase); - eisa_probe(dev, iobase); +#ifdef CONFIG_EISA + eisa_driver_register (&depca_eisa_driver); +#endif if ((tmp == num_depcas) && (iobase != 0) && loading_module) { printk("%s: depca_probe() cannot find device at 0x%04lx.\n", dev->name, iobase); @@ -530,6 +557,7 @@ int i, j, offset, netRAM, mem_len, status = 0; s16 nicsr; u_long mem_start = 0, mem_base[] = DEPCA_RAM_BASE_ADDRESSES; + int is_eisa = ((ioaddr & 0x0fff) == DEPCA_EISA_IO_PORTS); STOP_DEPCA; @@ -555,7 +583,7 @@ if (mca_slot != -1) { printk("%s: %s at 0x%04lx (MCA slot %d)", dev->name, name, ioaddr, mca_slot); - } else if ((ioaddr & 0x0fff) == DEPCA_EISA_IO_PORTS) { /* EISA slot address */ + } else if (is_eisa) { /* EISA slot address */ printk("%s: %s at 0x%04lx (EISA slot %d)", dev->name, name, ioaddr, (int) ((ioaddr >> 12) & 0x0f)); } else { /* ISA port address */ printk("%s: %s at 0x%04lx", dev->name, name, ioaddr); @@ -600,9 +628,11 @@ } /* Define the device private memory */ - dev->priv = (void *) kmalloc(sizeof(struct depca_private), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; + if (!is_eisa) { + dev->priv = (void *) kmalloc(sizeof(struct depca_private), GFP_KERNEL); + if (dev->priv == NULL) + return -ENOMEM; + } lp = (struct depca_private *) dev->priv; memset((char *) dev->priv, 0, sizeof(struct depca_private)); lp->adapter = adapter; @@ -610,18 +640,23 @@ lp->lock = SPIN_LOCK_UNLOCKED; sprintf(lp->adapter_name, "%s (%s)", name, dev->name); status = -EBUSY; - if (!request_region(ioaddr, DEPCA_TOTAL_SIZE, lp->adapter_name)) { - printk(KERN_ERR "depca: I/O resource 0x%x @ 0x%lx busy\n", DEPCA_TOTAL_SIZE, ioaddr); - goto out_priv; - } /* Initialisation Block */ - lp->sh_mem = ioremap(mem_start, mem_len); + if (!request_mem_region (mem_start, mem_len, lp->adapter_name)) { + printk(KERN_ERR "depca: cannot request ISA memory, aborting\n"); + goto out_priv; + } + status = -EIO; + lp->sh_mem = ioremap(mem_start, mem_len); if (lp->sh_mem == NULL) { printk(KERN_ERR "depca: cannot remap ISA memory, aborting\n"); - goto out_region; + release_mem_region (mem_start, mem_len); + goto out_priv; } + + lp->mem_start = mem_start; + lp->mem_len = mem_len; lp->device_ram_start = mem_start & LA_MASK; offset = 0; @@ -703,7 +738,7 @@ status = -ENXIO; if (!irqnum) { printk(" and failed to detect IRQ line.\n"); - goto out_region; + goto out_priv; } else { for (dev->irq = 0, i = 0; (depca_irq[i]) && (!dev->irq); i++) if (irqnum == depca_irq[i]) { @@ -714,7 +749,7 @@ status = -ENXIO; if (!dev->irq) { printk(" but incorrect IRQ line detected.\n"); - goto out_region; + goto out_priv; } } #endif /* MODULE */ @@ -739,13 +774,16 @@ dev->mem_start = 0; /* Fill in the generic field of the device structure. */ - ether_setup(dev); + if (!is_eisa) + ether_setup(dev); return 0; - out_region: - release_region(ioaddr, DEPCA_TOTAL_SIZE); out_priv: - kfree(dev->priv); - dev->priv = NULL; + if (!is_eisa) { + kfree(dev->priv); + dev->priv = NULL; + } else { + unregister_netdev (dev); + } return status; } @@ -1351,31 +1389,35 @@ ** Get everything allocated and initialized... (almost just ** like the ISA and EISA probes) */ + if (!request_region (iobase, DEPCA_TOTAL_SIZE, "depca")) { + if (autoprobed) + printk(KERN_WARNING "%s: region already allocated at 0x%04lx.\n", dev->name, iobase); + goto next; + } if (DevicePresent(iobase) != 0) { /* ** If the MCA configuration says the card should be here, ** it really should be here. */ printk(KERN_ERR "%s: MCA reports card at 0x%lx but it is not responding.\n", dev->name, iobase); + goto release_next; } - if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) { - if ((dev = alloc_device(dev, iobase)) != NULL) { - dev->irq = irq; - if (depca_hw_init(dev, iobase, slot) == 0) { - /* - ** Adapter initialized correctly: Name it in - ** /proc/mca. - */ - mca_set_adapter_name(slot, "DE210/212 Ethernet Adapter"); - mca_mark_as_used(slot); - num_depcas++; - } - num_eth++; - } - } else if (autoprobed) { - printk(KERN_WARNING "%s: region already allocated at 0x%04lx.\n", dev->name, iobase); - } + if (!(dev = alloc_device(dev, iobase))) + goto release_next; + + num_eth++; + dev->irq = irq; + if (depca_hw_init(dev, iobase, slot)) + goto release_next; + + /* + ** Adapter initialized correctly: Name it in + ** /proc/mca. + */ + mca_set_adapter_name(slot, "DE210/212 Ethernet Adapter"); + mca_mark_as_used(slot); + num_depcas++; /* ** If this is a probe by a module, return after setting up the @@ -1385,9 +1427,15 @@ return; /* - ** Set up to check the next slot and loop. + ** Set up to check the next slot and loop. */ slot++; + continue; + + release_next: + release_region (iobase, DEPCA_TOTAL_SIZE); + next: + slot++; } } @@ -1418,69 +1466,100 @@ } for (; (i < maxSlots) && (dev != NULL) && ports[i]; i++) { - if (check_region(ports[i], DEPCA_TOTAL_SIZE) == 0) { - if (DevicePresent(ports[i]) == 0) { - if ((dev = alloc_device(dev, ports[i])) != NULL) { - if (depca_hw_init(dev, ports[i], -1) == 0) { - num_depcas++; - } - num_eth++; - } - } - } else if (autoprobed) { - printk("%s: region already allocated at 0x%04x.\n", dev->name, ports[i]); + if (!request_region (ports[i], DEPCA_TOTAL_SIZE, "depca")) { + if (autoprobed) + printk("%s: region already allocated at 0x%04x.\n", dev->name, ports[i]); + continue; } + + if (DevicePresent(ports[i])) { + release_region (ports[i], DEPCA_TOTAL_SIZE); + continue; + } + + if (!(dev = alloc_device(dev, ports[i]))) { + release_region (ports[i], DEPCA_TOTAL_SIZE); + continue; + } + + num_eth++; + + if (depca_hw_init(dev, ports[i], -1)) { + release_region (ports[i], DEPCA_TOTAL_SIZE); + continue; + } + + num_depcas++; } return; } /* -** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually -** the motherboard. Upto 15 EISA devices are supported. +** EISA callbacks from sysfs. */ -static void __init eisa_probe(struct net_device *dev, u_long ioaddr) + +#ifdef CONFIG_EISA +static int __init depca_eisa_probe (struct device *device) { - int i, maxSlots; + struct eisa_device *edev; + struct net_device *dev; u_long iobase; - char name[DEPCA_STRLEN]; + int status = 0; - if (!ioaddr && autoprobed) - return; /* Been here before ! */ - if ((ioaddr < 0x400) && (ioaddr > 0)) - return; /* ISA Address */ + edev = to_eisa_device (device); + iobase = edev->base_addr + DEPCA_EISA_IO_PORTS; - if (ioaddr == 0) { /* Autoprobing */ - iobase = EISA_SLOT_INC; /* Get the first slot address */ - i = 1; - maxSlots = MAX_EISA_SLOTS; - } else { /* Probe a specific location */ - iobase = ioaddr; - i = (ioaddr >> 12); - maxSlots = i + 1; + if (!request_region (iobase, DEPCA_TOTAL_SIZE, "depca")) { + status = -EBUSY; + goto out; + } + + if (DevicePresent(iobase)) { + status = -ENODEV; + goto out_release; } - if ((iobase & 0x0fff) == 0) - iobase += DEPCA_EISA_IO_PORTS; - for (; (i < maxSlots) && (dev != NULL); i++, iobase += EISA_SLOT_INC) { - if (check_region(iobase, DEPCA_TOTAL_SIZE) == 0) { - if (EISA_signature(name, EISA_ID)) { - if (DevicePresent(iobase) == 0) { - if ((dev = alloc_device(dev, iobase)) != NULL) { - if (depca_hw_init(dev, iobase, -1) == 0) { - num_depcas++; - } - num_eth++; - } - } - } - } else if (autoprobed) { - printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase); - } + if (!(dev = init_etherdev (NULL, sizeof (struct depca_private)))) { + status = -ENOMEM; + goto out_release; } + + eisa_set_drvdata (edev, dev); - return; + if ((status = depca_hw_init(dev, iobase, -1))) + goto out_free; + + num_depcas++; + return 0; + + out_free: + kfree (dev); + out_release: + release_region (iobase, DEPCA_TOTAL_SIZE); + out: + return status; +} + +static int __devexit depca_eisa_remove (struct device *device) +{ + struct net_device *dev; + struct eisa_device *edev; + struct depca_private *lp; + + edev = to_eisa_device (device); + dev = eisa_get_drvdata (edev); + lp = dev->priv; + + unregister_netdev (dev); + iounmap (lp->sh_mem); + release_mem_region (lp->mem_start, lp->mem_len); + release_region (dev->base_addr, DEPCA_TOTAL_SIZE); + kfree (dev); + + return 0; } +#endif /* ** Search the entire 'eth' device list for a fixed probe. If a match isn't @@ -1781,40 +1860,6 @@ return status; } -/* -** Look for a particular board name in the EISA configuration space -*/ -static int __init EISA_signature(char *name, s32 eisa_id) -{ - u_int i; - const char *signatures[] = DEPCA_SIGNATURE; - char ManCode[DEPCA_STRLEN]; - union { - s32 ID; - char Id[4]; - } Eisa; - int status = 0; - - *name = '\0'; - Eisa.ID = inl(eisa_id); - - ManCode[0] = (((Eisa.Id[0] >> 2) & 0x1f) + 0x40); - ManCode[1] = (((Eisa.Id[1] & 0xe0) >> 5) + ((Eisa.Id[0] & 0x03) << 3) + 0x40); - ManCode[2] = (((Eisa.Id[2] >> 4) & 0x0f) + 0x30); - ManCode[3] = ((Eisa.Id[2] & 0x0f) + 0x30); - ManCode[4] = (((Eisa.Id[3] >> 4) & 0x0f) + 0x30); - ManCode[5] = '\0'; - - for (i = 0; (*signatures[i] != '\0') && (*name == '\0'); i++) { - if (strstr(ManCode, signatures[i]) != NULL) { - strcpy(name, ManCode); - status = 1; - } - } - - return status; -} - static void depca_dbg_open(struct net_device *dev) { struct depca_private *lp = (struct depca_private *) dev->priv; @@ -2067,6 +2112,7 @@ unregister_netdev(&thisDepca); if (lp) { iounmap(lp->sh_mem); + release_mem_region (lp->mem_start, lp->mem_len); #ifdef CONFIG_MCA if (lp->mca_slot != -1) mca_mark_as_unused(lp->mca_slot); diff -Nru a/drivers/net/fc/iph5526.c b/drivers/net/fc/iph5526.c --- a/drivers/net/fc/iph5526.c Thu May 15 15:24:35 2003 +++ b/drivers/net/fc/iph5526.c Thu May 15 15:24:35 2003 @@ -2984,8 +2984,7 @@ */ if ((type == ETH_P_ARP) || (status == 0)) dev_kfree_skb(skb); - else - netif_wake_queue(dev); + netif_wake_queue(dev); LEAVE("iph5526_send_packet"); return 0; } diff -Nru a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c --- a/drivers/net/hamradio/mkiss.c Thu May 15 15:24:45 2003 +++ b/drivers/net/hamradio/mkiss.c Thu May 15 15:24:45 2003 @@ -347,6 +347,7 @@ netif_rx(skb); tmp_ax->dev->last_rx = jiffies; tmp_ax->rx_packets++; + tmp_ax->rx_bytes+=count; } /* Encapsulate one AX.25 packet and stuff into a TTY queue. */ @@ -386,6 +387,7 @@ ax->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); actual = ax->tty->driver->write(ax->tty, 0, ax->xbuff, count); ax->tx_packets++; + ax->tx_bytes+=actual; ax->dev->trans_start = jiffies; ax->xleft = count - actual; ax->xhead = ax->xbuff + actual; @@ -394,6 +396,7 @@ ax->mkiss->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP); actual = ax->mkiss->tty->driver->write(ax->mkiss->tty, 0, ax->mkiss->xbuff, count); ax->tx_packets++; + ax->tx_bytes+=actual; ax->mkiss->dev->trans_start = jiffies; ax->mkiss->xleft = count - actual; ax->mkiss->xhead = ax->mkiss->xbuff + actual; @@ -709,6 +712,8 @@ stats.rx_packets = ax->rx_packets; stats.tx_packets = ax->tx_packets; + stats.rx_bytes = ax->rx_bytes; + stats.tx_bytes = ax->tx_bytes; stats.rx_dropped = ax->rx_dropped; stats.tx_dropped = ax->tx_dropped; stats.tx_errors = ax->tx_errors; @@ -936,7 +941,7 @@ memcpy(dev->dev_addr, ax25_test, AX25_ADDR_LEN); /* New-style flags. */ - dev->flags = 0; + dev->flags = IFF_BROADCAST | IFF_MULTICAST; return 0; } diff -Nru a/drivers/net/hamradio/mkiss.h b/drivers/net/hamradio/mkiss.h --- a/drivers/net/hamradio/mkiss.h Thu May 15 15:24:34 2003 +++ b/drivers/net/hamradio/mkiss.h Thu May 15 15:24:34 2003 @@ -31,6 +31,8 @@ /* SLIP interface statistics. */ unsigned long rx_packets; /* inbound frames counter */ unsigned long tx_packets; /* outbound frames counter */ + unsigned long rx_bytes; /* inbound bytes counter */ + unsigned long tx_bytes; /* outbound bytes counter */ unsigned long rx_errors; /* Parity, etc. errors */ unsigned long tx_errors; /* Planned stuff */ unsigned long rx_dropped; /* No memory for skb */ diff -Nru a/drivers/net/mace.c b/drivers/net/mace.c --- a/drivers/net/mace.c Thu May 15 15:24:35 2003 +++ b/drivers/net/mace.c Thu May 15 15:24:35 2003 @@ -86,9 +86,9 @@ static void mace_set_multicast(struct net_device *dev); static void mace_reset(struct net_device *dev); static int mace_set_address(struct net_device *dev, void *addr); -static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs); -static void mace_txdma_intr(int irq, void *dev_id, struct pt_regs *regs); -static void mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t mace_txdma_intr(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs); static void mace_set_timeout(struct net_device *dev); static void mace_tx_timeout(unsigned long data); static inline void dbdma_reset(volatile struct dbdma_regs *dma); @@ -622,7 +622,7 @@ printk(KERN_DEBUG "mace: jabbering transceiver\n"); } -static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; struct mace_data *mp = (struct mace_data *) dev->priv; @@ -765,6 +765,7 @@ mace_set_timeout(dev); } spin_unlock_irqrestore(&mp->lock, flags); + return IRQ_HANDLED; } static void mace_tx_timeout(unsigned long data) @@ -833,11 +834,12 @@ spin_unlock_irqrestore(&mp->lock, flags); } -static void mace_txdma_intr(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t mace_txdma_intr(int irq, void *dev_id, struct pt_regs *regs) { + return IRQ_HANDLED; } -static void mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t mace_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_id; struct mace_data *mp = (struct mace_data *) dev->priv; @@ -947,6 +949,7 @@ mp->rx_fill = i; } spin_unlock_irqrestore(&mp->lock, flags); + return IRQ_HANDLED; } MODULE_AUTHOR("Paul Mackerras"); diff -Nru a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c --- a/drivers/net/pcmcia/3c589_cs.c Thu May 15 15:24:45 2003 +++ b/drivers/net/pcmcia/3c589_cs.c Thu May 15 15:24:45 2003 @@ -159,7 +159,7 @@ static int el3_config(struct net_device *dev, struct ifmap *map); static int el3_open(struct net_device *dev); static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev); -static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void update_stats(struct net_device *dev); static struct net_device_stats *el3_get_stats(struct net_device *dev); static int el3_rx(struct net_device *dev); @@ -816,15 +816,16 @@ } /* The EL3 interrupt handler. */ -static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct el3_private *lp = dev_id; struct net_device *dev = &lp->dev; ioaddr_t ioaddr, status; - int i = 0; + int i = 0, handled = 1; if (!netif_device_present(dev)) - return; + return IRQ_NONE; + ioaddr = dev->base_addr; DEBUG(3, "%s: interrupt, status %4.4x.\n", @@ -833,9 +834,9 @@ spin_lock(&lp->lock); while ((status = inw(ioaddr + EL3_STATUS)) & (IntLatch | RxComplete | StatsFull)) { - if (!netif_device_present(dev) || - ((status & 0xe000) != 0x2000)) { + if ((status & 0xe000) != 0x2000) { DEBUG(1, "%s: interrupt from dead card\n", dev->name); + handled = 0; break; } @@ -897,7 +898,7 @@ spin_unlock(&lp->lock); DEBUG(3, "%s: exiting interrupt, status %4.4x.\n", dev->name, inw(ioaddr + EL3_STATUS)); - return; + return IRQ_RETVAL(handled); } static void media_check(unsigned long arg) diff -Nru a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c --- a/drivers/net/pcmcia/fmvj18x_cs.c Thu May 15 15:24:41 2003 +++ b/drivers/net/pcmcia/fmvj18x_cs.c Thu May 15 15:24:41 2003 @@ -107,7 +107,7 @@ static int fjn_open(struct net_device *dev); static int fjn_close(struct net_device *dev); static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev); -static void fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void fjn_rx(struct net_device *dev); static void fjn_reset(struct net_device *dev); static struct net_device_stats *fjn_get_stats(struct net_device *dev); @@ -845,7 +845,7 @@ /*====================================================================*/ -static void fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs) { local_info_t *lp = dev_id; struct net_device *dev = &lp->dev; @@ -855,7 +855,7 @@ if (lp == NULL) { printk(KERN_NOTICE "fjn_interrupt(): irq %d for " "unknown device.\n", irq); - return; + return IRQ_NONE; } ioaddr = dev->base_addr; @@ -899,6 +899,7 @@ outb(D_TX_INTR, ioaddr + TX_INTR); outb(D_RX_INTR, ioaddr + RX_INTR); + return IRQ_HANDLED; } /* fjn_interrupt */ diff -Nru a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c --- a/drivers/net/pcmcia/ibmtr_cs.c Thu May 15 15:24:39 2003 +++ b/drivers/net/pcmcia/ibmtr_cs.c Thu May 15 15:24:39 2003 @@ -127,7 +127,7 @@ extern int ibmtr_probe(struct net_device *dev); extern int trdev_init(struct net_device *dev); -extern void tok_interrupt (int irq, void *dev_id, struct pt_regs *regs); +extern irqreturn_t tok_interrupt (int irq, void *dev_id, struct pt_regs *regs); /*====================================================================*/ diff -Nru a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c --- a/drivers/net/pcmcia/nmclan_cs.c Thu May 15 15:24:33 2003 +++ b/drivers/net/pcmcia/nmclan_cs.c Thu May 15 15:24:33 2003 @@ -431,7 +431,7 @@ static int mace_close(struct net_device *dev); static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev); static void mace_tx_timeout(struct net_device *dev); -static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs); static struct net_device_stats *mace_get_stats(struct net_device *dev); static int mace_rx(struct net_device *dev, unsigned char RxCnt); static void restore_multicast_list(struct net_device *dev); @@ -1143,7 +1143,7 @@ mace_interrupt The interrupt handler. ---------------------------------------------------------------------------- */ -static void mace_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs) { mace_private *lp = (mace_private *)dev_id; struct net_device *dev = &lp->dev; @@ -1154,7 +1154,7 @@ if (dev == NULL) { DEBUG(2, "mace_interrupt(): irq 0x%X for unknown device.\n", irq); - return; + return IRQ_NONE; } if (lp->tx_irq_disabled) { @@ -1169,12 +1169,12 @@ inb(ioaddr + AM2150_MACE_BASE + MACE_IMR) ); /* WARNING: MACE_IR has been read! */ - return; + return IRQ_NONE; } if (!netif_device_present(dev)) { DEBUG(2, "%s: interrupt from dead card\n", dev->name); - goto exception; + return IRQ_NONE; } do { @@ -1279,8 +1279,7 @@ } while ((status & ~MACE_IMR_DEFAULT) && (--IntrCnt)); -exception: - return; + return IRQ_HANDLED; } /* mace_interrupt */ /* ---------------------------------------------------------------------------- diff -Nru a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c --- a/drivers/net/pcmcia/smc91c92_cs.c Thu May 15 15:24:41 2003 +++ b/drivers/net/pcmcia/smc91c92_cs.c Thu May 15 15:24:41 2003 @@ -293,7 +293,7 @@ static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static void smc_tx_timeout(struct net_device *dev); static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev); -static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void smc_rx(struct net_device *dev); static struct net_device_stats *smc_get_stats(struct net_device *dev); static void set_rx_mode(struct net_device *dev); @@ -1574,16 +1574,18 @@ /*====================================================================*/ -static void smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct smc_private *smc = dev_id; struct net_device *dev = &smc->dev; ioaddr_t ioaddr; u_short saved_bank, saved_pointer, mask, status; + unsigned int handled = 1; char bogus_cnt = INTR_WORK; /* Work we are willing to do. */ if (!netif_device_present(dev)) - return; + return IRQ_NONE; + ioaddr = dev->base_addr; DEBUG(3, "%s: SMC91c92 interrupt %d at %#x.\n", dev->name, @@ -1596,6 +1598,7 @@ maybe it has been ejected. */ DEBUG(1, "%s: SMC91c92 interrupt %d for non-existent" "/ejected device.\n", dev->name, irq); + handled = 0; goto irq_done; } @@ -1609,9 +1612,11 @@ status = inw(ioaddr + INTERRUPT) & 0xff; DEBUG(3, "%s: Status is %#2.2x (mask %#2.2x).\n", dev->name, status, mask); - if ((status & mask) == 0) + if ((status & mask) == 0) { + if (bogus_cnt == INTR_WORK) + handled = 0; break; - + } if (status & IM_RCV_INT) { /* Got a packet(s). */ smc_rx(dev); @@ -1683,6 +1688,7 @@ readb(smc->base+MEGAHERTZ_ISR); } #endif + return IRQ_RETVAL(handled); } /*====================================================================*/ diff -Nru a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c --- a/drivers/net/pcmcia/xirc2ps_cs.c Thu May 15 15:24:37 2003 +++ b/drivers/net/pcmcia/xirc2ps_cs.c Thu May 15 15:24:37 2003 @@ -317,7 +317,7 @@ * less on other parts of the kernel. */ -static void xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs); /* * The dev_info variable is the "key" that is used to match up this @@ -1296,7 +1296,7 @@ /**************** * This is the Interrupt service route. */ -static void +static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = (struct net_device *)dev_id; @@ -1305,14 +1305,14 @@ u_char saved_page; unsigned bytes_rcvd; unsigned int_status, eth_status, rx_status, tx_status; - unsigned rsr, pktlen; + unsigned rsr, pktlen, handled = 1; ulong start_ticks = jiffies; /* fixme: jiffies rollover every 497 days * is this something to worry about? * -- on a laptop? */ if (!netif_device_present(dev)) - return; + return IRQ_NONE; ioaddr = dev->base_addr; if (lp->mohawk) { /* must disable the interrupt */ @@ -1330,6 +1330,7 @@ loop_entry: if (int_status == 0xff) { /* card may be ejected */ DEBUG(3, "%s: interrupt %d for dead card\n", dev->name, irq); + handled = 0; goto leave; } eth_status = GetByte(XIRCREG_ESR); @@ -1514,6 +1515,7 @@ * force an interrupt with this command: * PutByte(XIRCREG_CR, EnableIntr|ForceIntr); */ + return IRQ_RETVAL(handled); } /* xirc2ps_interrupt */ /*====================================================================*/ diff -Nru a/drivers/net/ppp_deflate.c b/drivers/net/ppp_deflate.c --- a/drivers/net/ppp_deflate.c Thu May 15 15:24:44 2003 +++ b/drivers/net/ppp_deflate.c Thu May 15 15:24:44 2003 @@ -88,7 +88,6 @@ if (state->strm.workspace) vfree(state->strm.workspace); kfree(state); - MOD_DEC_USE_COUNT; } } @@ -118,7 +117,6 @@ if (state == NULL) return NULL; - MOD_INC_USE_COUNT; memset (state, 0, sizeof (struct ppp_deflate_state)); state->strm.next_in = NULL; state->w_size = w_size; @@ -274,7 +272,6 @@ if (state->strm.workspace) kfree(state->strm.workspace); kfree(state); - MOD_DEC_USE_COUNT; } } @@ -303,7 +300,6 @@ if (state == NULL) return NULL; - MOD_INC_USE_COUNT; memset (state, 0, sizeof (struct ppp_deflate_state)); state->w_size = w_size; state->strm.next_out = NULL; diff -Nru a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c --- a/drivers/net/ppp_generic.c Thu May 15 15:24:44 2003 +++ b/drivers/net/ppp_generic.c Thu May 15 15:24:44 2003 @@ -57,7 +57,9 @@ #define NP_IPV6 1 /* Internet Protocol V6 */ #define NP_IPX 2 /* IPX protocol */ #define NP_AT 3 /* Appletalk protocol */ -#define NUM_NP 4 /* Number of NPs. */ +#define NP_MPLS_UC 4 /* MPLS unicast */ +#define NP_MPLS_MC 5 /* MPLS multicast */ +#define NUM_NP 6 /* Number of NPs. */ #define MPHDRLEN 6 /* multilink protocol header length */ #define MPHDRLEN_SSN 4 /* ditto with short sequence numbers */ @@ -281,6 +283,10 @@ return NP_IPX; case PPP_AT: return NP_AT; + case PPP_MPLS_UC: + return NP_MPLS_UC; + case PPP_MPLS_MC: + return NP_MPLS_MC; } return -EINVAL; } @@ -291,6 +297,8 @@ PPP_IPV6, PPP_IPX, PPP_AT, + PPP_MPLS_UC, + PPP_MPLS_MC, }; /* Translates an ethertype into an NP index */ @@ -306,6 +314,10 @@ case ETH_P_PPPTALK: case ETH_P_ATALK: return NP_AT; + case ETH_P_MPLS_UC: + return NP_MPLS_UC; + case ETH_P_MPLS_MC: + return NP_MPLS_MC; } return -1; } @@ -316,6 +328,8 @@ ETH_P_IPV6, ETH_P_IPX, ETH_P_PPPTALK, + ETH_P_MPLS_UC, + ETH_P_MPLS_MC, }; /* @@ -784,11 +798,14 @@ printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n"); err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops); - if (err) + if (!err) { + err = devfs_mk_cdev(MKDEV(PPP_MAJOR, 0), + S_IFCHR|S_IRUSR|S_IWUSR, "ppp"); + } + + if (!err) printk(KERN_ERR "failed to register PPP device (%d)\n", err); - devfs_register(NULL, "ppp", DEVFS_FL_DEFAULT, PPP_MAJOR, 0, - S_IFCHR | S_IRUSR | S_IWUSR, &ppp_device_fops, NULL); - return 0; + return err; } /* diff -Nru a/drivers/net/rclanmtl.h b/drivers/net/rclanmtl.h --- a/drivers/net/rclanmtl.h Thu May 15 15:24:38 2003 +++ b/drivers/net/rclanmtl.h Thu May 15 15:24:38 2003 @@ -54,10 +54,10 @@ #include /* Debug stuff. Define for debug output */ -#define RCDEBUG +#undef RCDEBUG #ifdef RCDEBUG -#define dprintk(args...) printk(KERN_DEBUG "(rcpci45 driver:) " args) +#define dprintk(args...) printk(KERN_DEBUG "rc: " args) #else #define dprintk(args...) { } #endif diff -Nru a/drivers/net/sb1000.c b/drivers/net/sb1000.c --- a/drivers/net/sb1000.c Thu May 15 15:24:33 2003 +++ b/drivers/net/sb1000.c Thu May 15 15:24:33 2003 @@ -49,7 +49,7 @@ #include #include /* for udelay() */ #include -#include +#include #include #include @@ -131,146 +131,118 @@ static inline int sb1000_rx(struct net_device *dev); static inline void sb1000_error_dpc(struct net_device *dev); -static struct isapnp_device_id id_table[] = { - { ISAPNP_ANY_ID, ISAPNP_ANY_ID, - ISAPNP_VENDOR('G','I','C'), ISAPNP_FUNCTION(0x1000), 0 }, - {0} +static const struct pnp_device_id sb1000_pnp_ids[] = { + { "GIC1000", 0 }, + { "", 0 } }; +MODULE_DEVICE_TABLE(pnp, sb1000_pnp_ids); -MODULE_DEVICE_TABLE(isapnp, id_table); - -/* probe for SB1000 using Plug-n-Play mechanism */ -int -sb1000_probe(struct net_device *dev) +static int +sb1000_probe_one(struct pnp_dev *pdev, const struct pnp_device_id *id) { - + struct net_device *dev; unsigned short ioaddr[2], irq; - struct pnp_dev *idev=NULL; unsigned int serial_number; + int error = -ENODEV; - while(1) - { - /* - * Find the card - */ - - idev=pnp_find_dev(NULL, ISAPNP_VENDOR('G','I','C'), - ISAPNP_FUNCTION(0x1000), idev); - - /* - * No card - */ - - if(idev==NULL || idev->card == NULL) - return -ENODEV; - - /* - * Bring it online - */ - - if (pnp_device_attach(idev) < 0) - continue; - if (pnp_activate_dev(idev) < 0) { - __again: - pnp_device_detach(idev); - continue; - } - - /* - * Ports free ? - */ - - if(!pnp_port_valid(idev, 0) || !pnp_port_valid(idev, 1) || !pnp_irq_valid(idev, 0)) - goto __again; + if (pnp_device_attach(pdev) < 0) + return -ENODEV; + if (pnp_activate_dev(pdev) < 0) + goto out_detach; + + if (!pnp_port_valid(pdev, 0) || !pnp_port_valid(pdev, 1)) + goto out_disable; + if (!pnp_irq_valid(pdev, 0)) + goto out_disable; - serial_number = idev->card->serial; + serial_number = pdev->card->serial; - ioaddr[0]=pnp_port_start(idev, 0); - ioaddr[1]=pnp_port_start(idev, 0); + ioaddr[0] = pnp_port_start(pdev, 0); + ioaddr[1] = pnp_port_start(pdev, 0); - irq = pnp_irq(idev, 0); + irq = pnp_irq(pdev, 0); - /* check I/O base and IRQ */ - if (dev->base_addr != 0 && dev->base_addr != ioaddr[0]) - goto __again; - if (dev->mem_start != 0 && dev->mem_start != ioaddr[1]) - goto __again; - if (dev->irq != 0 && dev->irq != irq) - goto __again; - - /* - * Ok set it up. - */ - if (!request_region(ioaddr[0], 16, dev->name)) - goto __again; - if (!request_region(ioaddr[1], 16, dev->name)) { - release_region(ioaddr[0], 16); - goto __again; - } + if (!request_region(ioaddr[0], 16, dev->name)) + goto out_disable; + if (!request_region(ioaddr[1], 16, dev->name)) + goto out_release_region0; - dev->base_addr = ioaddr[0]; - /* mem_start holds the second I/O address */ - dev->mem_start = ioaddr[1]; - dev->irq = irq; - - if (sb1000_debug > 0) - printk(KERN_NOTICE "%s: sb1000 at (%#3.3lx,%#3.3lx), " - "S/N %#8.8x, IRQ %d.\n", dev->name, dev->base_addr, - dev->mem_start, serial_number, dev->irq); - - dev = init_etherdev(dev, 0); - if (!dev) { - pnp_device_detach(idev); - release_region(ioaddr[1], 16); - release_region(ioaddr[0], 16); - return -ENOMEM; - } - SET_MODULE_OWNER(dev); - - /* Make up a SB1000-specific-data structure. */ - dev->priv = kmalloc(sizeof(struct sb1000_private), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; - memset(dev->priv, 0, sizeof(struct sb1000_private)); - - if (sb1000_debug > 0) - printk(KERN_NOTICE "%s", version); - - /* The SB1000-specific entries in the device structure. */ - dev->open = sb1000_open; - dev->do_ioctl = sb1000_dev_ioctl; - dev->hard_start_xmit = sb1000_start_xmit; - dev->stop = sb1000_close; - dev->get_stats = sb1000_stats; - - /* Fill in the generic fields of the device structure. */ - dev->change_mtu = NULL; - dev->hard_header = NULL; - dev->rebuild_header = NULL; - dev->set_mac_address = NULL; - dev->header_cache_update= NULL; - - dev->type = ARPHRD_ETHER; - dev->hard_header_len = 0; - dev->mtu = 1500; - dev->addr_len = ETH_ALEN; - /* hardware address is 0:0:serial_number */ - dev->dev_addr[0] = 0; - dev->dev_addr[1] = 0; - dev->dev_addr[2] = serial_number >> 24 & 0xff; - dev->dev_addr[3] = serial_number >> 16 & 0xff; - dev->dev_addr[4] = serial_number >> 8 & 0xff; - dev->dev_addr[5] = serial_number >> 0 & 0xff; - dev->tx_queue_len = 0; - - /* New-style flags. */ - dev->flags = IFF_POINTOPOINT|IFF_NOARP; + dev->base_addr = ioaddr[0]; + /* mem_start holds the second I/O address */ + dev->mem_start = ioaddr[1]; + dev->irq = irq; - /* Lock resources */ + if (sb1000_debug > 0) + printk(KERN_NOTICE "%s: sb1000 at (%#3.3lx,%#3.3lx), " + "S/N %#8.8x, IRQ %d.\n", dev->name, dev->base_addr, + dev->mem_start, serial_number, dev->irq); + + dev = alloc_etherdev(sizeof(struct sb1000_private)); + if (!dev) { + error = -ENOMEM; + goto out_release_regions; + } + + /* + * The SB1000 is an rx-only cable modem device. The uplink is a modem + * and we do not want to arp on it. + */ + dev->flags = IFF_POINTOPOINT|IFF_NOARP; + + SET_MODULE_OWNER(dev); + + if (sb1000_debug > 0) + printk(KERN_NOTICE "%s", version); + + /* The SB1000-specific entries in the device structure. */ + dev->open = sb1000_open; + dev->do_ioctl = sb1000_dev_ioctl; + dev->hard_start_xmit = sb1000_start_xmit; + dev->stop = sb1000_close; + dev->get_stats = sb1000_stats; + + /* hardware address is 0:0:serial_number */ + dev->dev_addr[2] = serial_number >> 24 & 0xff; + dev->dev_addr[3] = serial_number >> 16 & 0xff; + dev->dev_addr[4] = serial_number >> 8 & 0xff; + dev->dev_addr[5] = serial_number >> 0 & 0xff; + + pnp_set_drvdata(pdev, dev); + + error = register_netdev(dev); + if (error) + goto out_unregister; + return 0; - return 0; - } -} + out_unregister: + unregister_netdev(dev); + out_release_regions: + release_region(ioaddr[1], 16); + out_release_region0: + release_region(ioaddr[0], 16); + out_disable: + pnp_disable_dev(pdev); + out_detach: + pnp_device_detach(pdev); + return error; +} + +static void +sb1000_remove_one(struct pnp_dev *pdev) +{ + struct net_device *dev = pnp_get_drvdata(pdev); + + unregister_netdev(dev); + release_region(dev->base_addr, 16); + release_region(dev->mem_start, 16); +} + +static struct pnp_driver sb1000_driver = { + .name = "sb1000", + .id_table = sb1000_pnp_ids, + .probe = sb1000_probe_one, + .remove = sb1000_remove_one, +}; /* @@ -1207,60 +1179,21 @@ return 0; } -#ifdef MODULE MODULE_AUTHOR("Franco Venturi "); MODULE_DESCRIPTION("General Instruments SB1000 driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(io, "1-2i"); -MODULE_PARM(irq, "i"); -MODULE_PARM_DESC(io, "SB1000 I/O base addresses"); -MODULE_PARM_DESC(irq, "SB1000 IRQ number"); - -static struct net_device dev_sb1000; -static int io[2]; -static int irq; - -int -init_module(void) +static int __init +sb1000_init(void) { - int i; - for (i = 0; i < 100; i++) { - sprintf(dev_sb1000.name, "cm%d", i); - if (dev_get(dev_sb1000.name) == 0) break; - } - if (i == 100) { - printk(KERN_ERR "sb1000: can't register any device cm\n"); - return -ENFILE; - } - dev_sb1000.init = sb1000_probe; - dev_sb1000.base_addr = io[0]; - /* mem_start holds the second I/O address */ - dev_sb1000.mem_start = io[1]; - dev_sb1000.irq = irq; - if (register_netdev(&dev_sb1000) != 0) { - printk(KERN_ERR "sb1000: failed to register device (io: %03x,%03x " - "irq: %d)\n", io[0], io[1], irq); - return -EIO; - } - return 0; + return pnp_register_driver(&sb1000_driver); } -void cleanup_module(void) +static void __exit +sb1000_exit(void) { - unregister_netdev(&dev_sb1000); - release_region(dev_sb1000.base_addr, 16); - release_region(dev_sb1000.mem_start, 16); - kfree(dev_sb1000.priv); - dev_sb1000.priv = NULL; + pnp_unregister_driver(&sb1000_driver); } -#endif /* MODULE */ - -/* - * Local variables: - * compile-command: "gcc -D__KERNEL__ -DMODULE -Wall -Wstrict-prototypes -O -m486 -c sb1000.c" - * version-control: t - * tab-width: 4 - * c-basic-offset: 4 - * End: - */ + +module_init(sb1000_init); +module_exit(sb1000_exit); diff -Nru a/drivers/net/setup.c b/drivers/net/setup.c --- a/drivers/net/setup.c Thu May 15 15:24:44 2003 +++ b/drivers/net/setup.c Thu May 15 15:24:44 2003 @@ -9,15 +9,11 @@ #include #include -extern int slip_init_ctrl_dev(void); -extern int x25_asy_init_ctrl_dev(void); - extern int dmascc_init(void); extern int arcnet_init(void); extern int scc_enet_init(void); extern int fec_enet_init(void); -extern int dlci_setup(void); extern int sdla_setup(void); extern int sdla_c_setup(void); extern int comx_init(void); @@ -25,14 +21,6 @@ extern int madgemc_probe(void); -/* Pad device name to IFNAMSIZ=16. F.e. __PAD6 is string of 9 zeros. */ -#define __PAD6 "\0\0\0\0\0\0\0\0\0" -#define __PAD5 __PAD6 "\0" -#define __PAD4 __PAD5 "\0" -#define __PAD3 __PAD4 "\0" -#define __PAD2 __PAD3 "\0" - - /* * Devices in this list must do new style probing. That is they must * allocate their own device objects and do their own bus scans. @@ -52,9 +40,6 @@ #if defined(CONFIG_DMASCC) {dmascc_init, 0}, #endif -#if defined(CONFIG_DLCI) - {dlci_setup, 0}, -#endif #if defined(CONFIG_SDLA) {sdla_c_setup, 0}, #endif @@ -91,7 +76,7 @@ * into them. */ -static void __init network_probe(void) +void __init net_device_init(void) { struct net_probe *p = pci_probes; @@ -100,48 +85,4 @@ p->status = p->probe(); p++; } -} - - -/* - * Initialise the line discipline drivers - */ - -static void __init network_ldisc_init(void) -{ -#if defined(CONFIG_SLIP) - slip_init_ctrl_dev(); -#endif -#if defined(CONFIG_X25_ASY) - x25_asy_init_ctrl_dev(); -#endif -} - - -static void __init special_device_init(void) -{ -#ifdef CONFIG_NET_SB1000 - extern int sb1000_probe(struct net_device *dev); - - static struct net_device sb1000_dev = { - .name = "cm0" __PAD3, - .init = sb1000_probe, - }; - register_netdev(&sb1000_dev); -#endif -} - -/* - * Initialise network devices - */ - -void __init net_device_init(void) -{ - /* Devices supporting the new probing API */ - network_probe(); - /* Line disciplines */ - network_ldisc_init(); - /* Special devices */ - special_device_init(); - /* That kicks off the legacy init functions */ } diff -Nru a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c --- a/drivers/net/sk98lin/skge.c Thu May 15 15:24:34 2003 +++ b/drivers/net/sk98lin/skge.c Thu May 15 15:24:34 2003 @@ -348,12 +348,12 @@ static int SkGeIocMib(DEV_NET*, unsigned int, int); -/*Extern */ +static const char SK_Root_Dir_entry[] = "sk98lin"; +static struct proc_dir_entry *pSkRootDir; -extern struct proc_dir_entry *pSkRootDir; //extern struct proc_dir_entry Our_Proc_Dir; -extern int proc_read(char *buffer, char **buffer_location, +extern int sk_proc_read(char *buffer, char **buffer_location, off_t offset, int buffer_length, int *eof, void *data); @@ -376,17 +376,6 @@ static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480}; - -void proc_fill_inode(struct inode *inode, int fill) -{ - if (fill) - MOD_INC_USE_COUNT; - else - MOD_DEC_USE_COUNT; -} - - - /***************************************************************************** * * skge_probe - find all SK-98xx adapters @@ -481,20 +470,20 @@ dev->change_mtu = &SkGeChangeMtu; if(!proc_root_initialized) { - pSkRootDir = create_proc_entry("sk98lin", + pSkRootDir = create_proc_entry(SK_Root_Dir_entry, S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO, proc_net); pSkRootDir->owner = THIS_MODULE; - proc_root_initialized = 1; } pProcFile = create_proc_entry(dev->name, S_IFREG | 0444, pSkRootDir); - pProcFile->read_proc = proc_read; + pProcFile->read_proc = sk_proc_read; pProcFile->write_proc = NULL; pProcFile->nlink = 1; pProcFile->size = sizeof(dev->name+1); pProcFile->data = (void*)pProcFile; + pProcFile->owner = THIS_MODULE; /* * Dummy value. @@ -571,11 +560,12 @@ pProcFile = create_proc_entry(dev->name, S_IFREG | 0444, pSkRootDir); - pProcFile->read_proc = proc_read; + pProcFile->read_proc = sk_proc_read; pProcFile->write_proc = NULL; pProcFile->nlink = 1; pProcFile->size = sizeof(dev->name+1); pProcFile->data = (void*)pProcFile; + pProcFile->owner = THIS_MODULE; memcpy((caddr_t) &dev->dev_addr, (caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6); diff -Nru a/drivers/net/sk98lin/skproc.c b/drivers/net/sk98lin/skproc.c --- a/drivers/net/sk98lin/skproc.c Thu May 15 15:24:33 2003 +++ b/drivers/net/sk98lin/skproc.c Thu May 15 15:24:33 2003 @@ -54,7 +54,6 @@ //#define SPECIAL 32 /* 0x */ #define LARGE 64 -extern void proc_fill_inode(struct inode *inode, int fill); extern char * SkNumber(char * str, long long num, int base, int size, int precision ,int type); int proc_read(char *buffer, @@ -64,19 +63,8 @@ int *eof, void *data); -static const char SK_Root_Dir_entry[] = "sk98lin"; -extern struct net_device *sk98lin_root_dev; - - -struct proc_dir_entry pSkRootDir = { - 0, - sizeof(SK_Root_Dir_entry)-1, - (const char*)SK_Root_Dir_entry, - S_IFDIR | S_IRUGO, - 2, 0, 0, 0, NULL, - NULL -}; +extern struct net_device *sk98lin_root_dev; /***************************************************************************** * @@ -90,7 +78,7 @@ * Returns: buffer with statistic data * */ -int proc_read(char *buffer, +int sk_proc_read(char *buffer, char **buffer_location, off_t offset, int buffer_length, diff -Nru a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c --- a/drivers/net/skfp/skfddi.c Thu May 15 15:24:33 2003 +++ b/drivers/net/skfp/skfddi.c Thu May 15 15:24:33 2003 @@ -539,6 +539,8 @@ dev->header_cache_update = NULL; /* not supported */ dev->change_mtu = NULL; /* set in fddi_setup() */ + SET_MODULE_OWNER(dev); + /* Initialize remaining device structure information */ fddi_setup(dev); } // init_device @@ -791,8 +793,6 @@ smt_online(smc, 1); STI_FBI(); - MOD_INC_USE_COUNT; - /* Clear local multicast address tables */ mac_clear_multicast(smc); @@ -853,8 +853,6 @@ bp->QueueSkb++; dev_kfree_skb(skb); } - - MOD_DEC_USE_COUNT; return (0); } // skfp_close diff -Nru a/drivers/net/slip.c b/drivers/net/slip.c --- a/drivers/net/slip.c Thu May 15 15:24:46 2003 +++ b/drivers/net/slip.c Thu May 15 15:24:46 2003 @@ -81,11 +81,7 @@ #include #endif -#ifdef MODULE -#define SLIP_VERSION "0.8.4-NET3.019-NEWTTY-MODULAR" -#else -#define SLIP_VERSION "0.8.4-NET3.019-NEWTTY" -#endif +#define SLIP_VERSION "0.8.4-NET3.019-NEWTTY" typedef struct slip_ctrl { @@ -98,8 +94,6 @@ MODULE_PARM(slip_maxdev, "i"); MODULE_PARM_DESC(slip_maxdev, "Maximum number of slip devices"); -static struct tty_ldisc sl_ldisc; - static int slip_esc(unsigned char *p, unsigned char *d, int len); static void slip_unesc(struct slip *sl, unsigned char c); #ifdef CONFIG_SLIP_MODE_SLIP6 @@ -1309,13 +1303,24 @@ #endif /* VSV changes end */ -/* Initialize SLIP control device -- register SLIP line discipline */ +static struct tty_ldisc sl_ldisc = { + .owner = THIS_MODULE, + .magic = TTY_LDISC_MAGIC, + .name = "slip", + .open = slip_open, + .close = slip_close, + .ioctl = slip_ioctl, + .receive_buf = slip_receive_buf, + .receive_room = slip_receive_room, + .write_wakeup = slip_write_wakeup, +}; -int __init slip_init_ctrl_dev(void) +static int __init slip_init(void) { int status; - if (slip_maxdev < 4) slip_maxdev = 4; /* Sanity */ + if (slip_maxdev < 4) + slip_maxdev = 4; /* Sanity */ printk(KERN_INFO "SLIP: version %s (dynamic channels, max=%d)" #ifdef CONFIG_SLIP_MODE_SLIP6 @@ -1323,16 +1328,15 @@ #endif ".\n", SLIP_VERSION, slip_maxdev ); -#if defined(SL_INCLUDE_CSLIP) && !defined(MODULE) +#if defined(SL_INCLUDE_CSLIP) printk(KERN_INFO "CSLIP: code copyright 1989 Regents of the University of California.\n"); #endif #ifdef CONFIG_SLIP_SMART printk(KERN_INFO "SLIP linefill/keepalive option.\n"); #endif - slip_ctrls = (slip_ctrl_t **) kmalloc(sizeof(void*)*slip_maxdev, GFP_KERNEL); - if (slip_ctrls == NULL) - { + slip_ctrls = kmalloc(sizeof(void*)*slip_maxdev, GFP_KERNEL); + if (!slip_ctrls) { printk(KERN_ERR "SLIP: Can't allocate slip_ctrls[] array! Uaargh! (-> No SLIP available)\n"); return -ENOMEM; } @@ -1347,28 +1351,7 @@ return status; } -static struct tty_ldisc sl_ldisc = -{ - .owner = THIS_MODULE, - .magic = TTY_LDISC_MAGIC, - .name = "slip", - .open = slip_open, - .close = slip_close, - .ioctl = slip_ioctl, - .receive_buf = slip_receive_buf, - .receive_room = slip_receive_room, - .write_wakeup = slip_write_wakeup, -}; - -#ifdef MODULE - -int init_module(void) -{ - return slip_init_ctrl_dev(); -} - -void -cleanup_module(void) +static void __exit slip_exit(void) { int i; @@ -1425,7 +1408,9 @@ printk(KERN_ERR "SLIP: can't unregister line discipline (err = %d)\n", i); } } -#endif /* MODULE */ + +module_init(slip_init); +module_exit(slip_exit); #ifdef CONFIG_SLIP_SMART /* diff -Nru a/drivers/net/slip.h b/drivers/net/slip.h --- a/drivers/net/slip.h Thu May 15 15:24:39 2003 +++ b/drivers/net/slip.h Thu May 15 15:24:39 2003 @@ -116,10 +116,6 @@ #endif }; - - #define SLIP_MAGIC 0x5302 - -extern int slip_init(struct net_device *dev); #endif /* _LINUX_SLIP.H */ diff -Nru a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c --- a/drivers/net/tulip/tulip_core.c Thu May 15 15:24:40 2003 +++ b/drivers/net/tulip/tulip_core.c Thu May 15 15:24:40 2003 @@ -223,6 +223,7 @@ { 0x1626, 0x8410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, { 0x1737, 0xAB09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, { 0x17B3, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, + { 0x10b9, 0x5261, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DM910X }, /* ALi 1563 integrated ethernet */ { } /* terminate list */ }; MODULE_DEVICE_TABLE(pci, tulip_pci_tbl); @@ -1325,12 +1326,14 @@ csr0 &= ~0xfff10000; /* zero reserved bits 31:20, 16 */ /* DM9102A has troubles with MRM & clear reserved bits 24:22, 20, 16, 7:1 */ - if (pdev->vendor == 0x1282 && pdev->device == 0x9102) + if ((pdev->vendor == 0x1282 && pdev->device == 0x9102) + || (pdev->vendor == 0x10b9 && pdev->device == 0x5261)) csr0 &= ~0x01f100ff; #if defined(__sparc__) /* DM9102A needs 32-dword alignment/burst length on sparc - chip bug? */ - if (pdev->vendor == 0x1282 && pdev->device == 0x9102) + if ((pdev->vendor == 0x1282 && pdev->device == 0x9102) + || (pdev->vendor == 0x10b9 && pdev->device == 0x5261)) csr0 = (csr0 & ~0xff00) | 0xe000; #endif diff -Nru a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c --- a/drivers/net/wan/cosa.c Thu May 15 15:24:33 2003 +++ b/drivers/net/wan/cosa.c Thu May 15 15:24:33 2003 @@ -392,12 +392,9 @@ } devfs_mk_dir("cosa"); for (i=0; i #include #include +#include #include #include #include @@ -577,9 +578,10 @@ return(0); } -int __init dlci_setup(void) +int __init init_dlci(void) { int i; + dlci_ioctl_set(dlci_ioctl); printk("%s.\n", version); @@ -589,25 +591,16 @@ for(i=0;idev))) return err; - MOD_INC_USE_COUNT; - /* Done. We have linked the TTY line to a channel. */ return sl->dev->base_addr; } @@ -664,7 +660,6 @@ sl->tty = NULL; x25_asy_free(sl); unregister_netdev(sl->dev); - MOD_DEC_USE_COUNT; } @@ -769,32 +764,29 @@ /* Perform I/O control on an active X.25 channel. */ -static int x25_asy_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg) +static int x25_asy_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) { struct x25_asy *sl = (struct x25_asy *) tty->disc_data; /* First make sure we're connected. */ - if (!sl || sl->magic != X25_ASY_MAGIC) { + if (!sl || sl->magic != X25_ASY_MAGIC) return -EINVAL; - } - switch(cmd) - { - case SIOCGIFNAME: - if(copy_to_user(arg, sl->dev->name, strlen(sl->dev->name) + 1)) - return -EFAULT; - return 0; - - case SIOCSIFHWADDR: - return -EINVAL; - - /* Allow stty to read, but not set, the serial port */ - case TCGETS: - case TCGETA: - return n_tty_ioctl(tty, (struct file *) file, cmd, (unsigned long) arg); - - default: - return -ENOIOCTLCMD; + switch(cmd) { + case SIOCGIFNAME: + if (copy_to_user((void *)arg, sl->dev->name, + strlen(sl->dev->name) + 1)) + return -EFAULT; + return 0; + case SIOCSIFHWADDR: + return -EINVAL; + /* Allow stty to read, but not set, the serial port */ + case TCGETS: + case TCGETA: + return n_tty_ioctl(tty, file, cmd, arg); + default: + return -ENOIOCTLCMD; } } @@ -806,51 +798,7 @@ return 0; } -/* Initialize X.25 control device -- register X.25 line discipline */ - -int __init x25_asy_init_ctrl_dev(void) -{ - int status; - - if (x25_asy_maxdev < 4) x25_asy_maxdev = 4; /* Sanity */ - - printk(KERN_INFO "X.25 async: version 0.00 ALPHA (dynamic channels, max=%d).\n", - x25_asy_maxdev ); - x25_asy_ctrls = (x25_asy_ctrl_t **) kmalloc(sizeof(void*)*x25_asy_maxdev, GFP_KERNEL); - if (x25_asy_ctrls == NULL) - { - printk("X25 async: Can't allocate x25_asy_ctrls[] array! Uaargh! (-> No X.25 available)\n"); - return -ENOMEM; - } - - /* Clear the pointer array, we allocate devices when we need them */ - memset(x25_asy_ctrls, 0, sizeof(void*)*x25_asy_maxdev); /* Pointers */ - - /* Fill in our line protocol discipline, and register it */ - memset(&x25_ldisc, 0, sizeof(x25_ldisc)); - x25_ldisc.magic = TTY_LDISC_MAGIC; - x25_ldisc.name = "X.25"; - x25_ldisc.flags = 0; - x25_ldisc.open = x25_asy_open_tty; - x25_ldisc.close = x25_asy_close_tty; - x25_ldisc.read = NULL; - x25_ldisc.write = NULL; - x25_ldisc.ioctl = (int (*)(struct tty_struct *, struct file *, - unsigned int, unsigned long)) x25_asy_ioctl; - x25_ldisc.poll = NULL; - x25_ldisc.receive_buf = x25_asy_receive_buf; - x25_ldisc.receive_room = x25_asy_receive_room; - x25_ldisc.write_wakeup = x25_asy_write_wakeup; - if ((status = tty_register_ldisc(N_X25, &x25_ldisc)) != 0) { - printk("X.25 async: can't register line discipline (err = %d)\n", status); - } - - return status; -} - - /* Initialise the X.25 driver. Called by the device init code */ - int x25_asy_init(struct net_device *dev) { struct x25_asy *sl = (struct x25_asy*)(dev->priv); @@ -885,43 +833,58 @@ return 0; } -#ifdef MODULE -int -init_module(void) -{ - return x25_asy_init_ctrl_dev(); +static struct tty_ldisc x25_ldisc = { + .owner = THIS_MODULE, + .magic = TTY_LDISC_MAGIC, + .name = "X.25", + .open = x25_asy_open_tty, + .close = x25_asy_close_tty, + .ioctl = x25_asy_ioctl, + .receive_buf = x25_asy_receive_buf, + .receive_room = x25_asy_receive_room, + .write_wakeup = x25_asy_write_wakeup, +}; + +static int __init init_x25_asy(void) +{ + if (x25_asy_maxdev < 4) + x25_asy_maxdev = 4; /* Sanity */ + + printk(KERN_INFO "X.25 async: version 0.00 ALPHA " + "(dynamic channels, max=%d).\n", x25_asy_maxdev ); + x25_asy_ctrls = kmalloc(sizeof(void*)*x25_asy_maxdev, GFP_KERNEL); + if (!x25_asy_ctrls) { + printk(KERN_WARNING "X25 async: Can't allocate x25_asy_ctrls[] " + "array! Uaargh! (-> No X.25 available)\n"); + return -ENOMEM; + } + memset(x25_asy_ctrls, 0, sizeof(void*)*x25_asy_maxdev); /* Pointers */ + + return tty_register_ldisc(N_X25, &x25_ldisc); } -void -cleanup_module(void) + +static void __exit exit_x25_asy(void) { int i; - if (x25_asy_ctrls != NULL) - { - for (i = 0; i < x25_asy_maxdev; i++) - { - if (x25_asy_ctrls[i]) - { - /* - * VSV = if dev->start==0, then device - * unregistered while close proc. - */ - if (netif_running(&(x25_asy_ctrls[i]->dev))) - unregister_netdev(&(x25_asy_ctrls[i]->dev)); + for (i = 0; i < x25_asy_maxdev; i++) { + if (x25_asy_ctrls[i]) { + /* + * VSV = if dev->start==0, then device + * unregistered while close proc. + */ + if (netif_running(&(x25_asy_ctrls[i]->dev))) + unregister_netdev(&(x25_asy_ctrls[i]->dev)); - kfree(x25_asy_ctrls[i]); - x25_asy_ctrls[i] = NULL; - } + kfree(x25_asy_ctrls[i]); } - kfree(x25_asy_ctrls); - x25_asy_ctrls = NULL; - } - if ((i = tty_register_ldisc(N_X25, NULL))) - { - printk("X.25 async: can't unregister line discipline (err = %d)\n", i); } + + kfree(x25_asy_ctrls); + tty_register_ldisc(N_X25, NULL); } -#endif /* MODULE */ +module_init(init_x25_asy); +module_exit(exit_x25_asy); diff -Nru a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c --- a/drivers/net/wireless/netwave_cs.c Thu May 15 15:24:45 2003 +++ b/drivers/net/wireless/netwave_cs.c Thu May 15 15:24:45 2003 @@ -227,7 +227,7 @@ static int netwave_rx( struct net_device *dev); /* Interrupt routines */ -static void netwave_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t netwave_interrupt(int irq, void *dev_id, struct pt_regs *regs); static void netwave_watchdog(struct net_device *); /* Statistics */ @@ -1456,7 +1456,7 @@ * ready to transmit another packet. * 3. A command has completed execution. */ -static void netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) { +static irqreturn_t netwave_interrupt(int irq, void* dev_id, struct pt_regs *regs) { ioaddr_t iobase; u_char *ramBase; struct net_device *dev = (struct net_device *)dev_id; @@ -1465,7 +1465,7 @@ int i; if (!netif_device_present(dev)) - return; + return IRQ_NONE; iobase = dev->base_addr; ramBase = priv->ramBase; @@ -1476,7 +1476,7 @@ wait_WOC(iobase); if (!(inb(iobase+NETWAVE_REG_CCSR) & 0x02)) - break; /* None of the interrupt sources asserted */ + break; /* None of the interrupt sources asserted (normal exit) */ status = inb(iobase + NETWAVE_REG_ASR); @@ -1569,6 +1569,8 @@ } */ } + /* Handled if we looped at least one time - Jean II */ + return IRQ_RETVAL(i); } /* netwave_interrupt */ /* diff -Nru a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c --- a/drivers/net/wireless/wavelan.c Thu May 15 15:24:44 2003 +++ b/drivers/net/wireless/wavelan.c Thu May 15 15:24:44 2003 @@ -1717,31 +1717,28 @@ return (i); } -#ifdef WIRELESS_SPY +#ifdef IW_WIRELESS_SPY /*------------------------------------------------------------------*/ /* * Gather wireless spy statistics: for each packet, compare the source * address with our list, and if they match, get the statistics. * Sorry, but this function really needs the wireless extensions. */ -static inline void wl_spy_gather(device * dev, u8 * mac, /* MAC address */ - u8 * stats) -{ /* Statistics to gather */ - net_local *lp = (net_local *) dev->priv; - int i; +static inline void wl_spy_gather(device * dev, + u8 * mac, /* MAC address */ + u8 * stats) /* Statistics to gather */ +{ + struct iw_quality wstats; - /* Check all addresses. */ - for (i = 0; i < lp->spy_number; i++) - /* If match */ - if (!memcmp(mac, lp->spy_address[i], WAVELAN_ADDR_SIZE)) { - /* Update statistics */ - lp->spy_stat[i].qual = stats[2] & MMR_SGNL_QUAL; - lp->spy_stat[i].level = stats[0] & MMR_SIGNAL_LVL; - lp->spy_stat[i].noise = stats[1] & MMR_SILENCE_LVL; - lp->spy_stat[i].updated = 0x7; - } + wstats.qual = stats[2] & MMR_SGNL_QUAL; + wstats.level = stats[0] & MMR_SIGNAL_LVL; + wstats.noise = stats[1] & MMR_SILENCE_LVL; + wstats.updated = 0x7; + + /* Update spy records */ + wireless_spy_update(dev, mac, &wstats); } -#endif /* WIRELESS_SPY */ +#endif /* IW_WIRELESS_SPY */ #ifdef HISTOGRAM /*------------------------------------------------------------------*/ @@ -1767,7 +1764,7 @@ /* Increment interval counter. */ (lp->his_sum[i])++; } -#endif /* HISTOGRAM */ +#endif /* HISTOGRAM */ /*------------------------------------------------------------------*/ /* @@ -2203,93 +2200,6 @@ return ret; } -#ifdef WIRELESS_SPY -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set spy list - */ -static int wavelan_set_spy(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ - struct sockaddr *address = (struct sockaddr *) extra; - int i; - int ret = 0; - - /* Disable spy while we copy the addresses. - * As we don't disable interrupts, we need to do this */ - lp->spy_number = 0; - - /* Are there are addresses to copy? */ - if (wrqu->data.length > 0) { - /* Copy addresses to the lp structure. */ - for (i = 0; i < wrqu->data.length; i++) { - memcpy(lp->spy_address[i], address[i].sa_data, - WAVELAN_ADDR_SIZE); - } - - /* Reset structure. */ - memset(lp->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY); - -#ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG - "SetSpy: set of new addresses is: \n"); - for (i = 0; i < wrqu->data.length; i++) - printk(KERN_DEBUG - "%02X:%02X:%02X:%02X:%02X:%02X \n", - lp->spy_address[i][0], - lp->spy_address[i][1], - lp->spy_address[i][2], - lp->spy_address[i][3], - lp->spy_address[i][4], - lp->spy_address[i][5]); -#endif /* DEBUG_IOCTL_INFO */ - } - - /* Now we can set the number of addresses */ - lp->spy_number = wrqu->data.length; - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get spy list - */ -static int wavelan_get_spy(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ - struct sockaddr *address = (struct sockaddr *) extra; - int i; - - /* Set the number of addresses */ - wrqu->data.length = lp->spy_number; - - /* Copy addresses from the lp structure. */ - for (i = 0; i < lp->spy_number; i++) { - memcpy(address[i].sa_data, - lp->spy_address[i], - WAVELAN_ADDR_SIZE); - address[i].sa_family = AF_UNIX; - } - /* Copy stats to the user buffer (just after). */ - if(lp->spy_number > 0) - memcpy(extra + (sizeof(struct sockaddr) * lp->spy_number), - lp->spy_stat, sizeof(iw_qual) * lp->spy_number); - - /* Reset updated flags. */ - for (i = 0; i < lp->spy_number; i++) - lp->spy_stat[i].updated = 0x0; - - return(0); -} -#endif /* WIRELESS_SPY */ - /*------------------------------------------------------------------*/ /* * Wireless Private Handler : set quality threshold @@ -2439,15 +2349,10 @@ NULL, /* SIOCGIWPRIV */ NULL, /* SIOCSIWSTATS */ NULL, /* SIOCGIWSTATS */ -#ifdef WIRELESS_SPY - wavelan_set_spy, /* SIOCSIWSPY */ - wavelan_get_spy, /* SIOCGIWSPY */ -#else /* WIRELESS_SPY */ - NULL, /* SIOCSIWSPY */ - NULL, /* SIOCGIWSPY */ -#endif /* WIRELESS_SPY */ - NULL, /* -- hole -- */ - NULL, /* -- hole -- */ + iw_handler_set_spy, /* SIOCSIWSPY */ + iw_handler_get_spy, /* SIOCGIWSPY */ + iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ + iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ NULL, /* SIOCSIWAP */ NULL, /* SIOCGIWAP */ NULL, /* -- hole -- */ @@ -2501,6 +2406,8 @@ .standard = (iw_handler *) wavelan_handler, .private = (iw_handler *) wavelan_private_handler, .private_args = (struct iw_priv_args *) wavelan_private_args, + .spy_offset = ((void *) (&((net_local *) NULL)->spy_data) - + (void *) NULL), }; /*------------------------------------------------------------------*/ @@ -2618,22 +2525,23 @@ #endif /* DEBUG_RX_INFO */ /* Statistics-gathering and associated stuff. - * It seem a bit messy with all the define, but it's really simple... */ -#if defined(WIRELESS_SPY) || defined(HISTOGRAM) + * It seem a bit messy with all the define, but it's really + * simple... */ if ( -#ifdef WIRELESS_SPY - (lp->spy_number > 0) || -#endif /* WIRELESS_SPY */ +#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ + (lp->spy_data.spy_number > 0) || +#endif /* IW_WIRELESS_SPY */ #ifdef HISTOGRAM (lp->his_number > 0) || -#endif /* HISTOGRAM */ +#endif /* HISTOGRAM */ 0) { u8 stats[3]; /* signal level, noise level, signal quality */ - /* Read signal level, silence level and signal quality bytes. */ - /* Note: in the PCMCIA hardware, these are part of the frame. It seems - * that for the ISA hardware, it's nowhere to be found in the frame, - * so I'm obliged to do this (it has a side effect on /proc/net/wireless). + /* Read signal level, silence level and signal quality bytes */ + /* Note: in the PCMCIA hardware, these are part of the frame. + * It seems that for the ISA hardware, it's nowhere to be + * found in the frame, so I'm obliged to do this (it has a + * side effect on /proc/net/wireless). * Any ideas? */ mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1); @@ -2648,15 +2556,14 @@ #endif /* Spying stuff */ -#ifdef WIRELESS_SPY +#ifdef IW_WIRELESS_SPY wl_spy_gather(dev, skb->mac.raw + WAVELAN_ADDR_SIZE, stats); -#endif /* WIRELESS_SPY */ +#endif /* IW_WIRELESS_SPY */ #ifdef HISTOGRAM wl_his_gather(dev, stats); -#endif /* HISTOGRAM */ +#endif /* HISTOGRAM */ } -#endif /* defined(WIRELESS_SPY) || defined(HISTOGRAM) */ /* * Hand the packet to the network module. @@ -2884,10 +2791,6 @@ length); #endif - /* Do we need some padding? */ - if (clen < ETH_ZLEN) - clen = ETH_ZLEN; - spin_lock_irqsave(&lp->spinlock, flags); /* Check nothing bad has happened */ @@ -3008,12 +2911,6 @@ (unsigned) skb); #endif - if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) - return 0; - } - /* * Block a timer-based transmit from overlapping. * In other words, prevent reentering this routine. @@ -3035,6 +2932,17 @@ if (skb->next) printk(KERN_INFO "skb has next\n"); #endif + + /* Do we need some padding? */ + /* Note : on wireless the propagation time is in the order of 1us, + * and we don't have the Ethernet specific requirement of beeing + * able to detect collisions, therefore in theory we don't really + * need to pad. Jean II */ + if (skb->len < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + } /* Write packet on the card */ if(wv_packet_write(dev, skb->data, skb->len)) diff -Nru a/drivers/net/wireless/wavelan.p.h b/drivers/net/wireless/wavelan.p.h --- a/drivers/net/wireless/wavelan.p.h Thu May 15 15:24:41 2003 +++ b/drivers/net/wireless/wavelan.p.h Thu May 15 15:24:41 2003 @@ -509,13 +509,9 @@ #ifdef WIRELESS_EXT iw_stats wstats; /* Wireless-specific statistics */ -#endif -#ifdef WIRELESS_SPY - int spy_number; /* number of addresses to spy */ - mac_addr spy_address[IW_MAX_SPY]; /* the addresses to spy */ - iw_qual spy_stat[IW_MAX_SPY]; /* statistics gathered */ -#endif /* WIRELESS_SPY */ + struct iw_spy_data spy_data; +#endif #ifdef HISTOGRAM int his_number; /* number of intervals */ diff -Nru a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c --- a/drivers/net/wireless/wavelan_cs.c Thu May 15 15:24:39 2003 +++ b/drivers/net/wireless/wavelan_cs.c Thu May 15 15:24:39 2003 @@ -1757,10 +1757,8 @@ u_short table[10]; /* Authorized frequency table */ long freq = 0L; /* offset to 2.4 GHz in .5 MHz + 12 MHz */ int i; /* index in the table */ -#if WIRELESS_EXT > 7 const int BAND_NUM = 10; /* Number of bands */ int c = 0; /* Channel number */ -#endif /* WIRELESS_EXT */ /* Read the frequency table */ fee_read(base, 0x71 /* frequency table */, @@ -1772,13 +1770,11 @@ /* Look in the table if the frequency is allowed */ if(table[9 - (freq / 16)] & (1 << (freq % 16))) { -#if WIRELESS_EXT > 7 /* Compute approximate channel number */ while((((channel_bands[c] >> 1) - 24) < freq) && (c < BAND_NUM)) c++; list[i].i = c; /* Set the list index */ -#endif /* WIRELESS_EXT */ /* put in the list */ list[i].m = (((freq + 24) * 5) + 24000L) * 10000; @@ -1792,7 +1788,7 @@ return(i); } -#ifdef WIRELESS_SPY +#ifdef IW_WIRELESS_SPY /*------------------------------------------------------------------*/ /* * Gather wireless spy statistics : for each packet, compare the source @@ -1804,22 +1800,17 @@ u_char * mac, /* MAC address */ u_char * stats) /* Statistics to gather */ { - net_local * lp = (net_local *) dev->priv; - int i; + struct iw_quality wstats; - /* Look all addresses */ - for(i = 0; i < lp->spy_number; i++) - /* If match */ - if(!memcmp(mac, lp->spy_address[i], WAVELAN_ADDR_SIZE)) - { - /* Update statistics */ - lp->spy_stat[i].qual = stats[2] & MMR_SGNL_QUAL; - lp->spy_stat[i].level = stats[0] & MMR_SIGNAL_LVL; - lp->spy_stat[i].noise = stats[1] & MMR_SILENCE_LVL; - lp->spy_stat[i].updated = 0x7; - } + wstats.qual = stats[2] & MMR_SGNL_QUAL; + wstats.level = stats[0] & MMR_SIGNAL_LVL; + wstats.noise = stats[1] & MMR_SILENCE_LVL; + wstats.updated = 0x7; + + /* Update spy records */ + wireless_spy_update(dev, mac, &wstats); } -#endif /* WIRELESS_SPY */ +#endif /* IW_WIRELESS_SPY */ #ifdef HISTOGRAM /*------------------------------------------------------------------*/ @@ -1904,17 +1895,10 @@ spin_lock_irqsave(&lp->spinlock, flags); /* Set NWID in WaveLAN. */ -#if WIRELESS_EXT > 8 if (!wrqu->nwid.disabled) { /* Set NWID in psa */ psa.psa_nwid[0] = (wrqu->nwid.value & 0xFF00) >> 8; psa.psa_nwid[1] = wrqu->nwid.value & 0xFF; -#else /* WIRELESS_EXT > 8 */ - if(wrq->u.nwid.on) { - /* Set NWID in psa */ - psa.psa_nwid[0] = (wrq->u.nwid.nwid & 0xFF00) >> 8; - psa.psa_nwid[1] = wrq->u.nwid.nwid & 0xFF; -#endif /* WIRELESS_EXT > 8 */ psa.psa_nwid_select = 0x01; psa_write(dev, (char *) psa.psa_nwid - (char *) &psa, @@ -1971,14 +1955,9 @@ psa_read(dev, (char *) psa.psa_nwid - (char *) &psa, (unsigned char *) psa.psa_nwid, 3); -#if WIRELESS_EXT > 8 wrqu->nwid.value = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1]; wrqu->nwid.disabled = !(psa.psa_nwid_select); wrqu->nwid.fixed = 1; /* Superfluous */ -#else /* WIRELESS_EXT > 8 */ - wrq->u.nwid.nwid = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1]; - wrq->u.nwid.on = psa.psa_nwid_select; -#endif /* WIRELESS_EXT > 8 */ /* Enable interrupts and restore flags. */ spin_unlock_irqrestore(&lp->spinlock, flags); @@ -2081,13 +2060,9 @@ spin_lock_irqsave(&lp->spinlock, flags); /* Set the level threshold. */ -#if WIRELESS_EXT > 7 /* We should complain loudly if wrqu->sens.fixed = 0, because we * can't set auto mode... */ psa.psa_thr_pre_set = wrqu->sens.value & 0x3F; -#else /* WIRELESS_EXT > 7 */ - psa.psa_thr_pre_set = wrq->u.sensitivity & 0x3F; -#endif /* WIRELESS_EXT > 7 */ psa_write(dev, (char *) &psa.psa_thr_pre_set - (char *) &psa, (unsigned char *) &psa.psa_thr_pre_set, 1); @@ -2123,12 +2098,8 @@ psa_read(dev, (char *) &psa.psa_thr_pre_set - (char *) &psa, (unsigned char *) &psa.psa_thr_pre_set, 1); -#if WIRELESS_EXT > 7 wrqu->sens.value = psa.psa_thr_pre_set & 0x3F; wrqu->sens.fixed = 1; -#else /* WIRELESS_EXT > 7 */ - wrq->u.sensitivity = psa.psa_thr_pre_set & 0x3F; -#endif /* WIRELESS_EXT > 7 */ /* Enable interrupts and restore flags. */ spin_unlock_irqrestore(&lp->spinlock, flags); @@ -2136,7 +2107,6 @@ return ret; } -#if WIRELESS_EXT > 8 /*------------------------------------------------------------------*/ /* * Wireless Handler : set encryption key @@ -2253,10 +2223,8 @@ return ret; } -#endif /* WIRELESS_EXT > 8 */ #ifdef WAVELAN_ROAMING_EXT -#if WIRELESS_EXT > 5 /*------------------------------------------------------------------*/ /* * Wireless Handler : set ESSID (domain) @@ -2367,10 +2335,8 @@ return -EOPNOTSUPP; } -#endif /* WIRELESS_EXT > 5 */ #endif /* WAVELAN_ROAMING_EXT */ -#if WIRELESS_EXT > 8 #ifdef WAVELAN_ROAMING /*------------------------------------------------------------------*/ /* @@ -2429,7 +2395,6 @@ return 0; } #endif /* WAVELAN_ROAMING */ -#endif /* WIRELESS_EXT > 8 */ /*------------------------------------------------------------------*/ /* @@ -2452,11 +2417,9 @@ /* Set all the info we don't care or don't know about to zero */ memset(range, 0, sizeof(struct iw_range)); -#if WIRELESS_EXT > 10 /* Set the Wireless Extension versions */ range->we_version_compiled = WIRELESS_EXT; range->we_version_source = 9; -#endif /* WIRELESS_EXT > 10 */ /* Set information in the range struct. */ range->throughput = 1.4 * 1000 * 1000; /* don't argue on this ! */ @@ -2467,17 +2430,13 @@ range->max_qual.qual = MMR_SGNL_QUAL; range->max_qual.level = MMR_SIGNAL_LVL; range->max_qual.noise = MMR_SILENCE_LVL; -#if WIRELESS_EXT > 11 range->avg_qual.qual = MMR_SGNL_QUAL; /* Always max */ /* Need to get better values for those two */ range->avg_qual.level = 30; range->avg_qual.noise = 8; -#endif /* WIRELESS_EXT > 11 */ -#if WIRELESS_EXT > 7 range->num_bitrates = 1; range->bitrate[0] = 2000000; /* 2 Mb/s */ -#endif /* WIRELESS_EXT > 7 */ /* Disable interrupts and save flags. */ spin_lock_irqsave(&lp->spinlock, flags); @@ -2491,7 +2450,6 @@ } else range->num_channels = range->num_frequency = 0; -#if WIRELESS_EXT > 8 /* Encryption supported ? */ if (mmc_encr(base)) { range->encoding_size[0] = 8; /* DES = 64 bits key */ @@ -2501,7 +2459,6 @@ range->num_encoding_sizes = 0; range->max_encoding_tokens = 0; } -#endif /* WIRELESS_EXT > 8 */ /* Enable interrupts and restore flags. */ spin_unlock_irqrestore(&lp->spinlock, flags); @@ -2509,93 +2466,6 @@ return ret; } -#ifdef WIRELESS_SPY -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set spy list - */ -static int wavelan_set_spy(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ - struct sockaddr *address = (struct sockaddr *) extra; - int i; - int ret = 0; - - /* Disable spy while we copy the addresses. - * As we don't disable interrupts, we need to do this */ - lp->spy_number = 0; - - /* Are there are addresses to copy? */ - if (wrqu->data.length > 0) { - /* Copy addresses to the lp structure. */ - for (i = 0; i < wrqu->data.length; i++) { - memcpy(lp->spy_address[i], address[i].sa_data, - WAVELAN_ADDR_SIZE); - } - - /* Reset structure. */ - memset(lp->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY); - -#ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG - "SetSpy: set of new addresses is: \n"); - for (i = 0; i < wrqu->data.length; i++) - printk(KERN_DEBUG - "%02X:%02X:%02X:%02X:%02X:%02X \n", - lp->spy_address[i][0], - lp->spy_address[i][1], - lp->spy_address[i][2], - lp->spy_address[i][3], - lp->spy_address[i][4], - lp->spy_address[i][5]); -#endif /* DEBUG_IOCTL_INFO */ - } - - /* Now we can set the number of addresses */ - lp->spy_number = wrqu->data.length; - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get spy list - */ -static int wavelan_get_spy(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - net_local *lp = (net_local *) dev->priv; /* lp is not unused */ - struct sockaddr *address = (struct sockaddr *) extra; - int i; - - /* Set the number of addresses */ - wrqu->data.length = lp->spy_number; - - /* Copy addresses from the lp structure. */ - for (i = 0; i < lp->spy_number; i++) { - memcpy(address[i].sa_data, - lp->spy_address[i], - WAVELAN_ADDR_SIZE); - address[i].sa_family = AF_UNIX; - } - /* Copy stats to the user buffer (just after). */ - if(lp->spy_number > 0) - memcpy(extra + (sizeof(struct sockaddr) * lp->spy_number), - lp->spy_stat, sizeof(iw_qual) * lp->spy_number); - - /* Reset updated flags. */ - for (i = 0; i < lp->spy_number; i++) - lp->spy_stat[i].updated = 0x0; - - return(0); -} -#endif /* WIRELESS_SPY */ - /*------------------------------------------------------------------*/ /* * Wireless Private Handler : set quality threshold @@ -2781,8 +2651,6 @@ { SIOCGIPHISTO, 0, IW_PRIV_TYPE_INT | 16, "gethisto" }, }; -#if WIRELESS_EXT > 12 - static const iw_handler wavelan_handler[] = { NULL, /* SIOCSIWNAME */ @@ -2806,15 +2674,10 @@ NULL, /* SIOCGIWPRIV */ NULL, /* SIOCSIWSTATS */ NULL, /* SIOCGIWSTATS */ -#ifdef WIRELESS_SPY - wavelan_set_spy, /* SIOCSIWSPY */ - wavelan_get_spy, /* SIOCGIWSPY */ -#else /* WIRELESS_SPY */ - NULL, /* SIOCSIWSPY */ - NULL, /* SIOCGIWSPY */ -#endif /* WIRELESS_SPY */ - NULL, /* -- hole -- */ - NULL, /* -- hole -- */ + iw_handler_set_spy, /* SIOCSIWSPY */ + iw_handler_get_spy, /* SIOCGIWSPY */ + iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ + iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ #ifdef WAVELAN_ROAMING_EXT wavelan_set_wap, /* SIOCSIWAP */ wavelan_get_wap, /* SIOCGIWAP */ @@ -2834,7 +2697,6 @@ NULL, /* SIOCSIWESSID */ NULL, /* SIOCGIWESSID */ #endif /* WAVELAN_ROAMING_EXT */ -#if WIRELESS_EXT > 8 NULL, /* SIOCSIWNICKN */ NULL, /* SIOCGIWNICKN */ NULL, /* -- hole -- */ @@ -2851,7 +2713,6 @@ NULL, /* SIOCGIWRETRY */ wavelan_set_encode, /* SIOCSIWENCODE */ wavelan_get_encode, /* SIOCGIWENCODE */ -#endif /* WIRELESS_EXT > 8 */ }; static const iw_handler wavelan_private_handler[] = @@ -2879,8 +2740,9 @@ .standard = (iw_handler *) wavelan_handler, .private = (iw_handler *) wavelan_private_handler, .private_args = (struct iw_priv_args *) wavelan_private_args, + .spy_offset = ((void *) (&((net_local *) NULL)->spy_data) - + (void *) NULL), }; -#endif /* WIRELESS_EXT > 12 */ /*------------------------------------------------------------------*/ /* @@ -2892,9 +2754,6 @@ struct ifreq * rq, /* Data passed */ int cmd) /* Ioctl number */ { -#if WIRELESS_EXT <= 12 - struct iwreq * wrq = (struct iwreq *) rq; -#endif int ret = 0; #ifdef DEBUG_IOCTL_TRACE @@ -2908,284 +2767,6 @@ ret = wl_netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); break; -#if WIRELESS_EXT <= 12 - /* --------------- WIRELESS EXTENSIONS --------------- */ - /* Now done as iw_handler - Jean II */ - case SIOCGIWNAME: - wavelan_get_name(dev, NULL, &(wrq->u), NULL); - break; - - case SIOCSIWNWID: - ret = wavelan_set_nwid(dev, NULL, &(wrq->u), NULL); - break; - - case SIOCGIWNWID: - ret = wavelan_get_nwid(dev, NULL, &(wrq->u), NULL); - break; - - case SIOCSIWFREQ: - ret = wavelan_set_freq(dev, NULL, &(wrq->u), NULL); - break; - - case SIOCGIWFREQ: - ret = wavelan_get_freq(dev, NULL, &(wrq->u), NULL); - break; - - case SIOCSIWSENS: - ret = wavelan_set_sens(dev, NULL, &(wrq->u), NULL); - break; - - case SIOCGIWSENS: - ret = wavelan_get_sens(dev, NULL, &(wrq->u), NULL); - break; - -#if WIRELESS_EXT > 8 - case SIOCSIWENCODE: - { - char keybuf[8]; - if (wrq->u.encoding.pointer) { - /* We actually have a key to set */ - if (wrq->u.encoding.length != 8) { - ret = -EINVAL; - break; - } - if (copy_from_user(keybuf, - wrq->u.encoding.pointer, - wrq->u.encoding.length)) { - ret = -EFAULT; - break; - } - } else if (wrq->u.encoding.length != 0) { - ret = -EINVAL; - break; - } - ret = wavelan_set_encode(dev, NULL, &(wrq->u), keybuf); - } - break; - - case SIOCGIWENCODE: - if (! capable(CAP_NET_ADMIN)) { - ret = -EPERM; - break; - } - { - char keybuf[8]; - ret = wavelan_get_encode(dev, NULL, - &(wrq->u), - keybuf); - if (wrq->u.encoding.pointer) { - if (copy_to_user(wrq->u.encoding.pointer, - keybuf, - wrq->u.encoding.length)) - ret = -EFAULT; - } - } - break; -#endif /* WIRELESS_EXT > 8 */ - -#ifdef WAVELAN_ROAMING_EXT -#if WIRELESS_EXT > 5 - case SIOCSIWESSID: - { - char essidbuf[IW_ESSID_MAX_SIZE+1]; - if (wrq->u.essid.length > IW_ESSID_MAX_SIZE) { - ret = -E2BIG; - break; - } - if (copy_from_user(essidbuf, wrq->u.essid.pointer, - wrq->u.essid.length)) { - ret = -EFAULT; - break; - } - ret = wavelan_set_essid(dev, NULL, - &(wrq->u), - essidbuf); - } - break; - - case SIOCGIWESSID: - { - char essidbuf[IW_ESSID_MAX_SIZE+1]; - ret = wavelan_get_essid(dev, NULL, - &(wrq->u), - essidbuf); - if (wrq->u.essid.pointer) - if ( copy_to_user(wrq->u.essid.pointer, - essidbuf, - wrq->u.essid.length) ) - ret = -EFAULT; - } - break; - - case SIOCSIWAP: - ret = wavelan_set_wap(dev, NULL, &(wrq->u), NULL); - break; - - case SIOCGIWAP: - ret = wavelan_get_wap(dev, NULL, &(wrq->u), NULL); - break; -#endif /* WIRELESS_EXT > 5 */ -#endif /* WAVELAN_ROAMING_EXT */ - -#if WIRELESS_EXT > 8 -#ifdef WAVELAN_ROAMING - case SIOCSIWMODE: - ret = wavelan_set_mode(dev, NULL, &(wrq->u), NULL); - break; - - case SIOCGIWMODE: - ret = wavelan_get_mode(dev, NULL, &(wrq->u), NULL); - break; -#endif /* WAVELAN_ROAMING */ -#endif /* WIRELESS_EXT > 8 */ - - case SIOCGIWRANGE: - { - struct iw_range range; - ret = wavelan_get_range(dev, NULL, - &(wrq->u), - (char *) &range); - if (copy_to_user(wrq->u.data.pointer, &range, - sizeof(struct iw_range))) - ret = -EFAULT; - } - break; - - case SIOCGIWPRIV: - /* Basic checking... */ - if(wrq->u.data.pointer != (caddr_t) 0) - { - /* Set the number of ioctl available */ - wrq->u.data.length = sizeof(wavelan_private_args) / sizeof(wavelan_private_args[0]); - - /* Copy structure to the user buffer */ - if(copy_to_user(wrq->u.data.pointer, (u_char *) wavelan_private_args, - sizeof(wavelan_private_args))) - ret = -EFAULT; - } - break; - -#ifdef WIRELESS_SPY - case SIOCSIWSPY: - { - struct sockaddr address[IW_MAX_SPY]; - /* Check the number of addresses */ - if (wrq->u.data.length > IW_MAX_SPY) { - ret = -E2BIG; - break; - } - /* Get the data in the driver */ - if (wrq->u.data.pointer) { - if (copy_from_user((char *) address, - wrq->u.data.pointer, - sizeof(struct sockaddr) * - wrq->u.data.length)) { - ret = -EFAULT; - break; - } - } else if (wrq->u.data.length != 0) { - ret = -EINVAL; - break; - } - ret = wavelan_set_spy(dev, NULL, &(wrq->u), - (char *) address); - } - break; - - case SIOCGIWSPY: - { - char buffer[IW_MAX_SPY * (sizeof(struct sockaddr) + - sizeof(struct iw_quality))]; - ret = wavelan_get_spy(dev, NULL, &(wrq->u), - buffer); - if (wrq->u.data.pointer) { - if (copy_to_user(wrq->u.data.pointer, - buffer, - (wrq->u.data.length * - (sizeof(struct sockaddr) + - sizeof(struct iw_quality))) - )) - ret = -EFAULT; - } - } - break; -#endif /* WIRELESS_SPY */ - - /* ------------------ PRIVATE IOCTL ------------------ */ - - case SIOCSIPQTHR: - if(!capable(CAP_NET_ADMIN)) - { - ret = -EPERM; - break; - } - ret = wavelan_set_qthr(dev, NULL, &(wrq->u), NULL); - break; - - case SIOCGIPQTHR: - ret = wavelan_get_qthr(dev, NULL, &(wrq->u), NULL); - break; - -#ifdef WAVELAN_ROAMING - case SIOCSIPROAM: - /* Note : should check if user == root */ - ret = wavelan_set_roam(dev, NULL, &(wrq->u), NULL); - break; - - case SIOCGIPROAM: - ret = wavelan_get_roam(dev, NULL, &(wrq->u), NULL); - break; -#endif /* WAVELAN_ROAMING */ - -#ifdef HISTOGRAM - case SIOCSIPHISTO: - /* Verif if the user is root */ - if(!capable(CAP_NET_ADMIN)) - { - ret = -EPERM; - } - { - char buffer[16]; - /* Check the number of intervals */ - if(wrq->u.data.length > 16) - { - ret = -E2BIG; - break; - } - /* Get the data in the driver */ - if (wrq->u.data.pointer) { - if (copy_from_user(buffer, - wrq->u.data.pointer, - sizeof(struct sockaddr) * - wrq->u.data.length)) { - ret = -EFAULT; - break; - } - } else if (wrq->u.data.length != 0) { - ret = -EINVAL; - break; - } - ret = wavelan_set_histo(dev, NULL, &(wrq->u), - buffer); - } - break; - - case SIOCGIPHISTO: - { - long buffer[16]; - ret = wavelan_get_histo(dev, NULL, &(wrq->u), - (char *) buffer); - if (wrq->u.data.pointer) { - if (copy_to_user(wrq->u.data.pointer, - buffer, - (wrq->u.data.length * sizeof(long)))) - ret = -EFAULT; - } - } - break; -#endif /* HISTOGRAM */ -#endif /* WIRELESS_EXT <= 12 */ - /* ------------------- OTHER IOCTL ------------------- */ default: @@ -3368,9 +2949,9 @@ /* Statistics gathering & stuff associated. * It seem a bit messy with all the define, but it's really simple... */ if( -#ifdef WIRELESS_SPY - (lp->spy_number > 0) || -#endif /* WIRELESS_SPY */ +#ifdef IW_WIRELESS_SPY + (lp->spy_data.spy_number > 0) || +#endif /* IW_WIRELESS_SPY */ #ifdef HISTOGRAM (lp->his_number > 0) || #endif /* HISTOGRAM */ @@ -3581,10 +3162,6 @@ spin_lock_irqsave(&lp->spinlock, flags); - /* Check if we need some padding */ - if(clen < ETH_ZLEN) - clen = ETH_ZLEN; - /* Write the length of data buffer followed by the buffer */ outb(xmtdata_base & 0xff, PIORL(base)); outb(((xmtdata_base >> 8) & PIORH_MASK) | PIORH_SEL_TX, PIORH(base)); @@ -3664,6 +3241,17 @@ printk(KERN_INFO "skb has next\n"); #endif + /* Check if we need some padding */ + /* Note : on wireless the propagation time is in the order of 1us, + * and we don't have the Ethernet specific requirement of beeing + * able to detect collisions, therefore in theory we don't really + * need to pad. Jean II */ + if (skb->len < ETH_ZLEN) { + skb = skb_padto(skb, ETH_ZLEN); + if (skb == NULL) + return 0; + } + wv_packet_write(dev, skb->data, skb->len); dev_kfree_skb(skb); @@ -4644,7 +4232,7 @@ * ready to transmit another packet. * 3. A command has completed execution. */ -static void +static irqreturn_t wavelan_interrupt(int irq, void * dev_id, struct pt_regs * regs) @@ -4661,7 +4249,7 @@ printk(KERN_WARNING "wavelan_interrupt(): irq %d for unknown device.\n", irq); #endif - return; + return IRQ_NONE; } #ifdef DEBUG_INTERRUPT_TRACE @@ -4883,6 +4471,24 @@ #ifdef DEBUG_INTERRUPT_TRACE printk(KERN_DEBUG "%s: <-wavelan_interrupt()\n", dev->name); #endif + + /* We always return IRQ_HANDLED, because we will receive empty + * interrupts under normal operations. Anyway, it doesn't matter + * as we are dealing with an ISA interrupt that can't be shared. + * + * Explanation : under heavy receive, the following happens : + * ->wavelan_interrupt() + * (status0 & SR0_INTERRUPT) != 0 + * ->wv_packet_rcv() + * (status0 & SR0_INTERRUPT) != 0 + * ->wv_packet_rcv() + * (status0 & SR0_INTERRUPT) == 0 // i.e. no more event + * <-wavelan_interrupt() + * ->wavelan_interrupt() + * (status0 & SR0_INTERRUPT) == 0 // i.e. empty interrupt + * <-wavelan_interrupt() + * Jean II */ + return IRQ_HANDLED; } /* wv_interrupt */ /*------------------------------------------------------------------*/ @@ -5189,9 +4795,7 @@ dev->watchdog_timeo = WATCHDOG_JIFFIES; #ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */ -#if WIRELESS_EXT > 12 dev->wireless_handlers = (struct iw_handler_def *)&wavelan_handler_def; -#endif /* WIRELESS_EXT > 12 */ dev->do_ioctl = wavelan_ioctl; /* old wireless extensions */ dev->get_wireless_stats = wavelan_get_wireless_stats; #endif diff -Nru a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h --- a/drivers/net/wireless/wavelan_cs.p.h Thu May 15 15:24:42 2003 +++ b/drivers/net/wireless/wavelan_cs.p.h Thu May 15 15:24:42 2003 @@ -443,9 +443,7 @@ #ifdef CONFIG_NET_RADIO #include /* Wireless extensions */ -#if WIRELESS_EXT > 12 -#include -#endif /* WIRELESS_EXT > 12 */ +#include /* New driver API */ #endif /* Pcmcia headers that we need */ @@ -527,13 +525,6 @@ /* ------------------------ PRIVATE IOCTL ------------------------ */ -/* Wireless Extension Backward compatibility - Jean II - * If the new wireless device private ioctl range is not defined, - * default to standard device private ioctl range */ -#ifndef SIOCIWFIRSTPRIV -#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE -#endif /* SIOCIWFIRSTPRIV */ - #define SIOCSIPQTHR SIOCIWFIRSTPRIV /* Set quality threshold */ #define SIOCGIPQTHR SIOCIWFIRSTPRIV + 1 /* Get quality threshold */ #define SIOCSIPROAM SIOCIWFIRSTPRIV + 2 /* Set roaming state */ @@ -605,16 +596,6 @@ typedef struct net_local net_local; typedef struct timer_list timer_list; -#if WIRELESS_EXT <= 12 -/* Wireless extensions backward compatibility */ -/* Part of iw_handler prototype we need */ -struct iw_request_info -{ - __u16 cmd; /* Wireless Extension command */ - __u16 flags; /* More to come ;-) */ -}; -#endif /* WIRELESS_EXT <= 12 */ - /* Basic types */ typedef u_char mac_addr[WAVELAN_ADDR_SIZE]; /* Hardware address */ @@ -647,13 +628,10 @@ #ifdef WIRELESS_EXT iw_stats wstats; /* Wireless specific stats */ + + struct iw_spy_data spy_data; #endif -#ifdef WIRELESS_SPY - int spy_number; /* Number of addresses to spy */ - mac_addr spy_address[IW_MAX_SPY]; /* The addresses to spy */ - iw_qual spy_stat[IW_MAX_SPY]; /* Statistics gathered */ -#endif /* WIRELESS_SPY */ #ifdef HISTOGRAM int his_number; /* Number of intervals */ u_char his_range[16]; /* Boundaries of interval ]n-1; n] */ @@ -686,11 +664,6 @@ void wv_roam_cleanup(struct net_device *dev); #endif /* WAVELAN_ROAMING */ -/* ----------------------- MISC SUBROUTINES ------------------------ */ -static void - cs_error(client_handle_t, /* Report error to cardmgr */ - int, - int); /* ----------------- MODEM MANAGEMENT SUBROUTINES ----------------- */ static inline u_char /* data */ hasr_read(u_long); /* Read the host interface : base address */ @@ -791,7 +764,7 @@ wv_pcmcia_release(u_long), /* Remove a device */ wv_flush_stale_links(void); /* "detach" all possible devices */ /* ---------------------- INTERRUPT HANDLING ---------------------- */ -static void +static irqreturn_t wavelan_interrupt(int, /* Interrupt handler */ void *, struct pt_regs *); diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c --- a/drivers/pci/quirks.c Thu May 15 15:24:33 2003 +++ b/drivers/pci/quirks.c Thu May 15 15:24:33 2003 @@ -647,6 +647,56 @@ } /* + * On ASUS P4B boards, the SMBus PCI Device within the ICH2/4 southbridge + * is not activated. The myth is that Asus said that they do not want the + * users to be irritated by just another PCI Device in the Win98 device + * manager. (see the file prog/hotplug/README.p4b in the lm_sensors + * package 2.7.0 for details) + * + * The SMBus PCI Device can be activated by setting a bit in the ICH LPC + * bridge. Unfortunately, this device has no subvendor/subdevice ID. So it + * becomes necessary to do this tweak in two steps -- I've chosen the Host + * bridge as trigger. + */ + +static int __initdata asus_hides_smbus = 0; + +static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) +{ + if (likely(dev->subsystem_vendor != PCI_VENDOR_ID_ASUSTEK)) + return; + + if ((dev->device == PCI_DEVICE_ID_INTEL_82845_HB) && + (dev->subsystem_device == 0x8088)) /* P4B533 */ + asus_hides_smbus = 1; + if ((dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) && + (dev->subsystem_device == 0x80b2)) /* P4PE */ + asus_hides_smbus = 1; + if ((dev->device == PCI_DEVICE_ID_INTEL_82850_HB) && + (dev->subsystem_device == 0x8030)) /* P4T533 */ + asus_hides_smbus = 1; + return; +} + +static void __init asus_hides_smbus_lpc(struct pci_dev *dev) +{ + u16 val; + + if (likely(!asus_hides_smbus)) + return; + + pci_read_config_word(dev, 0xF2, &val); + if (val & 0x8) { + pci_write_config_word(dev, 0xF2, val & (~0x8)); + pci_read_config_word(dev, 0xF2, &val); + if(val & 0x8) + printk(KERN_INFO "PCI: i801 SMBus device continues to play 'hide and seek'! 0x%x\n", val); + else + printk(KERN_INFO "PCI: Enabled i801 SMBus device\n"); + } +} + +/* * The main table of quirks. */ @@ -724,6 +774,15 @@ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_eisa_bridge }, + + /* + * on Asus P4B boards, the i801SMBus device is disabled at startup. + */ + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845_HB, asus_hides_smbus_hostbridge }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845G_HB, asus_hides_smbus_hostbridge }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82850_HB, asus_hides_smbus_hostbridge }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc }, { 0 } }; diff -Nru a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c --- a/drivers/pcmcia/cs.c Thu May 15 15:24:35 2003 +++ b/drivers/pcmcia/cs.c Thu May 15 15:24:35 2003 @@ -302,11 +302,8 @@ ======================================================================*/ -static int setup_socket(socket_info_t *); -static void shutdown_socket(socket_info_t *); -static void reset_socket(socket_info_t *); -static void unreset_socket(socket_info_t *); -static void parse_events(void *info, u_int events); +static int pccardd(void *__skt); +void pcmcia_unregister_socket(struct class_device *dev); #define to_class_data(dev) dev->class_data @@ -317,7 +314,7 @@ { struct pcmcia_socket_class_data *cls_d = class_get_devdata(class_dev); socket_info_t *s_info; - unsigned int i, j; + unsigned int i, j, ret; if (!cls_d) return -EINVAL; @@ -330,6 +327,7 @@ memset(s_info, 0, cls_d->nsock * sizeof(socket_info_t)); cls_d->s_info = s_info; + ret = 0; /* socket initialization */ for (i = 0; i < cls_d->nsock; i++) { @@ -344,7 +342,7 @@ s->erase_busy.next = s->erase_busy.prev = &s->erase_busy; INIT_LIST_HEAD(&s->cis_cache); spin_lock_init(&s->lock); - + /* TBD: remove usage of socket_table, use class_for_each_dev instead */ for (j = 0; j < sockets; j++) if (socket_table[j] == NULL) break; @@ -353,6 +351,20 @@ init_socket(s); s->ss_entry->inquire_socket(s->sock, &s->cap); + + init_completion(&s->thread_done); + init_waitqueue_head(&s->thread_wait); + init_MUTEX(&s->skt_sem); + spin_lock_init(&s->thread_lock); + ret = kernel_thread(pccardd, s, CLONE_KERNEL); + if (ret < 0) { + pcmcia_unregister_socket(class_dev); + break; + } + + wait_for_completion(&s->thread_done); + BUG_ON(!s->thread); + #ifdef CONFIG_PROC_FS if (proc_pccard) { char name[3]; @@ -368,7 +380,7 @@ } #endif } - return 0; + return ret; } /* pcmcia_register_socket */ @@ -407,8 +419,12 @@ remove_proc_entry(name, proc_pccard); } #endif - - shutdown_socket(s); + if (s->thread) { + init_completion(&s->thread_done); + s->thread = NULL; + wake_up(&s->thread_wait); + wait_for_completion(&s->thread_done); + } release_cis_mem(s); while (s->clients) { client = s->clients; @@ -450,15 +466,6 @@ static int send_event(socket_info_t *s, event_t event, int priority); -/* - * Sleep for n_cs centiseconds (1 cs = 1/100th of a second) - */ -static void cs_sleep(unsigned int n_cs) -{ - current->state = TASK_INTERRUPTIBLE; - schedule_timeout( (n_cs * HZ + 99) / 100); -} - static void shutdown_socket(socket_info_t *s) { client_t **c; @@ -505,132 +512,6 @@ free_regions(&s->c_region); } /* shutdown_socket */ -/* - * Return zero if we think the card isn't actually present - */ -static int setup_socket(socket_info_t *s) -{ - int val, ret; - int setup_timeout = 100; - - /* Wait for "not pending" */ - for (;;) { - get_socket_status(s, &val); - if (!(val & SS_PENDING)) - break; - if (--setup_timeout) { - cs_sleep(10); - continue; - } - printk(KERN_NOTICE "cs: socket %p voltage interrogation" - " timed out\n", s); - ret = 0; - goto out; - } - - if (val & SS_DETECT) { - DEBUG(1, "cs: setup_socket(%p): applying power\n", s); - s->state |= SOCKET_PRESENT; - s->socket.flags &= SS_DEBOUNCED; - if (val & SS_3VCARD) - s->socket.Vcc = s->socket.Vpp = 33; - else if (!(val & SS_XVCARD)) - s->socket.Vcc = s->socket.Vpp = 50; - else { - printk(KERN_NOTICE "cs: socket %p: unsupported " - "voltage key\n", s); - s->socket.Vcc = 0; - } - if (val & SS_CARDBUS) { - s->state |= SOCKET_CARDBUS; -#ifndef CONFIG_CARDBUS - printk(KERN_NOTICE "cs: unsupported card type detected!\n"); -#endif - } - set_socket(s, &s->socket); - cs_sleep(vcc_settle); - reset_socket(s); - ret = 1; - } else { - DEBUG(0, "cs: setup_socket(%p): no card!\n", s); - ret = 0; - } -out: - return ret; -} /* setup_socket */ - -/*====================================================================== - - Reset_socket() and unreset_socket() handle hard resets. Resets - have several causes: card insertion, a call to reset_socket, or - recovery from a suspend/resume cycle. Unreset_socket() sends - a CS event that matches the cause of the reset. - -======================================================================*/ - -static void reset_socket(socket_info_t *s) -{ - DEBUG(1, "cs: resetting socket %p\n", s); - s->socket.flags |= SS_OUTPUT_ENA | SS_RESET; - set_socket(s, &s->socket); - udelay((long)reset_time); - s->socket.flags &= ~SS_RESET; - set_socket(s, &s->socket); - cs_sleep(unreset_delay); - unreset_socket(s); -} /* reset_socket */ - -#define EVENT_MASK \ -(SOCKET_SETUP_PENDING|SOCKET_SUSPEND|SOCKET_RESET_PENDING) - -static void unreset_socket(socket_info_t *s) -{ - int setup_timeout = unreset_limit; - int val; - - /* Wait for "ready" */ - for (;;) { - get_socket_status(s, &val); - if (val & SS_READY) - break; - DEBUG(2, "cs: socket %d not ready yet\n", s->sock); - if (--setup_timeout) { - cs_sleep(unreset_check); - continue; - } - printk(KERN_NOTICE "cs: socket %p timed out during" - " reset. Try increasing setup_delay.\n", s); - s->state &= ~EVENT_MASK; - return; - } - - DEBUG(1, "cs: reset done on socket %p\n", s); - if (s->state & SOCKET_SUSPEND) { - s->state &= ~EVENT_MASK; - if (verify_cis_cache(s) != 0) - parse_events(s, SS_DETECT); - else - send_event(s, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW); - } else if (s->state & SOCKET_SETUP_PENDING) { -#ifdef CONFIG_CARDBUS - if (s->state & SOCKET_CARDBUS) { - cb_alloc(s); - s->state |= SOCKET_CARDBUS_CONFIG; - } -#endif - send_event(s, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); - s->state &= ~SOCKET_SETUP_PENDING; - } else { - send_event(s, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW); - if (s->reset_handle) { - s->reset_handle->event_callback_args.info = NULL; - EVENT(s->reset_handle, CS_EVENT_RESET_COMPLETE, - CS_EVENT_PRI_LOW); - } - s->state &= ~EVENT_MASK; - } -} /* unreset_socket */ - /*====================================================================== The central event handler. Send_event() sends an event to all @@ -661,61 +542,266 @@ return ret; } /* send_event */ -static void do_shutdown(socket_info_t *s) +static void pcmcia_error(socket_info_t *skt, const char *fmt, ...) { - client_t *client; - if (s->state & SOCKET_SHUTDOWN_PENDING) - return; - s->state |= SOCKET_SHUTDOWN_PENDING; - send_event(s, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH); - for (client = s->clients; client; client = client->next) - if (!(client->Attributes & INFO_MASTER_CLIENT)) - client->state |= CLIENT_STALE; - if (s->state & (SOCKET_SETUP_PENDING|SOCKET_RESET_PENDING)) { - DEBUG(0, "cs: flushing pending setup\n"); - s->state &= ~EVENT_MASK; - } - cs_sleep(shutdown_delay); - s->state &= ~SOCKET_PRESENT; - shutdown_socket(s); + static char buf[128]; + va_list ap; + int len; + + va_start(ap, fmt); + len = vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + buf[len] = '\0'; + + printk(KERN_ERR "PCMCIA: socket %p: %s", skt, buf); +} + +#define cs_to_timeout(cs) (((cs) * HZ + 99) / 100) + +static void socket_remove_drivers(socket_info_t *skt) +{ + client_t *client; + + send_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH); + + for (client = skt->clients; client; client = client->next) + if (!(client->Attributes & INFO_MASTER_CLIENT)) + client->state |= CLIENT_STALE; +} + +static void socket_shutdown(socket_info_t *skt) +{ + socket_remove_drivers(skt); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(cs_to_timeout(shutdown_delay)); + skt->state &= ~SOCKET_PRESENT; + shutdown_socket(skt); +} + +static int socket_reset(socket_info_t *skt) +{ + int status, i; + + skt->socket.flags |= SS_OUTPUT_ENA | SS_RESET; + set_socket(skt, &skt->socket); + udelay((long)reset_time); + + skt->socket.flags &= ~SS_RESET; + set_socket(skt, &skt->socket); + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(cs_to_timeout(unreset_delay)); + for (i = 0; i < unreset_limit; i++) { + get_socket_status(skt, &status); + + if (!(status & SS_DETECT)) + return CS_NO_CARD; + + if (status & SS_READY) + return CS_SUCCESS; + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(cs_to_timeout(unreset_check)); + } + + pcmcia_error(skt, "time out after reset.\n"); + return CS_GENERAL_FAILURE; +} + +static int socket_setup(socket_info_t *skt, int initial_delay) +{ + int status, i; + + get_socket_status(skt, &status); + if (!(status & SS_DETECT)) + return CS_NO_CARD; + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(cs_to_timeout(initial_delay)); + + for (i = 0; i < 100; i++) { + get_socket_status(skt, &status); + if (!(status & SS_DETECT)) + return CS_NO_CARD; + + if (!(status & SS_PENDING)) + break; + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(cs_to_timeout(10)); + } + + if (status & SS_PENDING) { + pcmcia_error(skt, "voltage interrogation timed out.\n"); + return CS_GENERAL_FAILURE; + } + + if (status & SS_CARDBUS) { + skt->state |= SOCKET_CARDBUS; +#ifndef CONFIG_CARDBUS + pcmcia_error(skt, "cardbus cards are not supported.\n"); + return CS_BAD_TYPE; +#endif + } + + /* + * Decode the card voltage requirements, and apply power to the card. + */ + if (status & SS_3VCARD) + skt->socket.Vcc = skt->socket.Vpp = 33; + else if (!(status & SS_XVCARD)) + skt->socket.Vcc = skt->socket.Vpp = 50; + else { + pcmcia_error(skt, "unsupported voltage key.\n"); + return CS_BAD_TYPE; + } + skt->state |= SOCKET_PRESENT; + skt->socket.flags = SS_DEBOUNCED; + set_socket(skt, &skt->socket); + + /* + * Wait "vcc_settle" for the supply to stabilise. + */ + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(cs_to_timeout(vcc_settle)); + + return socket_reset(skt); +} + +/* + * Handle card insertion. Setup the socket, reset the card, + * and then tell the rest of PCMCIA that a card is present. + */ +static int socket_insert(socket_info_t *skt) +{ + int ret; + + ret = socket_setup(skt, setup_delay); + if (ret == CS_SUCCESS) { +#ifdef CONFIG_CARDBUS + if (skt->state & SOCKET_CARDBUS) { + cb_alloc(skt); + skt->state |= SOCKET_CARDBUS_CONFIG; + } +#endif + send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); + skt->socket.flags &= ~SS_DEBOUNCED; + } else + socket_shutdown(skt); + + return ret; +} + +static int socket_suspend(socket_info_t *skt) +{ + if (skt->state & SOCKET_SUSPEND) + return CS_IN_USE; + + send_event(skt, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW); + suspend_socket(skt); + skt->state |= SOCKET_SUSPEND; + + return CS_SUCCESS; +} + +/* + * Resume a socket. If a card is present, verify its CIS against + * our cached copy. If they are different, the card has been + * replaced, and we need to tell the drivers. + */ +static int socket_resume(socket_info_t *skt) +{ + int ret; + + if (!(skt->state & SOCKET_SUSPEND)) + return CS_IN_USE; + + init_socket(skt); + + ret = socket_setup(skt, resume_delay); + if (ret == CS_SUCCESS) { + /* + * FIXME: need a better check here for cardbus cards. + */ + if (verify_cis_cache(skt) != 0) { + socket_remove_drivers(skt); + destroy_cis_cache(skt); + send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); + } else { + send_event(skt, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW); + } + skt->socket.flags &= ~SS_DEBOUNCED; + } else + socket_shutdown(skt); + + skt->state &= ~SOCKET_SUSPEND; + + return CS_SUCCESS; +} + +static int pccardd(void *__skt) +{ + socket_info_t *skt = __skt; + DECLARE_WAITQUEUE(wait, current); + + daemonize("pccardd"); + skt->thread = current; + complete(&skt->thread_done); + + add_wait_queue(&skt->thread_wait, &wait); + for (;;) { + unsigned long flags; + unsigned int events; + + set_current_state(TASK_INTERRUPTIBLE); + + spin_lock_irqsave(&skt->thread_lock, flags); + events = skt->thread_events; + skt->thread_events = 0; + spin_unlock_irqrestore(&skt->thread_lock, flags); + + if (events) { + down(&skt->skt_sem); + if (events & SS_DETECT && !(skt->state & SOCKET_SUSPEND)) { + int status; + + get_socket_status(skt, &status); + if ((skt->state & SOCKET_PRESENT) && + !(status & SS_DETECT)) + socket_shutdown(skt); + if (status & SS_DETECT) + socket_insert(skt); + } + if (events & SS_BATDEAD) + send_event(skt, CS_EVENT_BATTERY_DEAD, CS_EVENT_PRI_LOW); + if (events & SS_BATWARN) + send_event(skt, CS_EVENT_BATTERY_LOW, CS_EVENT_PRI_LOW); + if (events & SS_READY) + send_event(skt, CS_EVENT_READY_CHANGE, CS_EVENT_PRI_LOW); + up(&skt->skt_sem); + continue; + } + + schedule(); + if (!skt->thread) + break; + } + remove_wait_queue(&skt->thread_wait, &wait); + + socket_shutdown(skt); + + complete_and_exit(&skt->thread_done, 0); } static void parse_events(void *info, u_int events) { - socket_info_t *s = info; - if (events & SS_DETECT) { - int status; - - get_socket_status(s, &status); - if ((s->state & SOCKET_PRESENT) && - (!(s->state & SOCKET_SUSPEND) || - !(status & SS_DETECT))) - do_shutdown(s); - if (status & SS_DETECT) { - if (s->state & SOCKET_SETUP_PENDING) { - DEBUG(1, "cs: delaying pending setup\n"); - return; - } - s->state |= SOCKET_SETUP_PENDING; - if (s->state & SOCKET_SUSPEND) - cs_sleep(resume_delay); - else - cs_sleep(setup_delay); - s->socket.flags |= SS_DEBOUNCED; - if (setup_socket(s) == 0) - s->state &= ~SOCKET_SETUP_PENDING; - s->socket.flags &= ~SS_DEBOUNCED; - } - } - if (events & SS_BATDEAD) - send_event(s, CS_EVENT_BATTERY_DEAD, CS_EVENT_PRI_LOW); - if (events & SS_BATWARN) - send_event(s, CS_EVENT_BATTERY_LOW, CS_EVENT_PRI_LOW); - if (events & SS_READY) { - if (!(s->state & SOCKET_RESET_PENDING)) - send_event(s, CS_EVENT_READY_CHANGE, CS_EVENT_PRI_LOW); - else DEBUG(1, "cs: ready change during reset\n"); - } + socket_info_t *s = info; + + spin_lock(&s->thread_lock); + s->thread_events |= events; + spin_unlock(&s->thread_lock); + + wake_up(&s->thread_wait); } /* parse_events */ /*====================================================================== @@ -727,27 +813,18 @@ ======================================================================*/ -void pcmcia_suspend_socket (socket_info_t *s) +void pcmcia_suspend_socket (socket_info_t *skt) { - if ((s->state & SOCKET_PRESENT) && !(s->state & SOCKET_SUSPEND)) { - send_event(s, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW); - suspend_socket(s); - s->state |= SOCKET_SUSPEND; - } + down(&skt->skt_sem); + socket_suspend(skt); + up(&skt->skt_sem); } -void pcmcia_resume_socket (socket_info_t *s) +void pcmcia_resume_socket (socket_info_t *skt) { - int stat; - - /* Do this just to reinitialize the socket */ - init_socket(s); - get_socket_status(s, &stat); - - /* If there was or is a card here, we need to do something - about it... but parse_events will sort it all out. */ - if ((s->state & SOCKET_PRESENT) || (stat & SS_DETECT)) - parse_events(s, SS_DETECT); + down(&skt->skt_sem); + socket_resume(skt); + up(&skt->skt_sem); } @@ -1461,15 +1538,8 @@ s = socket_table[ns]; if (++s->real_clients == 1) { - int status; register_callback(s, &parse_events, s); - get_socket_status(s, &status); - if ((status & SS_DETECT) && - !(s->state & SOCKET_SETUP_PENDING)) { - s->state |= SOCKET_SETUP_PENDING; - if (setup_socket(s) == 0) - s->state &= ~SOCKET_SETUP_PENDING; - } + parse_events(s, SS_DETECT); } *handle = client; @@ -2022,30 +2092,44 @@ int pcmcia_reset_card(client_handle_t handle, client_req_t *req) { - int i, ret; - socket_info_t *s; + socket_info_t *skt; + int ret; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - i = handle->Socket; s = socket_table[i]; - if (!(s->state & SOCKET_PRESENT)) - return CS_NO_CARD; - if (s->state & SOCKET_RESET_PENDING) - return CS_IN_USE; - s->state |= SOCKET_RESET_PENDING; + if (CHECK_HANDLE(handle)) + return CS_BAD_HANDLE; + DEBUG(1, "cs: resetting socket %d\n", handle->Socket); + skt = SOCKET(handle); + + down(&skt->skt_sem); + do { + if (!(skt->state & SOCKET_PRESENT)) { + ret = CS_NO_CARD; + break; + } + if (skt->state & SOCKET_SUSPEND) { + ret = CS_IN_USE; + break; + } + if (skt->state & SOCKET_CARDBUS) { + ret = CS_UNSUPPORTED_FUNCTION; + break; + } - ret = send_event(s, CS_EVENT_RESET_REQUEST, CS_EVENT_PRI_LOW); - if (ret != 0) { - s->state &= ~SOCKET_RESET_PENDING; - handle->event_callback_args.info = (void *)(u_long)ret; - EVENT(handle, CS_EVENT_RESET_COMPLETE, CS_EVENT_PRI_LOW); - } else { - DEBUG(1, "cs: resetting socket %d\n", i); - send_event(s, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW); - s->reset_handle = handle; - reset_socket(s); - } - return CS_SUCCESS; + ret = send_event(skt, CS_EVENT_RESET_REQUEST, CS_EVENT_PRI_LOW); + if (ret == 0) { + send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW); + if (socket_reset(skt) == CS_SUCCESS) + send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW); + } + + handle->event_callback_args.info = (void *)(u_long)ret; + EVENT(handle, CS_EVENT_RESET_COMPLETE, CS_EVENT_PRI_LOW); + + ret = CS_SUCCESS; + } while (0); + up(&skt->skt_sem); + + return ret; } /* reset_card */ /*====================================================================== @@ -2057,42 +2141,56 @@ int pcmcia_suspend_card(client_handle_t handle, client_req_t *req) { - int i; - socket_info_t *s; + socket_info_t *skt; + int ret; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - i = handle->Socket; s = socket_table[i]; - if (!(s->state & SOCKET_PRESENT)) - return CS_NO_CARD; - if (s->state & SOCKET_SUSPEND) - return CS_IN_USE; - - DEBUG(1, "cs: suspending socket %d\n", i); - send_event(s, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW); - suspend_socket(s); - s->state |= SOCKET_SUSPEND; + if (CHECK_HANDLE(handle)) + return CS_BAD_HANDLE; + DEBUG(1, "cs: suspending socket %d\n", handle->Socket); + skt = SOCKET(handle); + + down(&skt->skt_sem); + do { + if (!(skt->state & SOCKET_PRESENT)) { + ret = CS_NO_CARD; + break; + } + if (skt->state & SOCKET_CARDBUS) { + ret = CS_UNSUPPORTED_FUNCTION; + break; + } + ret = socket_suspend(skt); + } while (0); + up(&skt->skt_sem); - return CS_SUCCESS; + return ret; } /* suspend_card */ int pcmcia_resume_card(client_handle_t handle, client_req_t *req) { - int i; - socket_info_t *s; + socket_info_t *skt; + int ret; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - i = handle->Socket; s = socket_table[i]; - if (!(s->state & SOCKET_PRESENT)) - return CS_NO_CARD; - if (!(s->state & SOCKET_SUSPEND)) - return CS_IN_USE; - - DEBUG(1, "cs: waking up socket %d\n", i); - setup_socket(s); + if (CHECK_HANDLE(handle)) + return CS_BAD_HANDLE; + DEBUG(1, "cs: waking up socket %d\n", handle->Socket); + skt = SOCKET(handle); + + down(&skt->skt_sem); + do { + if (!(skt->state & SOCKET_PRESENT)) { + ret = CS_NO_CARD; + break; + } + if (skt->state & SOCKET_CARDBUS) { + ret = CS_UNSUPPORTED_FUNCTION; + break; + } + ret = socket_resume(skt); + } while (0); + up(&skt->skt_sem); - return CS_SUCCESS; + return ret; } /* resume_card */ /*====================================================================== @@ -2103,57 +2201,58 @@ int pcmcia_eject_card(client_handle_t handle, client_req_t *req) { - int i, ret; - socket_info_t *s; - u_long flags; + socket_info_t *skt; + int ret; - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - i = handle->Socket; s = socket_table[i]; - if (!(s->state & SOCKET_PRESENT)) - return CS_NO_CARD; + if (CHECK_HANDLE(handle)) + return CS_BAD_HANDLE; + DEBUG(1, "cs: user eject request on socket %d\n", handle->Socket); + skt = SOCKET(handle); + + down(&skt->skt_sem); + do { + if (!(skt->state & SOCKET_PRESENT)) { + ret = CS_NO_CARD; + break; + } - DEBUG(1, "cs: user eject request on socket %d\n", i); + ret = send_event(skt, CS_EVENT_EJECTION_REQUEST, CS_EVENT_PRI_LOW); + if (ret != 0) + break; - ret = send_event(s, CS_EVENT_EJECTION_REQUEST, CS_EVENT_PRI_LOW); - if (ret != 0) - return ret; + socket_shutdown(skt); + ret = CS_SUCCESS; + } while (0); + up(&skt->skt_sem); - spin_lock_irqsave(&s->lock, flags); - do_shutdown(s); - spin_unlock_irqrestore(&s->lock, flags); - - return CS_SUCCESS; - + return ret; } /* eject_card */ int pcmcia_insert_card(client_handle_t handle, client_req_t *req) { - int i, status; - socket_info_t *s; - u_long flags; - - if (CHECK_HANDLE(handle)) - return CS_BAD_HANDLE; - i = handle->Socket; s = socket_table[i]; - if (s->state & SOCKET_PRESENT) - return CS_IN_USE; - - DEBUG(1, "cs: user insert request on socket %d\n", i); + socket_info_t *skt; + int ret; - spin_lock_irqsave(&s->lock, flags); - if (!(s->state & SOCKET_SETUP_PENDING)) { - s->state |= SOCKET_SETUP_PENDING; - spin_unlock_irqrestore(&s->lock, flags); - get_socket_status(s, &status); - if ((status & SS_DETECT) == 0 || (setup_socket(s) == 0)) { - s->state &= ~SOCKET_SETUP_PENDING; - return CS_NO_CARD; - } - } else - spin_unlock_irqrestore(&s->lock, flags); + if (CHECK_HANDLE(handle)) + return CS_BAD_HANDLE; + DEBUG(1, "cs: user insert request on socket %d\n", handle->Socket); + skt = SOCKET(handle); + + down(&skt->skt_sem); + do { + if (skt->state & SOCKET_PRESENT) { + ret = CS_IN_USE; + break; + } + if (socket_insert(skt) == CS_NO_CARD) { + ret = CS_NO_CARD; + break; + } + ret = CS_SUCCESS; + } while (0); + up(&skt->skt_sem); - return CS_SUCCESS; + return ret; } /* insert_card */ /*====================================================================== diff -Nru a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h --- a/drivers/pcmcia/cs_internal.h Thu May 15 15:24:32 2003 +++ b/drivers/pcmcia/cs_internal.h Thu May 15 15:24:32 2003 @@ -133,7 +133,6 @@ u_short lock_count; client_handle_t clients; u_int real_clients; - client_handle_t reset_handle; pccard_mem_map cis_mem; u_char *cis_virt; config_t *config; @@ -155,6 +154,14 @@ #ifdef CONFIG_PROC_FS struct proc_dir_entry *proc; #endif + + struct semaphore skt_sem; /* protects socket h/w state */ + + struct task_struct *thread; + struct completion thread_done; + wait_queue_head_t thread_wait; + spinlock_t thread_lock; /* protects thread_events */ + unsigned int thread_events; } socket_info_t; /* Flags in config state */ diff -Nru a/drivers/pcmcia/sa11xx_core.c b/drivers/pcmcia/sa11xx_core.c --- a/drivers/pcmcia/sa11xx_core.c Thu May 15 15:24:34 2003 +++ b/drivers/pcmcia/sa11xx_core.c Thu May 15 15:24:34 2003 @@ -120,7 +120,6 @@ unsigned long flags; unsigned short speed; unsigned int bs_io, bs_mem, bs_attr; - int i; speed = calc_speed(skt->spd_io, MAX_IO_WIN, SA1100_PCMCIA_IO_ACCESS); bs_io = skt->ops->socket_get_timing(skt, cpu_clock, speed); @@ -324,13 +323,15 @@ * handling code performs scheduling operations which cannot be * executed from within an interrupt context. */ -static void sa1100_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs) +static irqreturn_t sa1100_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs) { struct sa1100_pcmcia_socket *skt = dev; DEBUG(3, "%s(): servicing IRQ %d\n", __FUNCTION__, irq); schedule_work(&skt->work); + + return IRQ_HANDLED; } /* sa1100_pcmcia_register_callback() diff -Nru a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c --- a/drivers/pnp/pnpbios/core.c Thu May 15 15:24:33 2003 +++ b/drivers/pnp/pnpbios/core.c Thu May 15 15:24:33 2003 @@ -252,41 +252,59 @@ { switch(status) { case PNP_SUCCESS: - printk(KERN_ERR "PnPBIOS: %s: function successful\n", module); + printk(KERN_ERR "PnPBIOS: %s: function successful\n", module); + break; case PNP_NOT_SET_STATICALLY: - printk(KERN_ERR "PnPBIOS: %s: unable to set static resources\n", module); + printk(KERN_ERR "PnPBIOS: %s: unable to set static resources\n", module); + break; case PNP_UNKNOWN_FUNCTION: - printk(KERN_ERR "PnPBIOS: %s: invalid function number passed\n", module); + printk(KERN_ERR "PnPBIOS: %s: invalid function number passed\n", module); + break; case PNP_FUNCTION_NOT_SUPPORTED: - printk(KERN_ERR "PnPBIOS: %s: function not supported on this system\n", module); + printk(KERN_ERR "PnPBIOS: %s: function not supported on this system\n", module); + break; case PNP_INVALID_HANDLE: - printk(KERN_ERR "PnPBIOS: %s: invalid handle\n", module); + printk(KERN_ERR "PnPBIOS: %s: invalid handle\n", module); + break; case PNP_BAD_PARAMETER: - printk(KERN_ERR "PnPBIOS: %s: invalid parameters were passed\n", module); + printk(KERN_ERR "PnPBIOS: %s: invalid parameters were passed\n", module); + break; case PNP_SET_FAILED: - printk(KERN_ERR "PnPBIOS: %s: unable to set resources\n", module); + printk(KERN_ERR "PnPBIOS: %s: unable to set resources\n", module); + break; case PNP_EVENTS_NOT_PENDING: - printk(KERN_ERR "PnPBIOS: %s: no events are pending\n", module); + printk(KERN_ERR "PnPBIOS: %s: no events are pending\n", module); + break; case PNP_SYSTEM_NOT_DOCKED: - printk(KERN_ERR "PnPBIOS: %s: the system is not docked\n", module); + printk(KERN_ERR "PnPBIOS: %s: the system is not docked\n", module); + break; case PNP_NO_ISA_PNP_CARDS: - printk(KERN_ERR "PnPBIOS: %s: no isapnp cards are installed on this system\n", module); + printk(KERN_ERR "PnPBIOS: %s: no isapnp cards are installed on this system\n", module); + break; case PNP_UNABLE_TO_DETERMINE_DOCK_CAPABILITIES: - printk(KERN_ERR "PnPBIOS: %s: cannot determine the capabilities of the docking station\n", module); + printk(KERN_ERR "PnPBIOS: %s: cannot determine the capabilities of the docking station\n", module); + break; case PNP_CONFIG_CHANGE_FAILED_NO_BATTERY: - printk(KERN_ERR "PnPBIOS: %s: unable to undock, the system does not have a battery\n", module); + printk(KERN_ERR "PnPBIOS: %s: unable to undock, the system does not have a battery\n", module); + break; case PNP_CONFIG_CHANGE_FAILED_RESOURCE_CONFLICT: - printk(KERN_ERR "PnPBIOS: %s: could not dock due to resource conflicts\n", module); + printk(KERN_ERR "PnPBIOS: %s: could not dock due to resource conflicts\n", module); + break; case PNP_BUFFER_TOO_SMALL: - printk(KERN_ERR "PnPBIOS: %s: the buffer passed is too small\n", module); + printk(KERN_ERR "PnPBIOS: %s: the buffer passed is too small\n", module); + break; case PNP_USE_ESCD_SUPPORT: - printk(KERN_ERR "PnPBIOS: %s: use ESCD instead\n", module); + printk(KERN_ERR "PnPBIOS: %s: use ESCD instead\n", module); + break; case PNP_MESSAGE_NOT_SUPPORTED: - printk(KERN_ERR "PnPBIOS: %s: the message is unsupported\n", module); + printk(KERN_ERR "PnPBIOS: %s: the message is unsupported\n", module); + break; case PNP_HARDWARE_ERROR: - printk(KERN_ERR "PnPBIOS: %s: a hardware failure has occured\n", module); + printk(KERN_ERR "PnPBIOS: %s: a hardware failure has occured\n", module); + break; default: - printk(KERN_ERR "PnPBIOS: %s: unexpected status 0x%x\n", module, status); + printk(KERN_ERR "PnPBIOS: %s: unexpected status 0x%x\n", module, status); + break; } } diff -Nru a/drivers/pnp/resource.c b/drivers/pnp/resource.c --- a/drivers/pnp/resource.c Thu May 15 15:24:39 2003 +++ b/drivers/pnp/resource.c Thu May 15 15:24:39 2003 @@ -422,7 +422,7 @@ static irqreturn_t pnp_test_handler(int irq, void *dev_id, struct pt_regs *regs) { - return IRQ_NONE; + return IRQ_HANDLED; } int pnp_check_irq(struct pnp_dev * dev, int idx) diff -Nru a/drivers/s390/char/tuball.c b/drivers/s390/char/tuball.c --- a/drivers/s390/char/tuball.c Thu May 15 15:24:42 2003 +++ b/drivers/s390/char/tuball.c Thu May 15 15:24:42 2003 @@ -468,9 +468,8 @@ } #endif /* CONFIG_TN3270_CONSOLE */ -#ifdef CONFIG_DEVFS_FS - fs3270_devfs_register(tubp); -#endif + devfs_mk_cdev(MKDEV(IBM_FS3270_MAJOR, tubp->minor), + S_IFCHR|S_IRUSR|S_IWUSR, "3270/tub%.4x"); TUBUNLOCK(tubp->irq, flags); return minor; @@ -492,9 +491,7 @@ for (i = 0; i < TUBMAXMINS; i++) { tubpp = &(*tubminors)[i]; if ((tubp = *tubpp)) { -#ifdef CONFIG_DEVFS_FS - fs3270_devfs_unregister(tubp); -#endif + devfs_remove("3270/tub%.4x", tubp->devno); tubdelbyirq(tubp, tubp->irq); tty3270_rcl_fini(tubp); kfree(tubp->tty_bcb.bc_buf); diff -Nru a/drivers/s390/char/tubfs.c b/drivers/s390/char/tubfs.c --- a/drivers/s390/char/tubfs.c Thu May 15 15:24:40 2003 +++ b/drivers/s390/char/tubfs.c Thu May 15 15:24:40 2003 @@ -23,9 +23,7 @@ extern void tty3270_refresh(tub_t *); static struct file_operations fs3270_fops = { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)) .owner = THIS_MODULE, /* owner */ -#endif .read = fs3270_read, /* read */ .write = fs3270_write, /* write */ .ioctl = fs3270_ioctl, /* ioctl */ @@ -33,27 +31,6 @@ .release = fs3270_close, /* release */ }; -#ifdef CONFIG_DEVFS_FS -void fs3270_devfs_register(tub_t *tubp) -{ - char name[16]; - - sprintf(name, "3270/tub%.4x", tubp->devno); - devfs_register(NULL, name, DEVFS_FL_DEFAULT, - IBM_FS3270_MAJOR, tubp->minor, - S_IFCHR | S_IRUSR | S_IWUSR, &fs3270_fops, NULL); - sprintf(name, "tty%.4x", tubp->devno); - tty_register_devfs_name(&tty3270_driver, 0, tubp->minor, - NULL, name); -} - -void fs3270_devfs_unregister(tub_t *tubp) -{ - devfs_remove("3270/tub%.4x", tubp->devno); - devfs_remove("3270/tty%.4x", tubp->devno); -} -#endif - /* * fs3270_init() -- Initialize fullscreen tubes */ @@ -69,10 +46,8 @@ return -1; } devfs_mk_dir("3270"); - devfs_register(NULL, "3270/tub", 0, - IBM_FS3270_MAJOR, 0, - S_IFCHR | S_IRUGO | S_IWUGO, - &fs3270_fops, NULL); + devfs_mk_cdev(MKDEV(IBM_FS3270_MAJOR, 0), + S_IFCHR|S_IRUGO|S_IWUGO, "3270/tub"); fs3270_major = IBM_FS3270_MAJOR; return 0; } diff -Nru a/drivers/s390/char/tubio.h b/drivers/s390/char/tubio.h --- a/drivers/s390/char/tubio.h Thu May 15 15:24:39 2003 +++ b/drivers/s390/char/tubio.h Thu May 15 15:24:39 2003 @@ -337,10 +337,6 @@ extern int tty3270_proc_misc; extern enum tubwhat tty3270_proc_what; extern struct tty_driver tty3270_driver; -#ifdef CONFIG_DEVFS_FS -extern void fs3270_devfs_register(tub_t *); -extern void fs3270_devfs_unregister(tub_t *); -#endif #ifndef spin_trylock_irqsave #define spin_trylock_irqsave(lock, flags) \ diff -Nru a/drivers/s390/char/tubtty.c b/drivers/s390/char/tubtty.c --- a/drivers/s390/char/tubtty.c Thu May 15 15:24:42 2003 +++ b/drivers/s390/char/tubtty.c Thu May 15 15:24:42 2003 @@ -90,9 +90,7 @@ td->subtype = SYSTEM_TYPE_TTY; td->init_termios = tty_std_termios; td->flags = TTY_DRIVER_RESET_TERMIOS; -#ifdef CONFIG_DEVFS_FS td->flags |= TTY_DRIVER_NO_DEVFS; -#endif td->refcount = &tty3270_refcount; td->table = tty3270_table; td->termios = tty3270_termios; diff -Nru a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c --- a/drivers/sbus/char/bpp.c Thu May 15 15:24:33 2003 +++ b/drivers/sbus/char/bpp.c Thu May 15 15:24:33 2003 @@ -1051,11 +1051,8 @@ } devfs_mk_dir("bpp"); for (idx = 0; idx < BPP_NO; idx++) { - char name[16]; - sprintf(name, "bpp/%d", idx); - devfs_register(NULL, name, DEVFS_FL_DEFAULT, - BPP_MAJOR, idx, S_IFCHR | S_IRUSR | S_IWUSR, - &bpp_fops, NULL); + devfs_mk_cdev(MKDEV(BPP_MAJOR, idx), + S_IFCHR | S_IRUSR | S_IWUSR, "bpp/%d", idx); } return 0; diff -Nru a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c --- a/drivers/sbus/char/vfc_dev.c Thu May 15 15:24:39 2003 +++ b/drivers/sbus/char/vfc_dev.c Thu May 15 15:24:39 2003 @@ -143,8 +143,6 @@ int init_vfc_device(struct sbus_dev *sdev,struct vfc_dev *dev, int instance) { - char devname[16]; - if(dev == NULL) { printk(KERN_ERR "VFC: Bogus pointer passed\n"); return -ENOMEM; @@ -167,11 +165,9 @@ if (init_vfc_hw(dev)) return -EIO; - sprintf (devname, "vfc/%d", instance); - dev->de = devfs_register (NULL, devname, DEVFS_FL_DEFAULT, - VFC_MAJOR, instance, - S_IFCHR | S_IRUSR | S_IWUSR, - &vfc_fops, NULL); + devfs_mk_cdev(MKDEV(VFC_MAJOR, instance), + S_IFCHR | S_IRUSR | S_IWUSR, + "vfc/%d", instance); return 0; } diff -Nru a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c --- a/drivers/scsi/3w-xxxx.c Thu May 15 15:24:44 2003 +++ b/drivers/scsi/3w-xxxx.c Thu May 15 15:24:44 2003 @@ -3439,7 +3439,24 @@ outl(control_reg_value, control_reg_addr); } /* End tw_unmask_command_interrupt() */ -/* Now get things going */ -static Scsi_Host_Template driver_template = TWXXXX; +static Scsi_Host_Template driver_template = { + .proc_name = "3w-xxxx", + .proc_info = tw_scsi_proc_info, + .name = "3ware Storage Controller", + .detect = tw_scsi_detect, + .release = tw_scsi_release, + .queuecommand = tw_scsi_queue, + .eh_abort_handler = tw_scsi_eh_abort, + .eh_host_reset_handler = tw_scsi_eh_reset, + .bios_param = tw_scsi_biosparam, + .can_queue = TW_Q_LENGTH-2, + .this_id = -1, + .sg_tablesize = TW_MAX_SGL_LENGTH, + .max_sectors = TW_MAX_SECTORS, + .cmd_per_lun = TW_MAX_CMDS_PER_LUN, + .use_clustering = ENABLE_CLUSTERING, + .emulated = 1, + .highmem_io = 1, +}; #include "scsi_module.c" diff -Nru a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h --- a/drivers/scsi/3w-xxxx.h Thu May 15 15:24:35 2003 +++ b/drivers/scsi/3w-xxxx.h Thu May 15 15:24:35 2003 @@ -497,26 +497,4 @@ int tw_state_request_start(TW_Device_Extension *tw_dev, int *request_id); void tw_unmask_command_interrupt(TW_Device_Extension *tw_dev); -/* Scsi_Host_Template Initializer */ -#define TWXXXX { \ - .proc_name = "3w-xxxx", \ - .proc_info = tw_scsi_proc_info, \ - .name = "3ware Storage Controller", \ - .detect = tw_scsi_detect, \ - .release = tw_scsi_release, \ - .queuecommand = tw_scsi_queue, \ - .eh_abort_handler = tw_scsi_eh_abort, \ - .eh_host_reset_handler = tw_scsi_eh_reset, \ - .bios_param = tw_scsi_biosparam, \ - .can_queue = TW_Q_LENGTH-2, \ - .this_id = -1, \ - .sg_tablesize = TW_MAX_SGL_LENGTH, \ - .max_sectors = TW_MAX_SECTORS, \ - .cmd_per_lun = TW_MAX_CMDS_PER_LUN, \ - .present = 0, \ - .unchecked_isa_dma = 0, \ - .use_clustering = ENABLE_CLUSTERING, \ - .emulated = 1, \ - .highmem_io = 1 \ -} #endif /* _3W_XXXX_H */ diff -Nru a/drivers/scsi/AM53C974.c b/drivers/scsi/AM53C974.c --- a/drivers/scsi/AM53C974.c Thu May 15 15:24:38 2003 +++ b/drivers/scsi/AM53C974.c Thu May 15 15:24:38 2003 @@ -2453,5 +2453,21 @@ MODULE_LICENSE("GPL"); -static Scsi_Host_Template driver_template = AM53C974; +static Scsi_Host_Template driver_template = { + .proc_name = "am53c974", + .name = "AM53C974", + .detect = AM53C974_pci_detect, + .release = AM53C974_release, + .info = AM53C974_info, + .command = AM53C974_command, + .queuecommand = AM53C974_queue_command, + .abort = AM53C974_abort, + .reset = AM53C974_reset, + .can_queue = 12, + .this_id = -1, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 1, + .use_clustering = DISABLE_CLUSTERING, +}; + #include "scsi_module.c" diff -Nru a/drivers/scsi/AM53C974.h b/drivers/scsi/AM53C974.h --- a/drivers/scsi/AM53C974.h Thu May 15 15:24:43 2003 +++ b/drivers/scsi/AM53C974.h Thu May 15 15:24:43 2003 @@ -50,23 +50,6 @@ unsigned char max_offset[8]; /* max. sync. offset (setup), only valid if corresponding sync_en is nonzero */ }; -#define AM53C974 { \ - .proc_name = "am53c974", \ - .name = "AM53C974", \ - .detect = AM53C974_pci_detect, \ - .release = AM53C974_release, \ - .info = AM53C974_info, \ - .command = AM53C974_command, \ - .queuecommand = AM53C974_queue_command, \ - .abort = AM53C974_abort, \ - .reset = AM53C974_reset, \ - .can_queue = 12, \ - .this_id = -1, \ - .sg_tablesize = SG_ALL, \ - .cmd_per_lun = 1, \ - .use_clustering = DISABLE_CLUSTERING \ - } - static int AM53C974_pci_detect(Scsi_Host_Template * tpnt); static int AM53C974_release(struct Scsi_Host *shp); static const char *AM53C974_info(struct Scsi_Host *); diff -Nru a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c --- a/drivers/scsi/BusLogic.c Thu May 15 15:24:45 2003 +++ b/drivers/scsi/BusLogic.c Thu May 15 15:24:45 2003 @@ -3213,6 +3213,7 @@ Place CCB back on the Host Adapter's free list. */ BusLogic_DeallocateCCB(CCB); +#if 0 /* this needs to be redone different for new EH */ /* Bus Device Reset CCBs have the Command field non-NULL only when a Bus Device Reset was requested for a Command that did not have a @@ -3228,6 +3229,7 @@ Command->scsi_done(Command); Command = NextCommand; } +#endif /* Iterate over the CCBs for this Host Adapter performing completion processing for any CCBs marked as Reset for this Target. @@ -3948,6 +3950,7 @@ { Command = CCB->Command; BusLogic_DeallocateCCB(CCB); +#if 0 /* this needs to be redone different for new EH */ while (Command != NULL) { SCSI_Command_T *NextCommand = Command->reset_chain; @@ -3956,6 +3959,7 @@ Command->scsi_done(Command); Command = NextCommand; } +#endif } for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) { @@ -3967,7 +3971,7 @@ return Result; } - +#if 0 /* old-style EH code references a dead struct scsi_cmnd member */ /* BusLogic_SendBusDeviceReset sends a Bus Device Reset to the Target Device associated with Command. @@ -4204,6 +4208,7 @@ } return SCSI_RESET_PUNT; } +#endif /* @@ -5113,6 +5118,18 @@ */ MODULE_LICENSE("GPL"); -static SCSI_Host_Template_T driver_template = BUSLOGIC; - +static SCSI_Host_Template_T driver_template = { + .proc_name = "BusLogic", + .proc_info = BusLogic_ProcDirectoryInfo, + .name = "BusLogic", + .detect = BusLogic_DetectHostAdapter, + .release = BusLogic_ReleaseHostAdapter, + .info = BusLogic_DriverInfo, + .queuecommand = BusLogic_QueueCommand, + .slave_configure = BusLogic_SlaveConfigure, + .bios_param = BusLogic_BIOSDiskParameters, + .unchecked_isa_dma = 1, + .max_sectors = 128, + .use_clustering = ENABLE_CLUSTERING, +}; #include "scsi_module.c" diff -Nru a/drivers/scsi/BusLogic.h b/drivers/scsi/BusLogic.h --- a/drivers/scsi/BusLogic.h Thu May 15 15:24:38 2003 +++ b/drivers/scsi/BusLogic.h Thu May 15 15:24:38 2003 @@ -59,30 +59,6 @@ extern int BusLogic_ProcDirectoryInfo(char *, char **, off_t, int, int, int); extern int BusLogic_SlaveConfigure(SCSI_Device_T *); - -/* - Define the BusLogic SCSI Host Template structure. -*/ - -#define BUSLOGIC \ - { .proc_name = "BusLogic", /* ProcFS Directory Entry */ \ - .proc_info = BusLogic_ProcDirectoryInfo, /* ProcFS Info Function */ \ - .name = "BusLogic", /* Driver Name */ \ - .detect = BusLogic_DetectHostAdapter, /* Detect Host Adapter */ \ - .release = BusLogic_ReleaseHostAdapter, /* Release Host Adapter */ \ - .info = BusLogic_DriverInfo, /* Driver Info Function */ \ - .queuecommand = BusLogic_QueueCommand, /* Queue Command Function */ \ - .slave_configure = BusLogic_SlaveConfigure, /* Configure a SCSI_Device*/ \ - .bios_param = BusLogic_BIOSDiskParameters, /* BIOS Disk Parameters */ \ - .unchecked_isa_dma = 1, /* Default Initial Value */ \ - .max_sectors = 128, /* I/O queue len limit */ \ - .use_clustering = ENABLE_CLUSTERING } /* Enable Clustering */ - - -/* - BusLogic_DriverVersion protects the private portion of this file. -*/ - #ifdef BusLogic_DriverVersion diff -Nru a/drivers/scsi/Makefile b/drivers/scsi/Makefile --- a/drivers/scsi/Makefile Thu May 15 15:24:42 2003 +++ b/drivers/scsi/Makefile Thu May 15 15:24:42 2003 @@ -124,7 +124,8 @@ scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \ scsicam.o scsi_error.o scsi_lib.o \ - scsi_scan.o scsi_syms.o scsi_sysfs.o + scsi_scan.o scsi_syms.o scsi_sysfs.o \ + scsi_devinfo.o scsi_mod-$(CONFIG_PROC_FS) += scsi_proc.o scsi_mod-$(CONFIG_X86_PC9800) += scsi_pc98.o diff -Nru a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c --- a/drivers/scsi/NCR_D700.c Thu May 15 15:24:34 2003 +++ b/drivers/scsi/NCR_D700.c Thu May 15 15:24:34 2003 @@ -92,18 +92,12 @@ #define NCR_D700_VERSION "2.2" -#include -#include +#include #include #include #include #include - -#include -#include #include -#include -#include #include "scsi.h" #include "hosts.h" @@ -111,16 +105,6 @@ #include "53c700.h" #include "NCR_D700.h" -#ifndef CONFIG_MCA -#error "NCR_D700 driver only compiles for MCA" -#endif - -#ifdef NCR_D700_DEBUG -#define STATIC -#else -#define STATIC static -#endif - char *NCR_D700; /* command line from insmod */ MODULE_AUTHOR("James Bottomley"); @@ -170,34 +154,101 @@ return 1; } -#ifndef MODULE -__setup("NCR_D700=", param_setup); -#endif +/* Host template. The 53c700 routine NCR_700_detect will + * fill in all of the missing routines */ +static Scsi_Host_Template NCR_D700_driver_template = { + .module = THIS_MODULE, + .name = "NCR Dual 700 MCA", + .proc_name = "NCR_D700", + .this_id = 7, +}; -/* private stack allocated structure for passing device information from - * detect to probe */ -struct NCR_700_info { - Scsi_Host_Template *tpnt; - int found; +/* We needs this helper because we have two hosts per struct device */ +struct NCR_D700_private { + struct device *dev; + struct Scsi_Host *hosts[2]; }; -/* Detect a D700 card. Note, because of the set up---the chips are +static int +NCR_D700_probe_one(struct NCR_D700_private *p, int siop, + int irq, int slot, u32 region, int differential) +{ + struct NCR_700_Host_Parameters *hostdata; + struct Scsi_Host *host; + int ret; + + hostdata = kmalloc(sizeof(*hostdata), GFP_KERNEL); + if (!hostdata) { + printk(KERN_ERR "NCR D700: SIOP%d: Failed to allocate host" + "data, detatching\n", siop); + return -ENOMEM; + } + memset(hostdata, 0, sizeof(*hostdata)); + + if (!request_region(region, 64, "NCR_D700")) { + printk(KERN_ERR "NCR D700: Failed to reserve IO region 0x%x\n", + region); + ret = -ENODEV; + goto region_failed; + } + + /* Fill in the three required pieces of hostdata */ + hostdata->base = region; + hostdata->differential = (((1<clock = NCR_D700_CLOCK_MHZ; + + /* and register the siop */ + host = NCR_700_detect(&NCR_D700_driver_template, hostdata); + if (!host) { + ret = -ENOMEM; + goto detect_failed; + } + + host->irq = irq; + /* FIXME: Read this from SUS */ + host->this_id = id_array[slot * 2 + siop]; + printk(KERN_NOTICE "NCR D700: SIOP%d, SCSI id is %d\n", + siop, host->this_id); + if (request_irq(irq, NCR_700_intr, SA_SHIRQ, "NCR_D700", host)) { + printk(KERN_ERR "NCR D700: SIOP%d: irq problem, " + "detatching\n", siop); + ret = -ENODEV; + goto irq_failed; + } + + scsi_add_host(host, p->dev); + + p->hosts[siop] = host; + hostdata->dev = p->dev; + return 0; + + irq_failed: + scsi_unregister(host); + NCR_700_release(host); + detect_failed: + release_region(host->base, 64); + region_failed: + kfree(hostdata); + + return ret; +} + +/* Detect a D700 card. Note, because of the setup --- the chips are * essentially connectecd to the MCA bus independently, it is easier * to set them up as two separate host adapters, rather than one * adapter with two channels */ static int NCR_D700_probe(struct device *dev) { + struct NCR_D700_private *p; int differential; static int banner = 1; struct mca_device *mca_dev = to_mca_device(dev); int slot = mca_dev->slot; - struct NCR_700_info *info = to_mca_driver(dev->driver)->driver_data; int found = 0; int irq, i; int pos3j, pos3k, pos3a, pos3b, pos4; __u32 base_addr, offset_addr; - struct Scsi_Host *host = NULL; /* enable board interrupt */ pos4 = mca_device_read_pos(mca_dev, 4); @@ -232,8 +283,6 @@ printk(KERN_NOTICE "NCR D700: found in slot %d irq = %d I/O base = 0x%x\n", slot, irq, offset_addr); - info->tpnt->proc_name = "NCR_D700"; - /*outb(BOARD_RESET, base_addr);*/ /* clear any pending interrupts */ @@ -259,70 +308,56 @@ break; } + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; + p->dev = dev; + /* plumb in both 700 chips */ - for(i=0; i<2; i++) { - __u32 region = offset_addr | (0x80 * i); - struct NCR_700_Host_Parameters *hostdata = - kmalloc(sizeof(struct NCR_700_Host_Parameters), - GFP_KERNEL); - if(hostdata == NULL) { - printk(KERN_ERR "NCR D700: Failed to allocate host data for channel %d, detatching\n", i); - continue; - } - memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters)); - if(request_region(region, 64, "NCR_D700") == NULL) { - printk(KERN_ERR "NCR D700: Failed to reserve IO region 0x%x\n", region); - kfree(hostdata); - continue; - } - - /* Fill in the three required pieces of hostdata */ - hostdata->base = region; - hostdata->differential = (((1<clock = NCR_D700_CLOCK_MHZ; - /* and register the chip */ - if((host = NCR_700_detect(info->tpnt, hostdata)) == NULL) { - kfree(hostdata); - release_region(host->base, 64); - continue; - } - host->irq = irq; - /* FIXME: Read this from SUS */ - host->this_id = id_array[slot * 2 + i]; - printk(KERN_NOTICE "NCR D700: SIOP%d, SCSI id is %d\n", - i, host->this_id); - if(request_irq(irq, NCR_700_intr, SA_SHIRQ, "NCR_D700", host)) { - printk(KERN_ERR "NCR D700, channel %d: irq problem, detatching\n", i); - scsi_unregister(host); - NCR_700_release(host); - continue; - } - scsi_set_device(host, dev); - hostdata->dev = dev; - found++; + for (i = 0; i < 2; i++) { + int err; + + if ((err = NCR_D700_probe_one(p, i, irq, slot, + offset_addr + (0x80 * i), + differential)) != 0) + printk("D700: SIOP%d: probe failed, error = %d\n", + i, err); + else + found++; } - info->found += found; - if(found) { - mca_device_set_claim(mca_dev, 1); - strncpy(dev->name, "NCR_D700", sizeof(dev->name)); + if (!found) { + kfree(p); + return -ENODEV; } - return found? 0 : -ENODEV; + mca_device_set_claim(mca_dev, 1); + strncpy(dev->name, "NCR_D700", sizeof(dev->name)); + dev_set_drvdata(dev, p); + return 0; } - -STATIC int -D700_release(struct Scsi_Host *host) +static void +NCR_D700_remove_one(struct Scsi_Host *host) { - struct D700_Host_Parameters *hostdata = - (struct D700_Host_Parameters *)host->hostdata[0]; - + scsi_remove_host(host); NCR_700_release(host); - kfree(hostdata); + kfree((struct NCR_700_Host_Parameters *)host->hostdata[0]); free_irq(host->irq, host); release_region(host->base, 64); - return 1; +} + +static int +NCR_D700_remove(struct device *dev) +{ + struct NCR_D700_private *p = dev_get_drvdata(dev); + int i; + + for (i = 0; i < 2; i++) + NCR_D700_remove_one(p->hosts[i]); + + kfree(p); + return 0; } static short NCR_D700_id_table[] = { NCR_D700_MCA_ID, 0 }; @@ -330,34 +365,29 @@ struct mca_driver NCR_D700_driver = { .id_table = NCR_D700_id_table, .driver = { - .name = "NCR_D700", - .bus = &mca_bus_type, - .probe = NCR_D700_probe, + .name = "NCR_D700", + .bus = &mca_bus_type, + .probe = NCR_D700_probe, + .remove = NCR_D700_remove, }, }; - -STATIC int __init -D700_detect(Scsi_Host_Template *tpnt) +static int __init NCR_D700_init(void) { - struct NCR_700_info info; - - if(!MCA_bus) - return 0; - #ifdef MODULE - if(NCR_D700) + if (NCR_D700) param_setup(NCR_D700); #endif - info.tpnt = tpnt; - info.found = 0; - NCR_D700_driver.driver_data = &info; - mca_register_driver(&NCR_D700_driver); - return info.found; + return mca_register_driver(&NCR_D700_driver); +} + +static void __exit NCR_D700_exit(void) +{ + mca_unregister_driver(&NCR_D700_driver); } - -static Scsi_Host_Template driver_template = NCR_D700_SCSI; -#include "scsi_module.c" +module_init(NCR_D700_init); +module_exit(NCR_D700_exit); +__setup("NCR_D700=", param_setup); diff -Nru a/drivers/scsi/NCR_D700.h b/drivers/scsi/NCR_D700.h --- a/drivers/scsi/NCR_D700.h Thu May 15 15:24:39 2003 +++ b/drivers/scsi/NCR_D700.h Thu May 15 15:24:39 2003 @@ -14,22 +14,6 @@ /* The MCA identifier */ #define NCR_D700_MCA_ID 0x0092 -static int D700_detect(Scsi_Host_Template *); -static int D700_release(struct Scsi_Host *host); - - -/* Host template. Note the name and proc_name are optional, all the - * remaining parameters shown below must be filled in. The 53c700 - * routine NCR_700_detect will fill in all of the missing routines */ -#define NCR_D700_SCSI { \ - .name = "NCR Dual 700 MCA", \ - .proc_name = "NCR_D700", \ - .detect = D700_detect, \ - .release = D700_release, \ - .this_id = 7, \ -} - - /* Defines for the Board registers */ #define BOARD_RESET 0x80 /* board level reset */ #define ADD_PARENB 0x04 /* Address Parity Enabled */ diff -Nru a/drivers/scsi/aacraid/README b/drivers/scsi/aacraid/README --- a/drivers/scsi/aacraid/README Thu May 15 15:24:33 2003 +++ b/drivers/scsi/aacraid/README Thu May 15 15:24:33 2003 @@ -18,6 +18,12 @@ ADAPTEC 2120S ADAPTEC 2200S ADAPTEC 5400S + Legend S220 + Legend S230 + Adaptec 3230S + Adaptec 3240S + ASR-2020S PCI-X + AAR-2410SA SATA People ------------------------- @@ -28,6 +34,9 @@ added new ioctls, changed scsi interface to use new error handler, increased the number of fibs and outstanding commands to a container) + (fixed 64bit and 64G memory model, changed confusing naming convention + where fibs that go to the hardware are consistently called hw_fibs and + not just fibs like the name of the driver tracking structure) Original Driver ------------------------- Adaptec Unix OEM Product Group diff -Nru a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c --- a/drivers/scsi/aacraid/aachba.c Thu May 15 15:24:37 2003 +++ b/drivers/scsi/aacraid/aachba.c Thu May 15 15:24:37 2003 @@ -40,8 +40,7 @@ #include "aacraid.h" /* SCSI Commands */ -/* TODO: dmb - use the ones defined in include/scsi/scsi.h */ - +/* TODO dmb - use the ones defined in include/scsi/scsi.h*/ #define SS_TEST 0x00 /* Test unit ready */ #define SS_REZERO 0x01 /* Rezero unit */ #define SS_REQSEN 0x03 /* Request Sense */ @@ -60,15 +59,15 @@ #define SS_SEEK 0x2B /* Seek */ /* values for inqd_pdt: Peripheral device type in plain English */ -#define INQD_PDT_DA 0x00 /* Direct-access (DISK) device */ -#define INQD_PDT_PROC 0x03 /* Processor device */ -#define INQD_PDT_CHNGR 0x08 /* Changer (jukebox, scsi2) */ -#define INQD_PDT_COMM 0x09 /* Communication device (scsi2) */ -#define INQD_PDT_NOLUN2 0x1f /* Unknown Device (scsi2) */ -#define INQD_PDT_NOLUN 0x7f /* Logical Unit Not Present */ +#define INQD_PDT_DA 0x00 /* Direct-access (DISK) device */ +#define INQD_PDT_PROC 0x03 /* Processor device */ +#define INQD_PDT_CHNGR 0x08 /* Changer (jukebox, scsi2) */ +#define INQD_PDT_COMM 0x09 /* Communication device (scsi2) */ +#define INQD_PDT_NOLUN2 0x1f /* Unknown Device (scsi2) */ +#define INQD_PDT_NOLUN 0x7f /* Logical Unit Not Present */ -#define INQD_PDT_DMASK 0x1F /* Peripheral Device Type Mask */ -#define INQD_PDT_QMASK 0xE0 /* Peripheral Device Qualifer Mask */ +#define INQD_PDT_DMASK 0x1F /* Peripheral Device Type Mask */ +#define INQD_PDT_QMASK 0xE0 /* Peripheral Device Qualifer Mask */ #define TARGET_LUN_TO_CONTAINER(target, lun) (target) #define CONTAINER_TO_TARGET(cont) ((cont)) @@ -81,22 +80,22 @@ /* * Sense keys */ -#define SENKEY_NO_SENSE 0x00 -#define SENKEY_UNDEFINED 0x01 -#define SENKEY_NOT_READY 0x02 -#define SENKEY_MEDIUM_ERR 0x03 -#define SENKEY_HW_ERR 0x04 -#define SENKEY_ILLEGAL 0x05 -#define SENKEY_ATTENTION 0x06 -#define SENKEY_PROTECTED 0x07 -#define SENKEY_BLANK 0x08 -#define SENKEY_V_UNIQUE 0x09 -#define SENKEY_CPY_ABORT 0x0A -#define SENKEY_ABORT 0x0B -#define SENKEY_EQUAL 0x0C -#define SENKEY_VOL_OVERFLOW 0x0D -#define SENKEY_MISCOMP 0x0E -#define SENKEY_RESERVED 0x0F +#define SENKEY_NO_SENSE 0x00 +#define SENKEY_UNDEFINED 0x01 +#define SENKEY_NOT_READY 0x02 +#define SENKEY_MEDIUM_ERR 0x03 +#define SENKEY_HW_ERR 0x04 +#define SENKEY_ILLEGAL 0x05 +#define SENKEY_ATTENTION 0x06 +#define SENKEY_PROTECTED 0x07 +#define SENKEY_BLANK 0x08 +#define SENKEY_V_UNIQUE 0x09 +#define SENKEY_CPY_ABORT 0x0A +#define SENKEY_ABORT 0x0B +#define SENKEY_EQUAL 0x0C +#define SENKEY_VOL_OVERFLOW 0x0D +#define SENKEY_MISCOMP 0x0E +#define SENKEY_RESERVED 0x0F /* * Sense codes @@ -160,24 +159,24 @@ *----------------------------------------------------------------------------*/ /* SCSI inquiry data */ struct inquiry_data { - u8 inqd_pdt; /* Peripheral qualifier | Peripheral Device Type */ - u8 inqd_dtq; /* RMB | Device Type Qualifier */ - u8 inqd_ver; /* ISO version | ECMA version | ANSI-approved version */ - u8 inqd_rdf; /* AENC | TrmIOP | Response data format */ - u8 inqd_len; /* Additional length (n-4) */ - u8 inqd_pad1[2]; /* Reserved - must be zero */ - u8 inqd_pad2; /* RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */ - u8 inqd_vid[8]; /* Vendor ID */ - u8 inqd_pid[16]; /* Product ID */ - u8 inqd_prl[4]; /* Product Revision Level */ + u8 inqd_pdt; /* Peripheral qualifier | Peripheral Device Type */ + u8 inqd_dtq; /* RMB | Device Type Qualifier */ + u8 inqd_ver; /* ISO version | ECMA version | ANSI-approved version */ + u8 inqd_rdf; /* AENC | TrmIOP | Response data format */ + u8 inqd_len; /* Additional length (n-4) */ + u8 inqd_pad1[2];/* Reserved - must be zero */ + u8 inqd_pad2; /* RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */ + u8 inqd_vid[8]; /* Vendor ID */ + u8 inqd_pid[16];/* Product ID */ + u8 inqd_prl[4]; /* Product Revision Level */ }; struct sense_data { u8 error_code; /* 70h (current errors), 71h(deferred errors) */ u8 valid:1; /* A valid bit of one indicates that the information */ - /* field contains valid information as defined in the - * SCSI-2 Standard. - */ + /* field contains valid information as defined in the + * SCSI-2 Standard. + */ u8 segment_number; /* Only used for COPY, COMPARE, or COPY AND VERIFY Commands */ u8 sense_key:4; /* Sense Key */ u8 reserved:1; @@ -257,13 +256,14 @@ 1, 1, NULL, NULL); if (status < 0 ) { - printk(KERN_WARNING "ProbeContainers: SendFIB failed.\n"); + printk(KERN_WARNING "aac_get_containers: SendFIB failed.\n"); break; } dresp = (struct aac_mount *)fib_data(fibptr); if ((le32_to_cpu(dresp->status) == ST_OK) && - (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) { + (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && + (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { fsa_dev_ptr->valid[index] = 1; fsa_dev_ptr->type[index] = le32_to_cpu(dresp->mnt[0].vol); fsa_dev_ptr->size[index] = le32_to_cpu(dresp->mnt[0].capacity); @@ -274,8 +274,9 @@ /* * If there are no more containers, then stop asking. */ - if ((index + 1) >= le32_to_cpu(dresp->count)) + if ((index + 1) >= le32_to_cpu(dresp->count)){ break; + } } fib_free(fibptr); fsa_dev[instance] = fsa_dev_ptr; @@ -328,7 +329,8 @@ dresp = (struct aac_mount *) fib_data(fibptr); if ((le32_to_cpu(dresp->status) == ST_OK) && - (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) { + (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && + (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { fsa_dev_ptr->valid[cid] = 1; fsa_dev_ptr->type[cid] = le32_to_cpu(dresp->mnt[0].vol); fsa_dev_ptr->size[cid] = le32_to_cpu(dresp->mnt[0].capacity); @@ -429,7 +431,7 @@ sense_buf[1] = 0; /* Segment number, always zero */ if (incorrect_length) { - sense_buf[2] = sense_key | 0x20; /* Set ILI bit | sense key */ + sense_buf[2] = sense_key | 0x20;/* Set ILI bit | sense key */ sense_buf[3] = BYTE3(residue); sense_buf[4] = BYTE2(residue); sense_buf[5] = BYTE1(residue); @@ -448,11 +450,11 @@ sense_buf[15] = 0; if (sense_code == SENCODE_INVALID_PARAM_FIELD) - sense_buf[15] = 0x80; /* Std sense key specific field */ + sense_buf[15] = 0x80;/* Std sense key specific field */ /* Illegal parameter is in the parameter block */ if (sense_code == SENCODE_INVALID_CDB_FIELD) - sense_buf[15] = 0xc0; /* Std sense key specific field */ + sense_buf[15] = 0xc0;/* Std sense key specific field */ /* Illegal parameter is in the CDB block */ sense_buf[15] |= bit_pointer; sense_buf[16] = field_pointer >> 8; /* MSB */ @@ -463,9 +465,10 @@ static void aac_io_done(Scsi_Cmnd * scsicmd) { unsigned long cpu_flags; - spin_lock_irqsave(scsicmd->device->host->host_lock, cpu_flags); + struct Scsi_Host *host = scsicmd->device->host; + spin_lock_irqsave(host->host_lock, cpu_flags); scsicmd->scsi_done(scsicmd); - spin_unlock_irqrestore(scsicmd->device->host->host_lock, cpu_flags); + spin_unlock_irqrestore(host->host_lock, cpu_flags); } static void __aac_io_done(Scsi_Cmnd * scsicmd) @@ -498,40 +501,53 @@ memcpy(&dev->adapter_info, info, sizeof(struct aac_adapter_info)); tmp = dev->adapter_info.kernelrev; - printk(KERN_INFO "%s%d: kernel %d.%d.%d build %d\n", + printk(KERN_INFO"%s%d: kernel %d.%d.%d build %d\n", dev->name, dev->id, tmp>>24,(tmp>>16)&0xff,(tmp>>8)&0xff, dev->adapter_info.kernelbuild); tmp = dev->adapter_info.monitorrev; - printk(KERN_INFO "%s%d: monitor %d.%d.%d build %d\n", + printk(KERN_INFO"%s%d: monitor %d.%d.%d build %d\n", dev->name, dev->id, tmp>>24,(tmp>>16)&0xff,(tmp>>8)&0xff, dev->adapter_info.monitorbuild); tmp = dev->adapter_info.biosrev; - printk(KERN_INFO "%s%d: bios %d.%d.%d build %d\n", + printk(KERN_INFO"%s%d: bios %d.%d.%d build %d\n", dev->name, dev->id, tmp>>24,(tmp>>16)&0xff,(tmp>>8)&0xff, dev->adapter_info.biosbuild); - printk(KERN_INFO "%s%d: serial %x%x\n", + printk(KERN_INFO"%s%d: serial %x%x\n", dev->name, dev->id, dev->adapter_info.serial[0], dev->adapter_info.serial[1]); - dev->pae_support = 0; + dev->nondasd_support = 0; - if( BITS_PER_LONG >= 64 && - (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)){ - printk(KERN_INFO "%s%d: 64 Bit PAE enabled\n", dev->name, dev->id); + if(dev->adapter_info.options & AAC_OPT_NONDASD){ +// dev->nondasd_support = 1; +// dmb - temporarily disable nondasd + } + if(nondasd != -1) { + dev->nondasd_support = (nondasd!=0); + } + if(dev->nondasd_support != 0){ + printk(KERN_INFO"%s%d: Non-DASD support enabled\n",dev->name, dev->id); + } + + dev->pae_support = 0; + if( (sizeof(dma_addr_t) > 4) && (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)){ dev->pae_support = 1; } - /* TODO - dmb temporary until fw can set this bit */ - dev->pae_support = (BITS_PER_LONG >= 64); + + if(paemode != -1){ + dev->pae_support = (paemode!=0); + } if(dev->pae_support != 0) { - printk(KERN_INFO "%s%d: 64 Bit PAE enabled\n", dev->name, dev->id); + printk(KERN_INFO"%s%d: 64 Bit PAE enabled\n", dev->name, dev->id); + pci_set_dma_mask(dev->pdev, (dma_addr_t)0xFFFFFFFFFFFFFFFFULL); } - if(dev->adapter_info.options & AAC_OPT_NONDASD){ - dev->nondasd_support = 1; - } + fib_complete(fibptr); + fib_free(fibptr); + return rcode; } @@ -550,7 +566,7 @@ cid =TARGET_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun); lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; - dprintk((KERN_DEBUG "read_callback[cpu %d]: lba = %d, t = %ld.\n", smp_processor_id(), lba, jiffies)); + dprintk((KERN_DEBUG "read_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies)); if (fibptr == NULL) BUG(); @@ -561,7 +577,7 @@ scsicmd->use_sg, scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); else if(scsicmd->request_bufflen) - pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle, + pci_unmap_single(dev->pdev, (dma_addr_t)(ulong)scsicmd->SCp.ptr, scsicmd->request_bufflen, scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); readreply = (struct aac_read_reply *)fib_data(fibptr); @@ -595,7 +611,7 @@ cid = TARGET_LUN_TO_CONTAINER(scsicmd->device->id, scsicmd->device->lun); lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; - dprintk((KERN_DEBUG "write_callback[cpu %d]: lba = %d, t = %ld.\n", smp_processor_id(), lba, jiffies)); + dprintk((KERN_DEBUG "write_callback[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies)); if (fibptr == NULL) BUG(); @@ -605,7 +621,7 @@ scsicmd->use_sg, scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); else if(scsicmd->request_bufflen) - pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle, + pci_unmap_single(dev->pdev, (dma_addr_t)(ulong)scsicmd->SCp.ptr, scsicmd->request_bufflen, scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); @@ -677,7 +693,7 @@ readcmd->block = cpu_to_le32(lba); readcmd->pad = cpu_to_le16(0); readcmd->flags = cpu_to_le16(0); - + aac_build_sg64(scsicmd, &readcmd->sg); if(readcmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT) BUG(); @@ -718,8 +734,9 @@ (fib_callback) read_callback, (void *) scsicmd); } + - + /* * Check that the command queued to the controller */ @@ -761,7 +778,7 @@ lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; } - dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %lu, t = %ld.\n", smp_processor_id(), lba, jiffies)); + dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies)); /* * Allocate and initialize a Fib then setup a BlockWrite command */ @@ -772,8 +789,7 @@ } fib_init(cmd_fibcontext); - if(dev->pae_support == 1) - { + if(dev->pae_support == 1){ struct aac_write64 *writecmd; writecmd = (struct aac_write64 *) fib_data(cmd_fibcontext); writecmd->command = cpu_to_le32(VM_CtHostWrite64); @@ -797,9 +813,7 @@ 0, 1, (fib_callback) write_callback, (void *) scsicmd); - } - else - { + } else { struct aac_write *writecmd; writecmd = (struct aac_write *) fib_data(cmd_fibcontext); writecmd->command = cpu_to_le32(VM_CtBlockWrite); @@ -809,8 +823,10 @@ writecmd->sg.count = cpu_to_le32(1); /* ->stable is not used - it did mean which type of write */ - if (count * 512 > (64 * 1024)) + if (count * 512 > (64 * 1024)) { BUG(); + } + aac_build_sg(scsicmd, &writecmd->sg); if(writecmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT) BUG(); @@ -861,18 +877,19 @@ struct fsa_scsi_hba *fsa_dev_ptr; int cardtype; int ret; - struct aac_dev *dev = (struct aac_dev *)scsicmd->device->host->hostdata; + struct Scsi_Host *host = scsicmd->device->host; + struct aac_dev *dev = (struct aac_dev *)host->hostdata; cardtype = dev->cardtype; - fsa_dev_ptr = fsa_dev[scsicmd->device->host->unique_id]; + fsa_dev_ptr = fsa_dev[host->unique_id]; /* * If the bus, target or lun is out of range, return fail * Test does not apply to ID 16, the pseudo id for the controller * itself. */ - if (scsicmd->device->id != scsicmd->device->host->this_id) { + if (scsicmd->device->id != host->this_id) { if ((scsicmd->device->channel == 0) ){ if( (scsicmd->device->id >= AAC_MAX_TARGET) || (scsicmd->device->lun != 0)){ scsicmd->result = DID_NO_CONNECT << 16; @@ -890,9 +907,9 @@ case SS_INQUIR: case SS_RDCAP: case SS_TEST: - spin_unlock_irq(scsicmd->device->host->host_lock); + spin_unlock_irq(host->host_lock); probe_container(dev, cid); - spin_lock_irq(scsicmd->device->host->host_lock); + spin_lock_irq(host->host_lock); if (fsa_dev_ptr->valid[cid] == 0) { scsicmd->result = DID_NO_CONNECT << 16; __aac_io_done(scsicmd); @@ -959,7 +976,7 @@ * see: .c i.e. aac.c */ setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), fsa_dev_ptr->type[cid]); - if (scsicmd->device->id == scsicmd->device->host->this_id) + if (scsicmd->device->id == host->this_id) inq_data_ptr->inqd_pdt = INQD_PDT_PROC; /* Processor device */ else inq_data_ptr->inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ @@ -1053,20 +1070,21 @@ * containers to /dev/sd device names */ - spin_unlock_irq(scsicmd->device->host->host_lock); + spin_unlock_irq(host->host_lock); if (scsicmd->request->rq_disk) memcpy(fsa_dev_ptr->devname[cid], scsicmd->request->rq_disk->disk_name, 8); + ret = aac_read(scsicmd, cid); - spin_lock_irq(scsicmd->device->host->host_lock); + spin_lock_irq(host->host_lock); return ret; case SS_WRITE: case SM_WRITE: - spin_unlock_irq(scsicmd->device->host->host_lock); + spin_unlock_irq(host->host_lock); ret = aac_write(scsicmd, cid); - spin_lock_irq(scsicmd->device->host->host_lock); + spin_lock_irq(host->host_lock); return ret; default: /* @@ -1219,8 +1237,7 @@ scsicmd->use_sg, scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); else if(scsicmd->request_bufflen) - pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle, - scsicmd->request_bufflen, + pci_unmap_single(dev->pdev, (ulong)scsicmd->SCp.ptr, scsicmd->request_bufflen, scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); /* @@ -1239,17 +1256,23 @@ /* * Next check the srb status */ - switch(le32_to_cpu(srbreply->srb_status)){ + switch( (le32_to_cpu(srbreply->srb_status))&0x3f){ case SRB_STATUS_ERROR_RECOVERY: case SRB_STATUS_PENDING: case SRB_STATUS_SUCCESS: if(scsicmd->cmnd[0] == INQUIRY ){ u8 b; + u8 b1; /* We can't expose disk devices because we can't tell whether they - * are the raw container drives or stand alone drives + * are the raw container drives or stand alone drives. If they have + * the removable bit set then we should expose them though. */ - b = *(u8*)scsicmd->buffer; - if( (b & 0x0f) == TYPE_DISK ){ + b = (*(u8*)scsicmd->buffer)&0x1f; + b1 = ((u8*)scsicmd->buffer)[1]; + if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER + || (b==TYPE_DISK && (b1&0x80)) ){ + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; + } else { scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; } } else { @@ -1271,6 +1294,22 @@ } scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8; break; + case INQUIRY: { + u8 b; + u8 b1; + /* We can't expose disk devices because we can't tell whether they + * are the raw container drives or stand alone drives + */ + b = (*(u8*)scsicmd->buffer)&0x0f; + b1 = ((u8*)scsicmd->buffer)[1]; + if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER + || (b==TYPE_DISK && (b1&0x80)) ){ + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; + } else { + scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; + } + break; + } default: scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8; break; @@ -1326,17 +1365,19 @@ case SRB_STATUS_DOMAIN_VALIDATION_FAIL: default: #ifdef AAC_DETAILED_STATUS_INFO - printk("aacraid: SRB ERROR (%s)\n",aac_get_status_string(le32_to_cpu(srbreply->srb_status))); + printk("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n",le32_to_cpu(srbreply->srb_status&0x3f),aac_get_status_string(le32_to_cpu(srbreply->srb_status)), scsicmd->cmnd[0], le32_to_cpu(srbreply->scsi_status) ); #endif scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8; break; } if (le32_to_cpu(srbreply->scsi_status) == 0x02 ){ // Check Condition int len; + scsicmd->result |= CHECK_CONDITION; len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))? sizeof(scsicmd->sense_buffer):srbreply->sense_data_size; printk(KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n", le32_to_cpu(srbreply->status), len); memcpy(scsicmd->sense_buffer, srbreply->sense_data, len); + } /* * OR in the scsi status (already shifted up a bit) @@ -1365,6 +1406,7 @@ struct aac_srb *srbcmd; u16 fibsize; u32 flag; + u32 timeout; if( scsicmd->device->id > 15 || scsicmd->device->lun > 7) { scsicmd->result = DID_NO_CONNECT << 16; @@ -1406,7 +1448,11 @@ srbcmd->target = cpu_to_le32(scsicmd->device->id); srbcmd->lun = cpu_to_le32(scsicmd->device->lun); srbcmd->flags = cpu_to_le32(flag); - srbcmd->timeout = cpu_to_le32(0); // timeout not used + timeout = (scsicmd->timeout-jiffies)/HZ; + if(timeout == 0){ + timeout = 1; + } + srbcmd->timeout = cpu_to_le32(timeout); // timeout in seconds srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter srbcmd->cdb_size = cpu_to_le32(scsicmd->cmd_len); @@ -1511,7 +1557,7 @@ psg->count = cpu_to_le32(1); psg->sg[0].addr = cpu_to_le32(addr); psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen); - scsicmd->SCp.dma_handle = addr; + scsicmd->SCp.ptr = (char *)addr; byte_count = scsicmd->request_bufflen; } return byte_count; @@ -1572,7 +1618,7 @@ psg->sg[0].addr[1] = (u32)(le_addr>>32); psg->sg[0].addr[0] = (u32)(le_addr & 0xffffffff); psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen); - scsicmd->SCp.dma_handle = addr; + scsicmd->SCp.ptr = (char *)addr; byte_count = scsicmd->request_bufflen; } return byte_count; diff -Nru a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h --- a/drivers/scsi/aacraid/aacraid.h Thu May 15 15:24:35 2003 +++ b/drivers/scsi/aacraid/aacraid.h Thu May 15 15:24:35 2003 @@ -1,18 +1,17 @@ +//#define dprintk(x) printk x #define dprintk(x) -/*#define dprintk(x) printk x */ /*------------------------------------------------------------------------------ * D E F I N E S *----------------------------------------------------------------------------*/ - #define MAXIMUM_NUM_CONTAINERS 31 #define MAXIMUM_NUM_ADAPTERS 8 #define AAC_NUM_FIB 578 -#define AAC_NUM_IO_FIB 512 +//#define AAC_NUM_IO_FIB 512 +#define AAC_NUM_IO_FIB 100 #define AAC_MAX_TARGET (MAXIMUM_NUM_CONTAINERS+1) -//#define AAC_MAX_TARGET (16) #define AAC_MAX_LUN (8) /* @@ -24,6 +23,9 @@ #define AAC_DETAILED_STATUS_INFO +extern int nondasd; +extern int paemode; + struct diskparm { int heads; @@ -237,6 +239,92 @@ }; /* + * Implement our own version of these so we have 64 bit compatability + * The adapter uses these and can only handle 32 bit addresses + */ + +struct aac_list_head { + u32 next; + u32 prev; +}; + +#define AAC_INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (u32)(ulong)(ptr); \ + (ptr)->prev = (u32)(ulong)(ptr); \ +} while (0) +/** + * aac_list_empty - tests whether a list is empty + * @head: the list to test. + */ +static __inline__ int aac_list_empty(struct aac_list_head *head) +{ + return head->next == ((u32)(ulong)head); +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static __inline__ void aac_list_add(struct aac_list_head * n, + struct aac_list_head * prev, + struct aac_list_head * next) +{ + next->prev = (u32)(ulong)n; + n->next = (u32)(ulong)next; + n->prev = (u32)(ulong)prev; + prev->next = (u32)(ulong)n; +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static __inline__ void aac_list_add_tail(struct aac_list_head *n, struct aac_list_head *head) +{ + aac_list_add(n, (struct aac_list_head*)(ulong)(head->prev), head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static __inline__ void __aac_list_del(struct aac_list_head * p, + struct aac_list_head * n) +{ + n->prev = (u32)(ulong)p; + p->next = (u32)(ulong)n; +} + +/** + * aac_list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is in an undefined state. + */ +static __inline__ void aac_list_del(struct aac_list_head *entry) +{ + __aac_list_del((struct aac_list_head*)(ulong)entry->prev,(struct aac_list_head*)(ulong) entry->next); + entry->next = entry->prev = 0; +} + +/** + * aac_list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define aac_list_entry(ptr, type, member) \ + ((type *)((char *)(ptr)-(ulong)(&((type *)0)->member))) + +/* * Assign type values to the FSA communication data structures */ @@ -249,11 +337,11 @@ #define FsaNormal 1 #define FsaHigh 2 + /* * Define the FIB. The FIB is the where all the requested data and * command information are put to the application on the FSA adapter. */ - struct aac_fibhdr { u32 XferState; // Current transfer state for this CCB u16 Command; // Routing information for the destination @@ -269,7 +357,8 @@ u32 _ReceiverTimeStart; // Timestamp for receipt of fib u32 _ReceiverTimeDone; // Timestamp for completion of fib } _s; - struct list_head _FibLinks; // Used to link Adapter Initiated Fibs on the host + struct aac_list_head _FibLinks; // Used to link Adapter Initiated Fibs on the host +// struct list_head _FibLinks; // Used to link Adapter Initiated Fibs on the host } _u; }; @@ -451,21 +540,22 @@ */ struct aac_queue { - u64 logical; /* This is the address we give the adapter */ - struct aac_entry *base; /* This is the system virtual address */ - struct aac_qhdr headers; /* A pointer to the producer and consumer queue headers for this queue */ - u32 entries; /* Number of queue entries on this queue */ - wait_queue_head_t qfull; /* Event to wait on if the queue is full */ - wait_queue_head_t cmdready; /* Indicates there is a Command ready from the adapter on this queue. */ - /* This is only valid for adapter to host command queues. */ - spinlock_t *lock; /* Spinlock for this queue must take this lock before accessing the lock */ - spinlock_t lockdata; /* Actual lock (used only on one side of the lock) */ - unsigned long SavedIrql; /* Previous IRQL when the spin lock is taken */ - u32 padding; /* Padding - FIXME - can remove I believe */ - struct list_head cmdq; /* A queue of FIBs which need to be prcessed by the FS thread. This is */ + u64 logical; /*address we give the adapter */ + struct aac_entry *base; /*system virtual address */ + struct aac_qhdr headers; /*producer,consumer q headers*/ + u32 entries; /*Number of queue entries */ + wait_queue_head_t qfull; /*Event to wait on if q full */ + wait_queue_head_t cmdready; /*Cmd ready from the adapter */ + /* This is only valid for adapter to host command queues. */ + spinlock_t *lock; /* Spinlock for this queue must take this lock before accessing the lock */ + spinlock_t lockdata; /* Actual lock (used only on one side of the lock) */ + u32 SavedIrql; /* Previous IRQL when the spin lock is taken */ + u32 padding; /* Padding - FIXME - can remove I believe */ + struct aac_list_head cmdq; /* A queue of FIBs which need to be prcessed by the FS thread. This is */ +// struct list_head cmdq; /* A queue of FIBs which need to be prcessed by the FS thread. This is */ /* only valid for command queues which receive entries from the adapter. */ struct list_head pendingq; /* A queue of outstanding fib's to the adapter. */ - unsigned long numpending; /* Number of entries on outstanding queue. */ + u32 numpending; /* Number of entries on outstanding queue. */ struct aac_dev * dev; /* Back pointer to adapter structure */ }; @@ -629,7 +719,7 @@ struct semaphore wait_sem; // this is used to wait for the next fib to arrive. int wait; // Set to true when thread is in WaitForSingleObject unsigned long count; // total number of FIBs on FibList - struct list_head fibs; + struct aac_list_head hw_fib_list; // this holds hw_fibs which should be 32 bit addresses }; struct fsa_scsi_hba { @@ -650,7 +740,6 @@ * The Adapter that this I/O is destined for. */ struct aac_dev *dev; - u64 logicaladdr; /* 64 bit */ /* * This is the event the sendfib routine will wait on if the * caller did not pass one and this is synch io. @@ -669,7 +758,8 @@ struct list_head queue; void *data; - struct hw_fib *fib; /* Actual shared object */ + struct hw_fib *hw_fib; /* Actual shared object */ + dma_addr_t hw_fib_pa; /* physical address of hw_fib*/ }; /* @@ -696,6 +786,7 @@ u32 biosrev; u32 biosbuild; u32 cluster; + u32 clusterchannelmask; u32 serial[2]; u32 battery; u32 options; @@ -746,13 +837,13 @@ */ dma_addr_t hw_fib_pa; struct hw_fib *hw_fib_va; -#if BITS_PER_LONG >= 64 ulong fib_base_va; -#endif /* * Fib Headers */ - struct fib fibs[AAC_NUM_FIB]; +// dmb struct fib fibs[AAC_NUM_FIB]; /* Doing it here takes up too much from the scsi pool*/ + struct fib *fibs; + struct fib *free_fib; struct fib *timeout_fib; spinlock_t fib_lock; @@ -771,6 +862,7 @@ unsigned long fsrev; /* Main driver's revision number */ struct aac_init *init; /* Holds initialization info to communicate with adapter */ +// void * init_pa; /* Holds physical address of the init struct */ dma_addr_t init_pa; /* Holds physical address of the init struct */ struct pci_dev *pdev; /* Our PCI interface */ @@ -1148,7 +1240,9 @@ u32 altoid; // != oid <==> snapshot or broken mirror exists }; -#define FSCS_READONLY 0x0002 /* possible result of broken mirror */ +#define FSCS_NOTCLEAN 0x0001 /* fsck is neccessary before mounting */ +#define FSCS_READONLY 0x0002 /* possible result of broken mirror */ +#define FSCS_HIDDEN 0x0004 /* should be ignored - set during a clear */ struct aac_query_mount { u32 command; @@ -1359,16 +1453,6 @@ u8 data[1]; /* Undefined length (from kernel viewpoint) */ }; -static inline u32 fib2addr(struct hw_fib *hw) -{ - return (u32)hw; -} - -static inline struct hw_fib *addr2fib(u32 addr) -{ - return (struct hw_fib *)addr; -} - /** * Convert capacity to cylinders * accounting for the fact capacity could be a 64 bit value @@ -1376,12 +1460,8 @@ */ static inline u32 cap_to_cyls(sector_t capacity, u32 divisor) { -#ifdef CONFIG_LBD - do_div(capacity, divisor); -#else - capacity /= divisor; -#endif - return (u32) capacity; + sector_div(capacity, divisor); + return (u32)capacity; } const char *aac_driverinfo(struct Scsi_Host *); @@ -1397,7 +1477,7 @@ int aac_consumer_avail(struct aac_dev * dev, struct aac_queue * q); void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum); int fib_complete(struct fib * context); -#define fib_data(fibctx) ((void *)(fibctx)->fib->data) +#define fib_data(fibctx) ((void *)(fibctx)->hw_fib->data) int aac_detach(struct aac_dev *dev); struct aac_dev *aac_init_adapter(struct aac_dev *dev); int aac_get_containers(struct aac_dev *dev); diff -Nru a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c --- a/drivers/scsi/aacraid/commctrl.c Thu May 15 15:24:37 2003 +++ b/drivers/scsi/aacraid/commctrl.c Thu May 15 15:24:37 2003 @@ -63,7 +63,7 @@ if(fibptr == NULL) return -ENOMEM; - kfib = fibptr->fib; + kfib = fibptr->hw_fib; /* * First copy in the header so that we can check the size field. */ @@ -150,7 +150,7 @@ * the list to 0. */ fibctx->count = 0; - INIT_LIST_HEAD(&fibctx->fibs); + AAC_INIT_LIST_HEAD(&fibctx->hw_fib_list); fibctx->jiffies = jiffies/HZ; /* * Now add this context onto the adapter's @@ -181,7 +181,7 @@ { struct fib_ioctl f; struct aac_fib_context *fibctx, *aifcp; - struct hw_fib * fib; + struct hw_fib * hw_fib; int status; struct list_head * entry; int found; @@ -224,25 +224,25 @@ * -EAGAIN */ return_fib: - if (!list_empty(&fibctx->fibs)) { - struct list_head * entry; + if (!aac_list_empty(&fibctx->hw_fib_list)) { + struct aac_list_head * entry; /* * Pull the next fib from the fibs */ - entry = fibctx->fibs.next; - list_del(entry); + entry = (struct aac_list_head*)(ulong)fibctx->hw_fib_list.next; + aac_list_del(entry); - fib = list_entry(entry, struct hw_fib, header.FibLinks); + hw_fib = aac_list_entry(entry, struct hw_fib, header.FibLinks); fibctx->count--; spin_unlock_irqrestore(&dev->fib_lock, flags); - if (copy_to_user(f.fib, fib, sizeof(struct hw_fib))) { - kfree(fib); + if (copy_to_user(f.fib, hw_fib, sizeof(struct hw_fib))) { + kfree(hw_fib); return -EFAULT; } /* * Free the space occupied by this copy of the fib. */ - kfree(fib); + kfree(hw_fib); status = 0; fibctx->jiffies = jiffies/HZ; } else { @@ -264,24 +264,24 @@ int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context * fibctx) { - struct hw_fib *fib; + struct hw_fib *hw_fib; /* * First free any FIBs that have not been consumed. */ - while (!list_empty(&fibctx->fibs)) { - struct list_head * entry; + while (!aac_list_empty(&fibctx->hw_fib_list)) { + struct aac_list_head * entry; /* * Pull the next fib from the fibs */ - entry = fibctx->fibs.next; - list_del(entry); - fib = list_entry(entry, struct hw_fib, header.FibLinks); + entry = (struct aac_list_head*)(ulong)(fibctx->hw_fib_list.next); + aac_list_del(entry); + hw_fib = aac_list_entry(entry, struct hw_fib, header.FibLinks); fibctx->count--; /* * Free the space occupied by this copy of the fib. */ - kfree(fib); + kfree(hw_fib); } /* * Remove the Context from the AdapterFibContext List @@ -372,6 +372,204 @@ return 0; } +/** + * + * aac_send_raw_scb + * + */ + +int aac_send_raw_srb(struct aac_dev* dev, void* arg) +{ + struct fib* srbfib; + int status; + struct aac_srb *srbcmd; + struct aac_srb *user_srb = arg; + struct aac_srb_reply* user_reply; + struct aac_srb_reply* reply; + u32 fibsize = 0; + u32 flags = 0; + s32 rcode = 0; + u32 data_dir; + ulong sg_user[32]; + ulong sg_list[32]; + u32 sg_indx = 0; + u32 byte_count = 0; + u32 actual_fibsize = 0; + int i; + + + if (!capable(CAP_SYS_ADMIN)){ + printk(KERN_DEBUG"aacraid: No permission to send raw srb\n"); + return -EPERM; + } + /* + * Allocate and initialize a Fib then setup a BlockWrite command + */ + if (!(srbfib = fib_alloc(dev))) { + return -1; + } + fib_init(srbfib); + + srbcmd = (struct aac_srb*) fib_data(srbfib); + + if(copy_from_user((void*)&fibsize, (void*)&user_srb->count,sizeof(u32))){ + printk(KERN_DEBUG"aacraid: Could not copy data size from user\n"); + rcode = -EFAULT; + goto cleanup; + } + + if(copy_from_user(srbcmd, user_srb,fibsize)){ + printk(KERN_DEBUG"aacraid: Could not copy srb from user\n"); + rcode = -EFAULT; + goto cleanup; + } + + user_reply = arg+fibsize; + + flags = srbcmd->flags; + // Fix up srb for endian and force some values + srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); // Force this + srbcmd->channel = cpu_to_le32(srbcmd->channel); + srbcmd->target = cpu_to_le32(srbcmd->target); + srbcmd->lun = cpu_to_le32(srbcmd->lun); + srbcmd->flags = cpu_to_le32(srbcmd->flags); + srbcmd->timeout = cpu_to_le32(srbcmd->timeout); + srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter + srbcmd->cdb_size = cpu_to_le32(srbcmd->cdb_size); + + switch(srbcmd->flags){ + case SRB_DataOut: + data_dir = SCSI_DATA_WRITE; + break; + case (SRB_DataIn | SRB_DataOut): + data_dir = SCSI_DATA_UNKNOWN; + break; + case SRB_DataIn: + data_dir = SCSI_DATA_READ; + break; + default: + data_dir = SCSI_DATA_NONE; + } + if( dev->pae_support ==1 ) { + struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg; + byte_count = 0; + + // This should also catch if user used the 32 bit sgmap + actual_fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry64)); + if(actual_fibsize != fibsize){ // User made a mistake - should not continue + printk(KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"); + rcode = -EINVAL; + goto cleanup; + } + + for (i = 0; i < psg->count; i++) { + dma_addr_t addr; + u64 le_addr; + void* p; + p = kmalloc(psg->sg[i].count,GFP_KERNEL|__GFP_DMA); + if(p == 0) { + printk(KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", + psg->sg[i].count,i,psg->count); + rcode = -ENOMEM; + goto cleanup; + } + sg_user[i] = (ulong)psg->sg[i].addr; + sg_list[i] = (ulong)p; // save so we can clean up later + sg_indx = i; + + if( flags & SRB_DataOut ){ + if(copy_from_user(p,psg->sg[i].addr,psg->sg[i].count)){ + printk(KERN_DEBUG"aacraid: Could not copy sg data from user\n"); + rcode = -EFAULT; + goto cleanup; + } + } + addr = pci_map_single(dev->pdev, p, psg->sg[i].count, scsi_to_pci_dma_dir(data_dir)); + + le_addr = cpu_to_le64(addr); + psg->sg[i].addr[1] = (u32)(le_addr>>32); + psg->sg[i].addr[0] = (u32)(le_addr & 0xffffffff); + psg->sg[i].count = cpu_to_le32(psg->sg[i].count); + byte_count += psg->sg[i].count; + } + + srbcmd->count = cpu_to_le32(byte_count); + status = fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,0,0); + } else { + struct sgmap* psg = &srbcmd->sg; + byte_count = 0; + + actual_fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry)); + if(actual_fibsize != fibsize){ // User made a mistake - should not continue + printk(KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"); + rcode = -EINVAL; + goto cleanup; + } + for (i = 0; i < psg->count; i++) { + dma_addr_t addr; + void* p; + p = kmalloc(psg->sg[i].count,GFP_KERNEL); + if(p == 0) { + printk(KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", + psg->sg[i].count,i,psg->count); + rcode = -ENOMEM; + goto cleanup; + } + sg_user[i] = (ulong)(psg->sg[i].addr); + sg_list[i] = (ulong)p; // save so we can clean up later + sg_indx = i; + + if( flags & SRB_DataOut ){ + if(copy_from_user((void*)p,(void*)(ulong)(psg->sg[i].addr),psg->sg[i].count)){ + printk(KERN_DEBUG"aacraid: Could not copy sg data from user\n"); + rcode = -EFAULT; + goto cleanup; + } + } + addr = pci_map_single(dev->pdev, p, psg->sg[i].count, scsi_to_pci_dma_dir(data_dir)); + + psg->sg[i].addr = cpu_to_le32(addr); + psg->sg[i].count = cpu_to_le32(psg->sg[i].count); + byte_count += psg->sg[i].count; + } + srbcmd->count = cpu_to_le32(byte_count); + status = fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, 0, 0); + } + + if (status != 0){ + printk(KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n"); + rcode = -1; + goto cleanup; + } + + if( flags & SRB_DataIn ) { + for(i = 0 ; i <= sg_indx; i++){ + if(copy_to_user((void*)(sg_user[i]),(void*)(sg_list[i]),le32_to_cpu(srbcmd->sg.sg[i].count))){ + printk(KERN_DEBUG"aacraid: Could not copy sg data to user\n"); + rcode = -EFAULT; + goto cleanup; + + } + } + } + + reply = (struct aac_srb_reply *) fib_data(srbfib); + if(copy_to_user(user_reply,reply,sizeof(struct aac_srb_reply))){ + printk(KERN_DEBUG"aacraid: Could not copy reply to user\n"); + rcode = -EFAULT; + goto cleanup; + } + +cleanup: + for(i=0; i <= sg_indx; i++){ + kfree((void*)sg_list[i]); + } + fib_complete(srbfib); + fib_free(srbfib); + + return rcode; +} + struct aac_pci_info { u32 bus; @@ -386,8 +584,10 @@ pci_info.bus = dev->pdev->bus->number; pci_info.slot = PCI_SLOT(dev->pdev->devfn); - if(copy_to_user( arg, (void*)&pci_info, sizeof(struct aac_pci_info))) + if(copy_to_user( arg, (void*)&pci_info, sizeof(struct aac_pci_info))){ + printk(KERN_DEBUG "aacraid: Could not copy pci info\n"); return -EFAULT; + } return 0; } @@ -419,6 +619,9 @@ break; case FSACTL_CLOSE_GET_ADAPTER_FIB: status = close_getadapter_fib(dev, arg); + break; + case FSACTL_SEND_RAW_SRB: + status = aac_send_raw_srb(dev,arg); break; case FSACTL_GET_PCI_INFO: status = aac_get_pci_info(dev,arg); diff -Nru a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c --- a/drivers/scsi/aacraid/comminit.c Thu May 15 15:24:33 2003 +++ b/drivers/scsi/aacraid/comminit.c Thu May 15 15:24:33 2003 @@ -39,6 +39,7 @@ #include #include #include +#include #include #include "scsi.h" #include "hosts.h" @@ -58,10 +59,11 @@ struct aac_init *init; dma_addr_t phys; - /* FIXME: Adaptec add 128 bytes to this value - WHY ?? */ size = fibsize + sizeof(struct aac_init) + commsize + commalign + printfbufsiz; + base = pci_alloc_consistent(dev->pdev, size, &phys); + if(base == NULL) { printk(KERN_ERR "aacraid: unable to create mapping.\n"); @@ -70,18 +72,10 @@ dev->comm_addr = (void *)base; dev->comm_phys = phys; dev->comm_size = size; - + dev->init = (struct aac_init *)(base + fibsize); dev->init_pa = phys + fibsize; - /* - * Cache the upper bits of the virtual mapping for 64bit boxes - * FIXME: this crap should be rewritten - */ -#if BITS_PER_LONG >= 64 - dev->fib_base_va = ((ulong)base & 0xffffffff00000000); -#endif - init = dev->init; init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION); @@ -92,16 +86,19 @@ * Adapter Fibs are the first thing allocated so that they * start page aligned */ - init->AdapterFibsVirtualAddress = cpu_to_le32((u32)base); - init->AdapterFibsPhysicalAddress = cpu_to_le32(phys); + dev->fib_base_va = (ulong)base; + + init->AdapterFibsVirtualAddress = cpu_to_le32((u32)(ulong)phys); + init->AdapterFibsPhysicalAddress = cpu_to_le32((u32)phys); init->AdapterFibsSize = cpu_to_le32(fibsize); init->AdapterFibAlign = cpu_to_le32(sizeof(struct hw_fib)); + init->HostPhysMemPages = cpu_to_le32(num_physpages); // number of 4k pages of host physical memory /* * Increment the base address by the amount already used */ base = base + fibsize + sizeof(struct aac_init); - phys = phys + fibsize + sizeof(struct aac_init); + phys = (dma_addr_t)((ulong)phys + fibsize + sizeof(struct aac_init)); /* * Align the beginning of Headers to commalign */ @@ -111,8 +108,8 @@ /* * Fill in addresses of the Comm Area Headers and Queues */ - *commaddr = (unsigned long *)base; - init->CommHeaderAddress = cpu_to_le32(phys); + *commaddr = base; + init->CommHeaderAddress = cpu_to_le32((u32)phys); /* * Increment the base address by the size of the CommArea */ @@ -134,14 +131,14 @@ q->dev = dev; INIT_LIST_HEAD(&q->pendingq); init_waitqueue_head(&q->cmdready); - INIT_LIST_HEAD(&q->cmdq); + AAC_INIT_LIST_HEAD(&q->cmdq); init_waitqueue_head(&q->qfull); spin_lock_init(&q->lockdata); q->lock = &q->lockdata; q->headers.producer = mem; q->headers.consumer = mem+1; - *q->headers.producer = cpu_to_le32(qsize); - *q->headers.consumer = cpu_to_le32(qsize); + *(q->headers.producer) = cpu_to_le32(qsize); + *(q->headers.consumer) = cpu_to_le32(qsize); q->entries = qsize; } @@ -227,7 +224,6 @@ struct aac_entry * queues; unsigned long size; struct aac_queue_block * comm = dev->queues; - /* * Now allocate and initialize the zone structures used as our * pool of FIB context records. The size of the zone is based @@ -246,9 +242,9 @@ if (!aac_alloc_comm(dev, (void * *)&headers, size, QUEUE_ALIGNMENT)) return -ENOMEM; - queues = (struct aac_entry *)((unsigned char *)headers + hdrsize); + queues = (struct aac_entry *)(((ulong)headers) + hdrsize); - /* Adapter to Host normal proirity Command queue */ + /* Adapter to Host normal priority Command queue */ comm->queue[HostNormCmdQueue].base = queues; aac_queue_init(dev, &comm->queue[HostNormCmdQueue], headers, HOST_NORM_CMD_ENTRIES); queues += HOST_NORM_CMD_ENTRIES; @@ -278,7 +274,6 @@ /* adapter to host normal priority response queue */ comm->queue[HostNormRespQueue].base = queues; aac_queue_init(dev, &comm->queue[HostNormRespQueue], headers, HOST_NORM_RESP_ENTRIES); - queues += HOST_NORM_RESP_ENTRIES; headers += 2; @@ -313,6 +308,7 @@ /* * Ok now init the communication subsystem */ + dev->queues = (struct aac_queue_block *) kmalloc(sizeof(struct aac_queue_block), GFP_KERNEL); if (dev->queues == NULL) { printk(KERN_ERR "Error could not allocate comm region.\n"); @@ -320,13 +316,17 @@ } memset(dev->queues, 0, sizeof(struct aac_queue_block)); - if (aac_comm_init(dev)<0) + if (aac_comm_init(dev)<0){ + kfree(dev->queues); return NULL; + } /* * Initialize the list of fibs */ - if(fib_setup(dev)<0) + if(fib_setup(dev)<0){ + kfree(dev->queues); return NULL; + } INIT_LIST_HEAD(&dev->fib_list); init_completion(&dev->aif_completion); diff -Nru a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c --- a/drivers/scsi/aacraid/commsup.c Thu May 15 15:24:41 2003 +++ b/drivers/scsi/aacraid/commsup.c Thu May 15 15:24:41 2003 @@ -79,39 +79,39 @@ * fib_setup - setup the fibs * @dev: Adapter to set up * - * Allocate the PCI space for the fibs, map it and then initialise the + * Allocate the PCI space for the fibs, map it and then intialise the * fib area, the unmapped fib data and also the free list */ int fib_setup(struct aac_dev * dev) { struct fib *fibptr; - struct hw_fib *fib; - dma_addr_t fibpa; + struct hw_fib *hw_fib_va; + dma_addr_t hw_fib_pa; int i; if(fib_map_alloc(dev)<0) return -ENOMEM; - fib = dev->hw_fib_va; - fibpa = dev->hw_fib_pa; - memset(fib, 0, sizeof(struct hw_fib) * AAC_NUM_FIB); + hw_fib_va = dev->hw_fib_va; + hw_fib_pa = dev->hw_fib_pa; + memset(hw_fib_va, 0, sizeof(struct hw_fib) * AAC_NUM_FIB); /* * Initialise the fibs */ for (i = 0, fibptr = &dev->fibs[i]; i < AAC_NUM_FIB; i++, fibptr++) { fibptr->dev = dev; - fibptr->fib = fib; - fibptr->data = (void *) fibptr->fib->data; + fibptr->hw_fib = hw_fib_va; + fibptr->data = (void *) fibptr->hw_fib->data; fibptr->next = fibptr+1; /* Forward chain the fibs */ init_MUTEX_LOCKED(&fibptr->event_wait); spin_lock_init(&fibptr->event_lock); - fib->header.XferState = cpu_to_le32(0xffffffff); - fib->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib)); - fibptr->logicaladdr = (unsigned long) fibpa; - fib = (struct hw_fib *)((unsigned char *)fib + sizeof(struct hw_fib)); - fibpa = fibpa + sizeof(struct hw_fib); + hw_fib_va->header.XferState = cpu_to_le32(0xffffffff); + hw_fib_va->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib)); + fibptr->hw_fib_pa = hw_fib_pa; + hw_fib_va = (struct hw_fib *)((unsigned char *)hw_fib_va + sizeof(struct hw_fib)); + hw_fib_pa = hw_fib_pa + sizeof(struct hw_fib); } /* * Add the fib chain to the free list @@ -136,11 +136,15 @@ { struct fib * fibptr; unsigned long flags; - spin_lock_irqsave(&dev->fib_lock, flags); fibptr = dev->free_fib; - if(!fibptr) - BUG(); + while(!fibptr){ + spin_unlock_irqrestore(&dev->fib_lock, flags); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + spin_lock_irqsave(&dev->fib_lock, flags); + fibptr = dev->free_fib; + } dev->free_fib = fibptr->next; spin_unlock_irqrestore(&dev->fib_lock, flags); /* @@ -152,7 +156,7 @@ * Null out fields that depend on being zero at the start of * each I/O */ - fibptr->fib->header.XferState = cpu_to_le32(0); + fibptr->hw_fib->header.XferState = cpu_to_le32(0); fibptr->callback = NULL; fibptr->callback_data = NULL; @@ -172,15 +176,14 @@ unsigned long flags; spin_lock_irqsave(&fibptr->dev->fib_lock, flags); - if (fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT) { aac_config.fib_timeouts++; fibptr->next = fibptr->dev->timeout_fib; fibptr->dev->timeout_fib = fibptr; } else { - if (fibptr->fib->header.XferState != 0) { + if (fibptr->hw_fib->header.XferState != 0) { printk(KERN_WARNING "fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n", - (void *)fibptr, fibptr->fib->header.XferState); + (void*)fibptr, fibptr->hw_fib->header.XferState); } fibptr->next = fibptr->dev->free_fib; fibptr->dev->free_fib = fibptr; @@ -197,14 +200,14 @@ void fib_init(struct fib *fibptr) { - struct hw_fib *fib = fibptr->fib; + struct hw_fib *hw_fib = fibptr->hw_fib; - fib->header.StructType = FIB_MAGIC; - fib->header.Size = cpu_to_le16(sizeof(struct hw_fib)); - fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable); - fib->header.SenderFibAddress = cpu_to_le32(0); - fib->header.ReceiverFibAddress = cpu_to_le32(0); - fib->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib)); + hw_fib->header.StructType = FIB_MAGIC; + hw_fib->header.Size = cpu_to_le16(sizeof(struct hw_fib)); + hw_fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable); + hw_fib->header.SenderFibAddress = cpu_to_le32(fibptr->hw_fib_pa); + hw_fib->header.ReceiverFibAddress = cpu_to_le32(fibptr->hw_fib_pa); + hw_fib->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib)); } /** @@ -217,10 +220,10 @@ void fib_dealloc(struct fib * fibptr) { - struct hw_fib *fib = fibptr->fib; - if(fib->header.StructType != FIB_MAGIC) + struct hw_fib *hw_fib = fibptr->hw_fib; + if(hw_fib->header.StructType != FIB_MAGIC) BUG(); - fib->header.XferState = cpu_to_le32(0); + hw_fib->header.XferState = cpu_to_le32(0); } /* @@ -257,7 +260,7 @@ q = &dev->queues->queue[qid]; *index = le32_to_cpu(*(q->headers.producer)); - if (*index - 2 == le32_to_cpu(*(q->headers.consumer))) + if ((*index - 2) == le32_to_cpu(*(q->headers.consumer))) *nonotify = 1; if (qid == AdapHighCmdQueue) { @@ -277,10 +280,14 @@ if (*index >= ADAP_NORM_RESP_ENTRIES) *index = 0; /* Wrap to front of the Producer Queue. */ } - else BUG(); + else { + printk("aacraid: invalid qid\n"); + BUG(); + } - if (*index + 1 == le32_to_cpu(*(q->headers.consumer))) { /* Queue is full */ - printk(KERN_WARNING "Queue %d full, %ld outstanding.\n", qid, q->numpending); + if ((*index + 1) == le32_to_cpu(*(q->headers.consumer))) { /* Queue is full */ + printk(KERN_WARNING "Queue %d full, %d outstanding.\n", + qid, q->numpending); return 0; } else { *entry = q->base + *index; @@ -288,7 +295,7 @@ } } -/** +/*Command thread: * * aac_queue_get - get the next free QE * @dev: Adapter * @index: Returned index @@ -304,7 +311,7 @@ * success. */ -static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * fib, int wait, struct fib * fibptr, unsigned long *nonotify) +static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify) { struct aac_entry * entry = NULL; int map = 0; @@ -322,7 +329,7 @@ /* * Setup queue entry with a command, status and fib mapped */ - entry->size = cpu_to_le32(le16_to_cpu(fib->header.Size)); + entry->size = cpu_to_le32(le16_to_cpu(hw_fib->header.Size)); map = 1; } else if (qid == AdapHighRespQueue || qid == AdapNormRespQueue) @@ -334,17 +341,18 @@ /* * Setup queue entry with command, status and fib mapped */ - entry->size = cpu_to_le32(le16_to_cpu(fib->header.Size)); - entry->addr = cpu_to_le32(fib->header.SenderFibAddress); /* Restore adapters pointer to the FIB */ - fib->header.ReceiverFibAddress = fib->header.SenderFibAddress; /* Let the adapter now where to find its data */ + entry->size = cpu_to_le32(le16_to_cpu(hw_fib->header.Size)); + entry->addr = hw_fib->header.SenderFibAddress; + /* Restore adapters pointer to the FIB */ + hw_fib->header.ReceiverFibAddress = hw_fib->header.SenderFibAddress; /* Let the adapter now where to find its data */ map = 0; - } + } /* * If MapFib is true than we need to map the Fib and put pointers * in the queue entry. */ if (map) - entry->addr = cpu_to_le32((unsigned long)(fibptr->logicaladdr)); + entry->addr = fibptr->hw_fib_pa; return 0; } @@ -415,11 +423,10 @@ u32 qid; struct aac_dev * dev = fibptr->dev; unsigned long nointr = 0; - struct hw_fib * fib = fibptr->fib; + struct hw_fib * hw_fib = fibptr->hw_fib; struct aac_queue * q; unsigned long flags = 0; - - if (!(le32_to_cpu(fib->header.XferState) & HostOwned)) + if (!(le32_to_cpu(hw_fib->header.XferState) & HostOwned)) return -EBUSY; /* * There are 5 cases with the wait and reponse requested flags. @@ -435,19 +442,22 @@ if (wait && !reply) { return -EINVAL; } else if (!wait && reply) { - fib->header.XferState |= cpu_to_le32(Async | ResponseExpected); + hw_fib->header.XferState |= cpu_to_le32(Async | ResponseExpected); FIB_COUNTER_INCREMENT(aac_config.AsyncSent); } else if (!wait && !reply) { - fib->header.XferState |= cpu_to_le32(NoResponseExpected); + hw_fib->header.XferState |= cpu_to_le32(NoResponseExpected); FIB_COUNTER_INCREMENT(aac_config.NoResponseSent); } else if (wait && reply) { - fib->header.XferState |= cpu_to_le32(ResponseExpected); + hw_fib->header.XferState |= cpu_to_le32(ResponseExpected); FIB_COUNTER_INCREMENT(aac_config.NormalSent); } /* * Map the fib into 32bits by using the fib number */ - fib->header.SenderData = fibptr-&dev->fibs[0]; /* for callback */ + +// hw_fib->header.SenderFibAddress = ((u32)(fibptr-dev->fibs)) << 1; + hw_fib->header.SenderFibAddress = cpu_to_le32((u32)(ulong)fibptr->hw_fib_pa); + hw_fib->header.SenderData = (u32)(fibptr - dev->fibs); /* * Set FIB state to indicate where it came from and if we want a * response from the adapter. Also load the command from the @@ -455,15 +465,14 @@ * * Map the hw fib pointer as a 32bit value */ - fib->header.SenderFibAddress = fib2addr(fib); - fib->header.Command = cpu_to_le16(command); - fib->header.XferState |= cpu_to_le32(SentFromHost); - fibptr->fib->header.Flags = 0; /* Zero the flags field - its internal only... */ + hw_fib->header.Command = cpu_to_le16(command); + hw_fib->header.XferState |= cpu_to_le32(SentFromHost); + fibptr->hw_fib->header.Flags = 0; /* 0 the flags field - internal only*/ /* * Set the size of the Fib we want to send to the adapter */ - fib->header.Size = cpu_to_le16(sizeof(struct aac_fibhdr) + size); - if (le16_to_cpu(fib->header.Size) > le16_to_cpu(fib->header.SenderSize)) { + hw_fib->header.Size = cpu_to_le16(sizeof(struct aac_fibhdr) + size); + if (le16_to_cpu(hw_fib->header.Size) > le16_to_cpu(hw_fib->header.SenderSize)) { return -EMSGSIZE; } /* @@ -471,22 +480,25 @@ * the adapter a command is ready. */ if (priority == FsaHigh) { - fib->header.XferState |= cpu_to_le32(HighPriority); + hw_fib->header.XferState |= cpu_to_le32(HighPriority); qid = AdapHighCmdQueue; } else { - fib->header.XferState |= cpu_to_le32(NormalPriority); + hw_fib->header.XferState |= cpu_to_le32(NormalPriority); qid = AdapNormCmdQueue; } q = &dev->queues->queue[qid]; if(wait) spin_lock_irqsave(&fibptr->event_lock, flags); - if(aac_queue_get( dev, &index, qid, fib, 1, fibptr, &nointr)<0) + if(aac_queue_get( dev, &index, qid, hw_fib, 1, fibptr, &nointr)<0) return -EWOULDBLOCK; dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index)); dprintk((KERN_DEBUG "Fib contents:.\n")); - dprintk((KERN_DEBUG " Command = %d.\n", fib->header.Command)); - dprintk((KERN_DEBUG " XferState = %x.\n", fib->header.XferState)); + dprintk((KERN_DEBUG " Command = %d.\n", hw_fib->header.Command)); + dprintk((KERN_DEBUG " XferState = %x.\n", hw_fib->header.XferState)); + dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib)); + dprintk((KERN_DEBUG " hw_fib pa being sent=%xl\n",(ulong)fibptr->hw_fib_pa)); + dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr)); /* * Fill in the Callback and CallbackContext if we are not * going to wait. @@ -500,6 +512,7 @@ q->numpending++; fibptr->done = 0; + fibptr->flags = 0; if(aac_insert_entry(dev, index, qid, (nointr & aac_config.irq_mod)) < 0) return -EWOULDBLOCK; @@ -513,10 +526,11 @@ if(fibptr->done == 0) BUG(); - if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) + if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)){ return -ETIMEDOUT; - else + } else { return 0; + } } /* * If the user does not want a response than return success otherwise @@ -543,8 +557,7 @@ { u32 index; int status; - - if (*q->headers.producer == *q->headers.consumer) { + if (le32_to_cpu(*q->headers.producer) == le32_to_cpu(*q->headers.consumer)) { status = 0; } else { /* @@ -564,7 +577,7 @@ int aac_consumer_avail(struct aac_dev *dev, struct aac_queue * q) { - return (*q->headers.producer != *q->headers.consumer); + return (le32_to_cpu(*q->headers.producer) != le32_to_cpu(*q->headers.consumer)); } @@ -583,7 +596,7 @@ int wasfull = 0; u32 notify; - if (*q->headers.producer+1 == *q->headers.consumer) + if ((le32_to_cpu(*q->headers.producer)+1) == le32_to_cpu(*q->headers.consumer)) wasfull = 1; if (le32_to_cpu(*q->headers.consumer) >= q->entries) @@ -625,16 +638,15 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size) { - struct hw_fib * fib = fibptr->fib; + struct hw_fib * hw_fib = fibptr->hw_fib; struct aac_dev * dev = fibptr->dev; unsigned long nointr = 0; - - if (le32_to_cpu(fib->header.XferState) == 0) + if (le32_to_cpu(hw_fib->header.XferState) == 0) return 0; /* * If we plan to do anything check the structure type first. */ - if ( fib->header.StructType != FIB_MAGIC ) { + if ( hw_fib->header.StructType != FIB_MAGIC ) { return -EINVAL; } /* @@ -644,37 +656,36 @@ * and want to send a response back to the adapter. This will * send the completed cdb to the adapter. */ - if (fib->header.XferState & cpu_to_le32(SentFromAdapter)) { - fib->header.XferState |= cpu_to_le32(HostProcessed); - if (fib->header.XferState & cpu_to_le32(HighPriority)) { + if (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) { + hw_fib->header.XferState |= cpu_to_le32(HostProcessed); + if (hw_fib->header.XferState & cpu_to_le32(HighPriority)) { u32 index; if (size) { size += sizeof(struct aac_fibhdr); - if (size > le16_to_cpu(fib->header.SenderSize)) + if (size > le16_to_cpu(hw_fib->header.SenderSize)) return -EMSGSIZE; - fib->header.Size = cpu_to_le16(size); + hw_fib->header.Size = cpu_to_le16(size); } - if(aac_queue_get(dev, &index, AdapHighRespQueue, fib, 1, NULL, &nointr) < 0) { + if(aac_queue_get(dev, &index, AdapHighRespQueue, hw_fib, 1, NULL, &nointr) < 0) { return -EWOULDBLOCK; } if (aac_insert_entry(dev, index, AdapHighRespQueue, (nointr & (int)aac_config.irq_mod)) != 0) { } } - else if (fib->header.XferState & NormalPriority) + else if (hw_fib->header.XferState & NormalPriority) { u32 index; if (size) { size += sizeof(struct aac_fibhdr); - if (size > le16_to_cpu(fib->header.SenderSize)) + if (size > le16_to_cpu(hw_fib->header.SenderSize)) return -EMSGSIZE; - fib->header.Size = cpu_to_le16(size); + hw_fib->header.Size = cpu_to_le16(size); } - if (aac_queue_get(dev, &index, AdapNormRespQueue, fib, 1, NULL, &nointr) < 0) + if (aac_queue_get(dev, &index, AdapNormRespQueue, hw_fib, 1, NULL, &nointr) < 0) return -EWOULDBLOCK; - if (aac_insert_entry(dev, index, AdapNormRespQueue, - (nointr & (int)aac_config.irq_mod)) != 0) + if (aac_insert_entry(dev, index, AdapNormRespQueue, (nointr & (int)aac_config.irq_mod)) != 0) { } } @@ -696,19 +707,19 @@ int fib_complete(struct fib * fibptr) { - struct hw_fib * fib = fibptr->fib; + struct hw_fib * hw_fib = fibptr->hw_fib; /* * Check for a fib which has already been completed */ - if (fib->header.XferState == cpu_to_le32(0)) + if (hw_fib->header.XferState == cpu_to_le32(0)) return 0; /* * If we plan to do anything check the structure type first. */ - if (fib->header.StructType != FIB_MAGIC) + if (hw_fib->header.StructType != FIB_MAGIC) return -EINVAL; /* * This block completes a cdb which orginated on the host and we @@ -716,19 +727,19 @@ * command is complete that we had sent to the adapter and this * cdb could be reused. */ - if((fib->header.XferState & cpu_to_le32(SentFromHost)) && - (fib->header.XferState & cpu_to_le32(AdapterProcessed))) + if((hw_fib->header.XferState & cpu_to_le32(SentFromHost)) && + (hw_fib->header.XferState & cpu_to_le32(AdapterProcessed))) { fib_dealloc(fibptr); } - else if(fib->header.XferState & cpu_to_le32(SentFromHost)) + else if(hw_fib->header.XferState & cpu_to_le32(SentFromHost)) { /* * This handles the case when the host has aborted the I/O * to the adapter because the adapter is not responding */ fib_dealloc(fibptr); - } else if(fib->header.XferState & cpu_to_le32(HostOwned)) { + } else if(hw_fib->header.XferState & cpu_to_le32(HostOwned)) { fib_dealloc(fibptr); } else { BUG(); @@ -778,13 +789,13 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) { - struct hw_fib * fib = fibptr->fib; + struct hw_fib * hw_fib = fibptr->hw_fib; /* * Set the status of this FIB to be Invalid parameter. * * *(u32 *)fib->data = ST_INVAL; */ - *(u32 *)fib->data = cpu_to_le32(ST_OK); + *(u32 *)hw_fib->data = cpu_to_le32(ST_OK); fib_adapter_complete(fibptr, sizeof(u32)); } @@ -800,7 +811,7 @@ int aac_command_thread(struct aac_dev * dev) { - struct hw_fib *fib, *newfib; + struct hw_fib *hw_fib, *newfib; struct fib fibptr; /* for error logging */ struct aac_queue_block *queues = dev->queues; struct aac_fib_context *fibctx; @@ -828,17 +839,18 @@ while(1) { spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags); - while(!list_empty(&(queues->queue[HostNormCmdQueue].cmdq))) { - struct list_head *entry; + while(!aac_list_empty(&(queues->queue[HostNormCmdQueue].cmdq))) { + struct aac_list_head *entry; struct aac_aifcmd * aifcmd; set_current_state(TASK_RUNNING); - entry = queues->queue[HostNormCmdQueue].cmdq.next; - list_del(entry); + entry = (struct aac_list_head*)(ulong)(queues->queue[HostNormCmdQueue].cmdq.next); + dprintk(("aacraid: Command thread: removing fib from cmdq (%p)\n",entry)); + aac_list_del(entry); spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock, flags); - fib = list_entry(entry, struct hw_fib, header.FibLinks); + hw_fib = aac_list_entry(entry, struct hw_fib, header.FibLinks); /* * We will process the FIB here or pass it to a * worker thread that is TBD. We Really can't @@ -848,16 +860,17 @@ memset(&fibptr, 0, sizeof(struct fib)); fibptr.type = FSAFS_NTC_FIB_CONTEXT; fibptr.size = sizeof( struct fib ); - fibptr.fib = fib; - fibptr.data = fib->data; + fibptr.hw_fib = hw_fib; + fibptr.data = hw_fib->data; fibptr.dev = dev; /* * We only handle AifRequest fibs from the adapter. */ - aifcmd = (struct aac_aifcmd *) fib->data; + aifcmd = (struct aac_aifcmd *) hw_fib->data; if (aifcmd->command == le16_to_cpu(AifCmdDriverNotify)) { aac_handle_aif(dev, &fibptr); } else { + struct list_head *entry; /* The u32 here is important and intended. We are using 32bit wrapping time to fit the adapter field */ @@ -906,12 +919,12 @@ /* * Make the copy of the FIB */ - memcpy(newfib, fib, sizeof(struct hw_fib)); + memcpy(newfib, hw_fib, sizeof(struct hw_fib)); /* * Put the FIB onto the * fibctx's fibs */ - list_add_tail(&newfib->header.FibLinks, &fibctx->fibs); + aac_list_add_tail(&newfib->header.FibLinks, &fibctx->hw_fib_list); fibctx->count++; /* * Set the event to wake up the @@ -926,7 +939,7 @@ /* * Set the status of this FIB */ - *(u32 *)fib->data = cpu_to_le32(ST_OK); + *(u32 *)hw_fib->data = cpu_to_le32(ST_OK); fib_adapter_complete(&fibptr, sizeof(u32)); spin_unlock_irqrestore(&dev->fib_lock, flagv); } diff -Nru a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c --- a/drivers/scsi/aacraid/dpcsup.c Thu May 15 15:24:38 2003 +++ b/drivers/scsi/aacraid/dpcsup.c Thu May 15 15:24:38 2003 @@ -65,7 +65,6 @@ unsigned long flags; spin_lock_irqsave(q->lock, flags); - /* * Keep pulling response QEs off the response queue and waking * up the waiters until there are no more QEs. We then return @@ -74,12 +73,13 @@ */ while(aac_consumer_get(dev, q, &entry)) { - int fast; + u32 fast ; + fast = (entry->addr & cpu_to_le32(0x01)); + hwfib = (struct hw_fib *)((char *)dev->hw_fib_va + + ((entry->addr & ~0x01) - dev->hw_fib_pa)); + fib = &dev->fibs[hwfib->header.SenderData]; - fast = (int) (entry->addr & 0x01); - hwfib = addr2fib(entry->addr & ~0x01); aac_consumer_free(dev, q, HostNormRespQueue); - fib = &dev->fibs[hwfib->header.SenderData]; /* * Remove this fib from the Outstanding I/O queue. * But only if it has not already been timed out. @@ -93,6 +93,7 @@ dev->queues->queue[AdapNormCmdQueue].numpending--; } else { printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags); + printk(KERN_DEBUG"aacraid: hwfib=%p fib index=%i fib=%p\n",hwfib, hwfib->header.SenderData,fib); continue; } spin_unlock_irqrestore(q->lock, flags); @@ -171,11 +172,12 @@ */ while(aac_consumer_get(dev, q, &entry)) { - struct hw_fib * fib; - fib = addr2fib(entry->addr); + struct hw_fib * hw_fib; + hw_fib = (struct hw_fib *)((char *)dev->hw_fib_va + + ((entry->addr & ~0x01) - dev->hw_fib_pa)); if (dev->aif_thread) { - list_add_tail(&fib->header.FibLinks, &q->cmdq); + aac_list_add_tail(&hw_fib->header.FibLinks, &q->cmdq); aac_consumer_free(dev, q, HostNormCmdQueue); wake_up_interruptible(&q->cmdready); } else { @@ -185,13 +187,13 @@ memset(&fibctx, 0, sizeof(struct fib)); fibctx.type = FSAFS_NTC_FIB_CONTEXT; fibctx.size = sizeof(struct fib); - fibctx.fib = fib; - fibctx.data = fib->data; + fibctx.hw_fib = hw_fib; + fibctx.data = hw_fib->data; fibctx.dev = dev; /* * Set the status of this FIB */ - *(u32 *)fib->data = cpu_to_le32(ST_OK); + *(u32 *)hw_fib->data = cpu_to_le32(ST_OK); fib_adapter_complete(&fibctx, sizeof(u32)); spin_lock_irqsave(q->lock, flags); } diff -Nru a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c --- a/drivers/scsi/aacraid/linit.c Thu May 15 15:24:37 2003 +++ b/drivers/scsi/aacraid/linit.c Thu May 15 15:24:37 2003 @@ -35,7 +35,7 @@ * */ -#define AAC_DRIVER_VERSION "0.9.9ac6-TEST" +#define AAC_DRIVER_VERSION "1.1.2" #define AAC_DRIVER_BUILD_DATE __DATE__ #include @@ -53,20 +53,23 @@ #include #include "scsi.h" #include "hosts.h" - #include #include "aacraid.h" + #define AAC_DRIVERNAME "aacraid" MODULE_AUTHOR("Red Hat Inc and Adaptec"); -MODULE_DESCRIPTION("Supports Dell PERC2, 2/Si, 3/Si, 3/Di, PERC 320/DC, Adaptec 2120S, 2200S, 5400S, and HP NetRAID-4M devices. http://domsch.com/linux/ or http://linux.adaptec.com"); +MODULE_DESCRIPTION("Supports Dell PERC2, 2/Si, 3/Si, 3/Di, Adaptec Advanced Raid Products, and HP NetRAID-4M devices. http://domsch.com/linux/ or http://linux.adaptec.com"); MODULE_LICENSE("GPL"); MODULE_PARM(nondasd, "i"); MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on"); +MODULE_PARM(paemode, "i"); +MODULE_PARM_DESC(paemode, "Control whether dma addressing is using PAE. 0=off, 1=on"); -static int nondasd=-1; +int nondasd=-1; +int paemode=-1; struct aac_dev *aac_devices[MAXIMUM_NUM_ADAPTERS]; @@ -76,12 +79,12 @@ /* * Because of the way Linux names scsi devices, the order in this table has * become important. Check for on-board Raid first, add-in cards second. - * + */ +/* * dmb - For now we add the number of channels to this structure. * In the future we should add a fib that reports the number of channels * for the card. At that time we can remove the channels from here */ - static struct aac_driver_ident aac_drivers[] = { { 0x1028, 0x0001, 0x1028, 0x0001, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 2/Si */ { 0x1028, 0x0002, 0x1028, 0x0002, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* PERC 3/Di */ @@ -97,11 +100,22 @@ { 0x9005, 0x0285, 0x9005, 0x0286, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2120S ", 1 }, /* Adaptec 2120S (Crusader)*/ { 0x9005, 0x0285, 0x9005, 0x0285, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2 }, /* Adaptec 2200S (Vulcan)*/ { 0x9005, 0x0285, 0x9005, 0x0287, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2 }, /* Adaptec 2200S (Vulcan-2m)*/ - { 0x9005, 0x0285, 0x1028, 0x0287, aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2 }, /* Dell PERC 320/DC */ + { 0x9005, 0x0285, 0x17aa, 0x0286, aac_rx_init, "aacraid", "Legend ", "Legend S220 ", 1 }, /* Legend S220*/ + { 0x9005, 0x0285, 0x17aa, 0x0287, aac_rx_init, "aacraid", "Legend ", "Legend S230 ", 2 }, /* Legend S230*/ + + { 0x9005, 0x0285, 0x9005, 0x0288, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 3230S ", 2 }, /* Adaptec 3230S (Harrier)*/ + { 0x9005, 0x0285, 0x9005, 0x0289, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 3240S ", 2 }, /* Adaptec 3240S (Tornado)*/ + { 0x9005, 0x0285, 0x9005, 0x028a, aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020S PCI-X ", 2 }, /* ASR-2020S PCI-X ZCR (Skyhawk)*/ + { 0x9005, 0x0285, 0x9005, 0x028b, aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2020S PCI-X ", 2 }, /* ASR-2020S SO-DIMM PCI-X ZCR(Terminator)*/ + { 0x9005, 0x0285, 0x9005, 0x0290, aac_rx_init, "aacraid", "ADAPTEC ", "AAR-2410SA SATA ", 2 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II)*/ + { 0x9005, 0x0250, 0x1014, 0x0279, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec ", 2 }, /* (Marco)*/ + { 0x9005, 0x0250, 0x1014, 0x028c, aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec ", 2 }, /* (Sebring)*/ + + { 0x9005, 0x0285, 0x1028, 0x0287, aac_rx_init, "percraid", "DELL ", "PERC 320/DC ", 2 }, /* Perc 320/DC*/ { 0x1011, 0x0046, 0x9005, 0x0365, aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4 }, /* Adaptec 5400S (Mustang)*/ { 0x1011, 0x0046, 0x9005, 0x0364, aac_sa_init, "aacraid", "ADAPTEC ", "AAC-364 ", 4 }, /* Adaptec 5400S (Mustang)*/ { 0x1011, 0x0046, 0x9005, 0x1364, aac_sa_init, "percraid", "DELL ", "PERCRAID ", 4 }, /* Dell PERC2 "Quad Channel" */ - { 0x1011, 0x0046, 0x103c, 0x10c2, aac_sa_init, "hpnraid", "HP ", "NetRAID-4M ", 4 } /* HP NetRAID-4M */ + { 0x1011, 0x0046, 0x103c, 0x10c2, aac_sa_init, "hpnraid", "HP ", "NetRAID ", 4 } /* HP NetRAID-4M */ }; #define NUM_AACTYPES (sizeof(aac_drivers) / sizeof(struct aac_driver_ident)) @@ -122,7 +136,7 @@ static int aac_release(struct Scsi_Host *); static int aac_queuecommand(Scsi_Cmnd *, void (*CompletionRoutine)(Scsi_Cmnd *)); static int aac_biosparm(struct scsi_device *, struct block_device *, - sector_t, int *); + sector_t, int *); static int aac_procinfo(char *, char **, off_t, int, int, int); static int aac_ioctl(Scsi_Device *, int, void *); static int aac_eh_abort(Scsi_Cmnd * cmd); @@ -130,7 +144,7 @@ static int aac_eh_bus_reset(Scsi_Cmnd* cmd); static int aac_eh_reset(Scsi_Cmnd* cmd); -static int aac_slave_configure(Scsi_Device *); +static int aac_slave_configure(struct scsi_device *); /** * aac_detect - Probe for aacraid cards @@ -162,13 +176,12 @@ struct fsa_scsi_hba *fsa_dev_ptr; char *name = NULL; - printk(KERN_INFO "Red Hat/Adaptec aacraid driver, %s\n", AAC_DRIVER_BUILD_DATE); + printk(KERN_INFO "Red Hat/Adaptec aacraid driver (%s %s)\n", AAC_DRIVER_VERSION, AAC_DRIVER_BUILD_DATE); /* setting up the proc directory structure */ template->proc_name = "aacraid"; - for( index = 0; index != num_aacdrivers; index++ ) - { + for( index = 0; index != num_aacdrivers; index++ ) { device_id = aac_drivers[index].device; vendor_id = aac_drivers[index].vendor; name = aac_drivers[index].name; @@ -206,16 +219,10 @@ * specific information. */ host_ptr = scsi_register( template, sizeof(struct aac_dev) ); - if(host_ptr == NULL) - continue; - /* * These three parameters can be used to allow for wide SCSI * and for host adapters that support multiple buses. */ - host_ptr->max_id = 17; - host_ptr->max_lun = 8; - host_ptr->max_channel = 1; host_ptr->irq = dev->irq; /* Adapter IRQ number */ /* host_ptr->base = ( char * )(dev->resource[0].start & ~0xff); */ host_ptr->base = dev->resource[0].start; @@ -236,9 +243,13 @@ /* attach a pointer back to Scsi_Host */ aac->scsi_host_ptr = host_ptr; aac->pdev = dev; - aac->cardtype = index; aac->name = aac->scsi_host_ptr->hostt->name; aac->id = aac->scsi_host_ptr->unique_id; + aac->cardtype = index; + + aac->fibs = (struct fib*) kmalloc(sizeof(struct fib)*AAC_NUM_FIB, GFP_KERNEL); + spin_lock_init(&aac->fib_lock); + /* Initialize the ordinal number of the device to -1 */ fsa_dev_ptr = &(aac->fsa_dev); for( container = 0; container < MAXIMUM_NUM_CONTAINERS; container++ ) @@ -255,46 +266,28 @@ } dprintk((KERN_DEBUG "%s:%d device initialization successful.\n", name, host_ptr->unique_id)); aac_get_adapter_info(aac); - if(nondasd != -1) - { - /* someone told us how to set this on the cmdline */ - aac->nondasd_support = (nondasd!=0); - } - if(aac->nondasd_support != 0){ - printk(KERN_INFO "%s%d: Non-DASD support enabled\n", aac->name, aac->id); - } - dprintk((KERN_DEBUG "%s:%d options flag %04x.\n",name, host_ptr->unique_id,aac->adapter_info.options)); - if(aac->nondasd_support == 1) - { - /* - * max channel will be the physical channels plus 1 virtual channel - * all containers are on the virtual channel 0 - * physical channels are address by their actual physical number+1 - */ + if(aac->nondasd_support == 1){ + /* + * max channel will be the physical channels plus 1 virtual channel + * all containers are on the virtual channel 0 + * physical channels are address by their actual physical number+1 + */ host_ptr->max_channel = aac_drivers[index].channels+1; } else { host_ptr->max_channel = 1; - } - dprintk((KERN_DEBUG "Device has %d logical channels\n", host_ptr->max_channel)); + } + dprintk((KERN_DEBUG "Device has %d logical channels\n",host_ptr->max_channel)); aac_get_containers(aac); aac_devices[aac_count-1] = aac; +// spin_unlock_irqrestore(&aac->fib_lock, flags); /* - * dmb - we may need to move these 3 parms somewhere else once + * dmb - we may need to move the setting of these parms somewhere else once * we get a fib that can report the actual numbers */ host_ptr->max_id = AAC_MAX_TARGET; host_ptr->max_lun = AAC_MAX_LUN; - - /* - * If we are PAE capable then our future DMA mappings - * (for read/write commands) are 64bit clean and don't - * need bouncing. This assumes we do no other 32bit only - * allocations (eg fib table expands) after this point. - */ - - if(aac->pae_support) - pci_set_dma_mask(dev, 0xFFFFFFFFFFFFFFFFUL); + } } @@ -356,17 +349,19 @@ * Queues a command for execution by the associated Host Adapter. */ -static int aac_queuecommand(Scsi_Cmnd *scsi_cmnd_ptr, void (*complete)(Scsi_Cmnd *)) +static int aac_queuecommand(Scsi_Cmnd *scsi_cmnd_ptr, void (*CompletionRoutine)(Scsi_Cmnd *)) { int ret; - scsi_cmnd_ptr->scsi_done = complete; + scsi_cmnd_ptr->scsi_done = CompletionRoutine; /* * aac_scsi_cmd() handles command processing, setting the * result code and calling completion routine. */ - if((ret = aac_scsi_cmd(scsi_cmnd_ptr)) != 0) + if((ret = aac_scsi_cmd(scsi_cmnd_ptr)) != 0){ dprintk((KERN_DEBUG "aac_scsi_cmd failed.\n")); + return FAILED; + } return ret; } @@ -396,8 +391,9 @@ /** * aac_biosparm - return BIOS parameters for disk - * @disk: SCSI disk object to process - * @device: Disk in question + * @sdev: The scsi device corresponding to the disk + * @bdev: the block device corresponding to the disk + * @capacity: the sector capacity of the disk * @geom: geometry block to fill in * * Return the Heads/Sectors/Cylinders BIOS Disk Parameters for Disk. @@ -416,10 +412,10 @@ */ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int *geom) + sector_t capacity, int *geom) { struct diskparm *param = (struct diskparm *)geom; - u8 *buf; + unsigned char *buf; dprintk((KERN_DEBUG "aac_biosparm.\n")); @@ -445,15 +441,14 @@ param->sectors = 32; } - param->cylinders = cap_to_cyls(capacity, - (param->heads * param->sectors)); + param->cylinders = cap_to_cyls(capacity, param->heads * param->sectors); /* - * Read the partition table block + * Read the first 1024 bytes from the disk device */ buf = scsi_bios_ptable(bdev); - + /* * If the boot sector partition table is valid, search for a partition * table entry whose end_head matches one of the standard geometry @@ -462,7 +457,7 @@ if(*(unsigned short *)(buf + 0x40) == cpu_to_le16(0xaa55)) { - struct partition *first = (struct partition *)buf; + struct partition *first = (struct partition * )buf; struct partition *entry = first; int saved_cylinders = param->cylinders; int num; @@ -500,8 +495,7 @@ end_sec = first->end_sector & 0x3f; } - param->cylinders = cap_to_cyls(capacity, - (param->heads * param->sectors)); + param->cylinders = cap_to_cyls(capacity, param->heads * param->sectors); if(num < 4 && end_sec == param->sectors) { @@ -522,15 +516,17 @@ } /** - * aac_slave_configure - do device specific setup - * @dev: SCSI device we are attaching + * aac_queuedepth - compute queue depths + * @host: SCSI host in question + * @dev: SCSI device we are considering * - * Currently, all we do is set the queue depth on the device. + * Selects queue depths for each target device based on the host adapter's + * total capacity and the queue depth supported by the target device. + * A queue depth of one automatically disables tagged queueing. */ -static int aac_slave_configure(Scsi_Device * dev ) +static int aac_slave_configure(struct scsi_device * dev ) { - if(dev->tagged_supported) scsi_adjust_queue_depth(dev, MSG_ORDERED_TAG, 128); else @@ -543,75 +539,13 @@ return 0; } +/*------------------------------------------------------------------------------ + aac_ioctl() -/** - * aac_eh_abort - Abort command if possible. - * @cmd: SCSI command block to abort - * - * Called when the midlayer wishes to abort a command. We don't support - * this facility, and our firmware looks after life for us. We just - * report this as failing - */ - -static int aac_eh_abort(Scsi_Cmnd *cmd) -{ - return FAILED; -} - -/** - * aac_eh_device_reset - Reset command handling - * @cmd: SCSI command block causing the reset - * - * Issue a reset of a SCSI device. We are ourselves not truely a SCSI - * controller and our firmware will do the work for us anyway. Thus this - * is a no-op. We just return FAILED. - */ - -static int aac_eh_device_reset(Scsi_Cmnd *cmd) -{ - return FAILED; -} - -/** - * aac_eh_bus_reset - Reset command handling - * @scsi_cmd: SCSI command block causing the reset - * - * Issue a reset of a SCSI bus. We are ourselves not truely a SCSI - * controller and our firmware will do the work for us anyway. Thus this - * is a no-op. We just return FAILED. - */ - -static int aac_eh_bus_reset(Scsi_Cmnd* cmd) -{ - return FAILED; -} - -/** - * aac_eh_hba_reset - Reset command handling - * @scsi_cmd: SCSI command block causing the reset - * - * Issue a reset of a SCSI host. If things get this bad then arguably we should - * go take a look at what the host adapter is doing and see if something really - * broke (as can occur at least on my Dell QC card if a drive keeps failing spinup) - */ - -static int aac_eh_reset(Scsi_Cmnd* cmd) -{ - printk(KERN_ERR "aacraid: Host adapter reset request. SCSI hang ?\n"); - return FAILED; -} - -/** - * aac_ioctl - Handle SCSI ioctls - * @scsi_dev_ptr: scsi device to operate upon - * @cmd: ioctl command to use issue - * @arg: ioctl data pointer - * - * Issue an ioctl on an aacraid device. Returns a standard unix error code or - * zero for success - */ - + Handle SCSI ioctls + *----------------------------------------------------------------------------*/ static int aac_ioctl(Scsi_Device * scsi_dev_ptr, int cmd, void * arg) +/*----------------------------------------------------------------------------*/ { struct aac_dev *dev; dprintk((KERN_DEBUG "aac_ioctl.\n")); @@ -694,13 +628,58 @@ .this_id = 16, .sg_tablesize = 16, .max_sectors = 128, - .cmd_per_lun = 1, - .eh_abort_handler = aac_eh_abort, - .eh_device_reset_handler = aac_eh_device_reset, + .cmd_per_lun = AAC_NUM_IO_FIB, + .eh_abort_handler = aac_eh_abort, + .eh_device_reset_handler = aac_eh_device_reset, .eh_bus_reset_handler = aac_eh_bus_reset, .eh_host_reset_handler = aac_eh_reset, .use_clustering = ENABLE_CLUSTERING, }; + +/*=========================================================================== + * Error Handling routines + *=========================================================================== + */ + + +/* + * + * We don't support abortting commands. + */ +static int aac_eh_abort(Scsi_Cmnd * scsicmd) +{ + printk("aacraid: abort failed\n"); + return FAILED; +} + +/* + * We don't support device resets. + */ +static int aac_eh_device_reset(Scsi_Cmnd* cmd) +{ + printk("aacraid: device reset failed\n"); + return FAILED; +} + + +static int aac_eh_bus_reset(Scsi_Cmnd* cmd) +{ + printk("aacraid: bus reset failed\n"); + return FAILED; +} + +static int aac_eh_reset(Scsi_Cmnd* cmd) +{ + printk("aacraid: hba reset failed\n"); + return FAILED; +} + + +/*=========================================================================== + * + *=========================================================================== + */ + #include "scsi_module.c" diff -Nru a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c --- a/drivers/scsi/aacraid/sa.c Thu May 15 15:24:40 2003 +++ b/drivers/scsi/aacraid/sa.c Thu May 15 15:24:40 2003 @@ -352,7 +352,7 @@ * Wait for the adapter to be up and running. Wait up to 3 minutes. */ while (!(sa_readl(dev, Mailbox7) & KERNEL_UP_AND_RUNNING)) { - if (time_after(start+180*HZ, jiffies)) { + if (time_after(jiffies, start+180*HZ)) { status = sa_readl(dev, Mailbox7) >> 16; printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %d.\n", name, instance, le32_to_cpu(status)); return -1; diff -Nru a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c --- a/drivers/scsi/advansys.c Thu May 15 15:24:35 2003 +++ b/drivers/scsi/advansys.c Thu May 15 15:24:35 2003 @@ -4303,7 +4303,6 @@ int leftlen; char *curbuf; off_t advoffset; - Scsi_Device *scd; #ifdef ADVANSYS_STATS int tgt_id; #endif /* ADVANSYS_STATS */ @@ -6198,13 +6197,33 @@ * --- Loadable Driver Support */ -#if ASC_LINUX_KERNEL24 -static -#endif -#if ASC_LINUX_KERNEL24 || (ASC_LINUX_KERNEL22 && defined(MODULE)) -Scsi_Host_Template driver_template = ADVANSYS; -# include "scsi_module.c" -#endif +static Scsi_Host_Template driver_template = { + .proc_name = "advansys", + .proc_info = advansys_proc_info, + .name = "advansys", + .detect = advansys_detect, + .release = advansys_release, + .info = advansys_info, + .queuecommand = advansys_queuecommand, + .eh_bus_reset_handler = advansys_reset, + .bios_param = advansys_biosparam, + .slave_configure = advansys_slave_configure, + /* + * Because the driver may control an ISA adapter 'unchecked_isa_dma' + * must be set. The flag will be cleared in advansys_detect for non-ISA + * adapters. Refer to the comment in scsi_module.c for more information. + */ + .unchecked_isa_dma = 1, + /* + * All adapters controlled by this driver are capable of large + * scatter-gather lists. According to the mid-level SCSI documentation + * this obviates any performance gain provided by setting + * 'use_clustering'. But empirically while CPU utilization is increased + * by enabling clustering, I/O throughput increases as well. + */ + .use_clustering = ENABLE_CLUSTERING, +}; +#include "scsi_module.c" /* diff -Nru a/drivers/scsi/advansys.h b/drivers/scsi/advansys.h --- a/drivers/scsi/advansys.h Thu May 15 15:24:45 2003 +++ b/drivers/scsi/advansys.h Thu May 15 15:24:45 2003 @@ -67,61 +67,4 @@ /* init/main.c setup function */ void advansys_setup(char *, int *); -/* - * AdvanSys Host Driver Scsi_Host_Template (struct SHT) from hosts.h. - */ -#if ASC_LINUX_KERNEL24 -#define ADVANSYS { \ - .proc_name = "advansys", \ - .proc_info = advansys_proc_info, \ - .name = "advansys", \ - .detect = advansys_detect, \ - .release = advansys_release, \ - .info = advansys_info, \ - .queuecommand = advansys_queuecommand, \ - .eh_bus_reset_handler = advansys_reset, \ - .bios_param = advansys_biosparam, \ - .slave_configure = advansys_slave_configure, \ - /* \ - * Because the driver may control an ISA adapter 'unchecked_isa_dma' \ - * must be set. The flag will be cleared in advansys_detect for non-ISA \ - * adapters. Refer to the comment in scsi_module.c for more information. \ - */ \ - .unchecked_isa_dma = 1, \ - /* \ - * All adapters controlled by this driver are capable of large \ - * scatter-gather lists. According to the mid-level SCSI documentation \ - * this obviates any performance gain provided by setting \ - * 'use_clustering'. But empirically while CPU utilization is increased \ - * by enabling clustering, I/O throughput increases as well. \ - */ \ - .use_clustering = ENABLE_CLUSTERING, \ -} -#elif ASC_LINUX_KERNEL22 -#define ADVANSYS { \ - .proc_info = advansys_proc_info, \ - .name = "advansys", \ - .detect = advansys_detect, \ - .release = advansys_release, \ - .info = advansys_info, \ - .queuecommand = advansys_queuecommand, \ - .use_new_eh_code = 1, \ - .eh_bus_reset_handler = advansys_reset, \ - .bios_param = advansys_biosparam, \ - /* \ - * Because the driver may control an ISA adapter 'unchecked_isa_dma' \ - * must be set. The flag will be cleared in advansys_detect for non-ISA \ - * adapters. Refer to the comment in scsi_module.c for more information. \ - */ \ - .unchecked_isa_dma = 1, \ - /* \ - * All adapters controlled by this driver are capable of large \ - * scatter-gather lists. According to the mid-level SCSI documentation \ - * this obviates any performance gain provided by setting \ - * 'use_clustering'. But empirically while CPU utilization is increased \ - * by enabling clustering, I/O throughput increases as well. \ - */ \ - .use_clustering = ENABLE_CLUSTERING, \ -} -#endif #endif /* _ADVANSYS_H */ diff -Nru a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c --- a/drivers/scsi/aha1542.c Thu May 15 15:24:39 2003 +++ b/drivers/scsi/aha1542.c Thu May 15 15:24:39 2003 @@ -67,7 +67,7 @@ int nseg, int badseg) { - printk(KERN_CRIT "sgpnt[%d:%d] page %p/0x%x length %d\n", + printk(KERN_CRIT "sgpnt[%d:%d] page %p/0x%x length %ld\n", badseg, nseg, page_address(sgpnt[badseg].page) + sgpnt[badseg].offset, SCSI_SG_PA(&sgpnt[badseg]), @@ -1813,7 +1813,22 @@ MODULE_LICENSE("GPL"); -/* Eventually this will go into an include file, but this will be later */ -static Scsi_Host_Template driver_template = AHA1542; - +static Scsi_Host_Template driver_template = { + .proc_name = "aha1542", + .name = "Adaptec 1542", + .detect = aha1542_detect, + .command = aha1542_command, + .queuecommand = aha1542_queuecommand, + .eh_abort_handler = aha1542_abort, + .eh_device_reset_handler= aha1542_dev_reset, + .eh_bus_reset_handler = aha1542_bus_reset, + .eh_host_reset_handler = aha1542_host_reset, + .bios_param = aha1542_biosparam, + .can_queue = AHA1542_MAILBOXES, + .this_id = 7, + .sg_tablesize = AHA1542_SCATTER, + .cmd_per_lun = AHA1542_CMDLUN, + .unchecked_isa_dma = 1, + .use_clustering = ENABLE_CLUSTERING, +}; #include "scsi_module.c" diff -Nru a/drivers/scsi/aha1542.h b/drivers/scsi/aha1542.h --- a/drivers/scsi/aha1542.h Thu May 15 15:24:41 2003 +++ b/drivers/scsi/aha1542.h Thu May 15 15:24:41 2003 @@ -151,21 +151,4 @@ #define NULL 0 #endif -#define AHA1542 { .proc_name = "aha1542", \ - .name = "Adaptec 1542", \ - .detect = aha1542_detect, \ - .command = aha1542_command, \ - .queuecommand = aha1542_queuecommand, \ - .eh_abort_handler = aha1542_abort, \ - .eh_device_reset_handler = aha1542_dev_reset, \ - .eh_bus_reset_handler = aha1542_bus_reset, \ - .eh_host_reset_handler = aha1542_host_reset, \ - .bios_param = aha1542_biosparam, \ - .can_queue = AHA1542_MAILBOXES, \ - .this_id = 7, \ - .sg_tablesize = AHA1542_SCATTER, \ - .cmd_per_lun = AHA1542_CMDLUN, \ - .unchecked_isa_dma = 1, \ - .use_clustering = ENABLE_CLUSTERING \ -} #endif diff -Nru a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c --- a/drivers/scsi/aha1740.c Thu May 15 15:24:35 2003 +++ b/drivers/scsi/aha1740.c Thu May 15 15:24:35 2003 @@ -598,9 +598,20 @@ MODULE_LICENSE("GPL"); -/* Eventually this will go into an include file, but this will be later */ -static Scsi_Host_Template driver_template = AHA1740; - +static Scsi_Host_Template driver_template = { + .proc_name = "aha1740", + .proc_info = aha1740_proc_info, + .name = "Adaptec 174x (EISA)", + .detect = aha1740_detect, + .command = aha1740_command, + .queuecommand = aha1740_queuecommand, + .bios_param = aha1740_biosparam, + .can_queue = AHA1740_ECBS, + .this_id = 7, + .sg_tablesize = AHA1740_SCATTER, + .cmd_per_lun = AHA1740_CMDLUN, + .use_clustering = ENABLE_CLUSTERING, +}; #include "scsi_module.c" /* Okay, you made it all the way through. As of this writing, 3/31/93, I'm diff -Nru a/drivers/scsi/aha1740.h b/drivers/scsi/aha1740.h --- a/drivers/scsi/aha1740.h Thu May 15 15:24:40 2003 +++ b/drivers/scsi/aha1740.h Thu May 15 15:24:40 2003 @@ -162,17 +162,4 @@ #define AHA1740_SCATTER 16 #define AHA1740_CMDLUN 1 -#define AHA1740 { .proc_name = "aha1740", \ - .proc_info = aha1740_proc_info, \ - .name = "Adaptec 174x (EISA)", \ - .detect = aha1740_detect, \ - .command = aha1740_command, \ - .queuecommand = aha1740_queuecommand, \ - .bios_param = aha1740_biosparam, \ - .can_queue = AHA1740_ECBS, \ - .this_id = 7, \ - .sg_tablesize = AHA1740_SCATTER, \ - .cmd_per_lun = AHA1740_CMDLUN, \ - .use_clustering = ENABLE_CLUSTERING} - #endif diff -Nru a/drivers/scsi/aic7xxx/Makefile b/drivers/scsi/aic7xxx/Makefile --- a/drivers/scsi/aic7xxx/Makefile Thu May 15 15:24:45 2003 +++ b/drivers/scsi/aic7xxx/Makefile Thu May 15 15:24:45 2003 @@ -1,7 +1,7 @@ # # Makefile for the Linux aic7xxx SCSI driver. # -# $Id: //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Makefile#5 $ +# $Id: //depot/linux-aic79xx-2.5.0/drivers/scsi/aic7xxx/Makefile#6 $ # # Let kbuild descend into aicasm when cleaning @@ -33,7 +33,7 @@ aic79xx_proc.o \ aic79xx_osm_pci.o -EXTRA_CFLAGS += -Idrivers/scsi +EXTRA_CFLAGS += -Idrivers/scsi -Werror #EXTRA_CFLAGS += -g # Files generated that shall be removed upon make clean diff -Nru a/drivers/scsi/aic7xxx/aic7770.c b/drivers/scsi/aic7xxx/aic7770.c --- a/drivers/scsi/aic7xxx/aic7770.c Thu May 15 15:24:46 2003 +++ b/drivers/scsi/aic7xxx/aic7770.c Thu May 15 15:24:46 2003 @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic7770.c#29 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7770.c#30 $ * * $FreeBSD$ */ @@ -314,7 +314,7 @@ if (bootverbose) printf("%s: Reading SEEPROM...", ahc_name(ahc)); have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)sc, - /*start_addr*/0, sizeof(sc)/2); + /*start_addr*/0, sizeof(*sc)/2); if (have_seeprom) { diff -Nru a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h --- a/drivers/scsi/aic7xxx/aic79xx.h Thu May 15 15:24:41 2003 +++ b/drivers/scsi/aic7xxx/aic79xx.h Thu May 15 15:24:41 2003 @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#88 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#89 $ * * $FreeBSD$ */ @@ -494,13 +494,11 @@ * transfer. */ #define SG_PTR_MASK 0xFFFFFFF8 -/*16*/ uint16_t tag; -/*18*/ uint8_t cdb_len; -/*19*/ uint8_t task_management; -/*20*/ uint32_t next_hscb_busaddr; -/*24*/ uint64_t dataptr; -/*32*/ uint32_t datacnt; /* Byte 3 is spare. */ -/*36*/ uint32_t sgptr; +/*16*/ uint64_t dataptr; +/*24*/ uint32_t datacnt; /* Byte 3 is spare. */ +/*28*/ uint32_t sgptr; +/*32*/ uint32_t hscb_busaddr; +/*36*/ uint32_t next_hscb_busaddr; /*40*/ uint8_t control; /* See SCB_CONTROL in aic79xx.reg for details */ /*41*/ uint8_t scsiid; /* * Selection out Id @@ -508,8 +506,10 @@ */ /*42*/ uint8_t lun; /*43*/ uint8_t task_attribute; -/*44*/ uint32_t hscb_busaddr; -/******* Long lun field only downloaded for full 8 byte lun support *******/ +/*44*/ uint8_t cdb_len; +/*45*/ uint8_t task_management; +/*46*/ uint16_t tag; /* Reused by Sequencer. */ +/********** Long lun field only downloaded for full 8 byte lun support ********/ /*48*/ uint8_t pkt_long_lun[8]; /******* Fields below are not Downloaded (Sequencer may use for scratch) ******/ /*56*/ uint8_t spare[8]; diff -Nru a/drivers/scsi/aic7xxx/aic79xx.reg b/drivers/scsi/aic7xxx/aic79xx.reg --- a/drivers/scsi/aic7xxx/aic79xx.reg Thu May 15 15:24:44 2003 +++ b/drivers/scsi/aic7xxx/aic79xx.reg Thu May 15 15:24:44 2003 @@ -39,7 +39,7 @@ * * $FreeBSD$ */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#65 $" +VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#67 $" /* * This file is processed by the aic7xxx_asm utility for use in assembling @@ -194,7 +194,8 @@ TRACEPOINT1, TRACEPOINT2, TRACEPOINT3, - SAW_HWERR + SAW_HWERR, + BAD_SCB_STATUS } } @@ -3484,9 +3485,6 @@ LONGJMP_ADDR { size 2 } - LONGJMP_SCB { - size 2 - } ACCUM_SAVE { size 1 } @@ -3799,23 +3797,6 @@ size 4 alias SCB_NEXT_COMPLETE } - SCB_TAG { - size 2 - } - SCB_CDB_LEN { - size 1 - field SCB_CDB_LEN_PTR 0x80 /* CDB in host memory */ - } - SCB_TASK_MANAGEMENT { - size 1 - } - SCB_NEXT { - alias SCB_NEXT_SCB_BUSADDR - size 2 - } - SCB_NEXT2 { - size 2 - } SCB_DATAPTR { size 8 } @@ -3834,6 +3815,16 @@ field SG_FULL_RESID 0x02 /* In the first byte */ field SG_LIST_NULL 0x01 /* In the first byte */ } + SCB_BUSADDR { + size 4 + } + SCB_NEXT { + alias SCB_NEXT_SCB_BUSADDR + size 2 + } + SCB_NEXT2 { + size 2 + } SCB_CONTROL { size 1 field TARGET_SCB 0x80 @@ -3856,8 +3847,16 @@ SCB_TASK_ATTRIBUTE { size 1 } - SCB_BUSADDR { - size 4 + SCB_CDB_LEN { + size 1 + field SCB_CDB_LEN_PTR 0x80 /* CDB in host memory */ + } + SCB_TASK_MANAGEMENT { + size 1 + } + SCB_TAG { + alias SCB_FIFO_USE_COUNT + size 2 } SCB_SPARE { size 8 diff -Nru a/drivers/scsi/aic7xxx/aic79xx.seq b/drivers/scsi/aic7xxx/aic79xx.seq --- a/drivers/scsi/aic7xxx/aic79xx.seq Thu May 15 15:24:43 2003 +++ b/drivers/scsi/aic7xxx/aic79xx.seq Thu May 15 15:24:43 2003 @@ -40,7 +40,7 @@ * $FreeBSD$ */ -VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#89 $" +VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#91 $" PATCH_ARG_LIST = "struct ahd_softc *ahd" PREFIX = "ahd_" @@ -108,8 +108,8 @@ test LQISTAT2, LQIGSAVAIL jz return; /* * We have received good status for this transaction. There may - * still be data in our FIFOs draining to the host. Setup - * monitoring of the draining process or complete the SCB. + * still be data in our FIFOs draining to the host. Complete + * the SCB only if all data has transferred to the host. */ good_status_IU_done: bmov SCBPTR, GSFIFO, 2; @@ -135,42 +135,20 @@ * 1) Configured and draining to the host, with a FIFO handler. * 2) Pending cfg4data, fifo not empty. * - * Case 1 can be detected by noticing that a longjmp is active for - * the FIFO and LONGJMP_SCB matches our SCB. In this case, we allow - * the routine servicing the FIFO to complete the SCB. + * Case 1 can be detected by noticing a non-zero FIFO active + * count in the SCB. In this case, we allow the routine servicing + * the FIFO to complete the SCB. * * Case 2 implies either a pending or yet to occur save data * pointers for this same context in the other FIFO. So, if * we detect case 1, we will properly defer the post of the SCB * and achieve the desired result. The pending cfg4data will * notice that status has been received and complete the SCB. - * - * If the data-transfer has been completed, or no data transfer - * was needed for this SCB, it is safe to complete the command. - */ - test SCB_SGPTR, SG_LIST_NULL jz good_status_check_fifos; - /* - * All segments have been loaded (or no data transfer), so - * it is safe to complete the command. Since this was a - * cheap command to check for completion, loop to see if - * more entries can be removed from the GSFIFO. */ + test SCB_FIFO_USE_COUNT, 0xFF jnz idle_loop_gsfifo_in_scsi_mode; call complete; END_CRITICAL; jmp idle_loop_gsfifo_in_scsi_mode; -BEGIN_CRITICAL; -good_status_check_fifos: - clc; - bmov ARG_1, SCBPTR, 2; - SET_MODE(M_DFF0, M_DFF0) - call check_fifo; - jc return; - SET_MODE(M_DFF1, M_DFF1) - call check_fifo; - jc return; - SET_MODE(M_SCSI, M_SCSI) - jmp queue_scb_completion; -END_CRITICAL; idle_loop_service_fifos: SET_MODE(M_DFF0, M_DFF0) @@ -179,6 +157,7 @@ idle_loop_next_fifo: SET_MODE(M_DFF1, M_DFF1) test LONGJMP_ADDR[1], INVALID_ADDR jz longjmp; +return: ret; idle_loop_cchan: @@ -196,12 +175,31 @@ scbdma_tohost_done: test CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone; /* - * A complete SCB upload requires no intervention. - * The SCB is already on the COMPLETE_SCB list - * and its completion notification will now be - * handled just like any other SCB. + * An SCB has been succesfully uploaded to the host. + * If the SCB was uploaded for some reason other than + * bad SCSI status (currently only for underruns), we + * queue the SCB for normal completion. Otherwise, we + * wait until any select-out activity has halted, and + * then notify the host so that the transaction can be + * dealt with. + */ + test SCB_SCSI_STATUS, 0xff jnz scbdma_notify_host; + and CCSCBCTL, ~(CCARREN|CCSCBEN); + bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2; + bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; + bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; +scbdma_notify_host: + SET_MODE(M_SCSI, M_SCSI) + test SCSISEQ0, ENSELO jnz return; + test SSTAT0, (SELDO|SELINGO) jnz return; + SET_MODE(M_CCHAN, M_CCHAN) + /* + * Remove SCB and notify host. */ - and CCSCBCTL, ~(CCARREN|CCSCBEN) ret; + and CCSCBCTL, ~(CCARREN|CCSCBEN); + bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2; + SET_SEQINTCODE(BAD_SCB_STATUS) + ret; fill_qoutfifo_dmadone: and CCSCBCTL, ~(CCARREN|CCSCBEN); call qoutfifo_updated; @@ -263,6 +261,13 @@ clr A; add CMDS_PENDING, 1; adc CMDS_PENDING[1], A; + /* + * The FIFO use count field is shared with the + * tag set by the host so that our SCB dma engine + * knows the correct location to store the SCB. + * Set it to zero before processing the SCB. + */ + mov SCB_FIFO_USE_COUNT, ALLZEROS; /* Update the next SCB address to download. */ bmov NEXT_QUEUED_SCB_ADDR, SCB_NEXT_SCB_BUSADDR, 4; mvi SCB_NEXT[1], SCB_LIST_NULL; @@ -339,15 +344,7 @@ dma_complete_scb: bmov SCBPTR, COMPLETE_DMA_SCB_HEAD, 2; bmov SCBHADDR, SCB_BUSADDR, 4; - mvi CCARREN|CCSCBEN|CCSCBRESET call dma_scb; - /* - * Now that we've started the DMA, push us onto - * the normal completion queue to have our SCBID - * posted to the kernel. - */ - bmov COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2; - bmov SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2; - bmov COMPLETE_SCB_HEAD, SCBPTR, 2 ret; + mvi CCARREN|CCSCBEN|CCSCBRESET jmp dma_scb; END_CRITICAL; /* @@ -366,8 +363,6 @@ mov CCSCBCTL, SINDEX ret; BEGIN_CRITICAL; -setjmp_setscb: - bmov LONGJMP_SCB, SCBPTR, 2; setjmp: bmov LONGJMP_ADDR, STACK, 2 ret; setjmp_inline: @@ -1035,9 +1030,18 @@ or SEQ_FLAGS2, SELECTOUT_QFROZEN; mov A, ACCUM_SAVE ret; -queue_arg1_scb_completion: +/* + * Complete the current FIFO's SCB if data for this same + * SCB is not transferring in the other FIFO. + */ +SET_SRC_MODE M_DFF1; +SET_DST_MODE M_DFF1; +pkt_complete_scb_if_fifos_idle: + bmov ARG_1, SCBPTR, 2; + mvi DFFSXFRCTL, CLRCHN; SET_MODE(M_SCSI, M_SCSI) bmov SCBPTR, ARG_1, 2; + test SCB_FIFO_USE_COUNT, 0xFF jnz return; queue_scb_completion: test SCB_SCSI_STATUS,0xff jnz bad_status; /* @@ -1053,6 +1057,12 @@ cmp SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb; call freeze_queue; upload_scb: + /* + * Restore SCB TAG since we reuse this field + * in the sequencer. We don't want to corrupt + * it on the host. + */ + bmov SCB_TAG, SCBPTR, 2; bmov SCB_NEXT_COMPLETE, COMPLETE_DMA_SCB_HEAD, 2; bmov COMPLETE_DMA_SCB_HEAD, SCBPTR, 2; or SCB_SGPTR, SG_STATUS_VALID ret; @@ -1363,7 +1373,7 @@ clr SG_STATE ret; p_data_handle_xfer: - call setjmp_setscb; + call setjmp; test SG_STATE, LOADING_NEEDED jnz service_fifo; p_data_clear_handler: or LONGJMP_ADDR[1], INVALID_ADDR ret; @@ -1616,25 +1626,32 @@ * and deffer the test by one instruction. */ mov REG_ISR, LQISTAT2; - test REG_ISR, LQIWORKONLQ jz data_valid; - test SEQINTSRC, SAVEPTRS jz data_valid; + test REG_ISR, LQIWORKONLQ jz main_isr; + test SEQINTSRC, SAVEPTRS jz main_isr; test LONGJMP_ADDR[1], INVALID_ADDR jz saveptr_active_fifo; /* - * Switch to the active FIFO. + * Switch to the active FIFO after clearing the snapshot + * savepointer in the current FIFO. We do this so that + * a pending CTXTDONE or SAVEPTR is visible in the active + * FIFO. This status is the only way we can detect if we + * have lost the race (e.g. host paused us) and our attepts + * to disable the channel occurred after all REQs were + * already seen and acked (REQINIT never comes true). */ + mvi DFFSXFRCTL, CLRCHN; xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); - test DFCNTRL, DIRECTION jz snapshot_other_fifo; + test DFCNTRL, DIRECTION jz interrupt_return; and DFCNTRL, ~SCSIEN; - test SSTAT1, REQINIT jz .; +snapshot_wait_data_valid: + test SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz snapshot_data_valid; + test SSTAT1, REQINIT jz snapshot_wait_data_valid; +snapshot_data_valid: or DFCNTRL, SCSIEN; - /* FALLTHROUGH */ -snapshot_other_fifo: - xor MODE_PTR, MK_MODE(M_DFF1, M_DFF1); - /* FALLTHROUGH */ + or SEQINTCTL, IRET ret; snapshot_saveptr: mvi DFFSXFRCTL, CLRCHN; or SEQINTCTL, IRET ret; -data_valid: +main_isr: } test SEQINTSRC, CFG4DATA jnz cfg4data_intr; test SEQINTSRC, CFG4ISTAT jnz cfg4istat_intr; @@ -1667,9 +1684,11 @@ or SEQINTCTL, IRET ret; cfg4data_intr: - test SCB_SGPTR[0], SG_LIST_NULL jnz pkt_handle_overrun; + test SCB_SGPTR[0], SG_LIST_NULL jnz pkt_handle_overrun_inc_use_count; call load_first_seg; call pkt_handle_xfer; + inc SCB_FIFO_USE_COUNT; +interrupt_return: or SEQINTCTL, IRET ret; cfg4istat_intr: @@ -1729,7 +1748,6 @@ test DFSTATUS, FIFOEMP jz pkt_handle_overrun pkt_handle_xfer: - bmov LONGJMP_SCB, SCBPTR, 2; test SG_STATE, LOADING_NEEDED jz pkt_last_seg; call setjmp; test SEQINTSRC, SAVEPTRS jnz pkt_saveptrs; @@ -1751,7 +1769,7 @@ pkt_last_seg: call setjmp; test SEQINTSRC, SAVEPTRS jnz pkt_saveptrs; - test SG_CACHE_SHADOW, LAST_SEG_DONE jnz last_pkt_xfer_done; + test SG_CACHE_SHADOW, LAST_SEG_DONE jnz pkt_last_seg_done; test SCSIPHASE, ~DATA_PHASE_MASK jz . + 2; test SCSISIGO, ATNO jnz . + 2; test SSTAT2, NONPACKREQ jz return; @@ -1760,7 +1778,7 @@ /* * Either a SAVEPTRS interrupt condition is pending for this FIFO - * or we have a pending nonpackreq for this FIFO. We differentiate + * or we have a pending NONPACKREQ for this FIFO. We differentiate * between the two by capturing the state of the SAVEPTRS interrupt * prior to clearing this status and executing the common code for * these two cases. @@ -1789,118 +1807,134 @@ pkt_saveptrs_check_status: or LONGJMP_ADDR[1], INVALID_ADDR; test REG0, SAVEPTRS jz unexpected_nonpkt_phase; - test SCB_CONTROL, STATUS_RCVD jz pkt_saveptrs_clrchn; - jmp last_pkt_complete; -pkt_saveptrs_clrchn: + dec SCB_FIFO_USE_COUNT; + test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle; mvi DFFSXFRCTL, CLRCHN ret; END_CRITICAL; -last_pkt_xfer_done: +/* + * LAST_SEG_DONE status has been seen in the current FIFO. + * This indicates that all of the allowed data for this + * command has transferred across the SCSI and host buses. + * Check for overrun and see if we can complete this command. + */ +pkt_last_seg_done: BEGIN_CRITICAL; - if ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0) { - or DFCNTRL, FIFOFLUSH; - } - test SCB_CONTROL, STATUS_RCVD jz wait_pkt_end; - check_overrun; - or SCB_SGPTR, SG_LIST_NULL; /* - * It is safe to skip the other FIFO check since - * we defer CLRCHN on SAVEPTRS until all data in - * the FIFO are seen by the host and a CFG4DATA - * in this FIFO for the same context is held off - * by hardware. + * Mark transfer as completed. */ -last_pkt_queue_scb: - or LONGJMP_ADDR[1], INVALID_ADDR; - bmov ARG_1, SCBPTR, 2; - mvi DFFSXFRCTL, CLRCHN; - jmp queue_arg1_scb_completion; - -last_pkt_complete: - bmov ARG_1, SCBPTR, 2; - mvi DFFSXFRCTL, CLRCHN; -check_other_fifo: - clc; - TOGGLE_DFF_MODE - call check_fifo; - jnc queue_arg1_scb_completion; -return: - ret; + or SCB_SGPTR, SG_LIST_NULL; -wait_pkt_end: + /* + * Wait for the current context to finish to verify that + * no overrun condition has occurred. + */ + test SEQINTSRC, CTXTDONE jnz pkt_ctxt_done; call setjmp; -END_CRITICAL; -wait_pkt_end_loop: - test SEQINTSRC, CTXTDONE jnz pkt_end; +pkt_wait_ctxt_done_loop: + test SEQINTSRC, CTXTDONE jnz pkt_ctxt_done; + /* + * A sufficiently large overrun or a NONPACKREQ may + * prevent CTXTDONE from ever asserting, so we must + * poll for these statuses too. + */ check_overrun; test SSTAT2, NONPACKREQ jz return; test SEQINTSRC, CTXTDONE jz unexpected_nonpkt_phase; -pkt_end: -BEGIN_CRITICAL; + /* FALLTHROUGH */ + +pkt_ctxt_done: check_overrun; or LONGJMP_ADDR[1], INVALID_ADDR; - or SCB_SGPTR, SG_LIST_NULL; - test SCB_CONTROL, STATUS_RCVD jnz last_pkt_complete; + /* + * If status has been received, it is safe to skip + * the check to see if another FIFO is active because + * LAST_SEG_DONE has been observed. However, we check + * the FIFO anyway since it costs us only one extra + * instruction to leverage common code to perform the + * SCB completion. + */ + dec SCB_FIFO_USE_COUNT; + test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle; mvi DFFSXFRCTL, CLRCHN ret; END_CRITICAL; /* + * Must wait until CDB xfer is over before issuing the + * clear channel. + */ +pkt_handle_cdb: + call setjmp; + test SG_CACHE_SHADOW, LAST_SEG_DONE jz return; + or LONGJMP_ADDR[1], INVALID_ADDR; + mvi DFFSXFRCTL, CLRCHN ret; + +/* * Watch over the status transfer. Our host sense buffer is * large enough to take the maximum allowed status packet. * None-the-less, we must still catch and report overruns to - * the host. + * the host. Additionally, properly catch unexpected non-packet + * phases that are typically caused by CRC errors in status packet + * transmission. */ pkt_handle_status: - call setjmp_setscb; - test SG_CACHE_SHADOW, LAST_SEG_DONE jz check_status_overrun; - test SEQINTSRC, CTXTDONE jz return; -status_IU_done: -BEGIN_CRITICAL; + call setjmp; + test SG_CACHE_SHADOW, LAST_SEG_DONE jnz pkt_status_check_overrun; + test SEQINTSRC, CTXTDONE jz pkt_status_check_nonpackreq; + test SG_CACHE_SHADOW, LAST_SEG_DONE jnz pkt_status_check_overrun; +pkt_status_IU_done: if ((ahd->bugs & AHD_AUTOFLUSH_BUG) != 0) { or DFCNTRL, FIFOFLUSH; } + test DFSTATUS, FIFOEMP jz return; +BEGIN_CRITICAL; or LONGJMP_ADDR[1], INVALID_ADDR; mvi SCB_SCSI_STATUS, STATUS_PKT_SENSE; or SCB_CONTROL, STATUS_RCVD; - jmp last_pkt_complete; + jmp pkt_complete_scb_if_fifos_idle; END_CRITICAL; -check_status_overrun: +pkt_status_check_overrun: /* - * We've filled the entire sense buffer. - * Wait for either context done or a negative - * shaddow count. If the context completes without - * causing the shaddow count to go negative, then - * this was a successful transfer up to the status - * limit. Otherwise we report the error. - */ - test SHCNT[2], 0xFF jnz report_status_overrun; - test SEQINTSRC, CTXTDONE jz return; - test SHCNT[2], 0xFF jz status_IU_done; -report_status_overrun: + * Status PKT overruns are uncerimoniously recovered with a + * bus reset. If we've overrun, let the host know so that + * recovery can be performed. + * + * LAST_SEG_DONE has been observed. If either CTXTDONE or + * a NONPACKREQ phase change have occurred and the FIFO is + * empty, there is no overrun. + */ + test DFSTATUS, FIFOEMP jz pkt_status_report_overrun; + test SEQINTSRC, CTXTDONE jz . + 2; + test DFSTATUS, FIFOEMP jnz pkt_status_IU_done; + test SCSIPHASE, ~DATA_PHASE_MASK jz return; + test DFSTATUS, FIFOEMP jnz pkt_status_check_nonpackreq; +pkt_status_report_overrun: SET_SEQINTCODE(STATUS_OVERRUN) - jmp status_IU_done; - -SET_SRC_MODE M_DFF0; -SET_DST_MODE M_DFF0; -BEGIN_CRITICAL; -check_fifo: - test LONGJMP_ADDR[1], INVALID_ADDR jnz return; - mov A, ARG_2; - cmp LONGJMP_SCB[1], A jne return; - mov A, ARG_1; - cmp LONGJMP_SCB[0], A jne return; - stc ret; -END_CRITICAL; - -/* - * Must wait until CDB xfer is over before issuing the - * clear channel. - */ -pkt_handle_cdb: - call setjmp_setscb; - test SG_CACHE_SHADOW, LAST_SEG_DONE jz return; - or LONGJMP_ADDR[1], INVALID_ADDR; - mvi DFFSXFRCTL, CLRCHN ret; + /* SEQUENCER RESTARTED */ +pkt_status_check_nonpackreq: + /* + * CTXTDONE may be held off if a NONPACKREQ is associated with + * the current context. If a NONPACKREQ is observed, decide + * if it is for the current context. If it is for the current + * context, we must defer NONPACKREQ processing until all data + * has transferred to the host. + */ + test SCSIPHASE, ~DATA_PHASE_MASK jz return; + test SCSISIGO, ATNO jnz . + 2; + test SSTAT2, NONPACKREQ jz return; + test SEQINTSRC, CTXTDONE jnz pkt_status_IU_done; + test DFSTATUS, FIFOEMP jz return; + /* + * The unexpected nonpkt phase handler assumes that any + * data channel use will have a FIFO reference count. It + * turns out that the status handler doesn't need a refernce + * count since the status received flag, and thus completion + * processing, cannot be set until the handler is finished. + * We increment the count here to make the nonpkt handler + * happy. + */ + inc SCB_FIFO_USE_COUNT; + /* FALLTHROUGH */ /* * Nonpackreq is a polled status. It can come true in three situations: @@ -1929,6 +1963,7 @@ SET_SRC_MODE M_DFF0; SET_DST_MODE M_DFF0; or LONGJMP_ADDR[1], INVALID_ADDR; + dec SCB_FIFO_USE_COUNT; mvi DFFSXFRCTL, CLRCHN; mvi CLRSINT2, CLRNONPACKREQ; test SCSIPHASE, ~(MSG_IN_PHASE|MSG_OUT_PHASE) jnz illegal_phase; @@ -1945,6 +1980,8 @@ * data. Otherwise use an overrun buffer in the host to simulate * BITBUCKET. */ +pkt_handle_overrun_inc_use_count: + inc SCB_FIFO_USE_COUNT; pkt_handle_overrun: SET_SEQINTCODE(CFG4OVERRUN) call freeze_queue; @@ -1970,8 +2007,9 @@ pkt_overrun_end: or SCB_RESIDUAL_SGPTR, SG_OVERRUN_RESID; test SEQINTSRC, CTXTDONE jz unexpected_nonpkt_phase; - test SCB_CONTROL, STATUS_RCVD jnz last_pkt_queue_scb; + dec SCB_FIFO_USE_COUNT; or LONGJMP_ADDR[1], INVALID_ADDR; + test SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle; mvi DFFSXFRCTL, CLRCHN ret; if ((ahd->bugs & AHD_PKT_BITBUCKET_BUG) != 0) { diff -Nru a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c --- a/drivers/scsi/aic7xxx/aic79xx_core.c Thu May 15 15:24:32 2003 +++ b/drivers/scsi/aic7xxx/aic79xx_core.c Thu May 15 15:24:32 2003 @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#178 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#190 $ * * $FreeBSD$ */ @@ -556,6 +556,26 @@ ahd_name(ahd), seqintcode); #endif switch (seqintcode) { + case BAD_SCB_STATUS: + { + struct scb *scb; + u_int scbid; + int cmds_pending; + + scbid = ahd_get_scbptr(ahd); + scb = ahd_lookup_scb(ahd, scbid); + if (scb != NULL) { + ahd_complete_scb(ahd, scb); + } else { + printf("%s: WARNING no command for scb %d " + "(bad status)\n", ahd_name(ahd), scbid); + ahd_dump_card_state(ahd); + } + cmds_pending = ahd_inw(ahd, CMDS_PENDING); + if (cmds_pending > 0) + ahd_outw(ahd, CMDS_PENDING, cmds_pending - 1); + break; + } case ENTERING_NONPACK: { struct scb *scb; @@ -604,7 +624,16 @@ break; case STATUS_OVERRUN: { - printf("%s: Status Overrun", ahd_name(ahd)); + struct scb *scb; + u_int scbid; + + scbid = ahd_get_scbptr(ahd); + scb = ahd_lookup_scb(ahd, scbid); + if (scb != NULL) + ahd_print_path(ahd, scb); + else + printf("%s: ", ahd_name(ahd)); + printf("SCB %d Packetized Status Overrun", scbid); ahd_dump_card_state(ahd); ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); break; @@ -1023,7 +1052,7 @@ switch (scb->hscb->task_management) { case SIU_TASKMGMT_ABORT_TASK: - tag = scb->hscb->tag; + tag = SCB_GET_TAG(scb); case SIU_TASKMGMT_ABORT_TASK_SET: case SIU_TASKMGMT_CLEAR_TASK_SET: lun = scb->hscb->lun; @@ -1087,7 +1116,7 @@ ahd_outb(ahd, SCB_TASK_MANAGEMENT, 0); ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb), SCB_GET_CHANNEL(ahd, scb), - SCB_GET_LUN(scb), scb->hscb->tag, + SCB_GET_LUN(scb), SCB_GET_TAG(scb), ROLE_INITIATOR, /*status*/0, SEARCH_REMOVE); } @@ -1166,7 +1195,7 @@ /* * A change in I/O mode is equivalent to a bus reset. */ - ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE); + ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE); ahd_pause(ahd); ahd_setup_iocell_workaround(ahd); ahd_unpause(ahd); @@ -2183,6 +2212,13 @@ ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) & ~STEP); ahd_outb(ahd, SIMODE1, simode1); + /* + * SCSIINT seems to glitch occassionally when + * the interrupt masks are restored. Clear SCSIINT + * one more time so that only persistent errors + * are seen as a real interrupt. + */ + ahd_outb(ahd, CLRINT, CLRSCSIINT); } ahd_restore_modes(ahd, saved_modes); } @@ -4887,7 +4923,6 @@ { int i; - ahd_fini_scbdata(ahd); switch (ahd->init_level) { default: case 5: @@ -4919,6 +4954,7 @@ ahd_dma_tag_destroy(ahd, ahd->parent_dmat); #endif ahd_platform_free(ahd); + ahd_fini_scbdata(ahd); for (i = 0; i < AHD_NUM_TARGETS; i++) { struct ahd_tmode_tstate *tstate; @@ -5481,7 +5517,7 @@ /* Clean up for the next user */ scb->flags = SCB_FLAG_NONE; scb->hscb->control = 0; - ahd->scb_data.scbindex[scb->hscb->tag] = NULL; + ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = NULL; if (scb->col_scb == NULL) { @@ -5584,8 +5620,8 @@ if (scb_data->sgs_left != 0) { int offset; - offset = ahd_sglist_allocsize(ahd) - - (scb_data->sgs_left * ahd_sglist_size(ahd)); + offset = ((ahd_sglist_allocsize(ahd) / ahd_sglist_size(ahd)) + - scb_data->sgs_left) * ahd_sglist_size(ahd); sg_map = SLIST_FIRST(&scb_data->sg_maps); segs = sg_map->vaddr + offset; sg_busaddr = sg_map->physaddr + offset; @@ -5894,7 +5930,7 @@ * specially from the DMA safe memory chunk used for the QOUTFIFO. */ ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr; - ahd->next_queued_hscb->hscb_busaddr = next_baddr; + ahd->next_queued_hscb->hscb_busaddr = ahd_htole32(next_baddr); ahd->init_level++; @@ -6056,7 +6092,6 @@ for (i = 0; i < 2; i++) { ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i); ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR); - ahd_outw(ahd, LONGJMP_SCB, SCB_LIST_NULL); ahd_outb(ahd, SG_STATE, 0); ahd_outb(ahd, CLRSEQINTSRC, 0xFF); ahd_outb(ahd, SEQIMODE, @@ -6605,24 +6640,29 @@ void ahd_pause_and_flushwork(struct ahd_softc *ahd) { - ahd_mode_state saved_modes; - u_int intstat; - u_int maxloops; - int paused; + u_int intstat; + u_int maxloops; + u_int qfreeze_cnt; maxloops = 1000; ahd->flags |= AHD_ALL_INTERRUPTS; - paused = FALSE; + ahd_pause(ahd); + /* + * Increment the QFreeze Count so that the sequencer + * will not start new selections. We do this only + * until we are safely paused without further selections + * pending. + */ + ahd_outw(ahd, QFREEZE_COUNT, ahd_inw(ahd, QFREEZE_COUNT) + 1); + ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) | SELECTOUT_QFROZEN); do { struct scb *waiting_scb; - if (paused) - ahd_unpause(ahd); + ahd_unpause(ahd); ahd_intr(ahd); ahd_pause(ahd); - paused = TRUE; ahd_clear_critical_section(ahd); - saved_modes = ahd_save_modes(ahd); + intstat = ahd_inb(ahd, INTSTAT); ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); if ((ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0) ahd_outb(ahd, SCSISEQ0, @@ -6639,22 +6679,32 @@ && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) != 0) ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) | ENSELO); - - intstat = ahd_inb(ahd, INTSTAT); } while (--maxloops && (intstat != 0xFF || (ahd->features & AHD_REMOVABLE) == 0) && ((intstat & INT_PEND) != 0 - || (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)))); + || (ahd_inb(ahd, SCSISEQ0) & ENSELO) != 0 + || (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) != 0)); + if (maxloops == 0) { printf("Infinite interrupt loop, INTSTAT = %x", ahd_inb(ahd, INTSTAT)); } + qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT); + if (qfreeze_cnt == 0) { + printf("%s: ahd_pause_and_flushwork with 0 qfreeze count!\n", + ahd_name(ahd)); + } else { + qfreeze_cnt--; + } + ahd_outw(ahd, QFREEZE_COUNT, qfreeze_cnt); + if (qfreeze_cnt == 0) + ahd_outb(ahd, SEQ_FLAGS2, + ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN); ahd_flush_qoutfifo(ahd); ahd_platform_flushwork(ahd); ahd->flags &= ~AHD_ALL_INTERRUPTS; - ahd_restore_modes(ahd, saved_modes); } int @@ -7514,14 +7564,17 @@ ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); ahd_outb(ahd, DFFSTAT, next_fifo); } while (next_fifo != fifo); + /* * Reset the bus if we are initiating this reset */ ahd_clear_msg_state(ahd); ahd_outb(ahd, SIMODE1, ahd_inb(ahd, SIMODE1) & ~(ENBUSFREE|ENSCSIRST|ENBUSFREE)); + if (initiate_reset) ahd_reset_current_bus(ahd); + ahd_clear_intstat(ahd); /* @@ -7719,9 +7772,6 @@ hscb = scb->hscb; /* Freeze the queue until the client sees the error. */ - ahd_pause(ahd); - ahd_clear_critical_section(ahd); - ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); ahd_freeze_devq(ahd, scb); ahd_freeze_scb(scb); qfreeze_cnt = ahd_inw(ahd, QFREEZE_COUNT); @@ -7734,7 +7784,7 @@ if (qfreeze_cnt == 0) ahd_outb(ahd, SEQ_FLAGS2, ahd_inb(ahd, SEQ_FLAGS2) & ~SELECTOUT_QFROZEN); - ahd_unpause(ahd); + /* Don't want to clobber the original sense code */ if ((scb->flags & SCB_SENSE) != 0) { /* @@ -8592,11 +8642,11 @@ LIST_FOREACH(scb, &ahd->pending_scbs, pending_links) { if (i++ > AHD_SCB_MAX) break; - cur_col = printf("\n%3d ", SCB_GET_TAG(scb)); + cur_col = printf("\n%3d FIFO_USE[0x%x] ", SCB_GET_TAG(scb), + ahd_inb(ahd, SCB_FIFO_USE_COUNT)); ahd_set_scbptr(ahd, SCB_GET_TAG(scb)); ahd_scb_control_print(ahd_inb(ahd, SCB_CONTROL), &cur_col, 60); ahd_scb_scsiid_print(ahd_inb(ahd, SCB_SCSIID), &cur_col, 60); - ahd_scb_tag_print(ahd_inb(ahd, SCB_TAG), &cur_col, 60); } printf("\nTotal %d\n", i); @@ -8659,12 +8709,10 @@ ahd_set_modes(ahd, AHD_MODE_DFF0 + i, AHD_MODE_DFF0 + i); fifo_scbptr = ahd_get_scbptr(ahd); - printf("\n%s: FIFO%d %s, LONGJMP == 0x%x, " - "SCB 0x%x, LJSCB 0x%x\n", + printf("\n%s: FIFO%d %s, LONGJMP == 0x%x, SCB 0x%x\n", ahd_name(ahd), i, (dffstat & (FIFO0FREE << i)) ? "Free" : "Active", - ahd_inw(ahd, LONGJMP_ADDR), fifo_scbptr, - ahd_inw(ahd, LONGJMP_SCB)); + ahd_inw(ahd, LONGJMP_ADDR), fifo_scbptr); cur_col = 0; ahd_seqimode_print(ahd_inb(ahd, SEQIMODE), &cur_col, 50); ahd_seqintsrc_print(ahd_inb(ahd, SEQINTSRC), &cur_col, 50); diff -Nru a/drivers/scsi/aic7xxx/aic79xx_inline.h b/drivers/scsi/aic7xxx/aic79xx_inline.h --- a/drivers/scsi/aic7xxx/aic79xx_inline.h Thu May 15 15:24:38 2003 +++ b/drivers/scsi/aic7xxx/aic79xx_inline.h Thu May 15 15:24:38 2003 @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#44 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx_inline.h#48 $ * * $FreeBSD$ */ @@ -223,7 +223,7 @@ ahd_set_modes(ahd, ahd->saved_src_mode, ahd->saved_dst_mode); } - if ((ahd_inb(ahd, INTSTAT) & ~(SWTMINT | CMDCMPLT)) == 0) + if ((ahd_inb(ahd, INTSTAT) & ~CMDCMPLT) == 0) ahd_outb(ahd, HCNTRL, ahd->unpause); ahd_known_modes(ahd, AHD_MODE_UNKNOWN, AHD_MODE_UNKNOWN); @@ -298,9 +298,12 @@ scb->hscb->datacnt = sg->len; } else { struct ahd_dma_seg *sg; + uint32_t *dataptr_words; sg = (struct ahd_dma_seg *)scb->sg_list; - scb->hscb->dataptr = sg->addr; + dataptr_words = (uint32_t*)&scb->hscb->dataptr; + dataptr_words[0] = sg->addr; + dataptr_words[1] = 0; if ((ahd->flags & AHD_39BIT_ADDRESSING) != 0) { uint64_t high_addr; @@ -777,12 +780,15 @@ #ifdef AHD_DEBUG if ((ahd_debug & AHD_SHOW_QUEUE) != 0) { + uint64_t host_dataptr; + + host_dataptr = ahd_le64toh(scb->hscb->dataptr); printf("%s: Queueing SCB 0x%x bus addr 0x%x - 0x%x%x/0x%x\n", ahd_name(ahd), - SCB_GET_TAG(scb), scb->hscb->hscb_busaddr, - (u_int)((scb->hscb->dataptr >> 32) & 0xFFFFFFFF), - (u_int)(scb->hscb->dataptr & 0xFFFFFFFF), - scb->hscb->datacnt); + SCB_GET_TAG(scb), ahd_le32toh(scb->hscb->hscb_busaddr), + (u_int)((host_dataptr >> 32) & 0xFFFFFFFF), + (u_int)(host_dataptr & 0xFFFFFFFF), + ahd_le32toh(scb->hscb->datacnt)); } #endif /* Tell the adapter about the newly queued SCB */ @@ -805,7 +811,7 @@ static __inline void ahd_sync_qoutfifo(struct ahd_softc *ahd, int op); static __inline void ahd_sync_tqinfifo(struct ahd_softc *ahd, int op); static __inline u_int ahd_check_cmdcmpltqueues(struct ahd_softc *ahd); -static __inline void ahd_intr(struct ahd_softc *ahd); +static __inline int ahd_intr(struct ahd_softc *ahd); static __inline void ahd_sync_qoutfifo(struct ahd_softc *ahd, int op) @@ -864,7 +870,7 @@ /* * Catch an interrupt from the adapter */ -static __inline void +static __inline int ahd_intr(struct ahd_softc *ahd) { u_int intstat; @@ -876,7 +882,7 @@ * so just return. This is likely just a shared * interrupt. */ - return; + return (0); } /* @@ -891,6 +897,9 @@ else intstat = ahd_inb(ahd, INTSTAT); + if ((intstat & INT_PEND) == 0) + return (0); + if (intstat & CMDCMPLT) { ahd_outb(ahd, CLRINT, CLRCMDINT); @@ -924,28 +933,25 @@ #endif } - if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0) - /* Hot eject */ - return; - - if ((intstat & INT_PEND) == 0) - return; - - if (intstat & HWERRINT) { + /* + * Handle statuses that may invalidate our cached + * copy of INTSTAT separately. + */ + if (intstat == 0xFF && (ahd->features & AHD_REMOVABLE) != 0) { + /* Hot eject. Do nothing */ + } else if (intstat & HWERRINT) { ahd_handle_hwerrint(ahd); - return; - } - - if ((intstat & (PCIINT|SPLTINT)) != 0) { + } else if ((intstat & (PCIINT|SPLTINT)) != 0) { ahd->bus_intr(ahd); - return; - } + } else { - if ((intstat & SEQINT) != 0) - ahd_handle_seqint(ahd, intstat); + if ((intstat & SEQINT) != 0) + ahd_handle_seqint(ahd, intstat); - if ((intstat & SCSIINT) != 0) - ahd_handle_scsiint(ahd, intstat); + if ((intstat & SCSIINT) != 0) + ahd_handle_scsiint(ahd, intstat); + } + return (1); } #endif /* _AIC79XX_INLINE_H_ */ diff -Nru a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c --- a/drivers/scsi/aic7xxx/aic79xx_osm.c Thu May 15 15:24:39 2003 +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c Thu May 15 15:24:39 2003 @@ -1,7 +1,7 @@ /* * Adaptec AIC79xx device driver for Linux. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#141 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#160 $ * * -------------------------------------------------------------------------- * Copyright (c) 1994-2000 Justin T. Gibbs. @@ -67,12 +67,10 @@ #include static int errno; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) /* * Lock protecting manipulation of the ahd softc list. */ spinlock_t ahd_list_spinlock; -#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) struct proc_dir_entry proc_scsi_aic79xx = { @@ -82,6 +80,11 @@ }; #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +/* For dynamic sglist size calculation. */ +u_int ahd_linux_nseg; +#endif + /* * Bucket size for counting good commands in between bad ones. */ @@ -352,14 +355,14 @@ * disabled at the very end. That should fix everyone up unless there are * really strange cirumstances. */ -static int aic79xx_reverse_scan = 0; +static uint32_t aic79xx_reverse_scan; /* * Should we force EXTENDED translation on a controller. * 0 == Use whatever is in the SEEPROM or default to off * 1 == Use whatever is in the SEEPROM or default to on */ -static uint32_t aic79xx_extended = 0; +static uint32_t aic79xx_extended; /* * PCI bus parity checking of the Adaptec controllers. This is somewhat @@ -367,16 +370,15 @@ * solved a PCI parity problem, but on certain machines with broken PCI * chipset configurations, it can generate tons of false error messages. * It's included in the driver for completeness. - * 0 = Shut off PCI parity check - * -1 = Normal polarity pci parity checking - * 1 = reverse polarity pci parity checking + * 0 = Shut off PCI parity check + * non-0 = Enable PCI parity check * * NOTE: you can't actually pass -1 on the lilo prompt. So, to set this * variable to -1 you would actually want to simply pass the variable * name without a number. That will invert the 0 which will result in * -1. */ -static int aic79xx_pci_parity = 0; +static uint32_t aic79xx_pci_parity = ~0; /* * There are lots of broken chipsets in the world. Some of them will @@ -384,7 +386,7 @@ * controller. I/O mapped register access, if allowed by the given * platform, will work in almost all cases. */ -int aic79xx_allow_memio = 1; +uint32_t aic79xx_allow_memio = ~0; /* * aic79xx_detect() has been run, so register all device arrivals @@ -403,7 +405,7 @@ * We default to 256ms because some older devices need a longer time * to respond to initial selection. */ -static int aic79xx_seltime = 0x00; +static uint32_t aic79xx_seltime; /* * Certain devices do not perform any aging on commands. Should the @@ -413,7 +415,7 @@ * force all outstanding transactions to be serviced prior to a new * transaction. */ -int aic79xx_periodic_otag; +uint32_t aic79xx_periodic_otag; /* * Module information and settable options. @@ -478,6 +480,7 @@ static void ahd_linux_dev_timed_unfreeze(u_long arg); static void ahd_linux_sem_timeout(u_long arg); static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd); +static void ahd_linux_size_nseg(void); static void ahd_linux_thread_run_complete_queue(struct ahd_softc *ahd); static void ahd_linux_start_dv(struct ahd_softc *ahd); static void ahd_linux_dv_timeout(struct scsi_cmnd *cmd); @@ -548,20 +551,17 @@ static aic_option_callback_t ahd_linux_setup_iocell_info; static int ahd_linux_next_unit(void); static void ahd_runq_tasklet(unsigned long data); -static int ahd_linux_halt(struct notifier_block *nb, u_long event, void *buf); static int aic79xx_setup(char *c); /****************************** Inlines ***************************************/ -static __inline void ahd_schedule_completeq(struct ahd_softc *ahd, - struct ahd_cmd *acmd); +static __inline void ahd_schedule_completeq(struct ahd_softc *ahd); static __inline void ahd_schedule_runq(struct ahd_softc *ahd); static __inline void ahd_setup_runq_tasklet(struct ahd_softc *ahd); static __inline void ahd_teardown_runq_tasklet(struct ahd_softc *ahd); static __inline struct ahd_linux_device* ahd_linux_get_device(struct ahd_softc *ahd, u_int channel, u_int target, u_int lun, int alloc); -static struct ahd_cmd *ahd_linux_run_complete_queue(struct ahd_softc *ahd, - struct ahd_cmd *acmd); +static struct ahd_cmd *ahd_linux_run_complete_queue(struct ahd_softc *ahd); static __inline void ahd_linux_check_device_queue(struct ahd_softc *ahd, struct ahd_linux_device *dev); static __inline struct ahd_linux_device * @@ -574,26 +574,8 @@ bus_addr_t addr, bus_size_t len); static __inline void -ahd_schedule_completeq(struct ahd_softc *ahd, struct ahd_cmd *acmd) +ahd_schedule_completeq(struct ahd_softc *ahd) { - while (acmd != NULL) { - struct ahd_completeq *completeq; - struct ahd_cmd *list_cmd; - struct ahd_cmd *next_cmd; - - next_cmd = TAILQ_NEXT(acmd, acmd_links.tqe); - completeq = &ahd->platform_data->completeq; - list_cmd = TAILQ_FIRST(completeq); - while (list_cmd != NULL - && acmd_scsi_cmd(list_cmd).serial_number - < acmd_scsi_cmd(acmd).serial_number) - list_cmd = TAILQ_NEXT(list_cmd, acmd_links.tqe); - if (list_cmd != NULL) - TAILQ_INSERT_BEFORE(list_cmd, acmd, acmd_links.tqe); - else - TAILQ_INSERT_TAIL(completeq, acmd, acmd_links.tqe); - acmd = next_cmd; - } if ((ahd->platform_data->flags & AHD_RUN_CMPLT_Q_TIMER) == 0) { ahd->platform_data->flags |= AHD_RUN_CMPLT_Q_TIMER; ahd->platform_data->completeq_timer.expires = jiffies; @@ -662,25 +644,17 @@ #define AHD_LINUX_MAX_RETURNED_ERRORS 4 static struct ahd_cmd * -ahd_linux_run_complete_queue(struct ahd_softc *ahd, struct ahd_cmd *acmd) +ahd_linux_run_complete_queue(struct ahd_softc *ahd) { + struct ahd_cmd *acmd; u_long done_flags; int with_errors; with_errors = 0; ahd_done_lock(ahd, &done_flags); - while (acmd != NULL) { + while ((acmd = TAILQ_FIRST(&ahd->platform_data->completeq)) != NULL) { Scsi_Cmnd *cmd; - cmd = &acmd_scsi_cmd(acmd); - acmd = TAILQ_NEXT(acmd, acmd_links.tqe); - cmd->host_scribble = NULL; - if (ahd_cmd_get_transaction_status(cmd) != DID_OK - || (cmd->result & 0xFF) != SCSI_STATUS_OK) - with_errors++; - - cmd->scsi_done(cmd); - if (with_errors > AHD_LINUX_MAX_RETURNED_ERRORS) { /* * Linux uses stack recursion to requeue @@ -690,8 +664,18 @@ * the operating system in case they are going * to be retried. "ick" */ + ahd_schedule_completeq(ahd); break; } + TAILQ_REMOVE(&ahd->platform_data->completeq, + acmd, acmd_links.tqe); + cmd = &acmd_scsi_cmd(acmd); + cmd->host_scribble = NULL; + if (ahd_cmd_get_transaction_status(cmd) != DID_OK + || (cmd->result & 0xFF) != SCSI_STATUS_OK) + with_errors++; + + cmd->scsi_done(cmd); } ahd_done_unlock(ahd, &done_flags); return (acmd); @@ -825,6 +809,67 @@ static int ahd_linux_abort(Scsi_Cmnd *); /* + * Calculate a safe value for AHD_NSEG (as expressed through ahd_linux_nseg). + * + * In pre-2.5.X... + * The midlayer allocates an S/G array dynamically when a command is issued + * using SCSI malloc. This array, which is in an OS dependent format that + * must later be copied to our private S/G list, is sized to house just the + * number of segments needed for the current transfer. Since the code that + * sizes the SCSI malloc pool does not take into consideration fragmentation + * of the pool, executing transactions numbering just a fraction of our + * concurrent transaction limit with SG list lengths aproaching AHC_NSEG will + * quickly depleat the SCSI malloc pool of usable space. Unfortunately, the + * mid-layer does not properly handle this scsi malloc failures for the S/G + * array and the result can be a lockup of the I/O subsystem. We try to size + * our S/G list so that it satisfies our drivers allocation requirements in + * addition to avoiding fragmentation of the SCSI malloc pool. + */ +static void +ahd_linux_size_nseg(void) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + u_int cur_size; + u_int best_size; + + /* + * The SCSI allocator rounds to the nearest 512 bytes + * an cannot allocate across a page boundary. Our algorithm + * is to start at 1K of scsi malloc space per-command and + * loop through all factors of the PAGE_SIZE and pick the best. + */ + best_size = 0; + for (cur_size = 1024; cur_size <= PAGE_SIZE; cur_size *= 2) { + u_int nseg; + + nseg = cur_size / sizeof(struct scatterlist); + if (nseg < AHD_LINUX_MIN_NSEG) + continue; + + if (best_size == 0) { + best_size = cur_size; + ahd_linux_nseg = nseg; + } else { + u_int best_rem; + u_int cur_rem; + + /* + * Compare the traits of the current "best_size" + * with the current size to determine if the + * current size is a better size. + */ + best_rem = best_size % sizeof(struct scatterlist); + cur_rem = cur_size % sizeof(struct scatterlist); + if (cur_rem < best_rem) { + best_size = cur_size; + ahd_linux_nseg = nseg; + } + } + } +#endif +} + +/* * Try to detect an Adaptec 79XX controller. */ static int @@ -852,6 +897,10 @@ printf("ahd_linux_detect: Unable to attach\n"); return (0); } + /* + * Determine an appropriate size for our Scatter Gatther lists. + */ + ahd_linux_size_nseg(); #ifdef MODULE /* * If we've been passed any parameters, process them now. @@ -991,7 +1040,7 @@ ahd_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ); ahd_linux_queue_cmd_complete(ahd, cmd); - ahd_schedule_completeq(ahd, NULL); + ahd_schedule_completeq(ahd); ahd_midlayer_entrypoint_unlock(ahd, &flags); return (0); } @@ -1001,7 +1050,7 @@ if (dev == NULL) { ahd_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL); ahd_linux_queue_cmd_complete(ahd, cmd); - ahd_schedule_completeq(ahd, NULL); + ahd_schedule_completeq(ahd); ahd_midlayer_entrypoint_unlock(ahd, &flags); printf("%s: aic79xx_linux_queue - Unable to allocate device!\n", ahd_name(ahd)); @@ -1087,7 +1136,8 @@ && (dev->flags & AHD_DEV_SLAVE_CONFIGURED) != 0) { dev->flags |= AHD_DEV_UNCONFIGURED; if (TAILQ_EMPTY(&dev->busyq) - && dev->active == 0) + && dev->active == 0 + && (dev->flags & AHD_DEV_TIMER_ACTIVE) == 0) ahd_linux_free_device(ahd, dev); } ahd_midlayer_entrypoint_unlock(ahd, &flags); @@ -1102,15 +1152,30 @@ Scsi_Device * scsi_devs) { Scsi_Device *device; + Scsi_Device *ldev; struct ahd_softc *ahd; u_long flags; - int scbnum; ahd = *((struct ahd_softc **)host->hostdata); ahd_lock(ahd, &flags); - scbnum = 0; for (device = scsi_devs; device != NULL; device = device->next) { + /* + * Watch out for duplicate devices. This works around + * some quirks in how the SCSI scanning code does its + * device management. + */ + for (ldev = scsi_devs; ldev != device; ldev = ldev->next) { + if (ldev->host == device->host + && ldev->channel == device->channel + && ldev->id == device->id + && ldev->lun == device->lun) + break; + } + /* Skip duplicate. */ + if (ldev != device) + continue; + if (device->host == host) { struct ahd_linux_device *dev; @@ -1226,6 +1291,7 @@ u_int last_phase; u_int cdb_byte; int retval; + int was_paused; int paused; int wait; int disconnected; @@ -1265,7 +1331,7 @@ * Start by searching the device queue. If not found * there, check the pending_scb list. If not found * at all, and the system wanted us to just abort the - * command return success. + * command, return success. */ dev = ahd_linux_get_device(ahd, cmd->device->channel, cmd->device->id, cmd->device->lun, @@ -1328,6 +1394,7 @@ * didn't "just" miss an interrupt that would * affect this cmd. */ + was_paused = ahd_is_paused(ahd); ahd_pause_and_flushwork(ahd); paused = TRUE; @@ -1338,11 +1405,13 @@ goto no_cmd; } + printf("%s: At time of recovery, card was %spaused\n", + ahd_name(ahd), was_paused ? "" : "not "); ahd_dump_card_state(ahd); disconnected = TRUE; if (ahd_search_qinfifo(ahd, cmd->device->id, cmd->device->channel + 'A', - cmd->device->lun, pending_scb->hscb->tag, + cmd->device->lun, SCB_GET_TAG(pending_scb), ROLE_INITIATOR, CAM_REQ_ABORTED, SEARCH_COMPLETE) > 0) { printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n", @@ -1371,7 +1440,7 @@ * bus or is in the disconnected state. */ if (last_phase != P_BUSFREE - && pending_scb->hscb->tag == active_scbptr) { + && SCB_GET_TAG(pending_scb) == active_scbptr) { /* * We're active on the bus, so assert ATN @@ -1392,7 +1461,7 @@ * to select the device before it reconnects. */ pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT; - ahd_set_scbptr(ahd, pending_scb->hscb->tag); + ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb)); pending_scb->hscb->cdb_len = 0; pending_scb->hscb->task_attribute = 0; pending_scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK; @@ -1476,21 +1545,15 @@ printf("Recovery code sleeping\n"); down(&ahd->platform_data->eh_sem); printf("Recovery code awake\n"); - ret = del_timer(&timer); + ret = del_timer_sync(&timer); if (ret == 0) { printf("Timer Expired\n"); retval = FAILED; } spin_lock_irq(&ahd->platform_data->spin_lock); } - acmd = TAILQ_FIRST(&ahd->platform_data->completeq); - TAILQ_INIT(&ahd->platform_data->completeq); ahd_schedule_runq(ahd); - if (acmd != NULL) { - acmd = ahd_linux_run_complete_queue(ahd, acmd); - if (acmd != NULL) - ahd_schedule_completeq(ahd, acmd); - } + ahd_linux_run_complete_queue(ahd); ahd_midlayer_entrypoint_unlock(ahd, &s); return (retval); } @@ -1515,7 +1578,6 @@ struct ahd_tmode_tstate *tstate; struct scb *scb; struct hardware_scb *hscb; - struct ahd_cmd *acmd; u_long s; struct timer_list timer; int retval; @@ -1581,19 +1643,13 @@ down(&ahd->platform_data->eh_sem); printf("Recovery code awake\n"); retval = SUCCESS; - if (del_timer(&timer) == 0) { + if (del_timer_sync(&timer) == 0) { printf("Timer Expired\n"); retval = FAILED; } spin_lock_irq(&ahd->platform_data->spin_lock); - acmd = TAILQ_FIRST(&ahd->platform_data->completeq); - TAILQ_INIT(&ahd->platform_data->completeq); ahd_schedule_runq(ahd); - if (acmd != NULL) { - acmd = ahd_linux_run_complete_queue(ahd, acmd); - if (acmd != NULL) - ahd_schedule_completeq(ahd, acmd); - } + ahd_linux_run_complete_queue(ahd); ahd_midlayer_entrypoint_unlock(ahd, &s); printf("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval); return (retval); @@ -1606,7 +1662,6 @@ ahd_linux_bus_reset(Scsi_Cmnd *cmd) { struct ahd_softc *ahd; - struct ahd_cmd *acmd; u_long s; int found; @@ -1619,14 +1674,7 @@ ahd_midlayer_entrypoint_lock(ahd, &s); found = ahd_reset_channel(ahd, cmd->device->channel + 'A', /*initiate reset*/TRUE); - acmd = TAILQ_FIRST(&ahd->platform_data->completeq); - TAILQ_INIT(&ahd->platform_data->completeq); - - if (acmd != NULL) { - acmd = ahd_linux_run_complete_queue(ahd, acmd); - if (acmd != NULL) - ahd_schedule_completeq(ahd, acmd); - } + ahd_linux_run_complete_queue(ahd); ahd_midlayer_entrypoint_unlock(ahd, &s); if (bootverbose) @@ -1650,7 +1698,6 @@ #endif .can_queue = AHD_MAX_QUEUE, .this_id = -1, - .sg_tablesize = AHD_NSEG, .cmd_per_lun = 2, .use_clustering = ENABLE_CLUSTERING, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) @@ -1708,44 +1755,17 @@ TAILQ_REMOVE(&ahd->platform_data->device_runq, dev, links); dev->flags &= ~AHD_DEV_ON_RUN_LIST; ahd_linux_check_device_queue(ahd, dev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* Yeild to our interrupt handler */ ahd_unlock(ahd, &flags); ahd_lock(ahd, &flags); +#endif } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) ahd_unlock(ahd, &flags); #endif } -/************************ Shutdown/halt/reboot hook ***************************/ -#include -#include - -static struct notifier_block ahd_linux_notifier = { - ahd_linux_halt, NULL, 0 -}; - -static int ahd_linux_halt(struct notifier_block *nb, u_long event, void *buf) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - struct ahd_softc *ahd; - - /* - * In 2.5.X, this is called prior to the filesystems - * being synced and the SCSI layer being properly - * shutdown. A different API is required there, - * but the device hooks for this don't quite look - * right. - */ - if (event == SYS_DOWN || event == SYS_HALT) { - TAILQ_FOREACH(ahd, &ahd_tailq, links) { - ahd_shutdown(ahd); - } - } -#endif - return (NOTIFY_OK); -} - /******************************** Bus DMA *************************************/ int ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent, @@ -1927,7 +1947,7 @@ } static void -ahd_linux_setup_tag_info(void *arg, int instance, int targ, int32_t value) +ahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value) { if ((instance >= 0) && (targ >= 0) @@ -1940,18 +1960,18 @@ } static void -ahd_linux_setup_rd_strm_info(void *arg, int instance, int targ, int32_t value) +ahd_linux_setup_rd_strm_info(u_long arg, int instance, int targ, int32_t value) { if ((instance >= 0) && (instance < NUM_ELEMENTS(aic79xx_rd_strm_info))) { - aic79xx_rd_strm_info[instance] = value * 0xFFFF; + aic79xx_rd_strm_info[instance] = value & 0xFFFF; if (bootverbose) printf("rd_strm[%d] = 0x%x\n", instance, value); } } static void -ahd_linux_setup_dv(void *arg, int instance, int targ, int32_t value) +ahd_linux_setup_dv(u_long arg, int instance, int targ, int32_t value) { if ((instance >= 0) && (instance < NUM_ELEMENTS(aic79xx_dv_settings))) { @@ -1962,11 +1982,9 @@ } static void -ahd_linux_setup_iocell_info(void *arg, int instance, int targ, int32_t value) +ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value) { - u_int index; - index = (u_int)arg; if ((instance >= 0) && (instance < NUM_ELEMENTS(aic79xx_iocell_info))) { uint8_t *iocell_info; @@ -1974,7 +1992,7 @@ iocell_info = (uint8_t*)&aic79xx_iocell_info[instance]; iocell_info[index] = value & 0xFFFF; if (bootverbose) - printf("iocell[%d:%d] = %d\n", instance, index, value); + printf("iocell[%d:%ld] = %d\n", instance, index, value); } } @@ -2053,32 +2071,31 @@ ahd_linux_setup_tag_info_global(p + n); } else if (strncmp(p, "tag_info", n) == 0) { s = aic_parse_brace_option("tag_info", p + n, end, - 2, ahd_linux_setup_tag_info, NULL); + 2, ahd_linux_setup_tag_info, 0); } else if (strncmp(p, "rd_strm", n) == 0) { - printf("Calling brace parse for %s\n", p); s = aic_parse_brace_option("rd_strm", p + n, end, - 1, ahd_linux_setup_rd_strm_info, NULL); + 1, ahd_linux_setup_rd_strm_info, 0); } else if (strncmp(p, "dv", n) == 0) { s = aic_parse_brace_option("dv", p + n, end, 1, - ahd_linux_setup_dv, NULL); + ahd_linux_setup_dv, 0); } else if (strncmp(p, "slewrate", n) == 0) { s = aic_parse_brace_option("slewrate", p + n, end, 1, ahd_linux_setup_iocell_info, - (void *)AIC79XX_SLEWRATE_INDEX); + AIC79XX_SLEWRATE_INDEX); } else if (strncmp(p, "precomp", n) == 0) { s = aic_parse_brace_option("precomp", p + n, end, 1, ahd_linux_setup_iocell_info, - (void *)AIC79XX_PRECOMP_INDEX); + AIC79XX_PRECOMP_INDEX); } else if (strncmp(p, "amplitude", n) == 0) { s = aic_parse_brace_option("amplitude", p + n, end, 1, ahd_linux_setup_iocell_info, - (void *)AIC79XX_AMPLITUDE_INDEX); + AIC79XX_AMPLITUDE_INDEX); } else if (p[n] == ':') { *(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0); } else if (!strncmp(p, "verbose", n)) { *(options[i].flag) = 1; } else { - *(options[i].flag) = ~(*(options[i].flag)); + *(options[i].flag) ^= 0xFFFFFFFF; } } return 1; @@ -2088,7 +2105,7 @@ __setup("aic79xx=", aic79xx_setup); #endif -int aic79xx_verbose; +uint32_t aic79xx_verbose; int ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template) @@ -2120,6 +2137,7 @@ host->max_id = (ahd->features & AHD_WIDE) ? 16 : 8; host->max_lun = AHD_NUM_LUNS; host->max_channel = 0; + host->sg_tablesize = AHD_NSEG; ahd_set_unit(ahd, ahd_linux_next_unit()); sprintf(buf, "scsi%d", host->host_no); new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); @@ -2291,8 +2309,6 @@ #endif ahd_setup_runq_tasklet(ahd); ahd->seltime = (aic79xx_seltime & 0x3) << 4; - if (TAILQ_EMPTY(&ahd_tailq)) - register_reboot_notifier(&ahd_linux_notifier); return (0); } @@ -2304,6 +2320,7 @@ int i, j; if (ahd->platform_data != NULL) { + del_timer_sync(&ahd->platform_data->completeq_timer); ahd_linux_kill_dv_thread(ahd); ahd_teardown_runq_tasklet(ahd); if (ahd->platform_data->host != NULL) { @@ -2317,15 +2334,20 @@ for (i = 0; i < AHD_NUM_TARGETS; i++) { targ = ahd->platform_data->targets[i]; if (targ != NULL) { + /* Keep target around through the loop. */ + targ->refcount++; for (j = 0; j < AHD_NUM_LUNS; j++) { - if (targ->devices[j] != NULL) { - dev = targ->devices[j]; - ahd_linux_free_device(ahd, dev); - } - if (ahd->platform_data->targets[i] == - NULL) - break; + + if (targ->devices[j] == NULL) + continue; + dev = targ->devices[j]; + ahd_linux_free_device(ahd, dev); } + /* + * Forcibly free the target now that + * all devices are gone. + */ + ahd_linux_free_target(ahd, targ); } } @@ -2546,19 +2568,12 @@ static void ahd_linux_thread_run_complete_queue(struct ahd_softc *ahd) { - struct ahd_cmd *acmd; u_long flags; ahd_lock(ahd, &flags); del_timer(&ahd->platform_data->completeq_timer); ahd->platform_data->flags &= ~AHD_RUN_CMPLT_Q_TIMER; - acmd = TAILQ_FIRST(&ahd->platform_data->completeq); - TAILQ_INIT(&ahd->platform_data->completeq); - if (acmd != NULL) { - acmd = ahd_linux_run_complete_queue(ahd, acmd); - if (acmd != NULL) - ahd_schedule_completeq(ahd, acmd); - } + ahd_linux_run_complete_queue(ahd); ahd_unlock(ahd, &flags); } @@ -2921,10 +2936,14 @@ } ahd_lock(ahd, &s); - if (targ->dv_buffer != NULL) + if (targ->dv_buffer != NULL) { free(targ->dv_buffer, M_DEVBUF); - if (targ->dv_buffer1 != NULL) + targ->dv_buffer = NULL; + } + if (targ->dv_buffer1 != NULL) { free(targ->dv_buffer1, M_DEVBUF); + targ->dv_buffer1 = NULL; + } targ->flags &= ~AHD_DV_REQUIRED; if (targ->refcount == 0) ahd_linux_free_target(ahd, targ); @@ -3760,7 +3779,6 @@ ahd_linux_dv_timeout(struct scsi_cmnd *cmd) { struct ahd_softc *ahd; - struct ahd_cmd *acmd; struct scb *scb; u_long flags; @@ -3807,16 +3825,9 @@ ahd->platform_data->reset_timer.function = (ahd_linux_callback_t *)ahd_release_simq; add_timer(&ahd->platform_data->reset_timer); - acmd = TAILQ_FIRST(&ahd->platform_data->completeq); - TAILQ_INIT(&ahd->platform_data->completeq); if (ahd_linux_next_device_to_run(ahd) != NULL) ahd_schedule_runq(ahd); - if (acmd != NULL) { - acmd = ahd_linux_run_complete_queue(ahd, acmd); - if (acmd != NULL) { - ahd_schedule_completeq(ahd, acmd); - } - } + ahd_linux_run_complete_queue(ahd); ahd_unlock(ahd, &flags); } @@ -4025,9 +4036,8 @@ && dev->scsi_device->tagged_supported != 0) { ahd_set_tags(ahd, &devinfo, AHD_QUEUE_TAGGED); - printf("scsi%d:%c:%d:%d: Tagged Queuing enabled. Depth %d\n", - ahd->platform_data->host->host_no, devinfo.channel, - devinfo.target, devinfo.lun, tags); + ahd_print_devinfo(ahd, &devinfo); + printf("Tagged Queuing enabled. Depth %d\n", tags); } else { ahd_set_tags(ahd, &devinfo, AHD_QUEUE_NONE); } @@ -4201,38 +4211,29 @@ /* * SCSI controller interrupt handler. */ -void +AIC_LINUX_IRQRETURN_T ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs) { struct ahd_softc *ahd; - struct ahd_cmd *acmd; u_long flags; + int ours; ahd = (struct ahd_softc *) dev_id; ahd_lock(ahd, &flags); - ahd_intr(ahd); - acmd = TAILQ_FIRST(&ahd->platform_data->completeq); - TAILQ_INIT(&ahd->platform_data->completeq); + ours = ahd_intr(ahd); if (ahd_linux_next_device_to_run(ahd) != NULL) ahd_schedule_runq(ahd); - if (acmd != NULL) { - acmd = ahd_linux_run_complete_queue(ahd, acmd); - if (acmd != NULL) { - ahd_schedule_completeq(ahd, acmd); - } - } + ahd_linux_run_complete_queue(ahd); ahd_unlock(ahd, &flags); + AIC_LINUX_IRQRETURN(ours); } void ahd_platform_flushwork(struct ahd_softc *ahd) { - struct ahd_cmd *acmd; - acmd = TAILQ_FIRST(&ahd->platform_data->completeq); - TAILQ_INIT(&ahd->platform_data->completeq); - while (acmd != NULL) - acmd = ahd_linux_run_complete_queue(ahd, acmd); + while (ahd_linux_run_complete_queue(ahd) != NULL) + ; } static struct ahd_linux_target* @@ -4403,22 +4404,19 @@ } case AC_SENT_BDR: { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + WARN_ON(lun != CAM_LUN_WILDCARD); + scsi_report_device_reset(ahd->platform_data->host, + channel - 'A', target); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) Scsi_Device *scsi_dev; /* * Find the SCSI device associated with this * request and indicate that a UA is expected. - * XXX This should really be handled by the mid-layer. */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - list_for_each_entry(scsi_dev, - &ahd->platform_data->host->my_devices, - siblings) { -#else for (scsi_dev = ahd->platform_data->host->host_queue; scsi_dev != NULL; scsi_dev = scsi_dev->next) { -#endif if (channel - 'A' == scsi_dev->channel && target == scsi_dev->id && (lun == CAM_LUN_WILDCARD @@ -4452,13 +4450,12 @@ Scsi_Cmnd *cmd; struct ahd_linux_device *dev; - LIST_REMOVE(scb, pending_links); - if ((scb->flags & SCB_ACTIVE) == 0) { - printf("SCB %d done'd twice\n", scb->hscb->tag); + printf("SCB %d done'd twice\n", SCB_GET_TAG(scb)); ahd_dump_card_state(ahd); panic("Stopping for safety"); } + LIST_REMOVE(scb, pending_links); cmd = scb->io_ctx; dev = scb->platform_data->dev; dev->active--; @@ -4542,7 +4539,8 @@ if (TAILQ_EMPTY(&dev->busyq)) { if ((dev->flags & AHD_DEV_UNCONFIGURED) != 0 - && dev->active == 0) + && dev->active == 0 + && (dev->flags & AHD_DEV_TIMER_ACTIVE) == 0) ahd_linux_free_device(ahd, dev); } else if ((dev->flags & AHD_DEV_ON_RUN_LIST) == 0) { TAILQ_INSERT_TAIL(&ahd->platform_data->device_runq, dev, links); @@ -5065,6 +5063,9 @@ if (dev->qfrozen == 0 && (dev->flags & AHD_DEV_ON_RUN_LIST) == 0) ahd_linux_run_device_queue(ahd, dev); + if ((dev->flags & AHD_DEV_UNCONFIGURED) != 0 + && dev->active == 0) + ahd_linux_free_device(ahd, dev); ahd_unlock(ahd, &s); } @@ -5143,8 +5144,6 @@ scsi_unregister_module(MODULE_SCSI_HA, &aic79xx_driver_template); #endif ahd_linux_pci_exit(); - - unregister_reboot_notifier(&ahd_linux_notifier); } module_init(ahd_linux_init); diff -Nru a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h --- a/drivers/scsi/aic7xxx/aic79xx_osm.h Thu May 15 15:24:40 2003 +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h Thu May 15 15:24:40 2003 @@ -36,7 +36,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#121 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.h#130 $ * */ #ifndef _AIC79XX_LINUX_H_ @@ -139,7 +139,7 @@ #endif /* BYTE_ORDER */ /************************* Configuration Data *********************************/ -extern int aic79xx_allow_memio; +extern uint32_t aic79xx_allow_memio; extern int aic79xx_detect_complete; extern Scsi_Host_Template aic79xx_driver_template; @@ -246,7 +246,7 @@ typedef struct timer_list ahd_timer_t; /********************************** Includes **********************************/ -#if CONFIG_AIC79XX_REG_PRETTY_PRINT +#ifdef CONFIG_AIC79XX_REG_PRETTY_PRINT #define AIC_DEBUG_REGISTERS 1 #else #define AIC_DEBUG_REGISTERS 0 @@ -255,7 +255,7 @@ /***************************** Timer Facilities *******************************/ #define ahd_timer_init init_timer -#define ahd_timer_stop del_timer +#define ahd_timer_stop del_timer_sync typedef void ahd_linux_callback_t (u_long); static __inline void ahd_timer_reset(ahd_timer_t *timer, u_int usec, ahd_callback_t *func, void *arg); @@ -293,7 +293,7 @@ #define AHD_SCSI_HAS_HOST_LOCK 0 #endif -#define AIC79XX_DRIVER_VERSION "1.3.5" +#define AIC79XX_DRIVER_VERSION "1.3.8" /**************************** Front End Queues ********************************/ /* @@ -488,7 +488,18 @@ * manner and are allocated below 4GB, the number of S/G segments is * unrestricted. */ -#define AHD_NSEG 128 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +/* + * We dynamically adjust the number of segments in pre-2.5 kernels to + * avoid fragmentation issues in the SCSI mid-layer's private memory + * allocator. See aic79xx_osm.c ahd_linux_size_nseg() for details. + */ +extern u_int ahd_linux_nseg; +#define AHD_NSEG ahd_linux_nseg +#define AHD_LINUX_MIN_NSEG 64 +#else +#define AHD_NSEG 128 +#endif /* * Per-SCB OSM storage. @@ -532,9 +543,7 @@ TAILQ_HEAD(, ahd_linux_device) device_runq; struct ahd_completeq completeq; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93) spinlock_t spin_lock; -#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) struct tasklet_struct runq_tasklet; #endif @@ -730,7 +739,6 @@ static __inline void ahd_list_lock(unsigned long *flags); static __inline void ahd_list_unlock(unsigned long *flags); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93) static __inline void ahd_lockinit(struct ahd_softc *ahd) { @@ -818,63 +826,6 @@ spin_unlock_irqrestore(&ahd_list_spinlock, *flags); } -#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) */ - -ahd_lockinit(struct ahd_softc *ahd) -{ -} - -static __inline void -ahd_lock(struct ahd_softc *ahd, unsigned long *flags) -{ - save_flags(*flags); - cli(); -} - -static __inline void -ahd_unlock(struct ahd_softc *ahd, unsigned long *flags) -{ - restore_flags(*flags); -} - -ahd_done_lockinit(struct ahd_softc *ahd) -{ -} - -static __inline void -ahd_done_lock(struct ahd_softc *ahd, unsigned long *flags) -{ - /* - * The done lock is always held while - * the ahd lock is held so blocking - * interrupts again would have no effect. - */ -} - -static __inline void -ahd_done_unlock(struct ahd_softc *ahd, unsigned long *flags) -{ -} - -static __inline void -ahd_list_lockinit() -{ -} - -static __inline void -ahd_list_lock(unsigned long *flags) -{ - save_flags(*flags); - cli(); -} - -static __inline void -ahd_list_unlock(unsigned long *flags) -{ - restore_flags(*flags); -} -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) */ - /******************************* PCI Definitions ******************************/ /* * PCIM_xxx: mask to locate subfield in register @@ -945,16 +896,6 @@ ahd_power_state new_state); /******************************* PCI Routines *********************************/ -/* - * We need to use the bios32.h routines if we are kernel version 2.1.92 or less. - */ -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,1,92) -#if defined(__sparc_v9__) || defined(__powerpc__) -#error "PPC and Sparc platforms are only supported under 2.1.92 and above" -#endif -#include -#endif - int ahd_linux_pci_init(void); void ahd_linux_pci_exit(void); int ahd_pci_map_registers(struct ahd_softc *ahd); @@ -1270,7 +1211,8 @@ int ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, char channel, int lun, u_int tag, role_t role, uint32_t status); -void ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs); +AIC_LINUX_IRQRETURN_T + ahd_linux_isr(int irq, void *dev_id, struct pt_regs * regs); void ahd_platform_flushwork(struct ahd_softc *ahd); int ahd_softc_comp(struct ahd_softc *, struct ahd_softc *); void ahd_done(struct ahd_softc*, struct scb*); @@ -1285,5 +1227,5 @@ #define AHD_PCI_CONFIG 0 #endif #define bootverbose aic79xx_verbose -extern int aic79xx_verbose; +extern uint32_t aic79xx_verbose; #endif /* _AIC79XX_LINUX_H_ */ diff -Nru a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c --- a/drivers/scsi/aic7xxx/aic79xx_pci.c Thu May 15 15:24:38 2003 +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c Thu May 15 15:24:38 2003 @@ -38,7 +38,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#70 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#71 $ * * $FreeBSD$ */ @@ -565,14 +565,13 @@ #if AHD_DEBUG if (have_seeprom != 0 && (ahd_debug & AHD_DUMP_SEEPROM) != 0) { - uint8_t *sc_data; - int i; + uint16_t *sc_data; + int i; printf("%s: Seeprom Contents:", ahd_name(ahd)); - sc_data = (uint8_t *)sc; + sc_data = (uint16_t *)sc; for (i = 0; i < (sizeof(*sc)); i += 2) - printf("\n\t0x%.4x", - sc_data[i] | (sc_data[i+1] << 8)); + printf("\n\t0x%.4x", sc_data[i]); printf("\n"); } #endif diff -Nru a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c --- a/drivers/scsi/aic7xxx/aic79xx_proc.c Thu May 15 15:24:42 2003 +++ b/drivers/scsi/aic7xxx/aic79xx_proc.c Thu May 15 15:24:42 2003 @@ -37,7 +37,7 @@ * String handling code courtesy of Gerard Roudier's * sym driver. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_proc.c#14 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_proc.c#17 $ */ #include "aic79xx_osm.h" #include "aic79xx_inline.h" @@ -173,8 +173,7 @@ tinfo = ahd_fetch_transinfo(ahd, channel, our_id, target_id, &tstate); - copy_info(info, "Channel %c Target %d Negotiation Settings\n", - channel, target_id); + copy_info(info, "Target %d Negotiation Settings\n", target_id); copy_info(info, "\tUser: "); ahd_format_transinfo(info, &tinfo->user); targ = ahd->platform_data->targets[target_offset]; @@ -318,7 +317,11 @@ AIC79XX_DRIVER_VERSION); copy_info(&info, "%s\n", ahd->description); ahd_controller_info(ahd, ahd_info); - copy_info(&info, "%s\n\n", ahd_info); + copy_info(&info, "%s\n", ahd_info); + copy_info(&info, "Allocated SCBs: %d, SG List Length: %d\n\n", + ahd->scb_data.numscbs, AHD_NSEG); + + max_targ = 15; if (ahd->seep_config == NULL) copy_info(&info, "No Serial EEPROM\n"); @@ -335,7 +338,6 @@ } copy_info(&info, "\n"); - max_targ = 15; if ((ahd->features & AHD_WIDE) == 0) max_targ = 7; diff -Nru a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped --- a/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped Thu May 15 15:24:46 2003 +++ b/drivers/scsi/aic7xxx/aic79xx_reg.h_shipped Thu May 15 15:24:46 2003 @@ -2,8 +2,8 @@ * DO NOT EDIT - This file is automatically generated * from the following source files: * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#89 $ - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#65 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#91 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#67 $ */ typedef int (ahd_reg_print_t)(u_int, u_int *, u_int); typedef struct ahd_reg_parse_entry { @@ -1924,17 +1924,10 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_longjmp_scb_print; -#else -#define ahd_longjmp_scb_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "LONGJMP_SCB", 0xfa, regvalue, cur_col, wrap) -#endif - -#if AIC_DEBUG_REGISTERS ahd_reg_print_t ahd_accum_save_print; #else #define ahd_accum_save_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "ACCUM_SAVE", 0xfc, regvalue, cur_col, wrap) + ahd_print_register(NULL, 0, "ACCUM_SAVE", 0xfa, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -2246,59 +2239,45 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_scb_tag_print; -#else -#define ahd_scb_tag_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SCB_TAG", 0x190, regvalue, cur_col, wrap) -#endif - -#if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_scb_cdb_len_print; -#else -#define ahd_scb_cdb_len_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SCB_CDB_LEN", 0x192, regvalue, cur_col, wrap) -#endif - -#if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_scb_task_management_print; +ahd_reg_print_t ahd_scb_dataptr_print; #else -#define ahd_scb_task_management_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SCB_TASK_MANAGEMENT", 0x193, regvalue, cur_col, wrap) +#define ahd_scb_dataptr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SCB_DATAPTR", 0x190, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_scb_next_print; +ahd_reg_print_t ahd_scb_datacnt_print; #else -#define ahd_scb_next_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SCB_NEXT", 0x194, regvalue, cur_col, wrap) +#define ahd_scb_datacnt_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SCB_DATACNT", 0x198, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_scb_next2_print; +ahd_reg_print_t ahd_scb_sgptr_print; #else -#define ahd_scb_next2_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SCB_NEXT2", 0x196, regvalue, cur_col, wrap) +#define ahd_scb_sgptr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SCB_SGPTR", 0x19c, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_scb_dataptr_print; +ahd_reg_print_t ahd_scb_busaddr_print; #else -#define ahd_scb_dataptr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SCB_DATAPTR", 0x198, regvalue, cur_col, wrap) +#define ahd_scb_busaddr_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SCB_BUSADDR", 0x1a0, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_scb_datacnt_print; +ahd_reg_print_t ahd_scb_next_print; #else -#define ahd_scb_datacnt_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SCB_DATACNT", 0x1a0, regvalue, cur_col, wrap) +#define ahd_scb_next_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SCB_NEXT", 0x1a4, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_scb_sgptr_print; +ahd_reg_print_t ahd_scb_next2_print; #else -#define ahd_scb_sgptr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SCB_SGPTR", 0x1a4, regvalue, cur_col, wrap) +#define ahd_scb_next2_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SCB_NEXT2", 0x1a6, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -2330,10 +2309,24 @@ #endif #if AIC_DEBUG_REGISTERS -ahd_reg_print_t ahd_scb_busaddr_print; +ahd_reg_print_t ahd_scb_cdb_len_print; #else -#define ahd_scb_busaddr_print(regvalue, cur_col, wrap) \ - ahd_print_register(NULL, 0, "SCB_BUSADDR", 0x1ac, regvalue, cur_col, wrap) +#define ahd_scb_cdb_len_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SCB_CDB_LEN", 0x1ac, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_scb_task_management_print; +#else +#define ahd_scb_task_management_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SCB_TASK_MANAGEMENT", 0x1ad, regvalue, cur_col, wrap) +#endif + +#if AIC_DEBUG_REGISTERS +ahd_reg_print_t ahd_scb_tag_print; +#else +#define ahd_scb_tag_print(regvalue, cur_col, wrap) \ + ahd_print_register(NULL, 0, "SCB_TAG", 0x1ae, regvalue, cur_col, wrap) #endif #if AIC_DEBUG_REGISTERS @@ -2367,6 +2360,7 @@ #define SPLTINT 0x01 #define SEQINTCODE 0x02 +#define BAD_SCB_STATUS 0x1a #define SAW_HWERR 0x19 #define TRACEPOINT3 0x18 #define TRACEPOINT2 0x17 @@ -3508,9 +3502,7 @@ #define LONGJMP_ADDR 0xf8 -#define LONGJMP_SCB 0xfa - -#define ACCUM_SAVE 0xfc +#define ACCUM_SAVE 0xfa #define WAITING_SCB_TAILS 0x100 @@ -3656,29 +3648,24 @@ #define SCB_SENSE_BUSADDR 0x18c #define SCB_NEXT_COMPLETE 0x18c -#define SCB_TAG 0x190 - -#define SCB_CDB_LEN 0x192 -#define SCB_CDB_LEN_PTR 0x80 - -#define SCB_TASK_MANAGEMENT 0x193 - -#define SCB_NEXT 0x194 -#define SCB_NEXT_SCB_BUSADDR 0x194 +#define SCB_DATAPTR 0x190 -#define SCB_NEXT2 0x196 - -#define SCB_DATAPTR 0x198 - -#define SCB_DATACNT 0x1a0 +#define SCB_DATACNT 0x198 #define SG_LAST_SEG 0x80 #define SG_HIGH_ADDR_BITS 0x7f -#define SCB_SGPTR 0x1a4 +#define SCB_SGPTR 0x19c #define SG_STATUS_VALID 0x04 #define SG_FULL_RESID 0x02 #define SG_LIST_NULL 0x01 +#define SCB_BUSADDR 0x1a0 + +#define SCB_NEXT 0x1a4 +#define SCB_NEXT_SCB_BUSADDR 0x1a4 + +#define SCB_NEXT2 0x1a6 + #define SCB_CONTROL 0x1a8 #define TARGET_SCB 0x80 #define DISCENB 0x40 @@ -3697,7 +3684,13 @@ #define SCB_TASK_ATTRIBUTE 0x1ab -#define SCB_BUSADDR 0x1ac +#define SCB_CDB_LEN 0x1ac +#define SCB_CDB_LEN_PTR 0x80 + +#define SCB_TASK_MANAGEMENT 0x1ad + +#define SCB_TAG 0x1ae +#define SCB_FIFO_USE_COUNT 0x1ae #define SCB_SPARE 0x1b0 #define SCB_PKT_LUN 0x1b0 @@ -3775,5 +3768,5 @@ /* Exported Labels */ -#define LABEL_seq_isr 0x26d -#define LABEL_timer_isr 0x269 +#define LABEL_seq_isr 0x270 +#define LABEL_timer_isr 0x26c diff -Nru a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped --- a/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped Thu May 15 15:24:32 2003 +++ b/drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped Thu May 15 15:24:32 2003 @@ -2,8 +2,8 @@ * DO NOT EDIT - This file is automatically generated * from the following source files: * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#89 $ - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#65 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#91 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#67 $ */ #include "aic79xx_osm.h" @@ -65,13 +65,14 @@ { "TRACEPOINT1", 0x16, 0xff }, { "TRACEPOINT2", 0x17, 0xff }, { "TRACEPOINT3", 0x18, 0xff }, - { "SAW_HWERR", 0x19, 0xff } + { "SAW_HWERR", 0x19, 0xff }, + { "BAD_SCB_STATUS", 0x1a, 0xff } }; int ahd_seqintcode_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(SEQINTCODE_parse_table, 26, "SEQINTCODE", + return (ahd_print_register(SEQINTCODE_parse_table, 27, "SEQINTCODE", 0x02, regvalue, cur_col, wrap)); } @@ -3098,17 +3099,10 @@ } int -ahd_longjmp_scb_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(NULL, 0, "LONGJMP_SCB", - 0xfa, regvalue, cur_col, wrap)); -} - -int ahd_accum_save_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "ACCUM_SAVE", - 0xfc, regvalue, cur_col, wrap)); + 0xfa, regvalue, cur_col, wrap)); } int @@ -3492,49 +3486,10 @@ } int -ahd_scb_tag_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(NULL, 0, "SCB_TAG", - 0x190, regvalue, cur_col, wrap)); -} - -static ahd_reg_parse_entry_t SCB_CDB_LEN_parse_table[] = { - { "SCB_CDB_LEN_PTR", 0x80, 0x80 } -}; - -int -ahd_scb_cdb_len_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(SCB_CDB_LEN_parse_table, 1, "SCB_CDB_LEN", - 0x192, regvalue, cur_col, wrap)); -} - -int -ahd_scb_task_management_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(NULL, 0, "SCB_TASK_MANAGEMENT", - 0x193, regvalue, cur_col, wrap)); -} - -int -ahd_scb_next_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(NULL, 0, "SCB_NEXT", - 0x194, regvalue, cur_col, wrap)); -} - -int -ahd_scb_next2_print(u_int regvalue, u_int *cur_col, u_int wrap) -{ - return (ahd_print_register(NULL, 0, "SCB_NEXT2", - 0x196, regvalue, cur_col, wrap)); -} - -int ahd_scb_dataptr_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(NULL, 0, "SCB_DATAPTR", - 0x198, regvalue, cur_col, wrap)); + 0x190, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t SCB_DATACNT_parse_table[] = { @@ -3546,7 +3501,7 @@ ahd_scb_datacnt_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(SCB_DATACNT_parse_table, 2, "SCB_DATACNT", - 0x1a0, regvalue, cur_col, wrap)); + 0x198, regvalue, cur_col, wrap)); } static ahd_reg_parse_entry_t SCB_SGPTR_parse_table[] = { @@ -3559,9 +3514,30 @@ ahd_scb_sgptr_print(u_int regvalue, u_int *cur_col, u_int wrap) { return (ahd_print_register(SCB_SGPTR_parse_table, 3, "SCB_SGPTR", + 0x19c, regvalue, cur_col, wrap)); +} + +int +ahd_scb_busaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "SCB_BUSADDR", + 0x1a0, regvalue, cur_col, wrap)); +} + +int +ahd_scb_next_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "SCB_NEXT", 0x1a4, regvalue, cur_col, wrap)); } +int +ahd_scb_next2_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "SCB_NEXT2", + 0x1a6, regvalue, cur_col, wrap)); +} + static ahd_reg_parse_entry_t SCB_CONTROL_parse_table[] = { { "SCB_TAG_TYPE", 0x03, 0x03 }, { "DISCONNECTED", 0x04, 0x04 }, @@ -3609,11 +3585,29 @@ 0x1ab, regvalue, cur_col, wrap)); } +static ahd_reg_parse_entry_t SCB_CDB_LEN_parse_table[] = { + { "SCB_CDB_LEN_PTR", 0x80, 0x80 } +}; + int -ahd_scb_busaddr_print(u_int regvalue, u_int *cur_col, u_int wrap) +ahd_scb_cdb_len_print(u_int regvalue, u_int *cur_col, u_int wrap) { - return (ahd_print_register(NULL, 0, "SCB_BUSADDR", + return (ahd_print_register(SCB_CDB_LEN_parse_table, 1, "SCB_CDB_LEN", 0x1ac, regvalue, cur_col, wrap)); +} + +int +ahd_scb_task_management_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "SCB_TASK_MANAGEMENT", + 0x1ad, regvalue, cur_col, wrap)); +} + +int +ahd_scb_tag_print(u_int regvalue, u_int *cur_col, u_int wrap) +{ + return (ahd_print_register(NULL, 0, "SCB_TAG", + 0x1ae, regvalue, cur_col, wrap)); } int diff -Nru a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped --- a/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped Thu May 15 15:24:45 2003 +++ b/drivers/scsi/aic7xxx/aic79xx_seq.h_shipped Thu May 15 15:24:45 2003 @@ -2,102 +2,104 @@ * DO NOT EDIT - This file is automatically generated * from the following source files: * - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#89 $ - * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#65 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#91 $ + * $Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#67 $ */ static uint8_t seqprog[] = { 0xff, 0x02, 0x06, 0x78, - 0x00, 0xea, 0x50, 0x59, + 0x00, 0xea, 0x4e, 0x59, 0x01, 0xea, 0x04, 0x30, 0xff, 0x04, 0x0c, 0x78, - 0x19, 0xea, 0x50, 0x59, + 0x19, 0xea, 0x4e, 0x59, 0x19, 0xea, 0x04, 0x00, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x42, 0x59, 0x33, 0xea, 0x00, 0x00, 0x60, 0x3a, 0x1a, 0x68, 0x04, 0x47, 0x1b, 0x68, 0xff, 0x21, 0x1b, 0x70, - 0x40, 0x4b, 0x92, 0x69, - 0x00, 0xe2, 0x54, 0x59, - 0x40, 0x4b, 0x92, 0x69, - 0x20, 0x4b, 0x82, 0x69, + 0x40, 0x4b, 0x90, 0x69, + 0x00, 0xe2, 0x52, 0x59, + 0x40, 0x4b, 0x90, 0x69, + 0x20, 0x4b, 0x80, 0x69, 0xfc, 0x42, 0x24, 0x78, 0x10, 0x40, 0x24, 0x78, - 0x00, 0xe2, 0xe0, 0x5d, + 0x00, 0xe2, 0xd2, 0x5d, 0x20, 0x4d, 0x28, 0x78, - 0x00, 0xe2, 0xe0, 0x5d, + 0x00, 0xe2, 0xd2, 0x5d, 0x30, 0x3f, 0xc0, 0x09, 0x30, 0xe0, 0x30, 0x60, 0x7f, 0x4a, 0x94, 0x08, 0x00, 0xe2, 0x32, 0x40, 0xc0, 0x4a, 0x94, 0x00, 0x00, 0xe2, 0x3e, 0x58, - 0x00, 0xe2, 0x70, 0x58, - 0x00, 0xe2, 0x80, 0x58, + 0x00, 0xe2, 0x56, 0x58, + 0x00, 0xe2, 0x66, 0x58, 0x00, 0xe2, 0x06, 0x40, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x42, 0x59, 0x33, 0xea, 0x00, 0x00, - 0x01, 0x52, 0x96, 0x7d, + 0x01, 0x52, 0x64, 0x78, 0x02, 0x58, 0x50, 0x31, 0xff, 0xea, 0x10, 0x0b, - 0xff, 0x93, 0x4f, 0x78, + 0xff, 0xad, 0x4f, 0x78, 0x50, 0x4b, 0x4a, 0x68, 0xbf, 0x3a, 0x74, 0x08, - 0x14, 0xea, 0x50, 0x59, + 0x14, 0xea, 0x4e, 0x59, 0x14, 0xea, 0x04, 0x00, 0x08, 0xa8, 0x51, 0x03, - 0x01, 0xa4, 0x57, 0x78, - 0x00, 0xe2, 0x4c, 0x5b, + 0xff, 0xae, 0x3f, 0x68, + 0x00, 0xe2, 0x50, 0x5b, 0x00, 0xe2, 0x3e, 0x40, - 0xff, 0xea, 0xd4, 0x19, - 0x02, 0xa8, 0x84, 0x32, - 0x00, 0xea, 0x44, 0x59, + 0x00, 0xea, 0x42, 0x59, 0x01, 0xea, 0x00, 0x30, - 0x00, 0xe2, 0xcc, 0x5d, - 0x00, 0xe2, 0x96, 0x4d, - 0x11, 0xea, 0x44, 0x59, + 0x80, 0xf9, 0x5e, 0x68, + 0x00, 0xe2, 0x40, 0x59, + 0x11, 0xea, 0x42, 0x59, 0x11, 0xea, 0x00, 0x00, - 0x00, 0xe2, 0xcc, 0x5d, - 0x00, 0xe2, 0x96, 0x4d, - 0x33, 0xea, 0x44, 0x59, - 0x33, 0xea, 0x00, 0x00, - 0x00, 0xe2, 0x44, 0x43, - 0x00, 0xea, 0x44, 0x59, - 0x01, 0xea, 0x00, 0x30, - 0x80, 0xf9, 0x78, 0x68, - 0x00, 0xe2, 0x42, 0x59, - 0x11, 0xea, 0x44, 0x59, - 0x11, 0xea, 0x00, 0x00, - 0x80, 0xf9, 0x42, 0x79, + 0x80, 0xf9, 0x40, 0x79, 0xff, 0xea, 0xd4, 0x0d, - 0x22, 0xea, 0x44, 0x59, + 0x22, 0xea, 0x42, 0x59, 0x22, 0xea, 0x00, 0x00, - 0x10, 0x16, 0x8a, 0x78, + 0x10, 0x16, 0x70, 0x78, 0x01, 0x0b, 0xa2, 0x32, 0x10, 0x16, 0x2c, 0x00, - 0x18, 0xad, 0xf8, 0x78, - 0x04, 0xad, 0xc6, 0x68, - 0x80, 0xad, 0x96, 0x7d, - 0x10, 0xad, 0x94, 0x78, - 0xe7, 0xad, 0x5a, 0x0d, + 0x18, 0xad, 0xfe, 0x78, + 0x04, 0xad, 0xca, 0x68, + 0x80, 0xad, 0x64, 0x78, + 0x10, 0xad, 0x98, 0x78, + 0xff, 0x88, 0x83, 0x68, + 0xe7, 0xad, 0x5a, 0x09, + 0x02, 0x8c, 0x59, 0x32, + 0x02, 0x28, 0x19, 0x33, + 0x02, 0xa8, 0x50, 0x36, + 0x33, 0xea, 0x42, 0x59, + 0x33, 0xea, 0x00, 0x00, + 0x40, 0x3a, 0x64, 0x68, + 0x50, 0x4b, 0x64, 0x68, + 0x22, 0xea, 0x42, 0x59, + 0x22, 0xea, 0x00, 0x00, 0xe7, 0xad, 0x5a, 0x09, - 0x00, 0xe2, 0xa2, 0x58, + 0x02, 0x8c, 0x59, 0x32, + 0x1a, 0xea, 0x4e, 0x59, + 0x1a, 0xea, 0x04, 0x00, + 0xff, 0xea, 0xd4, 0x0d, + 0xe7, 0xad, 0x5a, 0x09, + 0x00, 0xe2, 0xa6, 0x58, 0xff, 0xea, 0x56, 0x02, 0x04, 0x7c, 0x78, 0x32, - 0x20, 0x16, 0x96, 0x7d, + 0x20, 0x16, 0x64, 0x78, 0x04, 0x38, 0x79, 0x32, 0x80, 0x37, 0x6f, 0x16, - 0xff, 0x2d, 0xb1, 0x60, - 0xff, 0x29, 0xb1, 0x60, - 0x40, 0x51, 0xc1, 0x78, - 0xff, 0x4f, 0xb1, 0x68, + 0xff, 0x2d, 0xb5, 0x60, + 0xff, 0x29, 0xb5, 0x60, + 0x40, 0x51, 0xc5, 0x78, + 0xff, 0x4f, 0xb5, 0x68, 0xff, 0x4d, 0xc1, 0x19, 0x00, 0x4e, 0xd5, 0x19, - 0x00, 0xe2, 0xc0, 0x50, + 0x00, 0xe2, 0xc4, 0x50, 0x01, 0x4c, 0xc1, 0x31, 0x00, 0x50, 0xd5, 0x19, - 0x00, 0xe2, 0xc0, 0x48, - 0x80, 0x18, 0x96, 0x7d, + 0x00, 0xe2, 0xc4, 0x48, + 0x80, 0x18, 0x64, 0x78, 0x02, 0x4a, 0x1d, 0x30, 0x10, 0xea, 0x18, 0x00, 0x60, 0x18, 0x30, 0x00, @@ -105,35 +107,36 @@ 0x02, 0xea, 0x02, 0x00, 0xff, 0xea, 0xa0, 0x0a, 0x80, 0x18, 0x30, 0x04, - 0x40, 0xad, 0x96, 0x7d, + 0x40, 0xad, 0x64, 0x78, 0xe7, 0xad, 0x5a, 0x09, 0x02, 0xa8, 0x40, 0x31, 0xff, 0xea, 0xc0, 0x09, 0x01, 0x4e, 0x9d, 0x1a, 0x00, 0x4f, 0x9f, 0x22, - 0x04, 0x94, 0x49, 0x32, - 0xff, 0xea, 0x2a, 0x03, - 0xff, 0xea, 0x2e, 0x03, + 0x01, 0xea, 0x5c, 0x33, + 0x04, 0xa4, 0x49, 0x32, + 0xff, 0xea, 0x4a, 0x03, + 0xff, 0xea, 0x4e, 0x03, 0x01, 0x10, 0xd4, 0x31, - 0x10, 0xa8, 0xed, 0x68, + 0x10, 0xa8, 0xf3, 0x68, 0x3d, 0xa9, 0xc5, 0x29, 0xfe, 0xe2, 0xc4, 0x09, 0x01, 0xea, 0xc6, 0x01, 0x02, 0xe2, 0xc8, 0x31, 0x02, 0xec, 0x50, 0x31, 0x02, 0xa0, 0xda, 0x31, - 0xff, 0xa9, 0xec, 0x70, - 0x02, 0xa0, 0x28, 0x37, - 0xff, 0x21, 0xf5, 0x70, + 0xff, 0xa9, 0xf2, 0x70, + 0x02, 0xa0, 0x48, 0x37, + 0xff, 0x21, 0xfb, 0x70, 0x02, 0x22, 0x51, 0x31, - 0x02, 0xa0, 0x2c, 0x33, + 0x02, 0xa0, 0x4c, 0x33, 0x02, 0xa0, 0x44, 0x36, 0x02, 0xa0, 0x40, 0x32, 0x02, 0xa0, 0x44, 0x36, - 0x04, 0x47, 0xfd, 0x68, - 0x40, 0x16, 0x28, 0x69, - 0xff, 0x2d, 0x2d, 0x61, - 0xff, 0x29, 0x97, 0x75, + 0x04, 0x47, 0x03, 0x69, + 0x40, 0x16, 0x2e, 0x69, + 0xff, 0x2d, 0x33, 0x61, + 0xff, 0x29, 0x65, 0x70, 0x01, 0x37, 0xc1, 0x31, 0x02, 0x28, 0x55, 0x32, 0x01, 0xea, 0x5a, 0x01, @@ -145,11 +148,11 @@ 0x01, 0x50, 0xa1, 0x1a, 0xff, 0x4e, 0x9d, 0x1a, 0xff, 0x4f, 0x9f, 0x22, - 0xff, 0x8d, 0x21, 0x71, - 0x80, 0xac, 0x20, 0x71, - 0x20, 0x16, 0x20, 0x69, + 0xff, 0x8d, 0x27, 0x71, + 0x80, 0xac, 0x26, 0x71, + 0x20, 0x16, 0x26, 0x69, 0x02, 0x8c, 0x51, 0x31, - 0x00, 0xe2, 0x0a, 0x41, + 0x00, 0xe2, 0x10, 0x41, 0x01, 0xac, 0x08, 0x31, 0x09, 0xea, 0x5a, 0x01, 0x02, 0x8c, 0x51, 0x32, @@ -157,14 +160,10 @@ 0x04, 0x24, 0xf9, 0x30, 0x1d, 0xea, 0x38, 0x41, 0x02, 0x2c, 0x51, 0x31, - 0x04, 0xac, 0xf9, 0x30, - 0x19, 0xea, 0x38, 0x59, - 0x02, 0x8c, 0x59, 0x32, - 0x02, 0x28, 0x19, 0x33, - 0x02, 0xa8, 0x50, 0x36, + 0x04, 0xa0, 0xf9, 0x30, + 0x19, 0xea, 0x38, 0x41, 0x06, 0xea, 0x08, 0x81, 0x01, 0xe2, 0x5a, 0x35, - 0x02, 0xa8, 0xf4, 0x31, 0x02, 0xf2, 0xf0, 0x35, 0x02, 0xf2, 0xf0, 0x31, 0x02, 0xf8, 0xe4, 0x35, @@ -180,23 +179,23 @@ 0x02, 0x20, 0xb9, 0x30, 0x02, 0x20, 0x51, 0x31, 0x4c, 0xa9, 0xd7, 0x28, - 0x10, 0xa8, 0x63, 0x79, + 0x10, 0xa8, 0x61, 0x79, 0x01, 0x6b, 0xc0, 0x30, 0x02, 0x64, 0xc8, 0x00, 0x40, 0x3a, 0x74, 0x04, - 0x00, 0xe2, 0x70, 0x58, - 0x33, 0xea, 0x44, 0x59, + 0x00, 0xe2, 0x56, 0x58, + 0x33, 0xea, 0x42, 0x59, 0x33, 0xea, 0x00, 0x00, 0x30, 0x3f, 0xc0, 0x09, - 0x30, 0xe0, 0x64, 0x61, - 0x20, 0x3f, 0x7a, 0x69, - 0x10, 0x3f, 0x64, 0x79, + 0x30, 0xe0, 0x62, 0x61, + 0x20, 0x3f, 0x78, 0x69, + 0x10, 0x3f, 0x62, 0x79, 0x02, 0xea, 0x7e, 0x00, - 0x00, 0xea, 0x44, 0x59, + 0x00, 0xea, 0x42, 0x59, 0x01, 0xea, 0x00, 0x30, 0x02, 0x48, 0x51, 0x35, 0x01, 0xea, 0x7e, 0x00, - 0x11, 0xea, 0x44, 0x59, + 0x11, 0xea, 0x42, 0x59, 0x11, 0xea, 0x00, 0x00, 0x02, 0x48, 0x51, 0x35, 0x08, 0xea, 0x98, 0x00, @@ -206,11 +205,11 @@ 0x0f, 0x67, 0xc0, 0x09, 0x00, 0x34, 0x69, 0x02, 0x20, 0xea, 0x96, 0x00, - 0x00, 0xe2, 0xf8, 0x41, - 0x40, 0x3a, 0xae, 0x69, + 0x00, 0xe2, 0xf6, 0x41, + 0x40, 0x3a, 0xac, 0x69, 0x02, 0x55, 0x06, 0x68, - 0x02, 0x56, 0xae, 0x69, - 0xff, 0x5b, 0xae, 0x61, + 0x02, 0x56, 0xac, 0x69, + 0xff, 0x5b, 0xac, 0x61, 0x02, 0x20, 0x51, 0x31, 0x80, 0xea, 0xb2, 0x01, 0x44, 0xea, 0x00, 0x00, @@ -218,36 +217,36 @@ 0x33, 0xea, 0x00, 0x00, 0xff, 0xea, 0xb2, 0x09, 0xff, 0xe0, 0xc0, 0x19, - 0xff, 0xe0, 0xb0, 0x79, - 0x02, 0x94, 0x51, 0x31, - 0x00, 0xe2, 0xa6, 0x41, + 0xff, 0xe0, 0xae, 0x79, + 0x02, 0xa4, 0x51, 0x31, + 0x00, 0xe2, 0xa4, 0x41, 0x02, 0x5e, 0x50, 0x31, 0x02, 0xa8, 0xb8, 0x30, 0x02, 0x5c, 0x50, 0x31, - 0xff, 0x95, 0xc1, 0x71, - 0x02, 0x94, 0x41, 0x31, + 0xff, 0xa5, 0xbf, 0x71, + 0x02, 0xa4, 0x41, 0x31, 0x02, 0x22, 0x51, 0x31, - 0x02, 0xa0, 0x2c, 0x33, + 0x02, 0xa0, 0x4c, 0x33, 0x02, 0xa0, 0x44, 0x32, - 0x00, 0xe2, 0xca, 0x41, - 0x10, 0xa8, 0xcb, 0x69, + 0x00, 0xe2, 0xc8, 0x41, + 0x10, 0xa8, 0xc9, 0x69, 0x3d, 0xa9, 0xc9, 0x29, 0x01, 0xe4, 0xc8, 0x01, 0x01, 0xea, 0xca, 0x01, 0xff, 0xea, 0xda, 0x01, 0x02, 0x20, 0x51, 0x31, - 0x02, 0x96, 0x41, 0x32, - 0xff, 0x21, 0xd3, 0x61, + 0x02, 0xa6, 0x41, 0x32, + 0xff, 0x21, 0xd1, 0x61, 0xff, 0xea, 0x46, 0x02, 0x02, 0x5c, 0x50, 0x31, 0x40, 0xea, 0x96, 0x00, - 0x02, 0x56, 0xe8, 0x6d, - 0x01, 0x55, 0xe8, 0x6d, - 0x10, 0xa8, 0xdf, 0x79, - 0x10, 0x40, 0xe8, 0x69, - 0x01, 0x56, 0xe8, 0x79, - 0xff, 0x93, 0x07, 0x78, - 0x13, 0xea, 0x50, 0x59, + 0x02, 0x56, 0xda, 0x6d, + 0x01, 0x55, 0xda, 0x6d, + 0x10, 0xa8, 0xdd, 0x79, + 0x10, 0x40, 0xe6, 0x69, + 0x01, 0x56, 0xe6, 0x79, + 0xff, 0xad, 0x07, 0x78, + 0x13, 0xea, 0x4e, 0x59, 0x13, 0xea, 0x04, 0x00, 0x00, 0xe2, 0x06, 0x40, 0xbf, 0x3a, 0x74, 0x08, @@ -258,104 +257,104 @@ 0x40, 0xea, 0x66, 0x02, 0x08, 0x3c, 0x78, 0x00, 0x80, 0xea, 0x62, 0x02, - 0x00, 0xe2, 0xac, 0x5b, + 0x00, 0xe2, 0xb2, 0x5b, 0x01, 0x36, 0xc1, 0x31, - 0x9f, 0xe0, 0x4e, 0x7c, - 0x80, 0xe0, 0x0c, 0x72, - 0xa0, 0xe0, 0x44, 0x72, - 0xc0, 0xe0, 0x3a, 0x72, - 0xe0, 0xe0, 0x74, 0x72, - 0x01, 0xea, 0x50, 0x59, + 0x9f, 0xe0, 0x54, 0x7c, + 0x80, 0xe0, 0x0a, 0x72, + 0xa0, 0xe0, 0x42, 0x72, + 0xc0, 0xe0, 0x38, 0x72, + 0xe0, 0xe0, 0x72, 0x72, + 0x01, 0xea, 0x4e, 0x59, 0x01, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xf8, 0x41, - 0x80, 0x33, 0x13, 0x7a, - 0x03, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0xf6, 0x41, + 0x80, 0x33, 0x11, 0x7a, + 0x03, 0xea, 0x4e, 0x59, 0x03, 0xea, 0x04, 0x00, - 0xee, 0x00, 0x1a, 0x6a, + 0xee, 0x00, 0x18, 0x6a, 0x05, 0xea, 0xb4, 0x00, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x42, 0x59, 0x33, 0xea, 0x00, 0x00, 0x02, 0xa8, 0x90, 0x32, - 0x00, 0xe2, 0x6a, 0x59, - 0xef, 0x92, 0xd5, 0x19, - 0x00, 0xe2, 0x2a, 0x52, + 0x00, 0xe2, 0x68, 0x59, + 0xef, 0xac, 0xd5, 0x19, + 0x00, 0xe2, 0x28, 0x52, 0x09, 0x80, 0xe1, 0x30, 0x02, 0xea, 0x36, 0x00, 0xa8, 0xea, 0x32, 0x00, - 0x00, 0xe2, 0x30, 0x42, - 0x01, 0x92, 0xd1, 0x30, + 0x00, 0xe2, 0x2e, 0x42, + 0x01, 0xac, 0xd1, 0x30, 0x10, 0x80, 0x89, 0x31, 0x20, 0xea, 0x32, 0x00, 0xbf, 0x33, 0x67, 0x0a, - 0x20, 0x19, 0x32, 0x6a, - 0x02, 0x4d, 0xf8, 0x69, + 0x20, 0x19, 0x30, 0x6a, + 0x02, 0x4d, 0xf6, 0x69, 0x40, 0x33, 0x67, 0x02, - 0x00, 0xe2, 0xf8, 0x41, - 0x80, 0x33, 0xb1, 0x6a, + 0x00, 0xe2, 0xf6, 0x41, + 0x80, 0x33, 0xaf, 0x6a, 0x01, 0x44, 0x10, 0x33, 0x08, 0xa8, 0x51, 0x03, - 0x00, 0xe2, 0xf8, 0x41, + 0x00, 0xe2, 0xf6, 0x41, 0x10, 0xea, 0x80, 0x00, 0x01, 0x31, 0xc5, 0x31, - 0x80, 0xe2, 0x60, 0x62, - 0x10, 0xa8, 0x85, 0x6a, + 0x80, 0xe2, 0x5e, 0x62, + 0x10, 0xa8, 0x83, 0x6a, 0xc0, 0xaa, 0xc5, 0x01, - 0x40, 0xa8, 0x51, 0x6a, + 0x40, 0xa8, 0x4f, 0x6a, 0xbf, 0xe2, 0xc4, 0x09, - 0x20, 0xa8, 0x65, 0x7a, + 0x20, 0xa8, 0x63, 0x7a, 0x01, 0xe2, 0x88, 0x30, - 0x00, 0xe2, 0xac, 0x5b, - 0xa0, 0x36, 0x6d, 0x62, + 0x00, 0xe2, 0xb2, 0x5b, + 0xa0, 0x36, 0x6b, 0x62, 0x23, 0xa8, 0x89, 0x08, - 0x00, 0xe2, 0xac, 0x5b, - 0xa0, 0x36, 0x6d, 0x62, - 0x00, 0xa8, 0x64, 0x42, - 0xff, 0xe2, 0x64, 0x62, - 0x00, 0xe2, 0x84, 0x42, + 0x00, 0xe2, 0xb2, 0x5b, + 0xa0, 0x36, 0x6b, 0x62, + 0x00, 0xa8, 0x62, 0x42, + 0xff, 0xe2, 0x62, 0x62, + 0x00, 0xe2, 0x82, 0x42, 0x40, 0xea, 0x98, 0x00, 0x01, 0xe2, 0x88, 0x30, - 0x00, 0xe2, 0xac, 0x5b, - 0xa0, 0x36, 0x43, 0x72, + 0x00, 0xe2, 0xb2, 0x5b, + 0xa0, 0x36, 0x41, 0x72, 0x40, 0xea, 0x98, 0x00, 0x01, 0x31, 0x89, 0x32, 0x08, 0xea, 0x62, 0x02, - 0x00, 0xe2, 0xf8, 0x41, - 0xe0, 0xea, 0xc8, 0x5b, - 0x80, 0xe0, 0xbc, 0x6a, - 0x04, 0xe0, 0x5a, 0x73, - 0x02, 0xe0, 0x8a, 0x73, - 0x00, 0xea, 0x1a, 0x73, - 0x03, 0xe0, 0x9a, 0x73, - 0x23, 0xe0, 0x96, 0x72, - 0x08, 0xe0, 0xb8, 0x72, - 0x00, 0xe2, 0xac, 0x5b, - 0x07, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0xf6, 0x41, + 0xe0, 0xea, 0xce, 0x5b, + 0x80, 0xe0, 0xba, 0x6a, + 0x04, 0xe0, 0x60, 0x73, + 0x02, 0xe0, 0x90, 0x73, + 0x00, 0xea, 0x18, 0x73, + 0x03, 0xe0, 0xa0, 0x73, + 0x23, 0xe0, 0x94, 0x72, + 0x08, 0xe0, 0xb6, 0x72, + 0x00, 0xe2, 0xb2, 0x5b, + 0x07, 0xea, 0x4e, 0x59, 0x07, 0xea, 0x04, 0x00, - 0x08, 0x42, 0xf9, 0x71, - 0x04, 0x42, 0x93, 0x62, + 0x08, 0x42, 0xf7, 0x71, + 0x04, 0x42, 0x91, 0x62, 0x01, 0x43, 0x89, 0x30, - 0x00, 0xe2, 0x84, 0x42, + 0x00, 0xe2, 0x82, 0x42, 0x01, 0x44, 0xd4, 0x31, - 0x00, 0xe2, 0x84, 0x42, + 0x00, 0xe2, 0x82, 0x42, 0x01, 0x00, 0x60, 0x32, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x42, 0x59, 0x33, 0xea, 0x00, 0x00, 0x4c, 0x34, 0xc1, 0x28, 0x01, 0x64, 0xc0, 0x31, - 0x00, 0x30, 0x45, 0x59, + 0x00, 0x30, 0x43, 0x59, 0x01, 0x30, 0x01, 0x30, - 0x01, 0xe0, 0xb6, 0x7a, - 0xa0, 0xea, 0xbe, 0x5b, - 0x01, 0xa0, 0xb6, 0x62, - 0x01, 0x84, 0xaf, 0x7a, - 0x01, 0xa7, 0xb8, 0x7a, - 0x00, 0xe2, 0xb8, 0x42, - 0x03, 0xea, 0x50, 0x59, + 0x01, 0xe0, 0xb4, 0x7a, + 0xa0, 0xea, 0xc4, 0x5b, + 0x01, 0xa0, 0xb4, 0x62, + 0x01, 0x84, 0xad, 0x7a, + 0x01, 0xa7, 0xb6, 0x7a, + 0x00, 0xe2, 0xb6, 0x42, + 0x03, 0xea, 0x4e, 0x59, 0x03, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xb8, 0x42, - 0x07, 0xea, 0xd0, 0x5b, + 0x00, 0xe2, 0xb6, 0x42, + 0x07, 0xea, 0xd6, 0x5b, 0x01, 0x44, 0xd4, 0x31, - 0x00, 0xe2, 0xf8, 0x41, + 0x00, 0xe2, 0xf6, 0x41, 0x3f, 0xe0, 0x6a, 0x0a, 0xc0, 0x34, 0xc1, 0x09, 0x00, 0x35, 0x51, 0x01, @@ -366,78 +365,82 @@ 0x01, 0xea, 0xc6, 0x01, 0x02, 0xe2, 0xc8, 0x31, 0x02, 0xec, 0x40, 0x31, - 0xff, 0xa1, 0xd8, 0x72, + 0xff, 0xa1, 0xd6, 0x72, 0x02, 0xe8, 0xda, 0x31, 0x02, 0xa0, 0x50, 0x31, - 0x00, 0xe2, 0xfa, 0x42, + 0x00, 0xe2, 0xf8, 0x42, 0x80, 0x33, 0x67, 0x02, 0x01, 0x44, 0xd4, 0x31, - 0x00, 0xe2, 0xac, 0x5b, + 0x00, 0xe2, 0xb2, 0x5b, 0x01, 0x33, 0x67, 0x02, - 0xe0, 0x36, 0x15, 0x63, + 0xe0, 0x36, 0x13, 0x63, 0x02, 0x33, 0x67, 0x02, - 0x20, 0x46, 0x0e, 0x63, + 0x20, 0x46, 0x0c, 0x63, 0xff, 0xea, 0x52, 0x09, - 0xa8, 0xea, 0xbe, 0x5b, - 0x04, 0xa8, 0xf5, 0x7a, + 0xa8, 0xea, 0xc4, 0x5b, + 0x04, 0xa8, 0xf3, 0x7a, 0x01, 0x34, 0xc1, 0x31, - 0x00, 0xa9, 0xf5, 0x62, + 0x00, 0xa9, 0xf3, 0x62, 0x01, 0x35, 0xc1, 0x31, - 0x00, 0xaa, 0xff, 0x72, + 0x00, 0xaa, 0xfd, 0x72, 0x01, 0xa9, 0x52, 0x11, - 0xff, 0xa9, 0xea, 0x6a, - 0x00, 0xe2, 0x0e, 0x43, + 0xff, 0xa9, 0xe8, 0x6a, + 0x00, 0xe2, 0x0c, 0x43, 0x10, 0x33, 0x67, 0x02, - 0x04, 0xa8, 0x0f, 0x7b, + 0x04, 0xa8, 0x0d, 0x7b, 0xfb, 0xa8, 0x51, 0x0b, 0xff, 0xea, 0x66, 0x0a, - 0x01, 0xa4, 0x09, 0x6b, + 0x01, 0x9c, 0x07, 0x6b, 0x02, 0xa8, 0x90, 0x32, - 0x00, 0xe2, 0x6a, 0x59, - 0x10, 0xa8, 0xb9, 0x7a, - 0xff, 0xea, 0xd0, 0x5b, - 0x00, 0xe2, 0xb8, 0x42, - 0x04, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0x68, 0x59, + 0x10, 0xa8, 0xb7, 0x7a, + 0xff, 0xea, 0xd6, 0x5b, + 0x00, 0xe2, 0xb6, 0x42, + 0x04, 0xea, 0x4e, 0x59, 0x04, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xb8, 0x42, - 0x04, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0xb6, 0x42, + 0x04, 0xea, 0x4e, 0x59, 0x04, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xf8, 0x41, - 0x08, 0xa8, 0xb1, 0x7a, - 0xc0, 0x33, 0x25, 0x7b, - 0x80, 0x33, 0xb1, 0x6a, - 0xff, 0x88, 0x25, 0x6b, - 0x40, 0x33, 0xb1, 0x6a, - 0x10, 0xa8, 0x2b, 0x7b, - 0x0a, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0xf6, 0x41, + 0x08, 0xa8, 0xaf, 0x7a, + 0xc0, 0x33, 0x23, 0x7b, + 0x80, 0x33, 0xaf, 0x6a, + 0xff, 0x88, 0x23, 0x6b, + 0x40, 0x33, 0xaf, 0x6a, + 0x10, 0xa8, 0x29, 0x7b, + 0x0a, 0xea, 0x4e, 0x59, 0x0a, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x44, 0x5b, - 0x00, 0xe2, 0x76, 0x43, - 0x50, 0x4b, 0x32, 0x6b, + 0x00, 0xe2, 0x48, 0x5b, + 0x00, 0xe2, 0x7c, 0x43, + 0x50, 0x4b, 0x30, 0x6b, 0xbf, 0x3a, 0x74, 0x08, - 0x01, 0xe0, 0xf8, 0x31, + 0x01, 0xe0, 0xf4, 0x31, 0xff, 0xea, 0xc0, 0x09, 0x01, 0x2e, 0x5d, 0x1a, 0x00, 0x2f, 0x5f, 0x22, 0x04, 0x47, 0x8f, 0x02, - 0x01, 0xfc, 0xc0, 0x35, - 0x33, 0xea, 0x44, 0x59, + 0x01, 0xfa, 0xc0, 0x35, + 0x02, 0xa8, 0x84, 0x32, + 0x02, 0xea, 0xb4, 0x00, + 0x33, 0xea, 0x42, 0x59, 0x33, 0xea, 0x00, 0x00, 0x02, 0x42, 0x51, 0x31, - 0xff, 0x88, 0x51, 0x6b, - 0x01, 0xa4, 0x4d, 0x6b, - 0x02, 0xa4, 0x55, 0x6b, - 0x01, 0x84, 0x55, 0x7b, + 0xff, 0xae, 0x65, 0x68, + 0xff, 0x88, 0x55, 0x6b, + 0x01, 0x9c, 0x51, 0x6b, + 0x02, 0x9c, 0x59, 0x6b, + 0x01, 0x84, 0x59, 0x7b, 0x02, 0x28, 0x19, 0x33, 0x02, 0xa8, 0x50, 0x36, - 0xff, 0x88, 0x55, 0x73, - 0x00, 0xe2, 0x2e, 0x5b, + 0xff, 0x88, 0x59, 0x73, + 0x00, 0xe2, 0x2c, 0x5b, + 0x02, 0xa8, 0x5c, 0x33, 0x02, 0x2c, 0x19, 0x33, 0x02, 0xa8, 0x58, 0x32, - 0x04, 0xa4, 0x49, 0x07, - 0xc0, 0x33, 0xb1, 0x6a, + 0x04, 0x9c, 0x39, 0x07, + 0xc0, 0x33, 0xaf, 0x6a, 0x04, 0xa8, 0x51, 0x03, - 0x20, 0xa8, 0x77, 0x6b, + 0x20, 0xa8, 0x7d, 0x6b, 0x02, 0xa8, 0x40, 0x31, 0xc0, 0x34, 0xc1, 0x09, 0x00, 0x35, 0x51, 0x01, @@ -452,73 +455,73 @@ 0xf7, 0x57, 0xae, 0x08, 0x08, 0xea, 0x98, 0x00, 0x01, 0x44, 0xd4, 0x31, - 0xee, 0x00, 0x80, 0x6b, + 0xee, 0x00, 0x86, 0x6b, 0x02, 0xea, 0xb4, 0x00, - 0x00, 0xe2, 0xa8, 0x5b, - 0x09, 0x4c, 0x82, 0x7b, + 0x00, 0xe2, 0xae, 0x5b, + 0x09, 0x4c, 0x88, 0x7b, 0x08, 0x4c, 0x06, 0x68, - 0x0b, 0xea, 0x50, 0x59, + 0x0b, 0xea, 0x4e, 0x59, 0x0b, 0xea, 0x04, 0x00, 0x01, 0x44, 0xd4, 0x31, - 0x20, 0x33, 0xf9, 0x79, - 0x00, 0xe2, 0x92, 0x5b, - 0x00, 0xe2, 0xf8, 0x41, - 0x01, 0x84, 0x97, 0x7b, - 0x01, 0xa4, 0x49, 0x07, - 0x08, 0x60, 0x30, 0x33, - 0x08, 0x80, 0x41, 0x37, + 0x20, 0x33, 0xf7, 0x79, + 0x00, 0xe2, 0x98, 0x5b, + 0x00, 0xe2, 0xf6, 0x41, + 0x01, 0x84, 0x9d, 0x7b, + 0x01, 0x9c, 0x39, 0x07, + 0x08, 0x60, 0x20, 0x33, + 0x08, 0x80, 0x31, 0x37, 0xdf, 0x33, 0x67, 0x0a, - 0xee, 0x00, 0xa4, 0x6b, + 0xee, 0x00, 0xaa, 0x6b, 0x05, 0xea, 0xb4, 0x00, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x42, 0x59, 0x33, 0xea, 0x00, 0x00, - 0x00, 0xe2, 0x6a, 0x59, - 0x00, 0xe2, 0xb8, 0x42, + 0x00, 0xe2, 0x68, 0x59, + 0x00, 0xe2, 0xb6, 0x42, 0x01, 0xea, 0x6c, 0x02, 0xc0, 0xea, 0x66, 0x06, - 0xff, 0x42, 0xb8, 0x6b, - 0x01, 0x41, 0xac, 0x6b, - 0x02, 0x41, 0xac, 0x7b, - 0xff, 0x42, 0xb8, 0x6b, - 0x01, 0x41, 0xac, 0x6b, - 0x02, 0x41, 0xac, 0x7b, - 0xff, 0x42, 0xb8, 0x7b, - 0x04, 0x4c, 0xac, 0x6b, + 0xff, 0x42, 0xbe, 0x6b, + 0x01, 0x41, 0xb2, 0x6b, + 0x02, 0x41, 0xb2, 0x7b, + 0xff, 0x42, 0xbe, 0x6b, + 0x01, 0x41, 0xb2, 0x6b, + 0x02, 0x41, 0xb2, 0x7b, + 0xff, 0x42, 0xbe, 0x7b, + 0x04, 0x4c, 0xb2, 0x6b, 0xe0, 0x41, 0x6c, 0x0e, 0x01, 0x44, 0xd4, 0x31, - 0xff, 0x42, 0xc0, 0x7b, - 0x04, 0x4c, 0xc0, 0x6b, + 0xff, 0x42, 0xc6, 0x7b, + 0x04, 0x4c, 0xc6, 0x6b, 0xe0, 0x41, 0x6c, 0x0a, - 0xe0, 0x36, 0xf9, 0x61, + 0xe0, 0x36, 0xf7, 0x61, 0xff, 0xea, 0xca, 0x09, 0x01, 0xe2, 0xc8, 0x31, 0x01, 0x46, 0xda, 0x35, 0x01, 0x44, 0xd4, 0x35, 0x10, 0xea, 0x80, 0x00, 0x01, 0xe2, 0x62, 0x36, - 0x04, 0xa6, 0xd8, 0x7b, + 0x04, 0xa6, 0xde, 0x7b, 0xff, 0xea, 0x5a, 0x09, 0xff, 0xea, 0x4c, 0x0d, - 0x01, 0xa6, 0xf6, 0x6b, - 0x10, 0xad, 0x96, 0x7d, - 0x80, 0xad, 0xee, 0x6b, - 0x08, 0xad, 0x96, 0x6d, + 0x01, 0xa6, 0xfc, 0x6b, + 0x10, 0xad, 0x64, 0x78, + 0x80, 0xad, 0xf4, 0x6b, + 0x08, 0xad, 0x64, 0x68, 0x04, 0x84, 0xf9, 0x30, 0x00, 0xea, 0x08, 0x81, 0xff, 0xea, 0xd4, 0x09, 0x02, 0x84, 0xf9, 0x88, 0x0d, 0xea, 0x5a, 0x01, 0x04, 0xa6, 0x4c, 0x05, - 0x04, 0xa6, 0x96, 0x7d, + 0x04, 0xa6, 0x64, 0x78, 0xff, 0xea, 0x5a, 0x09, 0x03, 0x84, 0x59, 0x89, 0x03, 0xea, 0x4c, 0x01, - 0x80, 0x1a, 0x96, 0x7d, - 0x08, 0x19, 0x96, 0x7d, + 0x80, 0x1a, 0x64, 0x78, + 0x08, 0x19, 0x64, 0x78, 0x08, 0xb0, 0xe0, 0x30, 0x04, 0xb0, 0xe0, 0x30, 0x03, 0xb0, 0xf0, 0x30, - 0x01, 0x78, 0x04, 0x7c, + 0x01, 0x78, 0x0a, 0x7c, 0x01, 0xa7, 0x4e, 0x11, 0x01, 0xb0, 0x06, 0x33, 0x7f, 0x83, 0xe9, 0x08, @@ -529,275 +532,268 @@ 0x00, 0x86, 0x0d, 0x23, 0x00, 0x87, 0x0f, 0x23, 0x01, 0x84, 0xc5, 0x31, - 0x01, 0xa7, 0x1a, 0x7c, + 0x01, 0xa7, 0x20, 0x7c, 0x04, 0xe2, 0xc4, 0x01, - 0x80, 0x83, 0x21, 0x7c, + 0x80, 0x83, 0x27, 0x7c, 0x02, 0xe2, 0xc4, 0x01, 0xff, 0xea, 0x4c, 0x09, 0x01, 0xe2, 0x36, 0x30, 0xc8, 0x19, 0x32, 0x00, 0x88, 0x19, 0x32, 0x00, 0x01, 0xac, 0xd4, 0x99, - 0x00, 0xe2, 0x96, 0x55, + 0x00, 0xe2, 0x64, 0x50, 0xfe, 0xa6, 0x4c, 0x0d, - 0x0b, 0x98, 0xe1, 0x30, - 0x01, 0xa0, 0x4f, 0x09, - 0xfd, 0xa4, 0x49, 0x09, - 0x80, 0xa3, 0x37, 0x7c, + 0x0b, 0x90, 0xe1, 0x30, + 0x01, 0x98, 0x4f, 0x09, + 0xfd, 0x9c, 0x49, 0x09, + 0x80, 0x9b, 0x3d, 0x7c, 0x02, 0xa4, 0x48, 0x01, - 0x01, 0xa7, 0x3a, 0x7c, + 0x01, 0xa7, 0x40, 0x7c, 0x04, 0xa4, 0x48, 0x01, 0x01, 0xa4, 0x36, 0x30, 0xa8, 0xea, 0x32, 0x00, - 0xfd, 0xa4, 0x49, 0x0b, - 0x05, 0xa3, 0x07, 0x33, - 0x80, 0x83, 0x47, 0x6c, + 0xfd, 0x9c, 0x39, 0x0b, + 0x05, 0x9b, 0x07, 0x33, + 0x80, 0x83, 0x4d, 0x6c, 0x02, 0xea, 0x4c, 0x05, 0xff, 0xea, 0x4c, 0x0d, 0x00, 0xe2, 0x3c, 0x59, - 0x02, 0xa6, 0xda, 0x6b, + 0x02, 0xa6, 0xe0, 0x6b, 0x80, 0xf9, 0xf2, 0x05, - 0xc0, 0x33, 0x55, 0x7c, - 0x03, 0xea, 0x50, 0x59, + 0xc0, 0x33, 0x5b, 0x7c, + 0x03, 0xea, 0x4e, 0x59, 0x03, 0xea, 0x04, 0x00, - 0x20, 0x33, 0x79, 0x7c, - 0x01, 0x84, 0x5f, 0x6c, - 0x06, 0xea, 0x50, 0x59, + 0x20, 0x33, 0x7f, 0x7c, + 0x01, 0x84, 0x65, 0x6c, + 0x06, 0xea, 0x4e, 0x59, 0x06, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x7c, 0x44, + 0x00, 0xe2, 0x82, 0x44, 0x01, 0x00, 0x60, 0x32, - 0xee, 0x00, 0x68, 0x6c, + 0xee, 0x00, 0x6e, 0x6c, 0x05, 0xea, 0xb4, 0x00, - 0x33, 0xea, 0x44, 0x59, + 0x33, 0xea, 0x42, 0x59, 0x33, 0xea, 0x00, 0x00, 0x80, 0x3d, 0x7a, 0x00, - 0xfc, 0x42, 0x6a, 0x7c, + 0xfc, 0x42, 0x70, 0x7c, 0x7f, 0x3d, 0x7a, 0x08, - 0x00, 0x30, 0x45, 0x59, + 0x00, 0x30, 0x43, 0x59, 0x01, 0x30, 0x01, 0x30, - 0x09, 0xea, 0x50, 0x59, + 0x09, 0xea, 0x4e, 0x59, 0x09, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xf8, 0x41, - 0x01, 0xa4, 0x5f, 0x6c, - 0x00, 0xe2, 0x2c, 0x5c, + 0x00, 0xe2, 0xf6, 0x41, + 0x01, 0x9c, 0x65, 0x6c, + 0x00, 0xe2, 0x32, 0x5c, 0x20, 0x33, 0x67, 0x02, 0x01, 0x00, 0x60, 0x32, - 0x02, 0xa6, 0x84, 0x7c, - 0x00, 0xe2, 0x48, 0x5c, - 0x00, 0xe2, 0x70, 0x58, - 0x00, 0xe2, 0x80, 0x58, + 0x02, 0xa6, 0x8a, 0x7c, + 0x00, 0xe2, 0x4e, 0x5c, + 0x00, 0xe2, 0x56, 0x58, + 0x00, 0xe2, 0x66, 0x58, 0x00, 0xe2, 0x3a, 0x58, - 0x00, 0x30, 0x45, 0x59, + 0x00, 0x30, 0x43, 0x59, 0x01, 0x30, 0x01, 0x30, - 0x20, 0x19, 0x84, 0x6c, - 0x00, 0xe2, 0xb4, 0x5c, - 0x04, 0x19, 0x9e, 0x6c, + 0x20, 0x19, 0x8a, 0x6c, + 0x00, 0xe2, 0xba, 0x5c, + 0x04, 0x19, 0xa4, 0x6c, 0x02, 0x19, 0x32, 0x00, - 0x01, 0x84, 0x9f, 0x7c, - 0x01, 0x1b, 0x98, 0x7c, - 0x01, 0x1a, 0x9e, 0x6c, - 0x00, 0xe2, 0x4e, 0x44, - 0x80, 0x4b, 0xa4, 0x6c, - 0x01, 0x4c, 0xa0, 0x7c, - 0x03, 0x42, 0x4e, 0x6c, - 0x00, 0xe2, 0xd4, 0x5b, + 0x01, 0x84, 0xa5, 0x7c, + 0x01, 0x1b, 0x9e, 0x7c, + 0x01, 0x1a, 0xa4, 0x6c, + 0x00, 0xe2, 0x54, 0x44, + 0x80, 0x4b, 0xaa, 0x6c, + 0x01, 0x4c, 0xa6, 0x7c, + 0x03, 0x42, 0x54, 0x6c, + 0x00, 0xe2, 0xda, 0x5b, 0x80, 0xf9, 0xf2, 0x01, - 0x04, 0x33, 0xf9, 0x79, - 0x00, 0xe2, 0xf8, 0x41, - 0x08, 0x5d, 0xbc, 0x6c, - 0x00, 0xe2, 0x70, 0x58, - 0x00, 0x30, 0x45, 0x59, + 0x04, 0x33, 0xf7, 0x79, + 0x00, 0xe2, 0xf6, 0x41, + 0x08, 0x5d, 0xc2, 0x6c, + 0x00, 0xe2, 0x56, 0x58, + 0x00, 0x30, 0x43, 0x59, 0x01, 0x30, 0x01, 0x30, - 0x02, 0x1b, 0xac, 0x7c, - 0x08, 0x5d, 0xba, 0x7c, + 0x02, 0x1b, 0xb2, 0x7c, + 0x08, 0x5d, 0xc0, 0x7c, 0x03, 0x68, 0x00, 0x37, 0x01, 0x84, 0x09, 0x07, - 0x80, 0x1b, 0xc6, 0x7c, - 0x80, 0x84, 0xc7, 0x6c, + 0x80, 0x1b, 0xcc, 0x7c, + 0x80, 0x84, 0xcd, 0x6c, 0xff, 0x85, 0x0b, 0x1b, 0xff, 0x86, 0x0d, 0x23, 0xff, 0x87, 0x0f, 0x23, 0xf8, 0x1b, 0x08, 0x0b, 0xff, 0xea, 0x4e, 0x09, - 0x04, 0x1b, 0xce, 0x7c, + 0x04, 0x1b, 0xd4, 0x7c, 0x01, 0xa7, 0x4e, 0x01, 0xff, 0xea, 0x06, 0x0b, 0x03, 0x68, 0x00, 0x37, - 0x00, 0xe2, 0xc0, 0x58, + 0x00, 0xe2, 0xc4, 0x58, 0x10, 0xea, 0x18, 0x00, 0xf9, 0xd9, 0xb2, 0x0d, 0x01, 0xd9, 0xb2, 0x05, 0x01, 0x52, 0x48, 0x31, - 0x20, 0xa4, 0xf2, 0x7c, - 0x20, 0x5b, 0xf2, 0x7c, - 0x80, 0xf9, 0x00, 0x7d, + 0x20, 0xa4, 0xfc, 0x7c, + 0x20, 0x5b, 0xfc, 0x7c, + 0x80, 0xf9, 0x0a, 0x7d, + 0x02, 0xea, 0xb4, 0x00, 0x11, 0x00, 0x00, 0x10, - 0x04, 0x19, 0xec, 0x7c, + 0x04, 0x19, 0x16, 0x7d, 0xdf, 0x19, 0x32, 0x08, - 0x01, 0x4c, 0xe8, 0x7c, + 0x60, 0x5b, 0xf4, 0x6c, + 0x01, 0x4c, 0xf0, 0x7c, 0x20, 0x19, 0x32, 0x00, - 0x11, 0x00, 0x00, 0x10, + 0x01, 0xd9, 0xb2, 0x05, 0x02, 0xea, 0xb4, 0x00, 0x01, 0xd9, 0xb2, 0x05, - 0x10, 0x5b, 0x04, 0x6d, - 0x08, 0x5b, 0x0c, 0x6d, - 0x20, 0x5b, 0xfe, 0x6c, - 0x02, 0x5b, 0x2c, 0x6d, - 0x0e, 0xea, 0x50, 0x59, + 0x10, 0x5b, 0x0e, 0x6d, + 0x08, 0x5b, 0x18, 0x6d, + 0x20, 0x5b, 0x08, 0x6d, + 0x02, 0x5b, 0x38, 0x6d, + 0x0e, 0xea, 0x4e, 0x59, 0x0e, 0xea, 0x04, 0x00, - 0x80, 0xf9, 0xee, 0x6c, + 0x80, 0xf9, 0xf8, 0x6c, 0xdf, 0x5c, 0xb8, 0x08, 0x01, 0xd9, 0xb2, 0x05, - 0x01, 0xa4, 0xff, 0x6d, - 0x00, 0xe2, 0x2c, 0x5c, - 0x00, 0xe2, 0x36, 0x5d, + 0x01, 0x9c, 0xf3, 0x6d, + 0x00, 0xe2, 0x32, 0x5c, + 0x00, 0xe2, 0x42, 0x5d, + 0x01, 0xae, 0x5d, 0x1b, 0x01, 0xd9, 0xb2, 0x05, - 0x00, 0xe2, 0x2e, 0x5b, - 0xf3, 0x92, 0xd5, 0x19, - 0x00, 0xe2, 0x1a, 0x55, - 0x80, 0x92, 0x1b, 0x6d, - 0x0f, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0x2c, 0x5b, + 0xf3, 0xac, 0xd5, 0x19, + 0x00, 0xe2, 0x26, 0x55, + 0x80, 0xac, 0x27, 0x6d, + 0x0f, 0xea, 0x4e, 0x59, 0x0f, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x22, 0x45, + 0x00, 0xe2, 0x2e, 0x45, 0x04, 0x8c, 0xe1, 0x30, 0x01, 0xea, 0xf2, 0x00, 0x02, 0xea, 0x36, 0x00, 0xa8, 0xea, 0x32, 0x00, - 0xff, 0x93, 0x29, 0x7d, - 0x14, 0xea, 0x50, 0x59, + 0xff, 0xad, 0x35, 0x7d, + 0x14, 0xea, 0x4e, 0x59, 0x14, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xb0, 0x5d, + 0x00, 0xe2, 0xa4, 0x5d, 0x01, 0xd9, 0xb2, 0x05, 0x09, 0x80, 0xe1, 0x30, 0x02, 0xea, 0x36, 0x00, 0xa8, 0xea, 0x32, 0x00, - 0x00, 0xe2, 0xd8, 0x5d, + 0x00, 0xe2, 0x9c, 0x5d, 0x01, 0xd9, 0xb2, 0x05, - 0x02, 0xa8, 0xf4, 0x31, - 0x02, 0xa6, 0x48, 0x7d, - 0x00, 0xe2, 0x3e, 0x59, - 0x20, 0x5b, 0x56, 0x6d, - 0xfc, 0x42, 0x42, 0x7d, - 0x10, 0x40, 0x44, 0x6d, - 0x20, 0x4d, 0x46, 0x7d, - 0x08, 0x5d, 0x56, 0x6d, - 0x02, 0xa6, 0xda, 0x6b, - 0x00, 0xe2, 0x3e, 0x59, - 0x20, 0x5b, 0x56, 0x6d, - 0x01, 0x1b, 0x76, 0x6d, - 0xfc, 0x42, 0x52, 0x7d, - 0x10, 0x40, 0x54, 0x6d, - 0x20, 0x4d, 0x96, 0x7d, - 0x08, 0x5d, 0x96, 0x7d, + 0x02, 0xa6, 0x52, 0x7d, + 0x00, 0xe2, 0x3c, 0x59, + 0x20, 0x5b, 0x60, 0x6d, + 0xfc, 0x42, 0x4c, 0x7d, + 0x10, 0x40, 0x4e, 0x6d, + 0x20, 0x4d, 0x50, 0x7d, + 0x08, 0x5d, 0x60, 0x6d, + 0x02, 0xa6, 0xe0, 0x6b, + 0x00, 0xe2, 0x3c, 0x59, + 0x20, 0x5b, 0x60, 0x6d, + 0x01, 0x1b, 0x80, 0x6d, + 0xfc, 0x42, 0x5c, 0x7d, + 0x10, 0x40, 0x5e, 0x6d, + 0x20, 0x4d, 0x64, 0x78, + 0x08, 0x5d, 0x64, 0x78, 0x02, 0x19, 0x32, 0x00, 0x01, 0x5b, 0x40, 0x31, - 0x00, 0xe2, 0xb4, 0x5c, - 0x00, 0xe2, 0x92, 0x5b, + 0x00, 0xe2, 0xba, 0x5c, + 0x00, 0xe2, 0x98, 0x5b, 0x20, 0xea, 0xb6, 0x00, - 0x00, 0xe2, 0xd4, 0x5b, + 0x00, 0xe2, 0xda, 0x5b, 0x20, 0x5c, 0xb8, 0x00, - 0x04, 0x19, 0x6c, 0x6d, - 0x01, 0x1a, 0x6c, 0x6d, - 0x00, 0xe2, 0x3e, 0x59, - 0x01, 0x1a, 0x96, 0x7d, + 0x04, 0x19, 0x76, 0x6d, + 0x01, 0x1a, 0x76, 0x6d, + 0x00, 0xe2, 0x3c, 0x59, + 0x01, 0x1a, 0x64, 0x78, 0x80, 0xf9, 0xf2, 0x01, - 0x20, 0xa0, 0xe8, 0x7d, - 0x08, 0xa8, 0x75, 0x7d, - 0x00, 0xe2, 0x88, 0x45, + 0x20, 0xa0, 0xda, 0x7d, + 0xff, 0xae, 0x5d, 0x1b, + 0x08, 0xa8, 0x3d, 0x6b, 0x02, 0xea, 0xb4, 0x04, - 0x02, 0x19, 0x32, 0x00, - 0x08, 0xa8, 0x99, 0x7d, - 0x04, 0x5d, 0xfe, 0x7d, - 0x01, 0x1a, 0xfe, 0x7d, - 0x01, 0xa4, 0x49, 0x03, + 0x01, 0x9c, 0x39, 0x03, + 0x40, 0x5b, 0x90, 0x6d, + 0x00, 0xe2, 0x3c, 0x59, + 0x40, 0x5b, 0x90, 0x6d, + 0x04, 0x5d, 0xf4, 0x7d, + 0x01, 0x1a, 0xf4, 0x7d, + 0x20, 0x4d, 0x64, 0x78, + 0x40, 0x5b, 0xda, 0x7d, + 0x04, 0x5d, 0xf4, 0x7d, + 0x01, 0x1a, 0xf4, 0x7d, 0x80, 0xf9, 0xf2, 0x01, - 0x02, 0xa8, 0x84, 0x32, - 0x02, 0xea, 0xb4, 0x00, - 0x00, 0xe2, 0x3e, 0x43, - 0x02, 0xa8, 0x84, 0x32, - 0x02, 0xea, 0xb4, 0x00, - 0xff, 0xea, 0xd4, 0x19, - 0x00, 0xe2, 0x4a, 0x59, - 0x11, 0x00, 0x00, 0x10, - 0x00, 0xe2, 0xcc, 0x5d, - 0x00, 0xe2, 0x3e, 0x53, - 0xff, 0xea, 0xd4, 0x0d, - 0x00, 0xe2, 0x3e, 0x59, - 0x40, 0x5b, 0xa4, 0x6d, - 0x04, 0x5d, 0xfe, 0x7d, - 0x01, 0x1a, 0xfe, 0x7d, - 0x20, 0x4d, 0x96, 0x7d, - 0x40, 0x5b, 0xe8, 0x7d, - 0x04, 0x5d, 0xfe, 0x7d, - 0x01, 0x1a, 0xfe, 0x7d, + 0xff, 0xae, 0x5d, 0x1b, + 0x08, 0xa8, 0x3d, 0x6b, + 0x02, 0xea, 0xb4, 0x04, + 0x00, 0xe2, 0x3c, 0x59, + 0x01, 0x1b, 0x64, 0x78, 0x80, 0xf9, 0xf2, 0x01, - 0x01, 0xa4, 0x49, 0x03, - 0x08, 0xa8, 0x89, 0x6d, 0x02, 0xea, 0xb4, 0x04, 0x00, 0xe2, 0x3c, 0x59, - 0x01, 0x1b, 0xc0, 0x7d, - 0x40, 0x5b, 0x96, 0x7d, + 0x01, 0x1b, 0xb8, 0x6d, + 0x40, 0x5b, 0xc6, 0x7d, + 0x01, 0x1b, 0xb8, 0x6d, 0x02, 0x19, 0x32, 0x00, + 0x01, 0x1a, 0x64, 0x78, 0x80, 0xf9, 0xf2, 0x01, 0xff, 0xea, 0x10, 0x03, 0x08, 0xa8, 0x51, 0x03, - 0x00, 0xe2, 0x88, 0x45, - 0xff, 0x6a, 0xc6, 0x6d, - 0x40, 0x5b, 0x96, 0x7d, - 0xff, 0x6a, 0xb6, 0x7d, - 0x10, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0x3c, 0x43, + 0x01, 0x1a, 0xc2, 0x7d, + 0x40, 0x5b, 0xbe, 0x7d, + 0x01, 0x1a, 0xac, 0x6d, + 0xfc, 0x42, 0x64, 0x78, + 0x01, 0x1a, 0xc6, 0x6d, + 0x10, 0xea, 0x4e, 0x59, 0x10, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xb6, 0x45, - 0x80, 0xf9, 0x96, 0x6d, - 0x01, 0x43, 0xc1, 0x31, - 0x00, 0xfb, 0x96, 0x65, - 0x01, 0x42, 0xc1, 0x31, - 0x00, 0xfa, 0x96, 0x65, - 0x01, 0xe8, 0xd4, 0x1d, - 0x00, 0xe2, 0x3c, 0x59, - 0x01, 0x1b, 0x96, 0x7d, - 0x80, 0xf9, 0xf2, 0x01, - 0x02, 0xea, 0xb4, 0x04, + 0xfc, 0x42, 0x64, 0x78, + 0x10, 0x40, 0xcc, 0x6d, + 0x20, 0x4d, 0x64, 0x78, + 0x40, 0x5b, 0xac, 0x6d, + 0x01, 0x1a, 0x64, 0x78, + 0x01, 0xae, 0x5d, 0x1b, 0x30, 0x3f, 0xc0, 0x09, - 0x30, 0xe0, 0x96, 0x65, - 0x40, 0x4b, 0x96, 0x6d, + 0x30, 0xe0, 0x64, 0x60, + 0x40, 0x4b, 0x64, 0x68, 0xff, 0xea, 0x52, 0x01, - 0xee, 0x00, 0xee, 0x6d, + 0xee, 0x00, 0xe0, 0x6d, 0x80, 0xf9, 0xf2, 0x01, + 0xff, 0xae, 0x5d, 0x1b, 0x02, 0xea, 0xb4, 0x00, 0x20, 0xea, 0x9a, 0x00, - 0xf3, 0x42, 0xf8, 0x6d, - 0x12, 0xea, 0x50, 0x59, + 0xf3, 0x42, 0xec, 0x6d, + 0x12, 0xea, 0x4e, 0x59, 0x12, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xf8, 0x41, - 0x0d, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0xf6, 0x41, + 0x0d, 0xea, 0x4e, 0x59, 0x0d, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0xf8, 0x41, - 0x11, 0xea, 0x50, 0x59, + 0x00, 0xe2, 0xf6, 0x41, + 0x01, 0xae, 0x5d, 0x1b, + 0x11, 0xea, 0x4e, 0x59, 0x11, 0xea, 0x04, 0x00, - 0x00, 0xe2, 0x2e, 0x5b, + 0x00, 0xe2, 0x2c, 0x5b, 0x08, 0x5a, 0xb4, 0x00, - 0x00, 0xe2, 0x22, 0x5e, + 0x00, 0xe2, 0x1a, 0x5e, 0xa8, 0xea, 0x32, 0x00, - 0x00, 0xe2, 0x3e, 0x59, - 0x80, 0x1a, 0x12, 0x7e, - 0x00, 0xe2, 0x22, 0x5e, + 0x00, 0xe2, 0x3c, 0x59, + 0x80, 0x1a, 0x08, 0x7e, + 0x00, 0xe2, 0x1a, 0x5e, 0x80, 0x19, 0x32, 0x00, - 0x40, 0x5b, 0x18, 0x6e, - 0x08, 0x5a, 0x18, 0x7e, - 0x20, 0x4d, 0x96, 0x7d, + 0x40, 0x5b, 0x0e, 0x6e, + 0x08, 0x5a, 0x0e, 0x7e, + 0x20, 0x4d, 0x64, 0x78, 0x02, 0x84, 0x09, 0x03, - 0x40, 0x5b, 0xe8, 0x7d, - 0x08, 0xa8, 0x81, 0x6d, + 0x40, 0x5b, 0xda, 0x7d, + 0xff, 0xae, 0x5d, 0x1b, 0x80, 0xf9, 0xf2, 0x01, + 0x08, 0xa8, 0x3d, 0x6b, 0x02, 0xea, 0xb4, 0x04, 0x01, 0x38, 0xe1, 0x30, 0x05, 0x39, 0xe3, 0x98, - 0x01, 0xe0, 0xf8, 0x31, + 0x01, 0xe0, 0xf4, 0x31, 0xff, 0xea, 0xc0, 0x09, 0x00, 0x3a, 0xe5, 0x20, 0x00, 0x3b, 0xe7, 0x20, - 0x01, 0xfc, 0xc0, 0x31, + 0x01, 0xfa, 0xc0, 0x31, 0x04, 0xea, 0xe8, 0x30, 0xff, 0xea, 0xf0, 0x08, 0x02, 0xea, 0xf2, 0x00, @@ -1000,124 +996,121 @@ { ahd_patch0_func, 30, 1, 1 }, { ahd_patch1_func, 37, 1, 2 }, { ahd_patch0_func, 38, 1, 1 }, - { ahd_patch2_func, 45, 1, 2 }, - { ahd_patch0_func, 46, 1, 1 }, - { ahd_patch2_func, 49, 1, 2 }, - { ahd_patch0_func, 50, 1, 1 }, - { ahd_patch2_func, 53, 1, 2 }, - { ahd_patch0_func, 54, 1, 1 }, - { ahd_patch2_func, 56, 1, 2 }, - { ahd_patch0_func, 57, 1, 1 }, - { ahd_patch2_func, 60, 1, 2 }, - { ahd_patch0_func, 61, 1, 1 }, - { ahd_patch2_func, 64, 1, 2 }, - { ahd_patch0_func, 65, 1, 1 }, - { ahd_patch2_func, 162, 6, 1 }, - { ahd_patch1_func, 168, 2, 1 }, - { ahd_patch4_func, 170, 1, 1 }, - { ahd_patch2_func, 179, 1, 2 }, - { ahd_patch0_func, 180, 1, 1 }, - { ahd_patch5_func, 181, 2, 2 }, - { ahd_patch0_func, 183, 6, 3 }, - { ahd_patch2_func, 186, 1, 2 }, - { ahd_patch0_func, 187, 1, 1 }, - { ahd_patch2_func, 190, 1, 2 }, - { ahd_patch0_func, 191, 1, 1 }, - { ahd_patch6_func, 193, 2, 1 }, - { ahd_patch4_func, 201, 16, 2 }, - { ahd_patch0_func, 217, 1, 1 }, - { ahd_patch7_func, 237, 2, 1 }, - { ahd_patch1_func, 241, 1, 2 }, - { ahd_patch0_func, 242, 1, 1 }, - { ahd_patch6_func, 245, 2, 1 }, - { ahd_patch1_func, 259, 1, 2 }, - { ahd_patch0_func, 260, 1, 1 }, - { ahd_patch1_func, 263, 1, 2 }, - { ahd_patch0_func, 264, 1, 1 }, - { ahd_patch2_func, 267, 1, 2 }, - { ahd_patch0_func, 268, 1, 1 }, - { ahd_patch1_func, 323, 1, 2 }, - { ahd_patch0_func, 324, 1, 1 }, - { ahd_patch2_func, 332, 1, 2 }, - { ahd_patch0_func, 333, 1, 1 }, - { ahd_patch2_func, 336, 1, 2 }, - { ahd_patch0_func, 337, 1, 1 }, - { ahd_patch1_func, 344, 1, 2 }, - { ahd_patch0_func, 345, 1, 1 }, - { ahd_patch8_func, 364, 1, 1 }, - { ahd_patch8_func, 367, 1, 1 }, - { ahd_patch8_func, 369, 1, 1 }, - { ahd_patch8_func, 381, 1, 1 }, - { ahd_patch1_func, 391, 1, 2 }, - { ahd_patch0_func, 392, 1, 1 }, - { ahd_patch1_func, 394, 1, 2 }, - { ahd_patch0_func, 395, 1, 1 }, - { ahd_patch1_func, 403, 1, 2 }, - { ahd_patch0_func, 404, 1, 1 }, - { ahd_patch2_func, 415, 1, 2 }, - { ahd_patch0_func, 416, 1, 1 }, - { ahd_patch9_func, 444, 1, 1 }, - { ahd_patch1_func, 451, 1, 2 }, - { ahd_patch0_func, 452, 1, 1 }, - { ahd_patch2_func, 464, 1, 2 }, - { ahd_patch0_func, 465, 1, 1 }, - { ahd_patch10_func, 470, 6, 2 }, - { ahd_patch0_func, 476, 1, 1 }, - { ahd_patch11_func, 499, 1, 1 }, - { ahd_patch12_func, 508, 1, 1 }, - { ahd_patch13_func, 509, 1, 2 }, - { ahd_patch0_func, 510, 1, 1 }, - { ahd_patch14_func, 515, 1, 1 }, - { ahd_patch13_func, 516, 1, 1 }, - { ahd_patch15_func, 529, 1, 2 }, - { ahd_patch0_func, 530, 1, 1 }, - { ahd_patch1_func, 552, 1, 2 }, - { ahd_patch0_func, 553, 1, 1 }, - { ahd_patch1_func, 556, 1, 2 }, - { ahd_patch0_func, 557, 1, 1 }, - { ahd_patch2_func, 562, 1, 2 }, - { ahd_patch0_func, 563, 1, 1 }, - { ahd_patch2_func, 567, 1, 2 }, - { ahd_patch0_func, 568, 1, 1 }, - { ahd_patch1_func, 569, 1, 2 }, - { ahd_patch0_func, 570, 1, 1 }, - { ahd_patch2_func, 581, 1, 2 }, - { ahd_patch0_func, 582, 1, 1 }, - { ahd_patch16_func, 586, 1, 1 }, - { ahd_patch17_func, 591, 1, 1 }, - { ahd_patch18_func, 592, 2, 1 }, - { ahd_patch17_func, 596, 1, 2 }, - { ahd_patch0_func, 597, 1, 1 }, - { ahd_patch2_func, 600, 1, 2 }, - { ahd_patch0_func, 601, 1, 1 }, - { ahd_patch2_func, 619, 1, 2 }, - { ahd_patch0_func, 620, 1, 1 }, - { ahd_patch19_func, 621, 12, 1 }, - { ahd_patch1_func, 637, 1, 2 }, - { ahd_patch0_func, 638, 1, 1 }, - { ahd_patch19_func, 639, 1, 1 }, - { ahd_patch1_func, 650, 1, 2 }, - { ahd_patch0_func, 651, 1, 1 }, - { ahd_patch1_func, 658, 1, 2 }, - { ahd_patch0_func, 659, 1, 1 }, - { ahd_patch16_func, 683, 1, 1 }, - { ahd_patch16_func, 699, 1, 1 }, - { ahd_patch2_func, 711, 1, 2 }, - { ahd_patch0_func, 712, 1, 1 }, - { ahd_patch16_func, 731, 1, 1 }, - { ahd_patch1_func, 739, 1, 2 }, - { ahd_patch0_func, 740, 1, 1 }, - { ahd_patch1_func, 761, 1, 2 }, - { ahd_patch0_func, 762, 1, 1 }, - { ahd_patch1_func, 764, 1, 2 }, - { ahd_patch0_func, 765, 1, 1 }, - { ahd_patch1_func, 767, 1, 2 }, - { ahd_patch0_func, 768, 1, 1 }, - { ahd_patch20_func, 770, 1, 2 }, - { ahd_patch0_func, 771, 2, 1 }, - { ahd_patch21_func, 774, 4, 2 }, - { ahd_patch0_func, 778, 1, 1 }, - { ahd_patch21_func, 785, 11, 1 } + { ahd_patch2_func, 43, 1, 2 }, + { ahd_patch0_func, 44, 1, 1 }, + { ahd_patch2_func, 47, 1, 2 }, + { ahd_patch0_func, 48, 1, 1 }, + { ahd_patch2_func, 51, 1, 2 }, + { ahd_patch0_func, 52, 1, 1 }, + { ahd_patch2_func, 65, 1, 2 }, + { ahd_patch0_func, 66, 1, 1 }, + { ahd_patch2_func, 69, 1, 2 }, + { ahd_patch0_func, 70, 1, 1 }, + { ahd_patch1_func, 73, 1, 2 }, + { ahd_patch0_func, 74, 1, 1 }, + { ahd_patch2_func, 161, 6, 1 }, + { ahd_patch1_func, 167, 2, 1 }, + { ahd_patch4_func, 169, 1, 1 }, + { ahd_patch2_func, 178, 1, 2 }, + { ahd_patch0_func, 179, 1, 1 }, + { ahd_patch5_func, 180, 2, 2 }, + { ahd_patch0_func, 182, 6, 3 }, + { ahd_patch2_func, 185, 1, 2 }, + { ahd_patch0_func, 186, 1, 1 }, + { ahd_patch2_func, 189, 1, 2 }, + { ahd_patch0_func, 190, 1, 1 }, + { ahd_patch6_func, 192, 2, 1 }, + { ahd_patch4_func, 200, 16, 2 }, + { ahd_patch0_func, 216, 1, 1 }, + { ahd_patch7_func, 236, 2, 1 }, + { ahd_patch1_func, 240, 1, 2 }, + { ahd_patch0_func, 241, 1, 1 }, + { ahd_patch6_func, 244, 2, 1 }, + { ahd_patch1_func, 258, 1, 2 }, + { ahd_patch0_func, 259, 1, 1 }, + { ahd_patch1_func, 262, 1, 2 }, + { ahd_patch0_func, 263, 1, 1 }, + { ahd_patch2_func, 266, 1, 2 }, + { ahd_patch0_func, 267, 1, 1 }, + { ahd_patch1_func, 322, 1, 2 }, + { ahd_patch0_func, 323, 1, 1 }, + { ahd_patch2_func, 331, 1, 2 }, + { ahd_patch0_func, 332, 1, 1 }, + { ahd_patch2_func, 335, 1, 2 }, + { ahd_patch0_func, 336, 1, 1 }, + { ahd_patch1_func, 343, 1, 2 }, + { ahd_patch0_func, 344, 1, 1 }, + { ahd_patch8_func, 363, 1, 1 }, + { ahd_patch8_func, 366, 1, 1 }, + { ahd_patch8_func, 368, 1, 1 }, + { ahd_patch8_func, 380, 1, 1 }, + { ahd_patch1_func, 390, 1, 2 }, + { ahd_patch0_func, 391, 1, 1 }, + { ahd_patch1_func, 393, 1, 2 }, + { ahd_patch0_func, 394, 1, 1 }, + { ahd_patch1_func, 402, 1, 2 }, + { ahd_patch0_func, 403, 1, 1 }, + { ahd_patch2_func, 416, 1, 2 }, + { ahd_patch0_func, 417, 1, 1 }, + { ahd_patch9_func, 447, 1, 1 }, + { ahd_patch1_func, 454, 1, 2 }, + { ahd_patch0_func, 455, 1, 1 }, + { ahd_patch2_func, 467, 1, 2 }, + { ahd_patch0_func, 468, 1, 1 }, + { ahd_patch10_func, 473, 6, 2 }, + { ahd_patch0_func, 479, 1, 1 }, + { ahd_patch11_func, 502, 1, 1 }, + { ahd_patch12_func, 511, 1, 1 }, + { ahd_patch13_func, 512, 1, 2 }, + { ahd_patch0_func, 513, 1, 1 }, + { ahd_patch14_func, 518, 1, 1 }, + { ahd_patch13_func, 519, 1, 1 }, + { ahd_patch15_func, 532, 1, 2 }, + { ahd_patch0_func, 533, 1, 1 }, + { ahd_patch1_func, 555, 1, 2 }, + { ahd_patch0_func, 556, 1, 1 }, + { ahd_patch1_func, 559, 1, 2 }, + { ahd_patch0_func, 560, 1, 1 }, + { ahd_patch2_func, 565, 1, 2 }, + { ahd_patch0_func, 566, 1, 1 }, + { ahd_patch2_func, 570, 1, 2 }, + { ahd_patch0_func, 571, 1, 1 }, + { ahd_patch1_func, 572, 1, 2 }, + { ahd_patch0_func, 573, 1, 1 }, + { ahd_patch2_func, 584, 1, 2 }, + { ahd_patch0_func, 585, 1, 1 }, + { ahd_patch16_func, 589, 1, 1 }, + { ahd_patch17_func, 594, 1, 1 }, + { ahd_patch18_func, 595, 2, 1 }, + { ahd_patch17_func, 599, 1, 2 }, + { ahd_patch0_func, 600, 1, 1 }, + { ahd_patch2_func, 603, 1, 2 }, + { ahd_patch0_func, 604, 1, 1 }, + { ahd_patch2_func, 622, 1, 2 }, + { ahd_patch0_func, 623, 1, 1 }, + { ahd_patch19_func, 624, 14, 1 }, + { ahd_patch1_func, 642, 1, 2 }, + { ahd_patch0_func, 643, 1, 1 }, + { ahd_patch19_func, 644, 1, 1 }, + { ahd_patch1_func, 656, 1, 2 }, + { ahd_patch0_func, 657, 1, 1 }, + { ahd_patch1_func, 664, 1, 2 }, + { ahd_patch0_func, 665, 1, 1 }, + { ahd_patch16_func, 688, 1, 1 }, + { ahd_patch16_func, 726, 1, 1 }, + { ahd_patch1_func, 737, 1, 2 }, + { ahd_patch0_func, 738, 1, 1 }, + { ahd_patch1_func, 755, 1, 2 }, + { ahd_patch0_func, 756, 1, 1 }, + { ahd_patch1_func, 758, 1, 2 }, + { ahd_patch0_func, 759, 1, 1 }, + { ahd_patch1_func, 762, 1, 2 }, + { ahd_patch0_func, 763, 1, 1 }, + { ahd_patch20_func, 765, 1, 2 }, + { ahd_patch0_func, 766, 2, 1 }, + { ahd_patch21_func, 769, 4, 2 }, + { ahd_patch0_func, 773, 1, 1 }, + { ahd_patch21_func, 781, 11, 1 } }; static struct cs { @@ -1127,18 +1120,15 @@ { 11, 12 }, { 13, 14 }, { 29, 42 }, - { 43, 56 }, - { 69, 72 }, - { 99, 124 }, - { 125, 156 }, - { 158, 162 }, - { 170, 178 }, - { 201, 250 }, - { 683, 699 }, - { 699, 717 }, - { 722, 728 }, - { 731, 736 }, - { 742, 748 } + { 56, 59 }, + { 101, 127 }, + { 128, 156 }, + { 158, 161 }, + { 169, 177 }, + { 200, 249 }, + { 688, 704 }, + { 704, 718 }, + { 728, 732 } }; static const int num_critical_sections = sizeof(critical_sections) diff -Nru a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h --- a/drivers/scsi/aic7xxx/aic7xxx.h Thu May 15 15:24:39 2003 +++ b/drivers/scsi/aic7xxx/aic7xxx.h Thu May 15 15:24:39 2003 @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#74 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#75 $ * * $FreeBSD$ */ @@ -1081,6 +1081,14 @@ /* PCI cacheline size. */ u_int pci_cachesize; + + /* + * Count of parity errors we have seen as a target. + * We auto-disable parity error checking after seeing + * AHC_PCI_TARGET_PERR_THRESH number of errors. + */ + u_int pci_target_perr_count; +#define AHC_PCI_TARGET_PERR_THRESH 10 /* Maximum number of sequencer instructions supported. */ u_int instruction_ram_size; diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c --- a/drivers/scsi/aic7xxx/aic7xxx_core.c Thu May 15 15:24:38 2003 +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c Thu May 15 15:24:38 2003 @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#124 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#128 $ * * $FreeBSD$ */ @@ -3949,7 +3949,6 @@ { int i; - ahc_fini_scbdata(ahc); switch (ahc->init_level) { default: case 5: @@ -3981,6 +3980,7 @@ ahc_dma_tag_destroy(ahc, ahc->parent_dmat); #endif ahc_platform_free(ahc); + ahc_fini_scbdata(ahc); for (i = 0; i < AHC_NUM_TARGETS; i++) { struct ahc_tmode_tstate *tstate; @@ -5100,7 +5100,7 @@ } while (--maxloops && (intstat != 0xFF || (ahc->features & AHC_REMOVABLE) == 0) && ((intstat & INT_PEND) != 0 - || (ahc_inb(ahc, SSTAT0) & (SELDO|SELINGO)))); + || (ahc_inb(ahc, SSTAT0) & (SELDO|SELINGO)) != 0)); if (maxloops == 0) { printf("Infinite interrupt loop, INTSTAT = %x", ahc_inb(ahc, INTSTAT)); diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_inline.h b/drivers/scsi/aic7xxx/aic7xxx_inline.h --- a/drivers/scsi/aic7xxx/aic7xxx_inline.h Thu May 15 15:24:46 2003 +++ b/drivers/scsi/aic7xxx/aic7xxx_inline.h Thu May 15 15:24:46 2003 @@ -37,7 +37,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#40 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#42 $ * * $FreeBSD$ */ @@ -500,7 +500,7 @@ static __inline void ahc_sync_qoutfifo(struct ahc_softc *ahc, int op); static __inline void ahc_sync_tqinfifo(struct ahc_softc *ahc, int op); static __inline u_int ahc_check_cmdcmpltqueues(struct ahc_softc *ahc); -static __inline void ahc_intr(struct ahc_softc *ahc); +static __inline int ahc_intr(struct ahc_softc *ahc); static __inline void ahc_sync_qoutfifo(struct ahc_softc *ahc, int op) @@ -558,7 +558,7 @@ /* * Catch an interrupt from the adapter */ -static __inline void +static __inline int ahc_intr(struct ahc_softc *ahc) { u_int intstat; @@ -570,7 +570,7 @@ * so just return. This is likely just a shared * interrupt. */ - return; + return (0); } /* * Instead of directly reading the interrupt status register, @@ -585,6 +585,20 @@ intstat = ahc_inb(ahc, INTSTAT); } + if ((intstat & INT_PEND) == 0) { +#if AHC_PCI_CONFIG > 0 + if (ahc->unsolicited_ints > 500) { + ahc->unsolicited_ints = 0; + if ((ahc->chip & AHC_PCI) != 0 + && (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0) + ahc->bus_intr(ahc); + } +#endif + ahc->unsolicited_ints++; + return (0); + } + ahc->unsolicited_ints = 0; + if (intstat & CMDCMPLT) { ahc_outb(ahc, CLRINT, CLRCMDINT); @@ -604,38 +618,25 @@ #endif } - if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0) - /* Hot eject */ - return; - - if ((intstat & INT_PEND) == 0) { -#if AHC_PCI_CONFIG > 0 - if (ahc->unsolicited_ints > 500) { - ahc->unsolicited_ints = 0; - if ((ahc->chip & AHC_PCI) != 0 - && (ahc_inb(ahc, ERROR) & PCIERRSTAT) != 0) - ahc->bus_intr(ahc); - } -#endif - ahc->unsolicited_ints++; - return; - } - ahc->unsolicited_ints = 0; - - if (intstat & BRKADRINT) { + /* + * Handle statuses that may invalidate our cached + * copy of INTSTAT separately. + */ + if (intstat == 0xFF && (ahc->features & AHC_REMOVABLE) != 0) { + /* Hot eject. Do nothing */ + } else if (intstat & BRKADRINT) { ahc_handle_brkadrint(ahc); - /* Fatal error, no more interrupts to handle. */ - return; - } + } else if ((intstat & (SEQINT|SCSIINT)) != 0) { - if ((intstat & (SEQINT|SCSIINT)) != 0) ahc_pause_bug_fix(ahc); - if ((intstat & SEQINT) != 0) - ahc_handle_seqint(ahc, intstat); + if ((intstat & SEQINT) != 0) + ahc_handle_seqint(ahc, intstat); - if ((intstat & SCSIINT) != 0) - ahc_handle_scsiint(ahc, intstat); + if ((intstat & SCSIINT) != 0) + ahc_handle_scsiint(ahc, intstat); + } + return (1); } #endif /* _AIC7XXX_INLINE_H_ */ diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c Thu May 15 15:24:33 2003 +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c Thu May 15 15:24:33 2003 @@ -1,7 +1,7 @@ /* * Adaptec AIC7xxx device driver for Linux. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#206 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.c#221 $ * * Copyright (c) 1994 John Aycock * The University of Calgary Department of Computer Science. @@ -146,18 +146,15 @@ #include static int errno; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0) /* * Lock protecting manipulation of the ahc softc list. */ spinlock_t ahc_list_spinlock; -#endif -/* - * To generate the correct addresses for the controller to issue - * on the bus. Originally added for DEC Alpha support. - */ -#define VIRT_TO_BUS(a) (uint32_t)virt_to_bus((void *)(a)) +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +/* For dynamic sglist size calculation. */ +u_int ahc_linux_nseg; +#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) struct proc_dir_entry proc_scsi_aic7xxx = { @@ -367,31 +364,26 @@ * disabled at the very end. That should fix everyone up unless there are * really strange cirumstances. */ -static int aic7xxx_reverse_scan = 0; +static uint32_t aic7xxx_reverse_scan; /* * Should we force EXTENDED translation on a controller. * 0 == Use whatever is in the SEEPROM or default to off * 1 == Use whatever is in the SEEPROM or default to on */ -static uint32_t aic7xxx_extended = 0; +static uint32_t aic7xxx_extended; /* * PCI bus parity checking of the Adaptec controllers. This is somewhat * dubious at best. To my knowledge, this option has never actually * solved a PCI parity problem, but on certain machines with broken PCI - * chipset configurations, it can generate tons of false error messages. + * chipset configurations where stray PCI transactions with bad parity are + * the norm rather than the exception, the error messages can be overwelming. * It's included in the driver for completeness. - * 0 = Shut off PCI parity check - * -1 = Normal polarity pci parity checking - * 1 = reverse polarity pci parity checking - * - * NOTE: you can't actually pass -1 on the lilo prompt. So, to set this - * variable to -1 you would actually want to simply pass the variable - * name without a number. That will invert the 0 which will result in - * -1. + * 0 = Shut off PCI parity check + * non-0 = reverse polarity pci parity checking */ -static int aic7xxx_pci_parity = 0; +static uint32_t aic7xxx_pci_parity = ~0; /* * Certain newer motherboards have put new PCI based devices into the @@ -404,12 +396,9 @@ * would result in never finding any devices :) */ #ifndef CONFIG_AIC7XXX_PROBE_EISA_VL -#define CONFIG_AIC7XXX_PROBE_EISA_VL n -#endif -#if CONFIG_AIC7XXX_PROBE_EISA_VL == n -static int aic7xxx_no_probe = 1; +static uint32_t aic7xxx_probe_eisa_vl; #else -static int aic7xxx_no_probe; +static uint32_t aic7xxx_probe_eisa_vl = ~0; #endif /* @@ -418,7 +407,7 @@ * controller. I/O mapped register access, if allowed by the given * platform, will work in almost all cases. */ -int aic7xxx_allow_memio = 1; +uint32_t aic7xxx_allow_memio = ~0; /* * aic7xxx_detect() has been run, so register all device arrivals @@ -437,7 +426,7 @@ * We default to 256ms because some older devices need a longer time * to respond to initial selection. */ -static int aic7xxx_seltime = 0x00; +static uint32_t aic7xxx_seltime; /* * Certain devices do not perform any aging on commands. Should the @@ -447,7 +436,7 @@ * force all outstanding transactions to be serviced prior to a new * transaction. */ -int aic7xxx_periodic_otag; +uint32_t aic7xxx_periodic_otag; /* * Module information and settable options. @@ -472,7 +461,8 @@ " verbose Enable verbose/diagnostic logging\n" " allow_memio Allow device registers to be memory mapped\n" " debug Bitmask of debug values to enable\n" -" no_probe Disable EISA/VLB controller probing\n" +" no_probe Toggle EISA/VLB controller probing\n" +" probe_eisa_vl Toggle EISA/VLB controller probing\n" " no_reset Supress initial bus resets\n" " extended Enable extended geometry on all controllers\n" " periodic_otag Send an ordered tagged transaction\n" @@ -489,10 +479,10 @@ "\n" " Sample /etc/modules.conf line:\n" " Toggle EISA/VLB probing\n" -" Set tag depth on Controller 1/Target 2 to 10 tags\n" +" Set tag depth on Controller 1/Target 1 to 10 tags\n" " Shorten the selection timeout to 128ms\n" "\n" -" options aic7xxx 'aic7xxx=no_probe.tag_info:{{}.{..10}}.seltime:1'\n" +" options aic7xxx 'aic7xxx=probe_eisa_vl.tag_info:{{}.{.10}}.seltime:1'\n" ); #endif @@ -508,6 +498,7 @@ static void ahc_linux_dev_timed_unfreeze(u_long arg); static int ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag); static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc); +static void ahc_linux_size_nseg(void); static void ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc); static void ahc_linux_start_dv(struct ahc_softc *ahc); static void ahc_linux_dv_timeout(struct scsi_cmnd *cmd); @@ -571,16 +562,14 @@ static int aic7xxx_setup(char *s); static int ahc_linux_next_unit(void); static void ahc_runq_tasklet(unsigned long data); -static int ahc_linux_halt(struct notifier_block *nb, u_long event, void *buf); -static void ahc_schedule_completeq(struct ahc_softc *ahc, struct ahc_cmd *acmd); +static struct ahc_cmd *ahc_linux_run_complete_queue(struct ahc_softc *ahc); /********************************* Inlines ************************************/ static __inline void ahc_schedule_runq(struct ahc_softc *ahc); static __inline struct ahc_linux_device* ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target, u_int lun, int alloc); -static struct ahc_cmd *ahc_linux_run_complete_queue(struct ahc_softc *ahc, - struct ahc_cmd *acmd); +static __inline void ahc_schedule_completeq(struct ahc_softc *ahc); static __inline void ahc_linux_check_device_queue(struct ahc_softc *ahc, struct ahc_linux_device *dev); static __inline struct ahc_linux_device * @@ -592,27 +581,9 @@ struct ahc_dma_seg *sg, bus_addr_t addr, bus_size_t len); -static void -ahc_schedule_completeq(struct ahc_softc *ahc, struct ahc_cmd *acmd) +static __inline void +ahc_schedule_completeq(struct ahc_softc *ahc) { - while (acmd != NULL) { - struct ahc_completeq *completeq; - struct ahc_cmd *list_cmd; - struct ahc_cmd *next_cmd; - - next_cmd = TAILQ_NEXT(acmd, acmd_links.tqe); - completeq = &ahc->platform_data->completeq; - list_cmd = TAILQ_FIRST(completeq); - while (list_cmd != NULL - && acmd_scsi_cmd(list_cmd).serial_number - < acmd_scsi_cmd(acmd).serial_number) - list_cmd = TAILQ_NEXT(list_cmd, acmd_links.tqe); - if (list_cmd != NULL) - TAILQ_INSERT_BEFORE(list_cmd, acmd, acmd_links.tqe); - else - TAILQ_INSERT_TAIL(completeq, acmd, acmd_links.tqe); - acmd = next_cmd; - } if ((ahc->platform_data->flags & AHC_RUN_CMPLT_Q_TIMER) == 0) { ahc->platform_data->flags |= AHC_RUN_CMPLT_Q_TIMER; ahc->platform_data->completeq_timer.expires = jiffies; @@ -664,25 +635,17 @@ #define AHC_LINUX_MAX_RETURNED_ERRORS 4 static struct ahc_cmd * -ahc_linux_run_complete_queue(struct ahc_softc *ahc, struct ahc_cmd *acmd) -{ +ahc_linux_run_complete_queue(struct ahc_softc *ahc) +{ + struct ahc_cmd *acmd; u_long done_flags; int with_errors; with_errors = 0; ahc_done_lock(ahc, &done_flags); - while (acmd != NULL) { + while ((acmd = TAILQ_FIRST(&ahc->platform_data->completeq)) != NULL) { Scsi_Cmnd *cmd; - cmd = &acmd_scsi_cmd(acmd); - acmd = TAILQ_NEXT(acmd, acmd_links.tqe); - cmd->host_scribble = NULL; - if (ahc_cmd_get_transaction_status(cmd) != DID_OK - || (cmd->result & 0xFF) != SCSI_STATUS_OK) - with_errors++; - - cmd->scsi_done(cmd); - if (with_errors > AHC_LINUX_MAX_RETURNED_ERRORS) { /* * Linux uses stack recursion to requeue @@ -692,8 +655,18 @@ * the operating system in case they are going * to be retried. "ick" */ + ahc_schedule_completeq(ahc); break; } + TAILQ_REMOVE(&ahc->platform_data->completeq, + acmd, acmd_links.tqe); + cmd = &acmd_scsi_cmd(acmd); + cmd->host_scribble = NULL; + if (ahc_cmd_get_transaction_status(cmd) != DID_OK + || (cmd->result & 0xFF) != SCSI_STATUS_OK) + with_errors++; + + cmd->scsi_done(cmd); } ahc_done_unlock(ahc, &done_flags); return (acmd); @@ -811,19 +784,84 @@ static int ahc_linux_slave_alloc(Scsi_Device *); static int ahc_linux_slave_configure(Scsi_Device *); static void ahc_linux_slave_destroy(Scsi_Device *); +#if defined(__i386__) static int ahc_linux_biosparam(struct scsi_device*, struct block_device*, sector_t, int[]); +#endif #else static void ahc_linux_select_queue_depth(struct Scsi_Host *host, Scsi_Device *scsi_devs); +#if defined(__i386__) static int ahc_linux_biosparam(Disk *, kdev_t, int[]); #endif +#endif static int ahc_linux_bus_reset(Scsi_Cmnd *); static int ahc_linux_dev_reset(Scsi_Cmnd *); static int ahc_linux_abort(Scsi_Cmnd *); /* + * Calculate a safe value for AHC_NSEG (as expressed through ahc_linux_nseg). + * + * In pre-2.5.X... + * The midlayer allocates an S/G array dynamically when a command is issued + * using SCSI malloc. This array, which is in an OS dependent format that + * must later be copied to our private S/G list, is sized to house just the + * number of segments needed for the current transfer. Since the code that + * sizes the SCSI malloc pool does not take into consideration fragmentation + * of the pool, executing transactions numbering just a fraction of our + * concurrent transaction limit with list lengths aproaching AHC_NSEG will + * quickly depleat the SCSI malloc pool of usable space. Unfortunately, the + * mid-layer does not properly handle this scsi malloc failures for the S/G + * array and the result can be a lockup of the I/O subsystem. We try to size + * our S/G list so that it satisfies our drivers allocation requirements in + * addition to avoiding fragmentation of the SCSI malloc pool. + */ +static void +ahc_linux_size_nseg(void) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + u_int cur_size; + u_int best_size; + + /* + * The SCSI allocator rounds to the nearest 512 bytes + * an cannot allocate across a page boundary. Our algorithm + * is to start at 1K of scsi malloc space per-command and + * loop through all factors of the PAGE_SIZE and pick the best. + */ + best_size = 0; + for (cur_size = 1024; cur_size <= PAGE_SIZE; cur_size *= 2) { + u_int nseg; + + nseg = cur_size / sizeof(struct scatterlist); + if (nseg < AHC_LINUX_MIN_NSEG) + continue; + + if (best_size == 0) { + best_size = cur_size; + ahc_linux_nseg = nseg; + } else { + u_int best_rem; + u_int cur_rem; + + /* + * Compare the traits of the current "best_size" + * with the current size to determine if the + * current size is a better size. + */ + best_rem = best_size % sizeof(struct scatterlist); + cur_rem = cur_size % sizeof(struct scatterlist); + if (cur_rem < best_rem) { + best_size = cur_size; + ahc_linux_nseg = nseg; + } + } + } +#endif +} + +/* * Try to detect an Adaptec 7XXX controller. */ static int @@ -851,6 +889,7 @@ printf("ahc_linux_detect: Unable to attach\n"); return (0); } + ahc_linux_size_nseg(); #ifdef MODULE /* * If we've been passed any parameters, process them now. @@ -881,7 +920,7 @@ ahc_linux_pci_init(); #endif - if (aic7xxx_no_probe == 0) + if (aic7xxx_probe_eisa_vl != 0) aic7770_linux_probe(template); /* @@ -991,7 +1030,7 @@ ahc_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ); ahc_linux_queue_cmd_complete(ahc, cmd); - ahc_schedule_completeq(ahc, NULL); + ahc_schedule_completeq(ahc); ahc_midlayer_entrypoint_unlock(ahc, &flags); return (0); } @@ -1000,7 +1039,7 @@ if (dev == NULL) { ahc_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL); ahc_linux_queue_cmd_complete(ahc, cmd); - ahc_schedule_completeq(ahc, NULL); + ahc_schedule_completeq(ahc); ahc_midlayer_entrypoint_unlock(ahc, &flags); printf("%s: aic7xxx_linux_queue - Unable to allocate device!\n", ahc_name(ahc)); @@ -1082,7 +1121,8 @@ && (dev->flags & AHC_DEV_SLAVE_CONFIGURED) != 0) { dev->flags |= AHC_DEV_UNCONFIGURED; if (TAILQ_EMPTY(&dev->busyq) - && dev->active == 0) + && dev->active == 0 + && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0) ahc_linux_free_device(ahc, dev); } ahc_midlayer_entrypoint_unlock(ahc, &flags); @@ -1093,16 +1133,33 @@ * off the input host adapter. */ static void -ahc_linux_select_queue_depth(struct Scsi_Host * host, - Scsi_Device * scsi_devs) +ahc_linux_select_queue_depth(struct Scsi_Host *host, Scsi_Device *scsi_devs) { Scsi_Device *device; + Scsi_Device *ldev; struct ahc_softc *ahc; u_long flags; ahc = *((struct ahc_softc **)host->hostdata); ahc_lock(ahc, &flags); for (device = scsi_devs; device != NULL; device = device->next) { + + /* + * Watch out for duplicate devices. This works around + * some quirks in how the SCSI scanning code does its + * device management. + */ + for (ldev = scsi_devs; ldev != device; ldev = ldev->next) { + if (ldev->host == device->host + && ldev->channel == device->channel + && ldev->id == device->id + && ldev->lun == device->lun) + break; + } + /* Skip duplicate. */ + if (ldev != device) + continue; + if (device->host == host) { struct ahc_linux_device *dev; @@ -1141,6 +1198,7 @@ /* * Return the disk geometry for the given SCSI device. */ +#if defined(__i386__) static int #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ahc_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev, @@ -1204,6 +1262,7 @@ geom[2] = cylinders; return (0); } +#endif /* * Abort the current SCSI command(s). @@ -1240,7 +1299,6 @@ ahc_linux_bus_reset(Scsi_Cmnd *cmd) { struct ahc_softc *ahc; - struct ahc_cmd *acmd; u_long s; int found; @@ -1248,14 +1306,7 @@ ahc_midlayer_entrypoint_lock(ahc, &s); found = ahc_reset_channel(ahc, cmd->device->channel + 'A', /*initiate reset*/TRUE); - acmd = TAILQ_FIRST(&ahc->platform_data->completeq); - TAILQ_INIT(&ahc->platform_data->completeq); - - if (acmd != NULL) { - acmd = ahc_linux_run_complete_queue(ahc, acmd); - if (acmd != NULL) - ahc_schedule_completeq(ahc, acmd); - } + ahc_linux_run_complete_queue(ahc); ahc_midlayer_entrypoint_unlock(ahc, &s); if (bootverbose) @@ -1279,7 +1330,6 @@ #endif .can_queue = AHC_MAX_QUEUE, .this_id = -1, - .sg_tablesize = AHC_NSEG, .cmd_per_lun = 2, .use_clustering = ENABLE_CLUSTERING, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7) @@ -1337,44 +1387,17 @@ TAILQ_REMOVE(&ahc->platform_data->device_runq, dev, links); dev->flags &= ~AHC_DEV_ON_RUN_LIST; ahc_linux_check_device_queue(ahc, dev); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) /* Yeild to our interrupt handler */ ahc_unlock(ahc, &flags); ahc_lock(ahc, &flags); +#endif } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) ahc_unlock(ahc, &flags); #endif } -/************************ Shutdown/halt/reboot hook ***************************/ -#include -#include - -static struct notifier_block ahc_linux_notifier = { - ahc_linux_halt, NULL, 0 -}; - -static int ahc_linux_halt(struct notifier_block *nb, u_long event, void *buf) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) - struct ahc_softc *ahc; - - /* - * In 2.5.X, this is called prior to the filesystems - * being synced and the SCSI layer being properly - * shutdown. A different API is required there, - * but the device hooks for this don't quite look - * right. - */ - if (event == SYS_DOWN || event == SYS_HALT) { - TAILQ_FOREACH(ahc, &ahc_tailq, links) { - ahc_shutdown(ahc); - } - } -#endif - return (NOTIFY_OK); -} - /******************************** Macros **************************************/ #define BUILD_SCSIID(ahc, cmd) \ ((((cmd)->device->id << TID_SHIFT) & TID) \ @@ -1482,6 +1505,7 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) stack_sg.ds_addr = map->bus_addr; #else +#define VIRT_TO_BUS(a) (uint32_t)virt_to_bus((void *)(a)) stack_sg.ds_addr = VIRT_TO_BUS(buf); #endif stack_sg.ds_len = dmat->maxsize; @@ -1613,7 +1637,7 @@ } static void -ahc_linux_setup_tag_info(void *arg, int instance, int targ, int32_t value) +ahc_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value) { if ((instance >= 0) && (targ >= 0) @@ -1626,7 +1650,7 @@ } static void -ahc_linux_setup_dv(void *arg, int instance, int targ, int32_t value) +ahc_linux_setup_dv(u_long arg, int instance, int targ, int32_t value) { if ((instance >= 0) @@ -1661,7 +1685,8 @@ { "debug", &ahc_debug }, #endif { "reverse_scan", &aic7xxx_reverse_scan }, - { "no_probe", &aic7xxx_no_probe }, + { "no_probe", &aic7xxx_probe_eisa_vl }, + { "probe_eisa_vl", &aic7xxx_probe_eisa_vl }, { "periodic_otag", &aic7xxx_periodic_otag }, { "pci_parity", &aic7xxx_pci_parity }, { "seltime", &aic7xxx_seltime }, @@ -1694,16 +1719,16 @@ ahc_linux_setup_tag_info_global(p + n); } else if (strncmp(p, "tag_info", n) == 0) { s = aic_parse_brace_option("tag_info", p + n, end, - 2, ahc_linux_setup_tag_info, NULL); + 2, ahc_linux_setup_tag_info, 0); } else if (strncmp(p, "dv", n) == 0) { s = aic_parse_brace_option("dv", p + n, end, 1, - ahc_linux_setup_dv, NULL); + ahc_linux_setup_dv, 0); } else if (p[n] == ':') { *(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0); } else if (strncmp(p, "verbose", n) == 0) { *(options[i].flag) = 1; } else { - *(options[i].flag) = ~(*(options[i].flag)); + *(options[i].flag) ^= 0xFFFFFFFF; } } return 1; @@ -1713,7 +1738,7 @@ __setup("aic7xxx=", aic7xxx_setup); #endif -int aic7xxx_verbose; +uint32_t aic7xxx_verbose; int ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template) @@ -1739,13 +1764,13 @@ ahc->platform_data->host = host; host->can_queue = AHC_MAX_QUEUE; host->cmd_per_lun = 2; - host->sg_tablesize = AHC_NSEG; /* XXX No way to communicate the ID for multiple channels */ host->this_id = ahc->our_id; host->irq = ahc->platform_data->irq; host->max_id = (ahc->features & AHC_WIDE) ? 16 : 8; host->max_lun = AHC_NUM_LUNS; host->max_channel = (ahc->features & AHC_TWIN) ? 1 : 0; + host->sg_tablesize = AHC_NSEG; ahc_set_unit(ahc, ahc_linux_next_unit()); sprintf(buf, "scsi%d", host->host_no); new_name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT); @@ -1953,8 +1978,6 @@ if (aic7xxx_pci_parity == 0) ahc->flags |= AHC_DISABLE_PCI_PERR; - if (TAILQ_EMPTY(&ahc_tailq)) - register_reboot_notifier(&ahc_linux_notifier); return (0); } @@ -1966,6 +1989,7 @@ int i, j; if (ahc->platform_data != NULL) { + del_timer_sync(&ahc->platform_data->completeq_timer); ahc_linux_kill_dv_thread(ahc); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) tasklet_kill(&ahc->platform_data->runq_tasklet); @@ -1981,17 +2005,22 @@ for (i = 0; i < AHC_NUM_TARGETS; i++) { targ = ahc->platform_data->targets[i]; if (targ != NULL) { + /* Keep target around through the loop. */ + targ->refcount++; for (j = 0; j < AHC_NUM_LUNS; j++) { - if (targ->devices[j] != NULL) { - dev = targ->devices[j]; - ahc_linux_free_device(ahc, dev); - } - if (ahc->platform_data->targets[i] == - NULL) - break; + + if (targ->devices[j] == NULL) + continue; + dev = targ->devices[j]; + ahc_linux_free_device(ahc, dev); } - } - } + /* + * Forcibly free the target now that + * all devices are gone. + */ + ahc_linux_free_target(ahc, targ); + } + } if (ahc->platform_data->irq != AHC_LINUX_NOIRQ) free_irq(ahc->platform_data->irq, ahc); @@ -2200,19 +2229,12 @@ static void ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc) { - struct ahc_cmd *acmd; u_long flags; ahc_lock(ahc, &flags); del_timer(&ahc->platform_data->completeq_timer); ahc->platform_data->flags &= ~AHC_RUN_CMPLT_Q_TIMER; - acmd = TAILQ_FIRST(&ahc->platform_data->completeq); - TAILQ_INIT(&ahc->platform_data->completeq); - if (acmd != NULL) { - acmd = ahc_linux_run_complete_queue(ahc, acmd); - if (acmd != NULL) - ahc_schedule_completeq(ahc, acmd); - } + ahc_linux_run_complete_queue(ahc); ahc_unlock(ahc, &flags); } @@ -2575,10 +2597,14 @@ } ahc_lock(ahc, &s); - if (targ->dv_buffer != NULL) + if (targ->dv_buffer != NULL) { free(targ->dv_buffer, M_DEVBUF); - if (targ->dv_buffer1 != NULL) + targ->dv_buffer = NULL; + } + if (targ->dv_buffer1 != NULL) { free(targ->dv_buffer1, M_DEVBUF); + targ->dv_buffer1 = NULL; + } targ->flags &= ~AHC_DV_REQUIRED; if (targ->refcount == 0) ahc_linux_free_target(ahc, targ); @@ -3408,7 +3434,6 @@ ahc_linux_dv_timeout(struct scsi_cmnd *cmd) { struct ahc_softc *ahc; - struct ahc_cmd *acmd; struct scb *scb; u_long flags; @@ -3455,15 +3480,9 @@ ahc->platform_data->reset_timer.function = (ahc_linux_callback_t *)ahc_linux_release_simq; add_timer(&ahc->platform_data->reset_timer); - acmd = TAILQ_FIRST(&ahc->platform_data->completeq); - TAILQ_INIT(&ahc->platform_data->completeq); if (ahc_linux_next_device_to_run(ahc) != NULL) ahc_schedule_runq(ahc); - if (acmd != NULL) { - acmd = ahc_linux_run_complete_queue(ahc, acmd); - if (acmd != NULL) - ahc_schedule_completeq(ahc, acmd); - } + ahc_linux_run_complete_queue(ahc); ahc_unlock(ahc, &flags); } @@ -3639,9 +3658,8 @@ && dev->scsi_device->tagged_supported != 0) { ahc_set_tags(ahc, &devinfo, AHC_QUEUE_TAGGED); - printf("scsi%d:%c:%d:%d: Tagged Queuing enabled. Depth %d\n", - ahc->platform_data->host->host_no, devinfo.channel, - devinfo.target, devinfo.lun, tags); + ahc_print_devinfo(ahc, &devinfo); + printf("Tagged Queuing enabled. Depth %d\n", tags); } else { ahc_set_tags(ahc, &devinfo, AHC_QUEUE_NONE); } @@ -3863,39 +3881,29 @@ /* * SCSI controller interrupt handler. */ -irqreturn_t +AIC_LINUX_IRQRETURN_T ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs) { struct ahc_softc *ahc; - struct ahc_cmd *acmd; u_long flags; + int ours; ahc = (struct ahc_softc *) dev_id; ahc_lock(ahc, &flags); - ahc_intr(ahc); - acmd = TAILQ_FIRST(&ahc->platform_data->completeq); - TAILQ_INIT(&ahc->platform_data->completeq); + ours = ahc_intr(ahc); if (ahc_linux_next_device_to_run(ahc) != NULL) ahc_schedule_runq(ahc); - if (acmd != NULL) { - acmd = ahc_linux_run_complete_queue(ahc, acmd); - if (acmd != NULL) - ahc_schedule_completeq(ahc, acmd); - } + ahc_linux_run_complete_queue(ahc); ahc_unlock(ahc, &flags); - /* FIXME! Was it really ours? */ - return IRQ_HANDLED; + AIC_LINUX_IRQRETURN(ours); } void ahc_platform_flushwork(struct ahc_softc *ahc) { - struct ahc_cmd *acmd; - acmd = TAILQ_FIRST(&ahc->platform_data->completeq); - TAILQ_INIT(&ahc->platform_data->completeq); - while (acmd != NULL) - acmd = ahc_linux_run_complete_queue(ahc, acmd); + while (ahc_linux_run_complete_queue(ahc) != NULL) + ; } static struct ahc_linux_target* @@ -4081,22 +4089,19 @@ } case AC_SENT_BDR: { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) + WARN_ON(lun != CAM_LUN_WILDCARD); + scsi_report_device_reset(ahc->platform_data->host, + channel - 'A', target); +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) Scsi_Device *scsi_dev; /* * Find the SCSI device associated with this * request and indicate that a UA is expected. - * XXX This should really be handled by the mid-layer. */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) - list_for_each_entry(scsi_dev, - &ahc->platform_data->host->my_devices, - siblings) { -#else for (scsi_dev = ahc->platform_data->host->host_queue; scsi_dev != NULL; scsi_dev = scsi_dev->next) { -#endif if (channel - 'A' == scsi_dev->channel && target == scsi_dev->id && (lun == CAM_LUN_WILDCARD @@ -4229,7 +4234,8 @@ if (TAILQ_EMPTY(&dev->busyq)) { if ((dev->flags & AHC_DEV_UNCONFIGURED) != 0 - && dev->active == 0) + && dev->active == 0 + && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0) ahc_linux_free_device(ahc, dev); } else if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) { TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links); @@ -4709,6 +4715,9 @@ if (dev->qfrozen == 0 && (dev->flags & AHC_DEV_ON_RUN_LIST) == 0) ahc_linux_run_device_queue(ahc, dev); + if (TAILQ_EMPTY(&dev->busyq) + && dev->active == 0) + ahc_linux_free_device(ahc, dev); ahc_unlock(ahc, &s); } @@ -4727,6 +4736,7 @@ u_int saved_scsiid; u_int cdb_byte; int retval; + int was_paused; int paused; int wait; int disconnected; @@ -4768,7 +4778,7 @@ * Start by searching the device queue. If not found * there, check the pending_scb list. If not found * at all, and the system wanted us to just abort the - * command return success. + * command, return success. */ dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id, cmd->device->lun, /*alloc*/FALSE); @@ -4855,11 +4865,10 @@ * behind our back and that we didn't "just" miss * an interrupt that would affect this cmd. */ + was_paused = ahc_is_paused(ahc); ahc_pause_and_flushwork(ahc); paused = TRUE; - ahc_dump_card_state(ahc); - if ((pending_scb->flags & SCB_ACTIVE) == 0) { printf("%s:%d:%d:%d: Command already completed\n", ahc_name(ahc), cmd->device->channel, cmd->device->id, @@ -4867,6 +4876,10 @@ goto no_cmd; } + printf("%s: At time of recovery, card was %spaused\n", + ahc_name(ahc), was_paused ? "" : "not "); + ahc_dump_card_state(ahc); + disconnected = TRUE; if (flag == SCB_ABORT) { if (ahc_search_qinfifo(ahc, cmd->device->id, @@ -5026,21 +5039,15 @@ printf("Recovery code sleeping\n"); down(&ahc->platform_data->eh_sem); printf("Recovery code awake\n"); - ret = del_timer(&timer); + ret = del_timer_sync(&timer); if (ret == 0) { printf("Timer Expired\n"); retval = FAILED; } spin_lock_irq(&ahc->platform_data->spin_lock); } - acmd = TAILQ_FIRST(&ahc->platform_data->completeq); - TAILQ_INIT(&ahc->platform_data->completeq); ahc_schedule_runq(ahc); - if (acmd != NULL) { - acmd = ahc_linux_run_complete_queue(ahc, acmd); - if (acmd != NULL) - ahc_schedule_completeq(ahc, acmd); - } + ahc_linux_run_complete_queue(ahc); ahc_midlayer_entrypoint_unlock(ahc, &s); return (retval); } @@ -5140,8 +5147,6 @@ */ ahc_linux_pci_exit(); #endif - - unregister_reboot_notifier(&ahc_linux_notifier); } module_init(ahc_linux_init); diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h Thu May 15 15:24:37 2003 +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h Thu May 15 15:24:37 2003 @@ -53,7 +53,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#131 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_osm.h#142 $ * */ #ifndef _AIC7XXX_LINUX_H_ @@ -150,8 +150,8 @@ #endif /* BYTE_ORDER */ /************************* Configuration Data *********************************/ -extern int aic7xxx_no_probe; -extern int aic7xxx_allow_memio; +extern u_int aic7xxx_no_probe; +extern u_int aic7xxx_allow_memio; extern int aic7xxx_detect_complete; extern Scsi_Host_Template aic7xxx_driver_template; @@ -258,7 +258,7 @@ typedef struct timer_list ahc_timer_t; /********************************** Includes **********************************/ -#if CONFIG_AIC7XXX_REG_PRETTY_PRINT +#ifdef CONFIG_AIC7XXX_REG_PRETTY_PRINT #define AIC_DEBUG_REGISTERS 1 #else #define AIC_DEBUG_REGISTERS 0 @@ -267,7 +267,7 @@ /***************************** Timer Facilities *******************************/ #define ahc_timer_init init_timer -#define ahc_timer_stop del_timer +#define ahc_timer_stop del_timer_sync typedef void ahc_linux_callback_t (u_long); static __inline void ahc_timer_reset(ahc_timer_t *timer, int usec, ahc_callback_t *func, void *arg); @@ -305,7 +305,7 @@ #define AHC_SCSI_HAS_HOST_LOCK 0 #endif -#define AIC7XXX_DRIVER_VERSION "6.2.31" +#define AIC7XXX_DRIVER_VERSION "6.2.33" /**************************** Front End Queues ********************************/ /* @@ -494,7 +494,18 @@ * manner and are allocated below 4GB, the number of S/G segments is * unrestricted. */ -#define AHC_NSEG 128 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +/* + * We dynamically adjust the number of segments in pre-2.5 kernels to + * avoid fragmentation issues in the SCSI mid-layer's private memory + * allocator. See aic7xxx_osm.c ahc_linux_size_nseg() for details. + */ +extern u_int ahc_linux_nseg; +#define AHC_NSEG ahc_linux_nseg +#define AHC_LINUX_MIN_NSEG 64 +#else +#define AHC_NSEG 128 +#endif /* * Per-SCB OSM storage. @@ -538,9 +549,7 @@ TAILQ_HEAD(, ahc_linux_device) device_runq; struct ahc_completeq completeq; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93) spinlock_t spin_lock; -#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) struct tasklet_struct runq_tasklet; #endif @@ -699,7 +708,6 @@ static __inline void ahc_list_lock(unsigned long *flags); static __inline void ahc_list_unlock(unsigned long *flags); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93) static __inline void ahc_lockinit(struct ahc_softc *ahc) { @@ -729,7 +737,8 @@ * trade the io_request_lock for our per-softc lock. */ #if AHC_SCSI_HAS_HOST_LOCK == 0 - ahc_lock(ahc, flags); + spin_unlock(&io_request_lock); + spin_lock(&ahc->platform_data->spin_lock); #endif } @@ -737,7 +746,8 @@ ahc_midlayer_entrypoint_unlock(struct ahc_softc *ahc, unsigned long *flags) { #if AHC_SCSI_HAS_HOST_LOCK == 0 - ahc_unlock(ahc, flags); + spin_unlock(&ahc->platform_data->spin_lock); + spin_lock(&io_request_lock); #endif } @@ -768,7 +778,7 @@ } static __inline void -ahc_list_lockinit() +ahc_list_lockinit(void) { spin_lock_init(&ahc_list_spinlock); } @@ -785,65 +795,6 @@ spin_unlock_irqrestore(&ahc_list_spinlock, *flags); } -#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,93) */ - -static __inline void -ahc_lockinit(struct ahc_softc *ahc) -{ -} - -static __inline void -ahc_lock(struct ahc_softc *ahc, unsigned long *flags) -{ - save_flags(*flags); - cli(); -} - -static __inline void -ahc_unlock(struct ahc_softc *ahc, unsigned long *flags) -{ - restore_flags(*flags); -} - -static __inline void -ahc_done_lockinit(struct ahc_softc *ahc) -{ -} - -static __inline void -ahc_done_lock(struct ahc_softc *ahc, unsigned long *flags) -{ - /* - * The done lock is always held while - * the ahc lock is held so blocking - * interrupts again would have no effect. - */ -} - -static __inline void -ahc_done_unlock(struct ahc_softc *ahc, unsigned long *flags) -{ -} - -static __inline void -ahc_list_lockinit() -{ -} - -static __inline void -ahc_list_lock(unsigned long *flags) -{ - save_flags(*flags); - cli(); -} - -static __inline void -ahc_list_unlock(unsigned long *flags) -{ - restore_flags(*flags); -} -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) */ - /******************************* PCI Definitions ******************************/ /* * PCIM_xxx: mask to locate subfield in register @@ -902,16 +853,6 @@ int aic7770_map_int(struct ahc_softc *ahc, u_int irq); /******************************* PCI Routines *********************************/ -/* - * We need to use the bios32.h routines if we are kernel version 2.1.92 or less. - */ -#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,1,92) -#if defined(__sparc_v9__) || defined(__powerpc__) -#error "PPC and Sparc platforms are only supported under 2.1.92 and above" -#endif -#include -#endif - int ahc_linux_pci_init(void); void ahc_linux_pci_exit(void); int ahc_pci_map_registers(struct ahc_softc *ahc); @@ -1224,7 +1165,8 @@ int ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, char channel, int lun, u_int tag, role_t role, uint32_t status); -irqreturn_t ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs); +AIC_LINUX_IRQRETURN_T + ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs); void ahc_platform_flushwork(struct ahc_softc *ahc); int ahc_softc_comp(struct ahc_softc *, struct ahc_softc *); void ahc_done(struct ahc_softc*, struct scb*); @@ -1239,5 +1181,5 @@ #define AHC_PCI_CONFIG 0 #endif #define bootverbose aic7xxx_verbose -extern int aic7xxx_verbose; +extern u_int aic7xxx_verbose; #endif /* _AIC7XXX_LINUX_H_ */ diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c --- a/drivers/scsi/aic7xxx/aic7xxx_pci.c Thu May 15 15:24:33 2003 +++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c Thu May 15 15:24:33 2003 @@ -39,7 +39,7 @@ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * - * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#62 $ + * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#63 $ * * $FreeBSD$ */ @@ -837,14 +837,6 @@ command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1); command |= PCIM_CMD_BUSMASTEREN; - /* - * Disable PCI parity error reporting. Users typically - * do this to work around broken PCI chipsets that get - * the parity timing wrong and thus generate lots of spurious - * errors. - */ - if ((ahc->flags & AHC_DISABLE_PCI_PERR) != 0) - command &= ~PCIM_CMD_PERRESPEN; ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/1); /* On all PCI adapters, we allow SCB paging */ @@ -854,6 +846,19 @@ if (error != 0) return (error); + /* + * Disable PCI parity error checking. Users typically + * do this to work around broken PCI chipsets that get + * the parity timing wrong and thus generate lots of spurious + * errors. The chip only allows us to disable *all* parity + * error reporting when doing this, so CIO bus, scb ram, and + * scratch ram parity errors will be ignored too. + */ + if ((ahc->flags & AHC_DISABLE_PCI_PERR) != 0) { + ahc->pause |= FAILDIS; + ahc->unpause |= FAILDIS; + } + ahc->bus_intr = ahc_pci_intr; ahc->bus_chip_init = ahc_pci_chip_init; ahc->bus_suspend = ahc_pci_suspend; @@ -1958,8 +1963,7 @@ } static uint8_t -read_brdctl(ahc) - struct ahc_softc *ahc; +read_brdctl(struct ahc_softc *ahc) { uint8_t brdctl; uint8_t value; @@ -1998,6 +2002,7 @@ ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); if (status1 & DPE) { + ahc->pci_target_perr_count++; printf("%s: Data Parity Error Detected during address " "or write data phase\n", ahc_name(ahc)); } @@ -2029,6 +2034,19 @@ ahc_outb(ahc, CLRINT, CLRPARERR); } + if (ahc->pci_target_perr_count > AHC_PCI_TARGET_PERR_THRESH) { + printf( +"%s: WARNING WARNING WARNING WARNING\n" +"%s: Too many PCI parity errors observed as a target.\n" +"%s: Some device on this bus is generating bad parity.\n" +"%s: This is an error *observed by*, not *generated by*, this controller.\n" +"%s: PCI parity error checking has been disabled.\n" +"%s: WARNING WARNING WARNING WARNING\n", + ahc_name(ahc), ahc_name(ahc), ahc_name(ahc), + ahc_name(ahc), ahc_name(ahc), ahc_name(ahc)); + ahc->pause |= FAILDIS; + ahc->unpause |= FAILDIS; + } ahc_unpause(ahc); } diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c --- a/drivers/scsi/aic7xxx/aic7xxx_proc.c Thu May 15 15:24:33 2003 +++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c Thu May 15 15:24:33 2003 @@ -37,7 +37,7 @@ * String handling code courtesy of Gerard Roudier's * sym driver. * - * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_proc.c#24 $ + * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic7xxx_proc.c#27 $ */ #include "aic7xxx_osm.h" #include "aic7xxx_inline.h" @@ -148,8 +148,9 @@ tinfo = ahc_fetch_transinfo(ahc, channel, our_id, target_id, &tstate); - copy_info(info, "Channel %c Target %d Negotiation Settings\n", - channel, target_id); + if ((ahc->features & AHC_TWIN) != 0) + copy_info(info, "Channel %c ", channel); + copy_info(info, "Target %d Negotiation Settings\n", target_id); copy_info(info, "\tUser: "); ahc_format_transinfo(info, &tinfo->user); targ = ahc->platform_data->targets[target_offset]; @@ -327,7 +328,10 @@ AIC7XXX_DRIVER_VERSION); copy_info(&info, "%s\n", ahc->description); ahc_controller_info(ahc, ahc_info); - copy_info(&info, "%s\n\n", ahc_info); + copy_info(&info, "%s\n", ahc_info); + copy_info(&info, "Allocated SCBs: %d, SG List Length: %d\n\n", + ahc->scb_data->numscbs, AHC_NSEG); + if (ahc->seep_config == NULL) copy_info(&info, "No Serial EEPROM\n"); diff -Nru a/drivers/scsi/aic7xxx/aiclib.c b/drivers/scsi/aic7xxx/aiclib.c --- a/drivers/scsi/aic7xxx/aiclib.c Thu May 15 15:24:39 2003 +++ b/drivers/scsi/aic7xxx/aiclib.c Thu May 15 15:24:39 2003 @@ -1335,7 +1335,7 @@ char * aic_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth, - aic_option_callback_t *callback, void *callback_arg) + aic_option_callback_t *callback, u_long callback_arg) { char *tok_end; char *tok_end2; diff -Nru a/drivers/scsi/aic7xxx/aiclib.h b/drivers/scsi/aic7xxx/aiclib.h --- a/drivers/scsi/aic7xxx/aiclib.h Thu May 15 15:24:33 2003 +++ b/drivers/scsi/aic7xxx/aiclib.h Thu May 15 15:24:33 2003 @@ -15,15 +15,58 @@ * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 * * $FreeBSD: src/sys/cam/scsi/scsi_all.h,v 1.21 2002/10/08 17:12:44 ken Exp $ + * + * Copyright (c) 2003 Adaptec Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * * $Id$ */ +#ifndef _AICLIB_H +#define _AICLIB_H + /* - * SCSI general interface description + * Linux Interrupt Support. */ - -#ifndef _SCSI_SCSI_ALL_H -#define _SCSI_SCSI_ALL_H 1 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) +#define AIC_LINUX_IRQRETURN_T irqreturn_t +#define AIC_LINUX_IRQRETURN(ours) return (IRQ_RETVAL(ours)) +#else +#define AIC_LINUX_IRQRETURN_T void +#define AIC_LINUX_IRQRETURN(ours) return +#endif /* * SCSI command format @@ -906,10 +949,10 @@ int aic_static_inquiry_match(caddr_t /*inqbuffer*/, caddr_t /*table_entry*/); -typedef void aic_option_callback_t(void *, int, int, int32_t); +typedef void aic_option_callback_t(u_long, int, int, int32_t); char * aic_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth, - aic_option_callback_t *, void *); + aic_option_callback_t *, u_long); static __inline void scsi_extract_sense(struct scsi_sense_data *sense, int *error_code, int *sense_key, @@ -1003,4 +1046,4 @@ return (rv); } -#endif /*_SCSI_SCSI_ALL_H*/ +#endif /*_AICLIB_H */ diff -Nru a/drivers/scsi/aic7xxx_old/aic7xxx.h b/drivers/scsi/aic7xxx_old/aic7xxx.h --- a/drivers/scsi/aic7xxx_old/aic7xxx.h Thu May 15 15:24:33 2003 +++ b/drivers/scsi/aic7xxx_old/aic7xxx.h Thu May 15 15:24:33 2003 @@ -25,48 +25,4 @@ #define AIC7XXX_H_VERSION "5.2.0" -/* - * Scsi_Host_Template (see hosts.h) for AIC-7xxx - some fields - * to do with card config are filled in after the card is detected. - */ -#define AIC7XXX { \ - .proc_info = aic7xxx_proc_info, \ - .detect = aic7xxx_detect, \ - .release = aic7xxx_release, \ - .info = aic7xxx_info, \ - .queuecommand = aic7xxx_queue, \ - .slave_alloc = aic7xxx_slave_alloc, \ - .slave_configure = aic7xxx_slave_configure, \ - .slave_destroy = aic7xxx_slave_destroy, \ - .bios_param = aic7xxx_biosparam, \ - .eh_abort_handler = aic7xxx_abort, \ - .eh_device_reset_handler = aic7xxx_bus_device_reset, \ - .eh_host_reset_handler = aic7xxx_reset, \ - .can_queue = 255, /* max simultaneous cmds */\ - .this_id = -1, /* scsi id of host adapter */\ - .sg_tablesize = 0, /* max scatter-gather cmds */\ - .max_sectors = 2048, /* max physical sectors in 1 cmd */\ - .cmd_per_lun = 3, /* cmds per lun (linked cmds) */\ - .present = 0, /* number of 7xxx's present */\ - .unchecked_isa_dma = 0, /* no memory DMA restrictions */\ - .use_clustering = ENABLE_CLUSTERING, \ -} - -extern int aic7xxx_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *)); -extern int aic7xxx_biosparam(struct scsi_device *, struct block_device *, - sector_t, int[]); -extern int aic7xxx_detect(Scsi_Host_Template *); -extern int aic7xxx_command(Scsi_Cmnd *); -extern int aic7xxx_release(struct Scsi_Host *); -static int aic7xxx_slave_alloc(Scsi_Device *); -static int aic7xxx_slave_configure(Scsi_Device *); -static void aic7xxx_slave_destroy(Scsi_Device *); -extern int aic7xxx_abort(Scsi_Cmnd *); -extern int aic7xxx_bus_device_reset(Scsi_Cmnd *); -extern int aic7xxx_reset(Scsi_Cmnd *); - -extern const char *aic7xxx_info(struct Scsi_Host *); - -extern int aic7xxx_proc_info(char *, char **, off_t, int, int, int); - #endif /* _aic7xxx_h */ diff -Nru a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c --- a/drivers/scsi/aic7xxx_old.c Thu May 15 15:24:37 2003 +++ b/drivers/scsi/aic7xxx_old.c Thu May 15 15:24:37 2003 @@ -1270,6 +1270,7 @@ * ***************************************************************************/ +static int aic7xxx_release(struct Scsi_Host *host); static void aic7xxx_set_syncrate(struct aic7xxx_host *p, struct aic7xxx_syncrate *syncrate, int target, int channel, unsigned int period, unsigned int offset, unsigned char options, @@ -8361,7 +8362,7 @@ * Perform a chip reset on the aic7xxx SCSI controller. The controller * is paused upon return. *-F*************************************************************************/ -int +static int aic7xxx_chip_reset(struct aic7xxx_host *p) { unsigned char sblkctl; @@ -8996,7 +8997,7 @@ * one do-it-all function. This may be useful when (and if) the * mid-level SCSI code is overhauled. *-F*************************************************************************/ -int +static int aic7xxx_detect(Scsi_Host_Template *template) { struct aic7xxx_host *temp_p = NULL; @@ -10293,7 +10294,7 @@ * Description: * Queue a SCB to the controller. *-F*************************************************************************/ -int +static int aic7xxx_queue(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *)) { struct aic7xxx_host *p; @@ -10364,7 +10365,7 @@ * aborted, then we will reset the channel and have all devices renegotiate. * Returns an enumerated type that indicates the status of the operation. *-F*************************************************************************/ -int +static int aic7xxx_bus_device_reset(Scsi_Cmnd *cmd) { struct aic7xxx_host *p; @@ -10566,7 +10567,7 @@ * Description: * Abort the current SCSI command(s). *-F*************************************************************************/ -void +static void aic7xxx_panic_abort(struct aic7xxx_host *p, Scsi_Cmnd *cmd) { @@ -10592,7 +10593,7 @@ * Description: * Abort the current SCSI command(s). *-F*************************************************************************/ -int +static int aic7xxx_abort(Scsi_Cmnd *cmd) { struct aic7xxx_scb *scb = NULL; @@ -10820,7 +10821,7 @@ * DEVICE RESET message - on the offending target before pulling * the SCSI bus reset line. *-F*************************************************************************/ -int +static int aic7xxx_reset(Scsi_Cmnd *cmd) { struct aic7xxx_scb *scb; @@ -10905,7 +10906,7 @@ * This function is broken for today's really large drives and needs * fixed. *-F*************************************************************************/ -int +static int aic7xxx_biosparam(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int geom[]) { @@ -10955,7 +10956,7 @@ * Free the passed in Scsi_Host memory structures prior to unloading the * module. *-F*************************************************************************/ -int +static int aic7xxx_release(struct Scsi_Host *host) { struct aic7xxx_host *p = (struct aic7xxx_host *) host->hostdata; @@ -11141,8 +11142,25 @@ MODULE_LICENSE("Dual BSD/GPL"); -/* Eventually this will go into an include file, but this will be later */ -static Scsi_Host_Template driver_template = AIC7XXX; +static Scsi_Host_Template driver_template = { + .proc_info = aic7xxx_proc_info, + .detect = aic7xxx_detect, + .release = aic7xxx_release, + .info = aic7xxx_info, + .queuecommand = aic7xxx_queue, + .slave_alloc = aic7xxx_slave_alloc, + .slave_configure = aic7xxx_slave_configure, + .slave_destroy = aic7xxx_slave_destroy, + .bios_param = aic7xxx_biosparam, + .eh_abort_handler = aic7xxx_abort, + .eh_device_reset_handler = aic7xxx_bus_device_reset, + .eh_host_reset_handler = aic7xxx_reset, + .can_queue = 255, + .this_id = -1, + .max_sectors = 2048, + .cmd_per_lun = 3, + .use_clustering = ENABLE_CLUSTERING, +}; #include "scsi_module.c" diff -Nru a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c --- a/drivers/scsi/atp870u.c Thu May 15 15:24:37 2003 +++ b/drivers/scsi/atp870u.c Thu May 15 15:24:37 2003 @@ -2748,5 +2748,19 @@ MODULE_LICENSE("GPL"); -static Scsi_Host_Template driver_template = ATP870U; +static Scsi_Host_Template driver_template = { + .proc_info = atp870u_proc_info, + .detect = atp870u_detect, + .release = atp870u_release, + .info = atp870u_info, + .command = atp870u_command, + .queuecommand = atp870u_queuecommand, + .eh_abort_handler = atp870u_abort, + .bios_param = atp870u_biosparam, + .can_queue = qcnt, + .this_id = 7, + .sg_tablesize = ATP870U_SCATTER, + .cmd_per_lun = ATP870U_CMDLUN, + .use_clustering = ENABLE_CLUSTERING, +}; #include "scsi_module.c" diff -Nru a/drivers/scsi/atp870u.h b/drivers/scsi/atp870u.h --- a/drivers/scsi/atp870u.h Thu May 15 15:24:33 2003 +++ b/drivers/scsi/atp870u.h Thu May 15 15:24:33 2003 @@ -37,22 +37,4 @@ extern int atp870u_proc_info(char *, char **, off_t, int, int, int); -#define ATP870U { \ - .proc_info = atp870u_proc_info, \ - .detect = atp870u_detect, \ - .release = atp870u_release, \ - .info = atp870u_info, \ - .command = atp870u_command, \ - .queuecommand = atp870u_queuecommand, \ - .eh_abort_handler = atp870u_abort, \ - .bios_param = atp870u_biosparam, \ - .can_queue = qcnt, /* max simultaneous cmds */\ - .this_id = 7, /* scsi id of host adapter */\ - .sg_tablesize = ATP870U_SCATTER, /* max scatter-gather cmds */\ - .cmd_per_lun = ATP870U_CMDLUN, /* cmds per lun (linked cmds) */\ - .present = 0, /* number of 7xxx's present */\ - .unchecked_isa_dma = 0, /* no memory DMA restrictions */\ - .use_clustering = ENABLE_CLUSTERING, \ -} - #endif diff -Nru a/drivers/scsi/cpqfcTS.h b/drivers/scsi/cpqfcTS.h --- a/drivers/scsi/cpqfcTS.h Thu May 15 15:24:37 2003 +++ b/drivers/scsi/cpqfcTS.h Thu May 15 15:24:37 2003 @@ -16,27 +16,4 @@ sector_t, int[]); extern int cpqfcTS_ioctl( Scsi_Device *ScsiDev, int Cmnd, void *arg); -// note: since Tachyon TS supports an extended scatter/gather -// linked list of infinite length (with linked Ext S/G pages, -// limited only by available physical memory) we use SG_ALL. - -#define CPQFCTS { \ - .detect = cpqfcTS_detect, \ - .release = cpqfcTS_release, \ - .info = cpqfcTS_info, \ - .proc_info = cpqfcTS_proc_info, \ - .ioctl = cpqfcTS_ioctl, \ - .queuecommand = cpqfcTS_queuecommand, \ - .eh_device_reset_handler = cpqfcTS_eh_device_reset, \ - .eh_abort_handler = cpqfcTS_eh_abort, \ - .bios_param = cpqfcTS_biosparam, \ - .can_queue = CPQFCTS_REQ_QUEUE_LEN, \ - .this_id = -1, \ - .sg_tablesize = SG_ALL, \ - .cmd_per_lun = CPQFCTS_CMD_PER_LUN, \ - .present = 0, \ - .unchecked_isa_dma = 0, \ - .use_clustering = ENABLE_CLUSTERING, \ -} - #endif /* CPQFCTS_H */ diff -Nru a/drivers/scsi/cpqfcTSinit.c b/drivers/scsi/cpqfcTSinit.c --- a/drivers/scsi/cpqfcTSinit.c Thu May 15 15:24:33 2003 +++ b/drivers/scsi/cpqfcTSinit.c Thu May 15 15:24:33 2003 @@ -677,11 +677,6 @@ scsi_release_request(ScsiPassThruReq); // "de-allocate" ScsiPassThruReq = NULL; - // if (!SDpnt->was_reset && SDpnt->scsi_request_fn) - // (*SDpnt->scsi_request_fn)(); - - wake_up(&SDpnt->scpnt_wait); - // need to pass data back to user (space)? if( (vendor_cmd->rw_flag == VENDOR_READ_OPCODE) && vendor_cmd->len ) @@ -1656,10 +1651,6 @@ scsi_put_command(SCpnt); SCpnt = NULL; - // if (!SDpnt->was_reset && SDpnt->scsi_request_fn) - // (*SDpnt->scsi_request_fn)(); - - wake_up(&SDpnt->scpnt_wait); // printk(" LEAVING cpqfcTS_TargetDeviceReset() - return SUCCESS \n"); return SUCCESS; } @@ -2060,7 +2051,21 @@ } -static Scsi_Host_Template driver_template = CPQFCTS; - +static Scsi_Host_Template driver_template = { + .detect = cpqfcTS_detect, + .release = cpqfcTS_release, + .info = cpqfcTS_info, + .proc_info = cpqfcTS_proc_info, + .ioctl = cpqfcTS_ioctl, + .queuecommand = cpqfcTS_queuecommand, + .eh_device_reset_handler = cpqfcTS_eh_device_reset, + .eh_abort_handler = cpqfcTS_eh_abort, + .bios_param = cpqfcTS_biosparam, + .can_queue = CPQFCTS_REQ_QUEUE_LEN, + .this_id = -1, + .sg_tablesize = SG_ALL, + .cmd_per_lun = CPQFCTS_CMD_PER_LUN, + .use_clustering = ENABLE_CLUSTERING, +}; #include "scsi_module.c" diff -Nru a/drivers/scsi/dc390.h b/drivers/scsi/dc390.h --- a/drivers/scsi/dc390.h Thu May 15 15:24:34 2003 +++ b/drivers/scsi/dc390.h Thu May 15 15:24:34 2003 @@ -50,45 +50,4 @@ extern int DC390_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,30) -#define DC390_T { \ - .proc_name = "tmscsim", \ - .proc_info = DC390_proc_info, \ - .name = DC390_BANNER " V" DC390_VERSION, \ - .detect = DC390_detect, \ - .release = DC390_release, \ - .queuecommand = DC390_queue_command, \ - .abort = DC390_abort, \ - .reset = DC390_reset, \ - .bios_param = DC390_bios_param, \ - .can_queue = 42, \ - .this_id = 7, \ - .sg_tablesize = SG_ALL, \ - .cmd_per_lun = 16, \ - .unchecked_isa_dma = 0, \ - .use_clustering = DISABLE_CLUSTERING \ - } -#else -extern struct proc_dir_entry DC390_proc_scsi_tmscsim; -#define DC390_T { \ - .proc_dir = &DC390_proc_scsi_tmscsim, \ - .proc_info = DC390_proc_info, \ - .name = DC390_BANNER " V" DC390_VERSION, \ - .detect = DC390_detect, \ - .release = DC390_release, \ - .queuecommand = DC390_queue_command, \ - .abort = DC390_abort, \ - .reset = DC390_reset, \ - .bios_param = DC390_bios_param, \ - .can_queue = 42, \ - .this_id = 7, \ - .sg_tablesize = SG_ALL, \ - .cmd_per_lun = 16, \ - NEW_EH \ - .unchecked_isa_dma = 0, \ - .use_clustering = DISABLE_CLUSTERING \ - } -#endif -#endif /* defined(HOSTS_C) || defined(MODULE) */ - #endif /* DC390_H */ diff -Nru a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c --- a/drivers/scsi/dc395x.c Thu May 15 15:24:34 2003 +++ b/drivers/scsi/dc395x.c Thu May 15 15:24:34 2003 @@ -51,6 +51,7 @@ #include #include #include +#include #include "scsi.h" #include "hosts.h" #include "dc395x.h" diff -Nru a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c --- a/drivers/scsi/dmx3191d.c Thu May 15 15:24:40 2003 +++ b/drivers/scsi/dmx3191d.c Thu May 15 15:24:40 2003 @@ -121,6 +121,21 @@ MODULE_LICENSE("GPL"); -static Scsi_Host_Template driver_template = DMX3191D; +static Scsi_Host_Template driver_template = { + .proc_info = dmx3191d_proc_info, + .name = "Domex DMX3191D", + .detect = dmx3191d_detect, + .release = dmx3191d_release_resources, + .info = dmx3191d_info, + .queuecommand = dmx3191d_queue_command, + .eh_abort_handler = dmx3191d_abort, + .eh_bus_reset_handler = dmx3191d_bus_reset, + .eh_device_reset_handler = dmx3191d_device_reset, + .eh_host_reset_handler = dmx3191d_host_reset, + .can_queue = 32, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 2, + .use_clustering = DISABLE_CLUSTERING, +}; #include "scsi_module.c" - diff -Nru a/drivers/scsi/dmx3191d.h b/drivers/scsi/dmx3191d.h --- a/drivers/scsi/dmx3191d.h Thu May 15 15:24:39 2003 +++ b/drivers/scsi/dmx3191d.h Thu May 15 15:24:39 2003 @@ -30,27 +30,6 @@ static int dmx3191d_host_reset(Scsi_Cmnd *); static int dmx3191d_device_reset(Scsi_Cmnd *); - -#define DMX3191D { \ - .proc_info = dmx3191d_proc_info, \ - .name = "Domex DMX3191D", \ - .detect = dmx3191d_detect, \ - .release = dmx3191d_release_resources, \ - .info = dmx3191d_info, \ - .queuecommand = dmx3191d_queue_command, \ - .eh_abort_handler = dmx3191d_abort, \ - .eh_bus_reset_handler = dmx3191d_bus_reset, \ - .eh_device_reset_handler = dmx3191d_device_reset, \ - .eh_host_reset_handler = dmx3191d_host_reset, \ - .bios_param = NULL, \ - .can_queue = 32, \ - .this_id = 7, \ - .sg_tablesize = SG_ALL, \ - .cmd_per_lun = 2, \ - .use_clustering = DISABLE_CLUSTERING \ -} - - #define NCR5380_read(reg) inb(port + reg) #define NCR5380_write(reg, value) outb(value, port + reg) diff -Nru a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c --- a/drivers/scsi/dpt_i2o.c Thu May 15 15:24:42 2003 +++ b/drivers/scsi/dpt_i2o.c Thu May 15 15:24:42 2003 @@ -2495,8 +2495,6 @@ pDev->pScsi_dev->online = FALSE; if (pDev->pScsi_dev->access_count) { // A drive that was mounted is no longer there... bad! - SCSI_LOG_ERROR_RECOVERY(1, printk ("%s:Rescan: Previously " - "mounted drive not found!\n",pHba->name)); printk(KERN_WARNING"%s:Mounted drive taken offline\n",pHba->name); } } @@ -3306,6 +3304,24 @@ #endif -static Scsi_Host_Template driver_template = DPT_I2O; +static Scsi_Host_Template driver_template = { + .name = "dpt_i2o", + .proc_name = "dpt_i2o", + .proc_info = adpt_proc_info, + .detect = adpt_detect, + .release = adpt_release, + .info = adpt_info, + .queuecommand = adpt_queue, + .eh_abort_handler = adpt_abort, + .eh_device_reset_handler = adpt_device_reset, + .eh_bus_reset_handler = adpt_bus_reset, + .eh_host_reset_handler = adpt_reset, + .bios_param = adpt_bios_param, + .slave_configure = adpt_slave_configure, + .can_queue = MAX_TO_IOP_MESSAGES, + .this_id = 7, + .cmd_per_lun = 1, + .use_clustering = ENABLE_CLUSTERING, +}; #include "scsi_module.c" MODULE_LICENSE("GPL"); diff -Nru a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h --- a/drivers/scsi/dpti.h Thu May 15 15:24:32 2003 +++ b/drivers/scsi/dpti.h Thu May 15 15:24:32 2003 @@ -60,49 +60,6 @@ #define DPT_DRIVER_NAME "Adaptec I2O RAID" -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,00) -#define DPT_I2O { \ - .proc_info = adpt_proc_info, \ - .detect = adpt_detect, \ - .release = adpt_release, \ - .info = adpt_info, \ - .queuecommand = adpt_queue, \ - .eh_abort_handler = adpt_abort, \ - .eh_device_reset_handler = adpt_device_reset, \ - .eh_bus_reset_handler = adpt_bus_reset, \ - .eh_host_reset_handler = adpt_reset, \ - .bios_param = adpt_bios_param, \ - .can_queue = MAX_TO_IOP_MESSAGES ,/* max simultaneous cmds */\ - .this_id = 7, /* scsi id of host adapter */\ - .sg_tablesize = 0, /* max scatter-gather cmds */\ - .cmd_per_lun = 256, /* cmds per lun (linked cmds) */\ - .use_clustering = ENABLE_CLUSTERING, \ - .use_new_eh_code = 1 \ -} - -#else /* KERNEL_VERSION > 2.2.16 */ - -#define DPT_I2O { \ - .proc_info = adpt_proc_info, \ - .detect = adpt_detect, \ - .release = adpt_release, \ - .info = adpt_info, \ - .queuecommand = adpt_queue, \ - .eh_abort_handler = adpt_abort, \ - .eh_device_reset_handler = adpt_device_reset, \ - .eh_bus_reset_handler = adpt_bus_reset, \ - .eh_host_reset_handler = adpt_reset, \ - .bios_param = adpt_bios_param, \ - .slave_configure = adpt_slave_configure, \ - .can_queue = MAX_TO_IOP_MESSAGES, /* max simultaneous cmds */\ - .this_id = 7, /* scsi id of host adapter */\ - .sg_tablesize = 0, /* max scatter-gather cmds */\ - .cmd_per_lun = 1, /* cmds per lun (linked cmds) */\ - .use_clustering = ENABLE_CLUSTERING, \ - .proc_name = "dpt_i2o" /* this is the name of our proc node*/ \ -} -#endif - #ifndef HOSTS_C #include "dpt/sys_info.h" diff -Nru a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c --- a/drivers/scsi/dtc.c Thu May 15 15:24:41 2003 +++ b/drivers/scsi/dtc.c Thu May 15 15:24:41 2003 @@ -447,6 +447,19 @@ #include "NCR5380.c" -/* Eventually this will go into an include file, but this will be later */ -static Scsi_Host_Template driver_template = DTC3x80; +static Scsi_Host_Template driver_template = { + .name = "DTC 3180/3280 ", + .detect = dtc_detect, + .queuecommand = dtc_queue_command, + .eh_abort_handler = dtc_abort, + .eh_bus_reset_handler = dtc_bus_reset, + .eh_device_reset_handler = dtc_device_reset, + .eh_host_reset_handler = dtc_host_reset, + .bios_param = dtc_biosparam, + .can_queue = CAN_QUEUE, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = CMD_PER_LUN, + .use_clustering = DISABLE_CLUSTERING, +}; #include "scsi_module.c" diff -Nru a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h --- a/drivers/scsi/dtc.h Thu May 15 15:24:33 2003 +++ b/drivers/scsi/dtc.h Thu May 15 15:24:33 2003 @@ -47,27 +47,6 @@ #define CAN_QUEUE 32 #endif -/* - * I hadn't thought of this with the earlier drivers - but to prevent - * macro definition conflicts, we shouldn't define all of the internal - * macros when this is being used solely for the host stub. - */ - -#define DTC3x80 { \ - .name = "DTC 3180/3280 ", \ - .detect = dtc_detect, \ - .queuecommand = dtc_queue_command, \ - .eh_abort_handler = dtc_abort, \ - .eh_bus_reset_handler = dtc_bus_reset, \ - .eh_device_reset_handler = dtc_device_reset, \ - .eh_host_reset_handler = dtc_host_reset, \ - .bios_param = dtc_biosparam, \ - .can_queue = CAN_QUEUE, \ - .this_id = 7, \ - .sg_tablesize = SG_ALL, \ - .cmd_per_lun = CMD_PER_LUN , \ - .use_clustering = DISABLE_CLUSTERING} - #define NCR5380_implementation_fields \ unsigned int base diff -Nru a/drivers/scsi/eata.c b/drivers/scsi/eata.c --- a/drivers/scsi/eata.c Thu May 15 15:24:43 2003 +++ b/drivers/scsi/eata.c Thu May 15 15:24:43 2003 @@ -2375,8 +2375,19 @@ return FALSE; } -static Scsi_Host_Template driver_template = EATA; - +static Scsi_Host_Template driver_template = { + .name = "EATA/DMA 2.0x rev. " EATA_VERSION " ", + .detect = eata2x_detect, + .release = eata2x_release, + .queuecommand = eata2x_queuecommand, + .eh_abort_handler = eata2x_eh_abort, + .eh_host_reset_handler = eata2x_eh_host_reset, + .bios_param = eata2x_bios_param, + .slave_configure = eata2x_slave_configure, + .this_id = 7, + .unchecked_isa_dma = 1, + .use_clustering = ENABLE_CLUSTERING, +}; #include "scsi_module.c" #ifndef MODULE diff -Nru a/drivers/scsi/eata.h b/drivers/scsi/eata.h --- a/drivers/scsi/eata.h Thu May 15 15:24:34 2003 +++ b/drivers/scsi/eata.h Thu May 15 15:24:34 2003 @@ -13,18 +13,3 @@ #define EATA_VERSION "8.03.00" -#define EATA { \ - .name = "EATA/DMA 2.0x rev. " EATA_VERSION " ", \ - .detect = eata2x_detect, \ - .release = eata2x_release, \ - .queuecommand = eata2x_queuecommand, \ - .eh_abort_handler = eata2x_eh_abort, \ - .eh_device_reset_handler = NULL, \ - .eh_bus_reset_handler = NULL, \ - .eh_host_reset_handler = eata2x_eh_host_reset, \ - .bios_param = eata2x_bios_param, \ - .slave_configure = eata2x_slave_configure, \ - .this_id = 7, \ - .unchecked_isa_dma = 1, \ - .use_clustering = ENABLE_CLUSTERING \ - } diff -Nru a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c --- a/drivers/scsi/eata_pio.c Thu May 15 15:24:40 2003 +++ b/drivers/scsi/eata_pio.c Thu May 15 15:24:40 2003 @@ -106,7 +106,6 @@ int length, int hostno, int rw) { struct Scsi_Host *shost; - struct scsi_device *sdev; static u8 buff[512]; int size, len = 0; off_t begin = 0, pos = 0; diff -Nru a/drivers/scsi/esp.c b/drivers/scsi/esp.c --- a/drivers/scsi/esp.c Thu May 15 15:24:45 2003 +++ b/drivers/scsi/esp.c Thu May 15 15:24:45 2003 @@ -4380,10 +4380,7 @@ .sg_tablesize = SG_ALL, .cmd_per_lun = 1, .use_clustering = ENABLE_CLUSTERING, -/* Sparc32's iommu code cannot handle highmem pages yet. */ -#ifdef CONFIG_SPARC64 .highmem_io = 1, -#endif }; #include "scsi_module.c" diff -Nru a/drivers/scsi/fcal.c b/drivers/scsi/fcal.c --- a/drivers/scsi/fcal.c Thu May 15 15:24:33 2003 +++ b/drivers/scsi/fcal.c Thu May 15 15:24:33 2003 @@ -302,7 +302,22 @@ return 0; } -static Scsi_Host_Template driver_template = FCAL; - +static Scsi_Host_Template driver_template = { + .name = "Fibre Channel Arbitrated Loop", + .detect = fcal_detect, + .release = fcal_release, + .proc_info = fcal_proc_info, + .queuecommand = fcp_scsi_queuecommand, + .slave_configure = fcal_slave_configure, + .can_queue = FCAL_CAN_QUEUE, + .this_id = -1, + .sg_tablesize = 1, + .cmd_per_lun = 1, + .use_clustering = ENABLE_CLUSTERING, + .eh_abort_handler = fcp_scsi_abort, + .eh_device_reset_handler = fcp_scsi_dev_reset, + .eh_bus_reset_handler = fcp_scsi_bus_reset, + .eh_host_reset_handler = fcp_scsi_host_reset, +}; #include "scsi_module.c" diff -Nru a/drivers/scsi/fcal.h b/drivers/scsi/fcal.h --- a/drivers/scsi/fcal.h Thu May 15 15:24:33 2003 +++ b/drivers/scsi/fcal.h Thu May 15 15:24:33 2003 @@ -25,22 +25,4 @@ int fcal_proc_info (char *, char **, off_t, int, int, int); int fcal_slave_configure(Scsi_Device *); -#define FCAL { \ - .name = "Fibre Channel Arbitrated Loop",\ - .detect = fcal_detect, \ - .release = fcal_release, \ - .proc_info = fcal_proc_info, \ - .queuecommand = fcp_scsi_queuecommand, \ - .slave_configure = fcal_slave_configure, \ - .can_queue = FCAL_CAN_QUEUE, \ - .this_id = -1, \ - .sg_tablesize = 1, \ - .cmd_per_lun = 1, \ - .use_clustering = ENABLE_CLUSTERING, \ - .eh_abort_handler = fcp_scsi_abort, \ - .eh_device_reset_handler = fcp_scsi_dev_reset, \ - .eh_bus_reset_handler = fcp_scsi_bus_reset, \ - .eh_host_reset_handler = fcp_scsi_host_reset, \ -} - #endif /* !(_FCAL_H) */ diff -Nru a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c --- a/drivers/scsi/fd_mcs.c Thu May 15 15:24:37 2003 +++ b/drivers/scsi/fd_mcs.c Thu May 15 15:24:37 2003 @@ -740,7 +740,7 @@ #if DEBUG_RACE in_interrupt_flag = 0; #endif - return; + return IRQ_HANDLED; } else if (current_SC->SCp.phase & in_selection) { status = inb(SCSI_Status_port); if (!(status & 0x01)) { @@ -1436,7 +1436,23 @@ return 0; } -/* Eventually this will go into an include file, but this will be later */ - static Scsi_Host_Template driver_template = FD_MCS; - +static Scsi_Host_Template driver_template = { + .proc_name = "fd_mcs", + .proc_info = fd_mcs_proc_info, + .detect = fd_mcs_detect, + .release = fd_mcs_release, + .info = fd_mcs_info, + .command = fd_mcs_command, + .queuecommand = fd_mcs_queue, + .eh_abort_handler = fd_mcs_abort, + .eh_bus_reset_handler = fd_mcs_bus_reset, + .eh_host_reset_handler = fd_mcs_host_reset, + .eh_device_reset_handler = fd_mcs_device_reset, + .bios_param = fd_mcs_biosparam, + .can_queue = 1, + .this_id = 7, + .sg_tablesize = 64, + .cmd_per_lun = 1, + .use_clustering = DISABLE_CLUSTERING, +}; #include "scsi_module.c" diff -Nru a/drivers/scsi/fd_mcs.h b/drivers/scsi/fd_mcs.h --- a/drivers/scsi/fd_mcs.h Thu May 15 15:24:34 2003 +++ b/drivers/scsi/fd_mcs.h Thu May 15 15:24:34 2003 @@ -35,24 +35,4 @@ static int fd_mcs_proc_info(char *, char **, off_t, int, int, int); static const char *fd_mcs_info(struct Scsi_Host *); -#define FD_MCS {\ - .proc_name = "fd_mcs", \ - .proc_info = fd_mcs_proc_info, \ - .detect = fd_mcs_detect, \ - .release = fd_mcs_release, \ - .info = fd_mcs_info, \ - .command = fd_mcs_command, \ - .queuecommand = fd_mcs_queue, \ - .eh_abort_handler = fd_mcs_abort, \ - .eh_bus_reset_handler = fd_mcs_bus_reset, \ - .eh_host_reset_handler = fd_mcs_host_reset, \ - .eh_device_reset_handler = fd_mcs_device_reset, \ - .bios_param = fd_mcs_biosparam, \ - .can_queue = 1, \ - .this_id = 7, \ - .sg_tablesize = 64, \ - .cmd_per_lun = 1, \ - .use_clustering = DISABLE_CLUSTERING \ - } - #endif /* _FD_MCS_H */ diff -Nru a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c --- a/drivers/scsi/g_NCR5380.c Thu May 15 15:24:34 2003 +++ b/drivers/scsi/g_NCR5380.c Thu May 15 15:24:34 2003 @@ -885,11 +885,24 @@ #undef PRINTP #undef ANDP -/* - * Eventually this will go into an include file, but this will be later - */ -static Scsi_Host_Template driver_template = GENERIC_NCR5380; - +static Scsi_Host_Template driver_template = { + .proc_info = generic_NCR5380_proc_info, + .name = "Generic NCR5380/NCR53C400 Scsi Driver", + .detect = generic_NCR5380_detect, + .release = generic_NCR5380_release_resources, + .info = generic_NCR5380_info, + .queuecommand = generic_NCR5380_queue_command, + .eh_abort_handler = generic_NCR5380_abort, + .eh_bus_reset_handler = generic_NCR5380_bus_reset, + .eh_device_reset_handler = generic_NCR5380_device_reset, + .eh_host_reset_handler = generic_NCR5380_host_reset, + .bios_param = NCR5380_BIOSPARAM, + .can_queue = CAN_QUEUE, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = CMD_PER_LUN, + .use_clustering = DISABLE_CLUSTERING, +}; #include #include "scsi_module.c" diff -Nru a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h --- a/drivers/scsi/g_NCR5380.h Thu May 15 15:24:33 2003 +++ b/drivers/scsi/g_NCR5380.h Thu May 15 15:24:33 2003 @@ -65,24 +65,6 @@ #define CAN_QUEUE 16 #endif -#define GENERIC_NCR5380 { \ - .proc_info = generic_NCR5380_proc_info, \ - .name = "Generic NCR5380/NCR53C400 Scsi Driver", \ - .detect = generic_NCR5380_detect, \ - .release = generic_NCR5380_release_resources, \ - .info = (void *)generic_NCR5380_info, \ - .queuecommand = generic_NCR5380_queue_command, \ - .eh_abort_handler = generic_NCR5380_abort, \ - .eh_bus_reset_handler = generic_NCR5380_bus_reset, \ - .eh_device_reset_handler = generic_NCR5380_device_reset, \ - .eh_host_reset_handler = generic_NCR5380_host_reset, \ - .bios_param = NCR5380_BIOSPARAM, \ - .can_queue = CAN_QUEUE, \ - .this_id = 7, \ - .sg_tablesize = SG_ALL, \ - .cmd_per_lun = CMD_PER_LUN , \ - .use_clustering = DISABLE_CLUSTERING} - #ifndef HOSTS_C #define __STRVAL(x) #x diff -Nru a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c --- a/drivers/scsi/gdth.c Thu May 15 15:24:40 2003 +++ b/drivers/scsi/gdth.c Thu May 15 15:24:40 2003 @@ -5790,7 +5790,34 @@ #else -static Scsi_Host_Template driver_template = GDTH; +static Scsi_Host_Template driver_template = { +#if LINUX_VERSION_CODE >= 0x02015F + .proc_name = "gdth", +#else + .proc_dir = &proc_scsi_gdth, +#endif + .proc_info = gdth_proc_info, + .name = "GDT SCSI Disk Array Controller", + .detect = gdth_detect, + .release = gdth_release, + .info = gdth_info, + .queuecommand = gdth_queuecommand, + .eh_abort_handler = gdth_eh_abort, + .eh_device_reset_handler = gdth_eh_device_reset, + .eh_bus_reset_handler = gdth_eh_bus_reset, + .eh_host_reset_handler = gdth_eh_host_reset, + .bios_param = gdth_bios_param, + .can_queue = GDTH_MAXCMDS, + .this_id = -1, + .sg_tablesize = GDTH_MAXSG, + .cmd_per_lun = GDTH_MAXC_P_L, + .unchecked_isa_dma = 1, + .use_clustering = ENABLE_CLUSTERING, +#if LINUX_VERSION_CODE < 0x020501 + .use_new_eh_code = 1, +#endif +}; + #include "scsi_module.c" #ifndef MODULE __setup("gdth=", option_setup); diff -Nru a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h --- a/drivers/scsi/gdth.h Thu May 15 15:24:37 2003 +++ b/drivers/scsi/gdth.h Thu May 15 15:24:37 2003 @@ -983,29 +983,6 @@ int gdth_eh_device_reset(Scsi_Cmnd *scp); int gdth_eh_bus_reset(Scsi_Cmnd *scp); int gdth_eh_host_reset(Scsi_Cmnd *scp); -#define GDTH { .proc_name = "gdth", \ - .proc_info = gdth_proc_info, \ - .name = "GDT SCSI Disk Array Controller",\ - .detect = gdth_detect, \ - .release = gdth_release, \ - .info = gdth_info, \ - .command = NULL, \ - .queuecommand = gdth_queuecommand, \ - .eh_abort_handler = gdth_eh_abort, \ - .eh_device_reset_handler = gdth_eh_device_reset, \ - .eh_bus_reset_handler = gdth_eh_bus_reset, \ - .eh_host_reset_handler = gdth_eh_host_reset, \ - .abort = NULL, \ - .reset = NULL, \ - .bios_param = gdth_bios_param, \ - .can_queue = GDTH_MAXCMDS, \ - .this_id = -1, \ - .sg_tablesize = GDTH_MAXSG, \ - .cmd_per_lun = GDTH_MAXC_P_L, \ - .present = 0, \ - .unchecked_isa_dma = 1, \ - .use_clustering = ENABLE_CLUSTERING} - #elif LINUX_VERSION_CODE >= 0x020322 int gdth_bios_param(Disk *,kdev_t,int *); int gdth_proc_info(char *,char **,off_t,int,int,int); @@ -1013,30 +990,6 @@ int gdth_eh_device_reset(Scsi_Cmnd *scp); int gdth_eh_bus_reset(Scsi_Cmnd *scp); int gdth_eh_host_reset(Scsi_Cmnd *scp); -#define GDTH { proc_name: "gdth", \ - proc_info: gdth_proc_info, \ - name: "GDT SCSI Disk Array Controller",\ - detect: gdth_detect, \ - release: gdth_release, \ - info: gdth_info, \ - command: NULL, \ - queuecommand: gdth_queuecommand, \ - eh_abort_handler: gdth_eh_abort, \ - eh_device_reset_handler: gdth_eh_device_reset, \ - eh_bus_reset_handler: gdth_eh_bus_reset, \ - eh_host_reset_handler: gdth_eh_host_reset, \ - abort: gdth_abort, \ - reset: gdth_reset, \ - bios_param: gdth_bios_param, \ - can_queue: GDTH_MAXCMDS, \ - this_id: -1, \ - sg_tablesize: GDTH_MAXSG, \ - cmd_per_lun: GDTH_MAXC_P_L, \ - present: 0, \ - unchecked_isa_dma: 1, \ - use_clustering: ENABLE_CLUSTERING, \ - use_new_eh_code: 1 /* use new error code */ } - #elif LINUX_VERSION_CODE >= 0x02015F int gdth_bios_param(Disk *,kdev_t,int *); extern struct proc_dir_entry proc_scsi_gdth; @@ -1045,76 +998,12 @@ int gdth_eh_device_reset(Scsi_Cmnd *scp); int gdth_eh_bus_reset(Scsi_Cmnd *scp); int gdth_eh_host_reset(Scsi_Cmnd *scp); -#define GDTH { proc_dir: &proc_scsi_gdth, \ - proc_info: gdth_proc_info, \ - name: "GDT SCSI Disk Array Controller",\ - detect: gdth_detect, \ - release: gdth_release, \ - info: gdth_info, \ - command: NULL, \ - queuecommand: gdth_queuecommand, \ - eh_abort_handler: gdth_eh_abort, \ - eh_device_reset_handler: gdth_eh_device_reset, \ - eh_bus_reset_handler: gdth_eh_bus_reset, \ - eh_host_reset_handler: gdth_eh_host_reset, \ - abort: gdth_abort, \ - reset: gdth_reset, \ - bios_param: gdth_bios_param, \ - can_queue: GDTH_MAXCMDS, \ - this_id: -1, \ - sg_tablesize: GDTH_MAXSG, \ - cmd_per_lun: GDTH_MAXC_P_L, \ - present: 0, \ - unchecked_isa_dma: 1, \ - use_clustering: ENABLE_CLUSTERING, \ - use_new_eh_code: 1 /* use new error code */ } - #elif LINUX_VERSION_CODE >= 0x010300 int gdth_bios_param(Disk *,kdev_t,int *); extern struct proc_dir_entry proc_scsi_gdth; int gdth_proc_info(char *,char **,off_t,int,int,int); -#define GDTH { NULL, NULL, \ - &proc_scsi_gdth, \ - gdth_proc_info, \ - "GDT SCSI Disk Array Controller", \ - gdth_detect, \ - gdth_release, \ - gdth_info, \ - NULL, \ - gdth_queuecommand, \ - gdth_abort, \ - gdth_reset, \ - NULL, \ - gdth_bios_param, \ - GDTH_MAXCMDS, \ - -1, \ - GDTH_MAXSG, \ - GDTH_MAXC_P_L, \ - 0, \ - 1, \ - ENABLE_CLUSTERING} - #else int gdth_bios_param(Disk *,int,int *); -#define GDTH { NULL, NULL, \ - "GDT SCSI Disk Array Controller", \ - gdth_detect, \ - gdth_release, \ - gdth_info, \ - NULL, \ - gdth_queuecommand, \ - gdth_abort, \ - gdth_reset, \ - NULL, \ - gdth_bios_param, \ - GDTH_MAXCMDS, \ - -1, \ - GDTH_MAXSG, \ - GDTH_MAXC_P_L, \ - 0, \ - 1, \ - ENABLE_CLUSTERING} #endif - #endif diff -Nru a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c --- a/drivers/scsi/hosts.c Thu May 15 15:24:33 2003 +++ b/drivers/scsi/hosts.c Thu May 15 15:24:33 2003 @@ -32,20 +32,20 @@ #include #include #include -#include #include #include #include #include - -#define __KERNEL_SYSCALLS__ - #include #include #include "scsi.h" #include "hosts.h" +#include "scsi_priv.h" +#include "scsi_logging.h" + + static LIST_HEAD(scsi_host_list); static spinlock_t scsi_host_list_lock = SPIN_LOCK_UNLOCKED; @@ -193,62 +193,6 @@ return 0; } -static int scsi_remove_legacy_host(struct Scsi_Host *shost) -{ - int error; - - error = scsi_remove_host(shost); - if (!error) - (*shost->hostt->release)(shost); - return 0; -} - -static int scsi_check_device_busy(struct scsi_device *sdev) -{ - struct Scsi_Host *shost = sdev->host; - struct scsi_cmnd *scmd; - unsigned long flags; - - /* - * Loop over all of the commands associated with the - * device. If any of them are busy, then set the state - * back to inactive and bail. - */ - spin_lock_irqsave(&sdev->list_lock, flags); - list_for_each_entry(scmd, &sdev->cmd_list, list) { - if (scmd->request && scmd->request->rq_status != RQ_INACTIVE) - goto active; - - /* - * No, this device is really free. Mark it as such, and - * continue on. - */ - scmd->state = SCSI_STATE_DISCONNECTING; - if (scmd->request) - scmd->request->rq_status = RQ_SCSI_DISCONNECTING; - } - spin_unlock_irqrestore(&sdev->list_lock, flags); - - return 0; - -active: - printk(KERN_ERR "SCSI device not inactive - rq_status=%d, target=%d, " - "pid=%ld, state=%d, owner=%d.\n", - scmd->request->rq_status, scmd->device->id, - scmd->pid, scmd->state, scmd->owner); - - list_for_each_entry(sdev, &shost->my_devices, siblings) { - list_for_each_entry(scmd, &sdev->cmd_list, list) { - if (scmd->request->rq_status == RQ_SCSI_DISCONNECTING) - scmd->request->rq_status = RQ_INACTIVE; - } - } - - spin_unlock_irqrestore(&sdev->list_lock, flags); - printk(KERN_ERR "Device busy???\n"); - return 1; -} - /** * scsi_remove_host - check a scsi host for release and release * @shost: a pointer to a scsi host to release @@ -268,11 +212,9 @@ list_for_each_entry(sdev, &shost->my_devices, siblings) sdev->online = FALSE; - list_for_each_entry(sdev, &shost->my_devices, siblings) - if (scsi_check_device_busy(sdev)) - return 1; - + scsi_proc_host_rm(shost); scsi_forget_host(shost); + scsi_sysfs_remove_host(shost); return 0; } @@ -293,9 +235,11 @@ printk(KERN_INFO "scsi%d : %s\n", shost->host_no, sht->info ? sht->info(shost) : sht->name); - if (dev) { - shost->host_gendev = dev; - } + error = scsi_sysfs_add_host(shost, dev); + if (error) + return error; + + scsi_proc_host_add(shost); scsi_scan_host(shost); @@ -314,6 +258,15 @@ **/ void scsi_unregister(struct Scsi_Host *shost) { + scsi_host_put(shost); +} + +/** + * scsi_free_sdev - free a scsi hosts resources + * @shost: scsi host to free + **/ +void scsi_free_shost(struct Scsi_Host *shost) +{ /* Remove shost from scsi_host_list */ spin_lock(&scsi_host_list_lock); list_del(&shost->sh_list); @@ -332,7 +285,6 @@ } shost->hostt->present--; - scsi_proc_host_rm(shost); scsi_destroy_command_freelist(shost); kfree(shost); } @@ -423,8 +375,14 @@ shost->use_clustering = shost_tp->use_clustering; if (!blk_nohighio) shost->highmem_io = shost_tp->highmem_io; - - shost->max_sectors = shost_tp->max_sectors; + if (!shost_tp->max_sectors) { + /* + * Driver imposes no hard sector transfer limit. + * start at machine infinity initially. + */ + shost->max_sectors = SCSI_DEFAULT_MAX_SECTORS; + } else + shost->max_sectors = shost_tp->max_sectors; shost->use_blk_tcq = shost_tp->use_blk_tcq; spin_lock(&scsi_host_list_lock); @@ -447,7 +405,8 @@ rval = scsi_setup_command_freelist(shost); if (rval) goto fail; - scsi_proc_host_add(shost); + + scsi_sysfs_init_host(shost); shost->eh_notify = &sem; kernel_thread((int (*)(void *)) scsi_error_handler, (void *) shost, 0); @@ -525,7 +484,7 @@ **/ int scsi_unregister_host(Scsi_Host_Template *shost_tp) { - scsi_tp_for_each_host(shost_tp, scsi_remove_legacy_host); + scsi_tp_for_each_host(shost_tp, scsi_remove_host); return 0; } @@ -576,15 +535,26 @@ } /** + * *scsi_host_get - inc a Scsi_Host ref count + * @shost: Pointer to Scsi_Host to inc. + **/ +void scsi_host_get(struct Scsi_Host *shost) +{ + + get_device(&shost->host_gendev); + class_device_get(&shost->class_dev); + return; +} + +/** * *scsi_host_put - dec a Scsi_Host ref count * @shost: Pointer to Scsi_Host to dec. **/ void scsi_host_put(struct Scsi_Host *shost) { - /* XXX Get list lock */ - /* XXX dec ref count */ - /* XXX Release list lock */ + class_device_put(&shost->class_dev); + put_device(&shost->host_gendev); return; } diff -Nru a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h --- a/drivers/scsi/hosts.h Thu May 15 15:24:36 2003 +++ b/drivers/scsi/hosts.h Thu May 15 15:24:36 2003 @@ -482,9 +482,10 @@ unsigned int max_host_blocked; /* - * Support for driverfs filesystem + * Support for sysfs */ - struct device *host_gendev; + struct device host_gendev; + struct class_device class_dev; /* * We should ensure that this is aligned, both for better performance @@ -495,8 +496,11 @@ __attribute__ ((aligned (sizeof(unsigned long)))); }; -#define to_scsi_host(d) d->driver_data /* Major logical breakage, but we compile again... */ - +#define dev_to_shost(d) \ + container_of(d, struct Scsi_Host, host_gendev) +#define class_to_shost(d) \ + container_of(d, struct Scsi_Host, class_dev) + /* * These two functions are used to allocate and free a pseudo device * which will connect to the host adapter itself rather than any @@ -510,6 +514,7 @@ extern void scsi_unblock_requests(struct Scsi_Host *); extern void scsi_block_requests(struct Scsi_Host *); extern void scsi_report_bus_reset(struct Scsi_Host *, int); +extern void scsi_report_device_reset(struct Scsi_Host *, int, int); static inline void scsi_assign_lock(struct Scsi_Host *shost, spinlock_t *lock) { @@ -519,21 +524,14 @@ static inline void scsi_set_device(struct Scsi_Host *shost, struct device *dev) { - shost->host_gendev = dev; + shost->host_gendev.parent = dev; } static inline struct device *scsi_get_device(struct Scsi_Host *shost) { - return shost->host_gendev; + return shost->host_gendev.parent; } -/* - * Prototypes for functions/data in scsi_scan.c - */ -extern void scsi_scan_host(struct Scsi_Host *); -extern void scsi_forget_host(struct Scsi_Host *); - - struct Scsi_Device_Template { struct list_head list; @@ -572,16 +570,8 @@ extern int scsi_register_host(Scsi_Host_Template *); extern int scsi_unregister_host(Scsi_Host_Template *); -extern struct Scsi_Host *scsi_host_get_next(struct Scsi_Host *); extern struct Scsi_Host *scsi_host_hn_get(unsigned short); extern void scsi_host_put(struct Scsi_Host *); -extern void scsi_host_init(void); - -/* - * host_busy inc/dec/test functions - */ -extern void scsi_host_busy_inc(struct Scsi_Host *, Scsi_Device *); -extern void scsi_host_busy_dec_and_test(struct Scsi_Host *, Scsi_Device *); /** * scsi_find_device - find a device given the host @@ -601,30 +591,4 @@ return NULL; } -/* - * sysfs support - */ -extern int scsi_upper_driver_register(struct Scsi_Device_Template *); -extern void scsi_upper_driver_unregister(struct Scsi_Device_Template *); - -extern struct class shost_class; - #endif -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff -Nru a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c --- a/drivers/scsi/ibmmca.c Thu May 15 15:24:33 2003 +++ b/drivers/scsi/ibmmca.c Thu May 15 15:24:33 2003 @@ -2484,6 +2484,21 @@ __setup("ibmmcascsi=", option_setup); -static Scsi_Host_Template driver_template = IBMMCA; - +static Scsi_Host_Template driver_template = { + .proc_name = "ibmmca", + .proc_info = ibmmca_proc_info, + .name = "IBM SCSI-Subsystem", + .detect = ibmmca_detect, + .release = ibmmca_release, + .command = ibmmca_command, + .queuecommand = ibmmca_queuecommand, + .eh_abort_handler = ibmmca_abort, + .eh_host_reset_handler = ibmmca_host_reset, + .bios_param = ibmmca_biosparam, + .can_queue = 16, + .this_id = 7, + .sg_tablesize = 16, + .cmd_per_lun = 1, + .use_clustering = ENABLE_CLUSTERING, +}; #include "scsi_module.c" diff -Nru a/drivers/scsi/ibmmca.h b/drivers/scsi/ibmmca.h --- a/drivers/scsi/ibmmca.h Thu May 15 15:24:41 2003 +++ b/drivers/scsi/ibmmca.h Thu May 15 15:24:41 2003 @@ -20,29 +20,4 @@ static int ibmmca_host_reset (Scsi_Cmnd *); static int ibmmca_biosparam (struct scsi_device *, struct block_device *, sector_t, int *); -/* - * 2/8/98 - * Note to maintainer of IBMMCA. Do not change this initializer back to - * the old format. Please ask eric@andante.jic.com if you have any questions - * about this, but it will break things in the future. - */ -#define IBMMCA { \ - .proc_name = "ibmmca", /*proc_name*/ \ - .proc_info = ibmmca_proc_info, /*proc info fn*/ \ - .name = "IBM SCSI-Subsystem", /*name*/ \ - .detect = ibmmca_detect, /*detect fn*/ \ - .release = ibmmca_release, /*release fn*/ \ - .command = ibmmca_command, /*command fn*/ \ - .queuecommand = ibmmca_queuecommand, /*queuecommand fn*/ \ - .eh_abort_handler = ibmmca_abort, /*abort fn*/ \ - .eh_host_reset_handler = ibmmca_host_reset, /*reset fn*/ \ - .bios_param = ibmmca_biosparam, /*bios fn*/ \ - .can_queue = 16, /*can_queue*/ \ - .this_id = 7, /*set by detect*/ \ - .sg_tablesize = 16, /*sg_tablesize*/ \ - .cmd_per_lun = 1, /*cmd_per_lun*/ \ - .unchecked_isa_dma = 0, /*32-Bit Busmaster */ \ - .use_clustering = ENABLE_CLUSTERING /*use_clustering*/ \ - } - #endif /* _IBMMCA_H */ diff -Nru a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c --- a/drivers/scsi/ide-scsi.c Thu May 15 15:24:40 2003 +++ b/drivers/scsi/ide-scsi.c Thu May 15 15:24:40 2003 @@ -78,6 +78,7 @@ #define PC_DMA_IN_PROGRESS 0 /* 1 while DMA in progress */ #define PC_WRITING 1 /* Data direction */ #define PC_TRANSFORM 2 /* transform SCSI commands */ +#define PC_DMA_OK 4 /* Use DMA */ /* * SCSI command transformation layer @@ -494,6 +495,10 @@ ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), NULL); /* Send the actual packet */ atapi_output_bytes(drive, scsi->pc->c, 12); + if (test_bit (PC_DMA_OK, &pc->flags)) { + set_bit (PC_DMA_IN_PROGRESS, &pc->flags); + (void) (HWIF(drive)->ide_dma_begin(drive)); + } return ide_started; } @@ -527,10 +532,9 @@ HWIF(drive)->OUTB(bcount.b.high, IDE_BCOUNTH_REG); HWIF(drive)->OUTB(bcount.b.low, IDE_BCOUNTL_REG); - if (feature.b.dma) { - set_bit(PC_DMA_IN_PROGRESS, &pc->flags); - (void) (HWIF(drive)->ide_dma_begin(drive)); - } + if (feature.b.dma) + set_bit(PC_DMA_OK, &pc->flags); + if (test_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags)) { if (HWGROUP(drive)->handler != NULL) BUG(); diff -Nru a/drivers/scsi/imm.c b/drivers/scsi/imm.c --- a/drivers/scsi/imm.c Thu May 15 15:24:46 2003 +++ b/drivers/scsi/imm.c Thu May 15 15:24:46 2003 @@ -107,7 +107,23 @@ * Parallel port probing routines * ***************************************************************************/ -static Scsi_Host_Template driver_template = IMM; +static Scsi_Host_Template driver_template = { + .proc_name = "imm", + .proc_info = imm_proc_info, + .name = "Iomega VPI2 (imm) interface", + .detect = imm_detect, + .release = imm_release, + .command = imm_command, + .queuecommand = imm_queuecommand, + .eh_abort_handler = imm_abort, + .eh_bus_reset_handler = imm_reset, + .eh_host_reset_handler = imm_reset, + .bios_param = imm_biosparam, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 1, + .use_clustering = ENABLE_CLUSTERING, +}; #include "scsi_module.c" int imm_detect(Scsi_Host_Template * host) diff -Nru a/drivers/scsi/imm.h b/drivers/scsi/imm.h --- a/drivers/scsi/imm.h Thu May 15 15:24:32 2003 +++ b/drivers/scsi/imm.h Thu May 15 15:24:32 2003 @@ -163,21 +163,4 @@ int imm_biosparam(struct scsi_device *, struct block_device *, sector_t, int *); -#define IMM { .proc_name = "imm", \ - .proc_info = imm_proc_info, \ - .name = "Iomega VPI2 (imm) interface",\ - .detect = imm_detect, \ - .release = imm_release, \ - .command = imm_command, \ - .queuecommand = imm_queuecommand, \ - .eh_abort_handler = imm_abort, \ - .eh_device_reset_handler = NULL, \ - .eh_bus_reset_handler = imm_reset, \ - .eh_host_reset_handler = imm_reset, \ - .bios_param = imm_biosparam, \ - .this_id = 7, \ - .sg_tablesize = SG_ALL, \ - .cmd_per_lun = 1, \ - .use_clustering = ENABLE_CLUSTERING \ -} #endif /* _IMM_H */ diff -Nru a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c --- a/drivers/scsi/in2000.c Thu May 15 15:24:41 2003 +++ b/drivers/scsi/in2000.c Thu May 15 15:24:41 2003 @@ -2312,5 +2312,22 @@ MODULE_LICENSE("GPL"); -static Scsi_Host_Template driver_template = IN2000; +static Scsi_Host_Template driver_template = { + .proc_name = "in2000", + .proc_info = in2000_proc_info, + .name = "Always IN2000", + .detect = in2000_detect, + .release = in2000_release, + .queuecommand = in2000_queuecommand, + .eh_abort_handler = in2000_abort, + .eh_bus_reset_handler = in2000_bus_reset, + .eh_device_reset_handler = in2000_device_reset, + .eh_host_reset_handler = in2000_host_reset, + .bios_param = in2000_biosparam, + .can_queue = IN2000_CAN_Q, + .this_id = IN2000_HOST_ID, + .sg_tablesize = IN2000_SG, + .cmd_per_lun = IN2000_CPL, + .use_clustering = DISABLE_CLUSTERING, +}; #include "scsi_module.c" diff -Nru a/drivers/scsi/in2000.h b/drivers/scsi/in2000.h --- a/drivers/scsi/in2000.h Thu May 15 15:24:32 2003 +++ b/drivers/scsi/in2000.h Thu May 15 15:24:32 2003 @@ -414,22 +414,4 @@ #define IN2000_CPL 2 #define IN2000_HOST_ID 7 -#define IN2000 { .proc_name = "in2000", /* name of /proc/scsi directory entry */ \ - .proc_info = in2000_proc_info, /* pointer to proc info function */ \ - .name = "Always IN2000", /* device name */ \ - .detect = in2000_detect, /* returns number of in2000's found */ \ - .release = in2000_release, /* release the in2000 controller */ \ - .queuecommand = in2000_queuecommand, /* queue scsi command, don't wait */ \ - .eh_abort_handler = in2000_abort, /* abort current command */ \ - .eh_bus_reset_handler = in2000_bus_reset, /* reset scsi bus */ \ - .eh_device_reset_handler = in2000_device_reset, /* reset scsi device */ \ - .eh_host_reset_handler = in2000_host_reset, /* reset scsi hba */ \ - .bios_param = in2000_biosparam, /* figures out BIOS parameters for lilo, etc */ \ - .can_queue = IN2000_CAN_Q, /* max commands we can queue up */ \ - .this_id = IN2000_HOST_ID, /* host-adapter scsi id */ \ - .sg_tablesize = IN2000_SG, /* scatter-gather table size */ \ - .cmd_per_lun = IN2000_CPL, /* commands per lun */ \ - .use_clustering = DISABLE_CLUSTERING, /* ENABLE_CLUSTERING may speed things up */ \ - } - #endif /* IN2000_H */ diff -Nru a/drivers/scsi/ini9100u.c b/drivers/scsi/ini9100u.c --- a/drivers/scsi/ini9100u.c Thu May 15 15:24:35 2003 +++ b/drivers/scsi/ini9100u.c Thu May 15 15:24:35 2003 @@ -141,7 +141,23 @@ unsigned int i91u_debug = DEBUG_DEFAULT; #endif -static Scsi_Host_Template driver_template = INI9100U; +static Scsi_Host_Template driver_template = { + .proc_name = "INI9100U", + .proc_info = "INI9100U", + .name = i91u_REVID, + .detect = i91u_detect, + .release = i91u_release, + .command = i91u_command, + .queuecommand = i91u_queue, + .abort = i91u_abort, + .reset = i91u_reset, + .bios_param = i91u_biosparam, + .can_queue = 1, + .this_id = 1, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 1, + .use_clustering = ENABLE_CLUSTERING, +}; #include "scsi_module.c" char *i91uCopyright = "Copyright (C) 1996-98"; diff -Nru a/drivers/scsi/ini9100u.h b/drivers/scsi/ini9100u.h --- a/drivers/scsi/ini9100u.h Thu May 15 15:24:39 2003 +++ b/drivers/scsi/ini9100u.h Thu May 15 15:24:39 2003 @@ -87,34 +87,6 @@ #define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.03g" -#define INI9100U { \ - .next = NULL, \ - .module = NULL, \ - .proc_name = "INI9100U", \ - .proc_info = NULL, \ - .name = i91u_REVID, \ - .detect = i91u_detect, \ - .release = i91u_release, \ - .info = NULL, \ - .command = i91u_command, \ - .queuecommand = i91u_queue, \ - .eh_strategy_handler = NULL, \ - .eh_abort_handler = NULL, \ - .eh_device_reset_handler = NULL, \ - .eh_bus_reset_handler = NULL, \ - .eh_host_reset_handler = NULL, \ - .abort = i91u_abort, \ - .reset = i91u_reset, \ - .bios_param = i91u_biosparam, \ - .can_queue = 1, \ - .this_id = 1, \ - .sg_tablesize = SG_ALL, \ - .cmd_per_lun = 1, \ - .present = 0, \ - .unchecked_isa_dma = 0, \ - .use_clustering = ENABLE_CLUSTERING, \ -} - #define VIRT_TO_BUS(i) (unsigned int) virt_to_bus((void *)(i)) #define ULONG unsigned long #define USHORT unsigned short diff -Nru a/drivers/scsi/inia100.c b/drivers/scsi/inia100.c --- a/drivers/scsi/inia100.c Thu May 15 15:24:36 2003 +++ b/drivers/scsi/inia100.c Thu May 15 15:24:36 2003 @@ -91,7 +91,21 @@ #include "hosts.h" #include "inia100.h" -static Scsi_Host_Template driver_template = INIA100; +static Scsi_Host_Template driver_template = { + .proc_name = "inia100", + .name = inia100_REVID, + .detect = inia100_detect, + .release = inia100_release, + .queuecommand = inia100_queue, + .eh_abort_handler = inia100_abort, + .eh_bus_reset_handler = inia100_bus_reset, + .eh_device_reset_handler = inia100_device_reset, + .can_queue = 1, + .this_id = 1, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 1, + .use_clustering = ENABLE_CLUSTERING, +}; #include "scsi_module.c" #define ORC_RDWORD(x,y) (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) )) diff -Nru a/drivers/scsi/inia100.h b/drivers/scsi/inia100.h --- a/drivers/scsi/inia100.h Thu May 15 15:24:32 2003 +++ b/drivers/scsi/inia100.h Thu May 15 15:24:32 2003 @@ -76,24 +76,6 @@ #define inia100_REVID "Initio INI-A100U2W SCSI device driver; Revision: 1.02d" -#define INIA100 { \ - .proc_name = "inia100", \ - .name = inia100_REVID, \ - .detect = inia100_detect, \ - .release = inia100_release, \ - .queuecommand = inia100_queue, \ - .eh_abort_handler = inia100_abort, \ - .eh_bus_reset_handler = inia100_bus_reset, \ - .eh_device_reset_handler = inia100_device_reset, \ - .can_queue = 1, \ - .this_id = 1, \ - .sg_tablesize = SG_ALL, \ - .cmd_per_lun = 1, \ - .present = 0, \ - .unchecked_isa_dma = 0, \ - .use_clustering = ENABLE_CLUSTERING, \ -} - #define ULONG unsigned long #define PVOID void * #define USHORT unsigned short diff -Nru a/drivers/scsi/ips.c b/drivers/scsi/ips.c --- a/drivers/scsi/ips.c Thu May 15 15:24:32 2003 +++ b/drivers/scsi/ips.c Thu May 15 15:24:32 2003 @@ -238,20 +238,43 @@ static const char ips_name[] = "ips"; static struct Scsi_Host *ips_sh[IPS_MAX_ADAPTERS]; /* Array of host controller structures */ static ips_ha_t *ips_ha[IPS_MAX_ADAPTERS]; /* Array of HA structures */ -static unsigned int ips_next_controller = 0; -static unsigned int ips_num_controllers = 0; -static unsigned int ips_released_controllers = 0; +static unsigned int ips_next_controller; +static unsigned int ips_num_controllers; +static unsigned int ips_released_controllers; static int ips_hotplug; static int ips_cmd_timeout = 60; static int ips_reset_timeout = 60 * 5; static int ips_force_memio = 1; /* Always use Memory Mapped I/O */ static int ips_force_i2o = 1; /* Always use I2O command delivery */ static int ips_ioctlsize = IPS_IOCTL_SIZE; /* Size of the ioctl buffer */ -static int ips_cd_boot = 0; /* Booting from Manager CD */ +static int ips_cd_boot; /* Booting from Manager CD */ static char *ips_FlashData = NULL; /* CD Boot - Flash Data Buffer */ -static long ips_FlashDataInUse = 0; /* CD Boot - Flash Data In Use Flag */ +static long ips_FlashDataInUse; /* CD Boot - Flash Data In Use Flag */ static uint32_t MaxLiteCmds = 32; /* Max Active Cmds for a Lite Adapter */ -static Scsi_Host_Template ips_driver_template = IPS; +static Scsi_Host_Template ips_driver_template = { + .detect = ips_detect, + .release = ips_release, + .info = ips_info, + .queuecommand = ips_queue, + .eh_abort_handler = ips_eh_abort, + .eh_host_reset_handler = ips_eh_reset, +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) + .slave_configure = ips_slave_configure, +#else + .select_queue_depths = ips_select_queue_depth, +#endif + .bios_param = ips_biosparam, + .this_id = -1, + .sg_tablesize = IPS_MAX_SG, + .cmd_per_lun = 3, + .use_clustering = ENABLE_CLUSTERING, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) || (defined CONFIG_HIGHIO) + .highmem_io = 1, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + .use_new_eh_code = 1, +#endif +}; IPS_DEFINE_COMPAT_TABLE( Compatable ); /* Version Compatability Table */ @@ -426,8 +449,8 @@ static void ips_enable_int_copperhead(ips_ha_t *); static void ips_enable_int_copperhead_memio(ips_ha_t *); static void ips_enable_int_morpheus(ips_ha_t *); -static void ips_intr_copperhead(ips_ha_t *); -static void ips_intr_morpheus(ips_ha_t *); +static int ips_intr_copperhead(ips_ha_t *); +static int ips_intr_morpheus(ips_ha_t *); static void ips_next(ips_ha_t *, int); static void ipsintr_blocking(ips_ha_t *, struct ips_scb *); static void ipsintr_done(ips_ha_t *, struct ips_scb *); @@ -562,8 +585,6 @@ printk( KERN_WARNING "ERROR: Can't Allocate Large Buffer for Flashing\n" ); } } - if (!pci_present()) - return (0); SHT->proc_info = ips_proc_info; SHT->proc_name = "ips"; @@ -682,13 +703,13 @@ scb->cmd.flush_cache.reserved3 = 0; scb->cmd.flush_cache.reserved4 = 0; - printk(KERN_NOTICE "(%s%d) Flushing Cache.\n", ips_name, ha->host_num); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "Flushing Cache.\n"); /* send command */ if (ips_send_wait(ha, scb, ips_cmd_timeout, IPS_INTR_ON) == IPS_FAILURE) - printk(KERN_NOTICE "(%s%d) Incomplete Flush.\n", ips_name, ha->host_num); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "Incomplete Flush.\n"); - printk(KERN_NOTICE "(%s%d) Flushing Complete.\n", ips_name, ha->host_num); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "Flushing Complete.\n"); ips_sh[i] = NULL; ips_ha[i] = NULL; @@ -755,13 +776,13 @@ scb->cmd.flush_cache.reserved3 = 0; scb->cmd.flush_cache.reserved4 = 0; - printk(KERN_NOTICE "(%s%d) Flushing Cache.\n", ips_name, ha->host_num); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "Flushing Cache.\n"); /* send command */ if (ips_send_wait(ha, scb, ips_cmd_timeout, IPS_INTR_ON) == IPS_FAILURE) - printk(KERN_NOTICE "(%s%d) Incomplete Flush.\n", ips_name, ha->host_num); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "Incomplete Flush.\n"); else - printk(KERN_NOTICE "(%s%d) Flushing Complete.\n", ips_name, ha->host_num); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "Flushing Complete.\n"); } return (NOTIFY_OK); @@ -911,7 +932,7 @@ /* Attempt the flush command */ ret = ips_send_wait(ha, scb, ips_cmd_timeout, IPS_INTR_IORL); if (ret == IPS_SUCCESS) { - printk(KERN_NOTICE "(%s%d) Reset Request - Flushed Cache\n", ips_name, ha->host_num); + IPS_PRINTK(KERN_NOTICE, ha->pcidev, "Reset Request - Flushed Cache\n"); return (SUCCESS); } } @@ -925,16 +946,14 @@ * command must have already been sent * reset the controller */ - printk(KERN_NOTICE "(%s%d) Resetting controller.\n", - ips_name, ha->host_num); + IPS_PRINTK(KERN_NOTICE, ha->pcidev, "Resetting controller.\n"); ret = (*ha->func.reset)(ha); if (!ret) { Scsi_Cmnd *scsi_cmd; - printk(KERN_NOTICE - "(%s%d) Controller reset failed - controller now offline.\n", - ips_name, ha->host_num); + IPS_PRINTK(KERN_NOTICE, ha->pcidev, + "Controller reset failed - controller now offline.\n"); /* Now fail all of the active commands */ DEBUG_VAR(1, "(%s%d) Failing active commands", @@ -962,9 +981,8 @@ if (!ips_clear_adapter(ha, IPS_INTR_IORL)) { Scsi_Cmnd *scsi_cmd; - printk(KERN_NOTICE - "(%s%d) Controller reset failed - controller now offline.\n", - ips_name, ha->host_num); + IPS_PRINTK(KERN_NOTICE, ha->pcidev, + "Controller reset failed - controller now offline.\n"); /* Now fail all of the active commands */ DEBUG_VAR(1, "(%s%d) Failing active commands", @@ -1269,7 +1287,8 @@ ips_ha_t *ha; unsigned long cpu_flags; struct Scsi_Host *host; - + int irqstatus; + METHOD_TRACE("do_ipsintr", 2); ha = (ips_ha_t *) dev_id; @@ -1289,13 +1308,13 @@ return IRQ_HANDLED; } - (*ha->func.intr)(ha); + irqstatus = (*ha->func.intr)(ha); IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags); /* start the next command */ ips_next(ha, IPS_INTR_ON); - return IRQ_HANDLED; + return IRQ_RETVAL(irqstatus); } /****************************************************************************/ @@ -1309,7 +1328,7 @@ /* ASSUMES interrupts are disabled */ /* */ /****************************************************************************/ -void +int ips_intr_copperhead(ips_ha_t *ha) { ips_stat_t *sp; ips_scb_t *scb; @@ -1319,10 +1338,10 @@ METHOD_TRACE("ips_intr", 2); if (!ha) - return; + return 0; if (!ha->active) - return; + return 0; intrstatus = (*ha->func.isintr)(ha); @@ -1331,7 +1350,7 @@ * Unexpected/Shared interrupt */ - return; + return 0; } while (TRUE) { @@ -1358,6 +1377,7 @@ */ (*scb->callback) (ha, scb); } /* end while */ + return 1; } /****************************************************************************/ @@ -1371,7 +1391,7 @@ /* ASSUMES interrupts are disabled */ /* */ /****************************************************************************/ -void +int ips_intr_morpheus(ips_ha_t *ha) { ips_stat_t *sp; ips_scb_t *scb; @@ -1381,10 +1401,10 @@ METHOD_TRACE("ips_intr_morpheus", 2); if (!ha) - return; + return 0; if (!ha->active) - return; + return 0; intrstatus = (*ha->func.isintr)(ha); @@ -1393,7 +1413,7 @@ * Unexpected/Shared interrupt */ - return; + return 0; } while (TRUE) { @@ -1411,8 +1431,7 @@ break; if (cstatus.fields.command_id > (IPS_MAX_CMDS - 1)) { - printk(KERN_WARNING "(%s%d) Spurious interrupt; no ccb.\n", - ips_name, ha->host_num); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "Spurious interrupt; no ccb.\n"); continue; } @@ -1426,6 +1445,7 @@ */ (*scb->callback) (ha, scb); } /* end while */ + return 1; } /****************************************************************************/ @@ -1728,7 +1748,7 @@ if(pt->CoppCP.cmd.flashfw.count + ha->flash_datasize > (PAGE_SIZE << ha->flash_order)){ ips_free_flash_copperhead(ha); - printk(KERN_WARNING "failed size sanity check\n"); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "failed size sanity check\n"); return IPS_FAILURE; } } @@ -2400,6 +2420,7 @@ minor = buffer[0x1fe + 0xC0]; /* Offset 0x1fe after the header (0xc0) */ subminor = buffer[0x1fd + 0xC0]; /* Offset 0x1fd after the header (0xc0) */ } else { + kfree(buffer); return; } @@ -2450,15 +2471,13 @@ ips_ffdc_reset(ha, IPS_INTR_IORL); if (!ips_read_config(ha, IPS_INTR_IORL)) { - printk(KERN_WARNING "(%s%d) unable to read config from controller.\n", - ips_name, ha->host_num); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "unable to read config from controller.\n"); return (0); } /* end if */ if (!ips_read_adapter_status(ha, IPS_INTR_IORL)) { - printk(KERN_WARNING "(%s%d) unable to read controller status.\n", - ips_name, ha->host_num); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "unable to read controller status.\n"); return (0); } @@ -2467,16 +2486,14 @@ ips_identify_controller(ha); if (!ips_read_subsystem_parameters(ha, IPS_INTR_IORL)) { - printk(KERN_WARNING "(%s%d) unable to read subsystem parameters.\n", - ips_name, ha->host_num); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "unable to read subsystem parameters.\n"); return (0); } /* write nvram user page 5 */ if (!ips_write_driver_status(ha, IPS_INTR_IORL)) { - printk(KERN_WARNING "(%s%d) unable to write driver info to controller.\n", - ips_name, ha->host_num); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "unable to write driver info to controller.\n"); return (0); } @@ -3233,16 +3250,14 @@ METHOD_TRACE("ipsintr_done", 2); if (!scb) { - printk(KERN_WARNING "(%s%d) Spurious interrupt; scb NULL.\n", - ips_name, ha->host_num); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "Spurious interrupt; scb NULL.\n"); return ; } if (scb->scsi_cmd == NULL) { /* unexpected interrupt */ - printk(KERN_WARNING "(%s%d) Spurious interrupt; scsi_cmd not set.\n", - ips_name, ha->host_num); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "Spurious interrupt; scsi_cmd not set.\n"); return; } @@ -4677,8 +4692,8 @@ } if (PostByte[0] < IPS_GOOD_POST_STATUS) { - printk(KERN_WARNING "(%s%d) reset controller fails (post status %x %x).\n", - ips_name, ha->host_num, PostByte[0], PostByte[1]); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "reset controller fails (post status %x %x).\n", + PostByte[0], PostByte[1]); return (0); } @@ -4769,8 +4784,8 @@ } if (PostByte[0] < IPS_GOOD_POST_STATUS) { - printk(KERN_WARNING "(%s%d) reset controller fails (post status %x %x).\n", - ips_name, ha->host_num, PostByte[0], PostByte[1]); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "reset controller fails (post status %x %x).\n", + PostByte[0], PostByte[1]); return (0); } @@ -4856,8 +4871,7 @@ if (i >= 45) { /* error occurred */ - printk(KERN_WARNING "(%s%d) timeout waiting for post.\n", - ips_name, ha->host_num); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "timeout waiting for post.\n"); return (0); } @@ -4865,7 +4879,7 @@ Post = readl(ha->mem_ptr + IPS_REG_I960_MSG0); if (Post == 0x4F00) { /* If Flashing the Battery PIC */ - printk(KERN_WARNING "Flashing Battery PIC, Please wait ...\n" ); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "Flashing Battery PIC, Please wait ...\n" ); /* Clear the interrupt bit */ Isr = (uint32_t) IPS_BIT_I960_MSG0I; @@ -4880,8 +4894,7 @@ } if (i >= 120) { - printk(KERN_WARNING "(%s%d) timeout waiting for Battery PIC Flash\n", - ips_name, ha->host_num); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "timeout waiting for Battery PIC Flash\n"); return (0); } @@ -4892,8 +4905,7 @@ writel(Isr, ha->mem_ptr + IPS_REG_I2O_HIR); if (Post < (IPS_GOOD_POST_STATUS << 8)) { - printk(KERN_WARNING "(%s%d) reset controller fails (post status %x).\n", - ips_name, ha->host_num, Post); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "reset controller fails (post status %x).\n", Post); return (0); } @@ -4911,8 +4923,7 @@ if (i >= 240) { /* error occurred */ - printk(KERN_WARNING "(%s%d) timeout waiting for config.\n", - ips_name, ha->host_num); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "timeout waiting for config.\n"); return (0); } @@ -5239,10 +5250,8 @@ if (!(val & IPS_BIT_START_STOP)) break; - printk(KERN_WARNING "(%s%d) ips_issue val [0x%x].\n", - ips_name, ha->host_num, val); - printk(KERN_WARNING "(%s%d) ips_issue semaphore chk timeout.\n", - ips_name, ha->host_num); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "ips_issue val [0x%x].\n", val); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "ips_issue semaphore chk timeout.\n"); return (IPS_FAILURE); } /* end if */ @@ -5295,10 +5304,8 @@ if (!(val & IPS_BIT_START_STOP)) break; - printk(KERN_WARNING "(%s%d) ips_issue val [0x%x].\n", - ips_name, ha->host_num, val); - printk(KERN_WARNING "(%s%d) ips_issue semaphore chk timeout.\n", - ips_name, ha->host_num); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "ips_issue val [0x%x].\n", val); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "ips_issue semaphore chk timeout.\n"); return (IPS_FAILURE); } /* end if */ @@ -5538,8 +5545,7 @@ METHOD_TRACE("ips_write_driver_status", 1); if (!ips_readwrite_page5(ha, FALSE, intr)) { - printk(KERN_WARNING "(%s%d) unable to read NVRAM page 5.\n", - ips_name, ha->host_num); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "unable to read NVRAM page 5.\n"); return (0); } @@ -5574,8 +5580,7 @@ /* now update the page */ if (!ips_readwrite_page5(ha, TRUE, intr)) { - printk(KERN_WARNING "(%s%d) unable to write NVRAM page 5.\n", - ips_name, ha->host_num); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "unable to write NVRAM page 5.\n"); return (0); } @@ -6538,10 +6543,10 @@ strncpy(&FirmwareString[0], ha->enq->CodeBlkVersion, 8); FirmwareString[8] = 0; - printk(KERN_WARNING "Warning ! ! ! ServeRAID Version Mismatch\n"); - printk(KERN_WARNING "Bios = %s, Firmware = %s, Device Driver = %s%s\n", - BiosString, FirmwareString, IPS_VERSION_HIGH, IPS_VERSION_LOW ); - printk(KERN_WARNING "These levels should match to avoid possible compatibility problems.\n" ); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "Warning ! ! ! ServeRAID Version Mismatch\n"); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "Bios = %s, Firmware = %s, Device Driver = %s%s\n", + BiosString, FirmwareString, IPS_VERSION_HIGH, IPS_VERSION_LOW ); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "These levels should match to avoid possible compatibility problems.\n"); } } else @@ -6682,6 +6687,7 @@ } break; default: + break; } } } @@ -6725,19 +6731,18 @@ static int ips_register_scsi( int index){ struct Scsi_Host *sh; - ips_ha_t *ha, *oldha; + ips_ha_t *ha, *oldha = ips_ha[index]; sh = scsi_register(&ips_driver_template, sizeof(ips_ha_t)); if(!sh) { - printk(KERN_WARNING "Unable to register controller with SCSI subsystem\n" ); + IPS_PRINTK(KERN_WARNING, oldha->pcidev, "Unable to register controller with SCSI subsystem\n"); return -1; } - oldha = ips_ha[index]; ha = IPS_HA(sh); memcpy(ha, oldha, sizeof(ips_ha_t)); free_irq(oldha->irq, oldha); /* Install the interrupt handler with the new ha */ if (request_irq(ha->irq, do_ipsintr, SA_SHIRQ, ips_name, ha)) { - printk(KERN_WARNING "Unable to install interrupt handler\n" ); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "Unable to install interrupt handler\n" ); scsi_unregister(sh); return -1; } @@ -6745,7 +6750,7 @@ kfree(oldha); ips_sh[index] = sh; ips_ha[index] = ha; - scsi_set_device(sh, &ha->pcidev->dev); + IPS_SCSI_SET_DEVICE(sh, ha); /* Store away needed values for later use */ sh->io_port = ha->io_addr; @@ -6940,7 +6945,7 @@ uint32_t offs; if (!request_mem_region(mem_addr, mem_len, "ips")) { - printk(KERN_WARNING "Couldn't allocate IO Memory space %x len %d.\n", mem_addr, mem_len); + IPS_PRINTK(KERN_WARNING, pci_dev, "Couldn't allocate IO Memory space %x len %d.\n", mem_addr, mem_len); return -1; } @@ -6956,14 +6961,14 @@ /* setup I/O mapped area (if applicable) */ if (io_addr) { if (!request_region(io_addr, io_len, "ips")) { - printk(KERN_WARNING "Couldn't allocate IO space %x len %d.\n", io_addr, io_len); + IPS_PRINTK(KERN_WARNING, pci_dev, "Couldn't allocate IO space %x len %d.\n", io_addr, io_len); return -1; } } /* get the revision ID */ if (pci_read_config_byte(pci_dev, PCI_REVISION_ID, &revision_id)) { - printk(KERN_WARNING "Can't get revision id.\n" ); + IPS_PRINTK(KERN_WARNING, pci_dev, "Can't get revision id.\n"); return -1; } @@ -6972,7 +6977,7 @@ /* found a controller */ ha = kmalloc(sizeof(ips_ha_t), GFP_KERNEL); if (ha == NULL) { - printk(KERN_WARNING "Unable to allocate temporary ha struct\n" ); + IPS_PRINTK(KERN_WARNING, pci_dev, "Unable to allocate temporary ha struct\n"); return -1; } @@ -7007,20 +7012,23 @@ !pci_set_dma_mask(ha->pcidev, (u64)0xffffffffffffffff)) { (ha)->flags |= IPS_HA_ENH_SG; } else { - pci_set_dma_mask(ha->pcidev, (u64)0xffffffff); + if ( pci_set_dma_mask(ha->pcidev, (u64)0xffffffff) != 0 ) { + printk(KERN_WARNING "Unable to set DMA Mask\n"); + return ips_abort_init(ha, index); + } } ha->enq = kmalloc(sizeof(IPS_ENQ), IPS_INIT_GFP); if (!ha->enq) { - printk(KERN_WARNING "Unable to allocate host inquiry structure\n" ); + IPS_PRINTK(KERN_WARNING, pci_dev, "Unable to allocate host inquiry structure\n" ); return ips_abort_init(ha, index); } ha->adapt = pci_alloc_consistent(pci_dev, sizeof(IPS_ADAPTER) + sizeof(IPS_IO_CMD), &dma_address); if (!ha->adapt) { - printk(KERN_WARNING "Unable to allocate host adapt & dummy structures\n"); + IPS_PRINTK(KERN_WARNING, pci_dev, "Unable to allocate host adapt & dummy structures\n"); return ips_abort_init(ha, index); } ha->adapt->hw_status_start = dma_address; @@ -7029,21 +7037,21 @@ ha->conf = kmalloc(sizeof(IPS_CONF), IPS_INIT_GFP); if (!ha->conf) { - printk(KERN_WARNING "Unable to allocate host conf structure\n" ); + IPS_PRINTK(KERN_WARNING, pci_dev, "Unable to allocate host conf structure\n"); return ips_abort_init(ha, index); } ha->nvram = kmalloc(sizeof(IPS_NVRAM_P5), IPS_INIT_GFP); if (!ha->nvram) { - printk(KERN_WARNING "Unable to allocate host NVRAM structure\n" ); + IPS_PRINTK(KERN_WARNING, pci_dev, "Unable to allocate host NVRAM structure\n"); return ips_abort_init(ha, index); } ha->subsys = kmalloc(sizeof(IPS_SUBSYS), IPS_INIT_GFP); if (!ha->subsys) { - printk(KERN_WARNING "Unable to allocate host subsystem structure\n" ); + IPS_PRINTK(KERN_WARNING, pci_dev, "Unable to allocate host subsystem structure\n"); return ips_abort_init(ha, index); } @@ -7055,7 +7063,7 @@ ha->ioctl_datasize = count; if (!ha->ioctl_data) { - printk(KERN_WARNING "Unable to allocate IOCTL data\n" ); + IPS_PRINTK(KERN_WARNING, pci_dev, "Unable to allocate IOCTL data\n"); ha->ioctl_data = NULL; ha->ioctl_order = 0; ha->ioctl_datasize = 0; @@ -7083,7 +7091,7 @@ /* * Initialization failed */ - printk(KERN_WARNING "Unable to initialize controller\n" ); + IPS_PRINTK(KERN_WARNING, pci_dev, "Unable to initialize controller\n"); return ips_abort_init(ha, index); } } @@ -7115,7 +7123,7 @@ /* Install the interrupt handler */ if (request_irq(ha->irq, do_ipsintr, SA_SHIRQ, ips_name, ha)) { - printk(KERN_WARNING "Unable to install interrupt handler\n" ); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "Unable to install interrupt handler\n"); return ips_abort_init(ha, index); } @@ -7124,13 +7132,13 @@ */ ha->max_cmds = 1; if (!ips_allocatescbs(ha)) { - printk(KERN_WARNING "Unable to allocate a CCB\n" ); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "Unable to allocate a CCB\n"); free_irq(ha->irq, ha); return ips_abort_init(ha, index); } if (!ips_hainit(ha)) { - printk(KERN_WARNING "Unable to initialize controller\n" ); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "Unable to initialize controller\n"); free_irq(ha->irq, ha); return ips_abort_init(ha, index); } @@ -7139,7 +7147,7 @@ /* allocate CCBs */ if (!ips_allocatescbs(ha)) { - printk(KERN_WARNING "Unable to allocate CCBs\n" ); + IPS_PRINTK(KERN_WARNING, ha->pcidev, "Unable to allocate CCBs\n"); free_irq(ha->irq, ha); return ips_abort_init(ha, index); } diff -Nru a/drivers/scsi/ips.h b/drivers/scsi/ips.h --- a/drivers/scsi/ips.h Thu May 15 15:24:35 2003 +++ b/drivers/scsi/ips.h Thu May 15 15:24:35 2003 @@ -66,9 +66,6 @@ */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) || defined CONFIG_HIGHIO #define IPS_HIGHIO - #define IPS_HIGHMEM_IO .highmem_io = 1, - #else - #define IPS_HIGHMEM_IO #endif #define IPS_HA(x) ((ips_ha_t *) x->hostdata) @@ -94,20 +91,31 @@ sizeof(IPS_ENH_SG_LIST) : sizeof(IPS_STD_SG_LIST)) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4) - #define pci_set_dma_mask(dev,mask) (1) + #define pci_set_dma_mask(dev,mask) ( mask > 0xffffffff ? 1:0 ) #define scsi_set_pci_device(sh,dev) (0) #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) + typedef void irqreturn_t; + #define IRQ_NONE + #define IRQ_HANDLED + #define IRQ_RETVAL(x) #define IPS_REGISTER_HOSTS(SHT) scsi_register_module(MODULE_SCSI_HA,SHT) #define IPS_UNREGISTER_HOSTS(SHT) scsi_unregister_module(MODULE_SCSI_HA,SHT) #define IPS_ADD_HOST(shost,device) #define IPS_REMOVE_HOST(shost) + #define IPS_SCSI_SET_DEVICE(sh,ha) scsi_set_pci_device(sh, (ha)->pcidev) + #define IPS_PRINTK(level, pcidev, format, arg...) \ + printk(level "%s %s:" format , (pcidev)->driver->name , \ + (pcidev)->slot_name , ## arg) #else #define IPS_REGISTER_HOSTS(SHT) (!ips_detect(SHT)) #define IPS_UNREGISTER_HOSTS(SHT) #define IPS_ADD_HOST(shost,device) scsi_add_host(shost,device) #define IPS_REMOVE_HOST(shost) scsi_remove_host(shost) + #define IPS_SCSI_SET_DEVICE(sh,ha) scsi_set_device(sh, &(ha)->pcidev->dev) + #define IPS_PRINTK(level, pcidev, format, arg...) \ + dev_printk(level , &((pcidev)->dev) , format , ## arg) #endif #ifndef MDELAY @@ -445,47 +453,10 @@ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) static void ips_select_queue_depth(struct Scsi_Host *, Scsi_Device *); static int ips_biosparam(Disk *disk, kdev_t dev, int geom[]); -#define IPS { \ - .detect = ips_detect, \ - .release = ips_release, \ - .info = ips_info, \ - .queuecommand = ips_queue, \ - .eh_abort_handler = ips_eh_abort, \ - .eh_host_reset_handler = ips_eh_reset, \ - .bios_param = ips_biosparam,\ - .select_queue_depths = ips_select_queue_depth, \ - .can_queue = 0, \ - .this_id = -1, \ - .sg_tablesize = IPS_MAX_SG, \ - .cmd_per_lun = 16, \ - .present = 0, \ - .unchecked_isa_dma = 0, \ - .use_clustering = ENABLE_CLUSTERING,\ - .use_new_eh_code = 1, \ - IPS_HIGHMEM_IO \ -} #else static int ips_biosparam(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int geom[]); int ips_slave_configure(Scsi_Device *SDptr); -#define IPS { \ - .detect = ips_detect, \ - .release = ips_release, \ - .info = ips_info, \ - .queuecommand = ips_queue, \ - .eh_abort_handler = ips_eh_abort, \ - .eh_host_reset_handler = ips_eh_reset, \ - .slave_configure = ips_slave_configure, \ - .bios_param = ips_biosparam, \ - .can_queue = 0, \ - .this_id = -1, \ - .sg_tablesize = IPS_MAX_SG, \ - .cmd_per_lun = 3, \ - .present = 0, \ - .unchecked_isa_dma = 0, \ - .use_clustering = ENABLE_CLUSTERING, \ - .highmem_io = 1 \ -} #endif /* @@ -1092,7 +1063,7 @@ int (*programbios)(struct ips_ha *, char *, uint32_t, uint32_t); int (*verifybios)(struct ips_ha *, char *, uint32_t, uint32_t); void (*statinit)(struct ips_ha *); - void (*intr)(struct ips_ha *); + int (*intr)(struct ips_ha *); void (*enableint)(struct ips_ha *); uint32_t (*statupd)(struct ips_ha *); } ips_hw_func_t; diff -Nru a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c --- a/drivers/scsi/lasi700.c Thu May 15 15:24:33 2003 +++ b/drivers/scsi/lasi700.c Thu May 15 15:24:33 2003 @@ -208,6 +208,11 @@ return 1; } -static Scsi_Host_Template driver_template = LASI700_SCSI; - +static Scsi_Host_Template driver_template = { + .name = "LASI SCSI 53c700", + .proc_name = "lasi700", + .detect = lasi700_detect, + .release = lasi700_release, + .this_id = 7, +}; #include "scsi_module.c" diff -Nru a/drivers/scsi/lasi700.h b/drivers/scsi/lasi700.h --- a/drivers/scsi/lasi700.h Thu May 15 15:24:34 2003 +++ b/drivers/scsi/lasi700.h Thu May 15 15:24:34 2003 @@ -29,15 +29,6 @@ static int lasi700_driver_callback(struct parisc_device *dev); static int lasi700_release(struct Scsi_Host *host); - -#define LASI700_SCSI { \ - .name = "LASI SCSI 53c700", \ - .proc_name = "lasi700", \ - .detect = lasi700_detect, \ - .release = lasi700_release, \ - .this_id = 7, \ -} - #define LASI_710_SVERSION 0x082 #define LASI_700_SVERSION 0x071 diff -Nru a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c --- a/drivers/scsi/mac53c94.c Thu May 15 15:24:33 2003 +++ b/drivers/scsi/mac53c94.c Thu May 15 15:24:33 2003 @@ -59,7 +59,7 @@ static void mac53c94_init(struct fsc_state *); static void mac53c94_start(struct fsc_state *); static void mac53c94_interrupt(int, void *, struct pt_regs *); -static void do_mac53c94_interrupt(int, void *, struct pt_regs *); +static irqreturn_t do_mac53c94_interrupt(int, void *, struct pt_regs *); static void cmd_done(struct fsc_state *, int result); static void set_dma_cmds(struct fsc_state *, Scsi_Cmnd *); static int data_goes_out(Scsi_Cmnd *); @@ -316,7 +316,7 @@ set_dma_cmds(state, cmd); } -static void +static irqreturn_t do_mac53c94_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) { unsigned long flags; @@ -325,6 +325,7 @@ spin_lock_irqsave(dev->host_lock, flags); mac53c94_interrupt(irq, dev_id, ptregs); spin_unlock_irqrestore(dev->host_lock, flags); + return IRQ_HANDLED; } static void diff -Nru a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c --- a/drivers/scsi/megaraid.c Thu May 15 15:24:32 2003 +++ b/drivers/scsi/megaraid.c Thu May 15 15:24:32 2003 @@ -5377,9 +5377,27 @@ kfree(pdev); } - -static Scsi_Host_Template driver_template = MEGARAID; - +static Scsi_Host_Template driver_template = { + .name = "MegaRAID", + .proc_info = megaraid_proc_info, + .detect = megaraid_detect, + .release = megaraid_release, + .info = megaraid_info, + .command = megaraid_command, + .queuecommand = megaraid_queue, + .bios_param = megaraid_biosparam, + .max_sectors = MAX_SECTORS_PER_IO, + .can_queue = MAX_COMMANDS, + .this_id = DEFAULT_INITIATOR_ID, + .sg_tablesize = MAX_SGLIST, + .cmd_per_lun = DEF_CMD_PER_LUN, + .use_clustering = ENABLE_CLUSTERING, + .eh_abort_handler = megaraid_abort, + .eh_device_reset_handler = megaraid_reset, + .eh_bus_reset_handler = megaraid_reset, + .eh_host_reset_handler = megaraid_reset, + .highmem_io = 1, +}; #include "scsi_module.c" /* vi: set ts=8 sw=8 tw=78: */ diff -Nru a/drivers/scsi/megaraid.h b/drivers/scsi/megaraid.h --- a/drivers/scsi/megaraid.h Thu May 15 15:24:39 2003 +++ b/drivers/scsi/megaraid.h Thu May 15 15:24:39 2003 @@ -121,33 +121,6 @@ #define NVIRT_CHAN 4 /* # of virtual channels to represent up to 60 logical drives */ -#define MEGARAID \ -{ \ - .name = "MegaRAID", \ - .proc_info = megaraid_proc_info, \ - .detect = megaraid_detect, \ - .release = megaraid_release, \ - .info = megaraid_info, \ - .command = megaraid_command, \ - .queuecommand = megaraid_queue, \ - .bios_param = megaraid_biosparam, \ - .max_sectors = MAX_SECTORS_PER_IO, \ - .can_queue = MAX_COMMANDS, \ - .this_id = DEFAULT_INITIATOR_ID, \ - .sg_tablesize = MAX_SGLIST, \ - .cmd_per_lun = DEF_CMD_PER_LUN, \ - .present = 0, \ - .unchecked_isa_dma = 0, \ - .use_clustering = ENABLE_CLUSTERING, \ - .eh_abort_handler = megaraid_abort, \ - .eh_device_reset_handler = megaraid_reset, \ - .eh_bus_reset_handler = megaraid_reset, \ - .eh_host_reset_handler = megaraid_reset, \ - .highmem_io = 1, \ -} - - - typedef struct { /* 0x0 */ u8 cmd; /* 0x1 */ u8 cmdid; diff -Nru a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c --- a/drivers/scsi/mesh.c Thu May 15 15:24:40 2003 +++ b/drivers/scsi/mesh.c Thu May 15 15:24:40 2003 @@ -212,7 +212,7 @@ static void handle_error(struct mesh_state *); static void handle_exception(struct mesh_state *); static void mesh_interrupt(int, void *, struct pt_regs *); -static void do_mesh_interrupt(int, void *, struct pt_regs *); +static irqreturn_t do_mesh_interrupt(int, void *, struct pt_regs *); static void handle_msgin(struct mesh_state *); static void mesh_done(struct mesh_state *, int); static void mesh_completed(struct mesh_state *, Scsi_Cmnd *); @@ -1471,7 +1471,7 @@ out_8(&mr->sequence, SEQ_ENBRESEL); } -static void +static irqreturn_t do_mesh_interrupt(int irq, void *dev_id, struct pt_regs *ptregs) { unsigned long flags; @@ -1480,6 +1480,7 @@ spin_lock_irqsave(dev->host_lock, flags); mesh_interrupt(irq, dev_id, ptregs); spin_unlock_irqrestore(dev->host_lock, flags); + return IRQ_HANDLED; } static void handle_error(struct mesh_state *ms) diff -Nru a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c --- a/drivers/scsi/ncr53c8xx.c Thu May 15 15:24:35 2003 +++ b/drivers/scsi/ncr53c8xx.c Thu May 15 15:24:35 2003 @@ -9430,18 +9430,6 @@ */ int __init ncr53c8xx_detect(Scsi_Host_Template *tpnt) { - /* - ** Initialize driver general stuff. - */ -#ifdef SCSI_NCR_PROC_INFO_SUPPORT -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,27) - tpnt->proc_dir = &proc_scsi_ncr53c8xx; -#else - tpnt->proc_name = NAME53C8XX; -#endif - tpnt->proc_info = ncr53c8xx_proc_info; -#endif - #if defined(SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT) && defined(MODULE) if (ncr53c8xx) ncr53c8xx_setup(ncr53c8xx); @@ -9467,29 +9455,27 @@ */ MODULE_LICENSE("GPL"); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -static -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) || defined(MODULE) +static Scsi_Host_Template driver_template = { #ifdef ENABLE_SCSI_ZALON -Scsi_Host_Template driver_template = { - .proc_name = "zalon720", - .detect = zalon7xx_detect, - .release = zalon7xx_release, - .info = ncr53c8xx_info, - .queuecommand = ncr53c8xx_queue_command, - .slave_configure = ncr53c8xx_slave_configure, - .eh_bus_reset_handler = ncr53c8xx_bus_reset, - .can_queue = SCSI_NCR_CAN_QUEUE, - .this_id = 7, - .sg_tablesize = SCSI_NCR_SG_TABLESIZE, - .cmd_per_lun = SCSI_NCR_CMD_PER_LUN, - .use_clustering = DISABLE_CLUSTERING, -}; - - + .proc_name = "zalon720", + .detect = zalon7xx_detect, + .release = zalon7xx_release, #else -Scsi_Host_Template driver_template = NCR53C8XX; + .proc_name = NAME53C8XX, + .detect = ncr53c8xx_detect, + .release = ncr53c8xx_release, #endif -#include "scsi_module.c" +#ifdef SCSI_NCR_PROC_INFO_SUPPORT + .proc_info = ncr53c8xx_proc_info, #endif + .info = ncr53c8xx_info, + .queuecommand = ncr53c8xx_queue_command, + .slave_configure = ncr53c8xx_slave_configure, + .eh_bus_reset_handler = ncr53c8xx_bus_reset, + .can_queue = SCSI_NCR_CAN_QUEUE, + .this_id = 7, + .sg_tablesize = SCSI_NCR_SG_TABLESIZE, + .cmd_per_lun = SCSI_NCR_CMD_PER_LUN, + .use_clustering = DISABLE_CLUSTERING, +}; +#include "scsi_module.c" diff -Nru a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h --- a/drivers/scsi/ncr53c8xx.h Thu May 15 15:24:37 2003 +++ b/drivers/scsi/ncr53c8xx.h Thu May 15 15:24:37 2003 @@ -44,38 +44,4 @@ #include "sym53c8xx_defs.h" -/* -** Define Scsi_Host_Template parameters -** -** Used by hosts.c and ncr53c8xx.c with module configuration. -*/ - -#if (LINUX_VERSION_CODE >= 0x020400) || defined(HOSTS_C) || defined(MODULE) - -#include - -int ncr53c8xx_abort(Scsi_Cmnd *); -int ncr53c8xx_detect(Scsi_Host_Template *tpnt); -const char *ncr53c8xx_info(struct Scsi_Host *host); -int ncr53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int ncr53c8xx_reset(Scsi_Cmnd *, unsigned int); -int ncr53c8xx_slave_configure(Scsi_Device *); -int ncr53c8xx_release(struct Scsi_Host *); - - -#define NCR53C8XX { .name = "ncr53c8xx", \ - .detect = ncr53c8xx_detect, \ - .release = ncr53c8xx_release, \ - .info = ncr53c8xx_info, \ - .queuecommand = ncr53c8xx_queue_command,\ - .slave_configure = ncr53c8xx_slave_configure,\ - .eh_bus_reset_handler = ncr53c8xx_bus_reset, \ - .can_queue = SCSI_NCR_CAN_QUEUE, \ - .this_id = 7, \ - .sg_tablesize = SCSI_NCR_SG_TABLESIZE, \ - .cmd_per_lun = SCSI_NCR_CMD_PER_LUN, \ - .use_clustering = DISABLE_CLUSTERING} - -#endif /* defined(HOSTS_C) || defined(MODULE) */ - #endif /* NCR53C8XX_H */ diff -Nru a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c --- a/drivers/scsi/nsp32.c Thu May 15 15:24:37 2003 +++ b/drivers/scsi/nsp32.c Thu May 15 15:24:37 2003 @@ -2420,7 +2420,6 @@ static void nsp32_msgout_occur(nsp32_hw_data *data) { unsigned int base = data->BaseAddress; - unsigned short command; long new_sgtp; int i; diff -Nru a/drivers/scsi/osst.c b/drivers/scsi/osst.c --- a/drivers/scsi/osst.c Thu May 15 15:24:38 2003 +++ b/drivers/scsi/osst.c Thu May 15 15:24:38 2003 @@ -5397,15 +5397,10 @@ if (SDp->type != TYPE_TAPE || !osst_supports(SDp)) return 1; - if (scsi_slave_attach(SDp)) { - printk(KERN_ERR "osst :E: Failed to attach scsi slave.\n"); - return 1; - } - drive = alloc_disk(1); if (!drive) { printk(KERN_ERR "osst :E: Out of memory. Device not attached.\n"); - goto out_slave_detach; + return 1; } /* if this is the first attach, build the infrastructure */ @@ -5527,11 +5522,10 @@ write_unlock(&os_scsi_tapes_lock); for (mode = 0; mode < ST_NBR_MODES; ++mode) { - char name[8], devfs_name[64]; + char name[8]; /* Rewind entry */ sprintf(name, "ot%s", osst_formats[mode]); - sprintf(devfs_name, "%s/ot%s", SDp->devfs_name, osst_formats[mode]); sprintf(tpnt->driverfs_dev_r[mode].bus_id, "%s:%s", SDp->sdev_driverfs_dev.bus_id, name); @@ -5545,13 +5539,13 @@ device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_type); device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_kdev); - devfs_register(NULL, devfs_name, 0, - OSST_MAJOR, dev_num + (mode << 5), - S_IFCHR | S_IRUGO | S_IWUGO, - &osst_fops, NULL); + + devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5)), + S_IFCHR | S_IRUGO | S_IWUGO, + "%s/ot%s", SDp->devfs_name, osst_formats[mode]); + /* No-rewind entry */ sprintf (name, "ot%sn", osst_formats[mode]); - sprintf(devfs_name, "%s/ot%sn", SDp->devfs_name, osst_formats[mode]); sprintf(tpnt->driverfs_dev_n[mode].bus_id, "%s:%s", SDp->sdev_driverfs_dev.bus_id, name); @@ -5566,10 +5560,10 @@ &dev_attr_type); device_create_file(&tpnt->driverfs_dev_n[mode], &dev_attr_kdev); - devfs_register(NULL, devfs_name, 0, - OSST_MAJOR, dev_num + (mode << 5) + 128, - S_IFCHR | S_IRUGO | S_IWUGO, - &osst_fops, NULL); + + devfs_mk_cdev(MKDEV(OSST_MAJOR, dev_num + (mode << 5) + 128), + S_IFCHR | S_IRUGO | S_IWUGO, + "%s/ot%sn", SDp->devfs_name, osst_formats[mode]); } drive->number = devfs_register_tape(SDp->devfs_name); @@ -5581,8 +5575,6 @@ out_put_disk: put_disk(drive); -out_slave_detach: - scsi_slave_detach(SDp); return 1; }; @@ -5605,7 +5597,6 @@ devfs_unregister_tape(tpnt->drive->number); put_disk(tpnt->drive); os_scsi_tapes[i] = NULL; - scsi_slave_detach(SDp); osst_nr_dev--; write_unlock(&os_scsi_tapes_lock); for (mode = 0; mode < ST_NBR_MODES; ++mode) { diff -Nru a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c --- a/drivers/scsi/pas16.c Thu May 15 15:24:33 2003 +++ b/drivers/scsi/pas16.c Thu May 15 15:24:33 2003 @@ -600,9 +600,21 @@ #include "NCR5380.c" -/* Eventually this will go into an include file, but this will be later */ -static Scsi_Host_Template driver_template = MV_PAS16; - +static Scsi_Host_Template driver_template = { + .name = "Pro Audio Spectrum-16 SCSI", + .detect = pas16_detect, + .queuecommand = pas16_queue_command, + .eh_abort_handler = pas16_abort, + .eh_bus_reset_handler = pas16_bus_reset, + .eh_device_reset_handler = pas16_device_reset, + .eh_host_reset_handler = pas16_host_reset, + .bios_param = pas16_biosparam, + .can_queue = CAN_QUEUE, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = CMD_PER_LUN, + .use_clustering = DISABLE_CLUSTERING, +}; #include "scsi_module.c" #ifdef MODULE diff -Nru a/drivers/scsi/pas16.h b/drivers/scsi/pas16.h --- a/drivers/scsi/pas16.h Thu May 15 15:24:41 2003 +++ b/drivers/scsi/pas16.h Thu May 15 15:24:41 2003 @@ -137,27 +137,6 @@ #define CAN_QUEUE 32 #endif -/* - * I hadn't thought of this with the earlier drivers - but to prevent - * macro definition conflicts, we shouldn't define all of the internal - * macros when this is being used solely for the host stub. - */ - -#define MV_PAS16 { \ - .name = "Pro Audio Spectrum-16 SCSI", \ - .detect = pas16_detect, \ - .queuecommand = pas16_queue_command, \ - .eh_abort_handler = pas16_abort, \ - .eh_bus_reset_handler = pas16_bus_reset, \ - .eh_device_reset_handler = pas16_device_reset, \ - .eh_host_reset_handler = pas16_host_reset, \ - .bios_param = pas16_biosparam, \ - .can_queue = CAN_QUEUE, \ - .this_id = 7, \ - .sg_tablesize = SG_ALL, \ - .cmd_per_lun = CMD_PER_LUN , \ - .use_clustering = DISABLE_CLUSTERING} - #ifndef HOSTS_C #define NCR5380_implementation_fields \ diff -Nru a/drivers/scsi/pci2000.c b/drivers/scsi/pci2000.c --- a/drivers/scsi/pci2000.c Thu May 15 15:24:41 2003 +++ b/drivers/scsi/pci2000.c Thu May 15 15:24:41 2003 @@ -857,7 +857,21 @@ MODULE_LICENSE("Dual BSD/GPL"); -/* Eventually this will go into an include file, but this will be later */ -static Scsi_Host_Template driver_template = PCI2000; +static Scsi_Host_Template driver_template = { + .proc_name = "pci2000", + .name = "PCI-2000 SCSI Intelligent Disk Controller", + .detect = Pci2000_Detect, + .release = Pci2000_Release, + .command = Pci2000_Command, + .queuecommand = Pci2000_QueueCommand, + .abort = Pci2000_Abort, + .reset = Pci2000_Reset, + .bios_param = Pci2000_BiosParam, + .can_queue = 16, + .this_id = -1, + .sg_tablesize = 16, + .cmd_per_lun = 1, + .use_clustering = DISABLE_CLUSTERING, +}; #include "scsi_module.c" diff -Nru a/drivers/scsi/pci2000.h b/drivers/scsi/pci2000.h --- a/drivers/scsi/pci2000.h Thu May 15 15:24:44 2003 +++ b/drivers/scsi/pci2000.h Thu May 15 15:24:44 2003 @@ -201,24 +201,4 @@ #define NULL 0 #endif -/* screen is 80 columns wide, damnit! */ -#define PCI2000 { \ - .proc_name = "pci2000", \ - .name = "PCI-2000 SCSI Intelligent Disk Controller", \ - .detect = Pci2000_Detect, \ - .release = Pci2000_Release, \ - .command = Pci2000_Command, \ - .queuecommand = Pci2000_QueueCommand, \ - .abort = Pci2000_Abort, \ - .reset = Pci2000_Reset, \ - .bios_param = Pci2000_BiosParam, \ - .can_queue = 16, \ - .this_id = -1, \ - .sg_tablesize = 16, \ - .cmd_per_lun = 1, \ - .present = 0, \ - .unchecked_isa_dma = 0, \ - .use_clustering = DISABLE_CLUSTERING, \ -} - #endif diff -Nru a/drivers/scsi/pci2220i.c b/drivers/scsi/pci2220i.c --- a/drivers/scsi/pci2220i.c Thu May 15 15:24:33 2003 +++ b/drivers/scsi/pci2220i.c Thu May 15 15:24:33 2003 @@ -2925,7 +2925,20 @@ MODULE_LICENSE("Dual BSD/GPL"); -/* Eventually this will go into an include file, but this will be later */ -static Scsi_Host_Template driver_template = PCI2220I; - +static Scsi_Host_Template driver_template = { + .proc_name = "pci2220i", + .name = "PCI-2220I/PCI-2240I", + .detect = Pci2220i_Detect, + .release = Pci2220i_Release, + .command = Pci2220i_Command, + .queuecommand = Pci2220i_QueueCommand, + .abort = Pci2220i_Abort, + .reset = Pci2220i_Reset, + .bios_param = Pci2220i_BiosParam, + .can_queue = 1, + .this_id = -1, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 1, + .use_clustering = DISABLE_CLUSTERING, +}; #include "scsi_module.c" diff -Nru a/drivers/scsi/pci2220i.h b/drivers/scsi/pci2220i.h --- a/drivers/scsi/pci2220i.h Thu May 15 15:24:38 2003 +++ b/drivers/scsi/pci2220i.h Thu May 15 15:24:38 2003 @@ -40,23 +40,4 @@ #ifndef NULL #define NULL 0 #endif - -#define PCI2220I { \ - .proc_name = "pci2220i", \ - .name = "PCI-2220I/PCI-2240I", \ - .detect = Pci2220i_Detect, \ - .release = Pci2220i_Release, \ - .command = Pci2220i_Command, \ - .queuecommand = Pci2220i_QueueCommand, \ - .abort = Pci2220i_Abort, \ - .reset = Pci2220i_Reset, \ - .bios_param = Pci2220i_BiosParam, \ - .can_queue = 1, \ - .this_id = -1, \ - .sg_tablesize = SG_ALL, \ - .cmd_per_lun = 1, \ - .present = 0, \ - .unchecked_isa_dma = 0, \ - .use_clustering = DISABLE_CLUSTERING, \ -} #endif diff -Nru a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c --- a/drivers/scsi/pcmcia/aha152x_stub.c Thu May 15 15:24:43 2003 +++ b/drivers/scsi/pcmcia/aha152x_stub.c Thu May 15 15:24:43 2003 @@ -98,9 +98,8 @@ typedef struct scsi_info_t { dev_link_t link; + dev_node_t node; struct Scsi_Host *host; - int ndev; - dev_node_t node[8]; } scsi_info_t; static void aha152x_release_cs(u_long arg); @@ -217,8 +216,6 @@ cisparse_t parse; int i, last_ret, last_fn; u_char tuple_data[64]; - struct scsi_device *dev; - dev_node_t *node, **tail; struct Scsi_Host *host; DEBUG(0, "aha152x_config(0x%p)\n", link); @@ -275,9 +272,6 @@ if (ext_trans) s.ext_trans = ext_trans; - tail = &link->dev; - info->ndev = 0; - host = aha152x_probe_one(&s); if (host == NULL) { printk(KERN_INFO "aha152x_cs: no SCSI devices found\n"); @@ -286,39 +280,10 @@ scsi_add_host(host, NULL); - list_for_each_entry(dev, &host->my_devices, siblings) { - u_long arg[2], id; - kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg); - id = (arg[0]&0x0f) + ((arg[0]>>4)&0xf0) + - ((arg[0]>>8)&0xf00) + ((arg[0]>>12)&0xf000); - node = &info->node[info->ndev]; - node->minor = 0; - switch (dev->type) { - case TYPE_TAPE: - node->major = SCSI_TAPE_MAJOR; - sprintf(node->dev_name, "st#%04lx", id); - break; - case TYPE_DISK: - case TYPE_MOD: - node->major = SCSI_DISK0_MAJOR; - sprintf(node->dev_name, "sd#%04lx", id); - break; - case TYPE_ROM: - case TYPE_WORM: - node->major = SCSI_CDROM_MAJOR; - sprintf(node->dev_name, "sr#%04lx", id); - break; - default: - node->major = SCSI_GENERIC_MAJOR; - sprintf(node->dev_name, "sg#%04lx", id); - break; - } - *tail = node; tail = &node->next; - info->ndev++; - info->host = dev->host; - } + sprintf(info->node.dev_name, "scsi%d", host->host_no); + link->dev = &info->node; + info->host = host; - *tail = NULL; link->state &= ~DEV_CONFIG_PENDING; return; diff -Nru a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c --- a/drivers/scsi/pcmcia/fdomain_stub.c Thu May 15 15:24:40 2003 +++ b/drivers/scsi/pcmcia/fdomain_stub.c Thu May 15 15:24:40 2003 @@ -81,9 +81,8 @@ typedef struct scsi_info_t { dev_link_t link; + dev_node_t node; struct Scsi_Host *host; - int ndev; - dev_node_t node[8]; } scsi_info_t; extern Scsi_Host_Template fdomain_driver_template; @@ -206,8 +205,6 @@ cisparse_t parse; int i, last_ret, last_fn, ints[3]; u_char tuple_data[64]; - Scsi_Device *dev; - dev_node_t *node, **tail; char str[16]; struct Scsi_Host *host; @@ -259,42 +256,8 @@ scsi_add_host(host, NULL); - tail = &link->dev; - info->ndev = 0; - - list_for_each_entry (dev, &host->my_devices, siblings) { - u_long arg[2], id; - kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg); - id = (arg[0]&0x0f) + ((arg[0]>>4)&0xf0) + - ((arg[0]>>8)&0xf00) + ((arg[0]>>12)&0xf000); - node = &info->node[info->ndev]; - node->minor = 0; - switch (dev->type) { - case TYPE_TAPE: - node->major = SCSI_TAPE_MAJOR; - sprintf(node->dev_name, "st#%04lx", id); - break; - case TYPE_DISK: - case TYPE_MOD: - node->major = SCSI_DISK0_MAJOR; - sprintf(node->dev_name, "sd#%04lx", id); - break; - case TYPE_ROM: - case TYPE_WORM: - node->major = SCSI_CDROM_MAJOR; - sprintf(node->dev_name, "sr#%04lx", id); - break; - default: - node->major = SCSI_GENERIC_MAJOR; - sprintf(node->dev_name, "sg#%04lx", id); - break; - } - *tail = node; tail = &node->next; - info->ndev++; - - } - - *tail = NULL; + sprintf(info->node.dev_name, "scsi%d", host->host_no); + link->dev = &info->node; info->host = host; link->state &= ~DEV_CONFIG_PENDING; diff -Nru a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c --- a/drivers/scsi/pcmcia/nsp_cs.c Thu May 15 15:24:45 2003 +++ b/drivers/scsi/pcmcia/nsp_cs.c Thu May 15 15:24:45 2003 @@ -88,9 +88,8 @@ typedef struct scsi_info_t { dev_link_t link; + dev_node_t node; struct Scsi_Host *host; - int ndev; - dev_node_t node[8]; int stop; } scsi_info_t; @@ -1621,8 +1620,6 @@ memreq_t map; cistpl_cftable_entry_t dflt = { 0 }; - Scsi_Device *dev; - dev_node_t **tail, *node; struct Scsi_Host *host; nsp_hw_data *data = &nsp_data; @@ -1762,58 +1759,13 @@ goto cs_failed; } -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2)) host = __nsp_detect(&nsp_driver_template); -#else - scsi_register_module(MODULE_SCSI_HA, &nsp_driver_template); - for (host = scsi_hostlist; host != NULL; host = host->next) { - if (host->hostt == &nsp_driver_template) - break; -#endif - if (!host) goto cs_failed; - DEBUG(0, "GET_SCSI_INFO\n"); - tail = &link->dev; - info->ndev = 0; - - list_for_each_entry (dev, &host->my_devices, siblings) { - u_long arg[2], id; - kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg); - id = (arg[0]&0x0f) + ((arg[0]>>4)&0xf0) + - ((arg[0]>>8)&0xf00) + ((arg[0]>>12)&0xf000); - node = &info->node[info->ndev]; - node->minor = 0; - switch (dev->type) { - case TYPE_TAPE: - node->major = SCSI_TAPE_MAJOR; - sprintf(node->dev_name, "st#%04lx", id); - break; - case TYPE_DISK: - case TYPE_MOD: - node->major = SCSI_DISK0_MAJOR; - sprintf(node->dev_name, "sd#%04lx", id); - break; - case TYPE_ROM: - case TYPE_WORM: - node->major = SCSI_CDROM_MAJOR; - sprintf(node->dev_name, "sr#%04lx", id); - break; - default: - node->major = SCSI_GENERIC_MAJOR; - sprintf(node->dev_name, "sg#%04lx", id); - break; - } - *tail = node; tail = &node->next; - info->ndev++; - info->host = dev->host; - } - - *tail = NULL; - if (info->ndev == 0) { - printk(KERN_INFO "nsp_cs: no SCSI devices found\n"); - } + sprintf(info->node.dev_name, "scsi%d", host->host_no); + link->dev = &info->node; + info->host = host; /* Finally, report what we've done */ printk(KERN_INFO "nsp_cs: index 0x%02x: Vcc %d.%d", @@ -1837,10 +1789,7 @@ req.Base+req.Size-1); printk("\n"); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) scsi_add_host(host, NULL); -#endif - link->state &= ~DEV_CONFIG_PENDING; return; diff -Nru a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c --- a/drivers/scsi/pcmcia/qlogic_stub.c Thu May 15 15:24:39 2003 +++ b/drivers/scsi/pcmcia/qlogic_stub.c Thu May 15 15:24:39 2003 @@ -85,10 +85,9 @@ typedef struct scsi_info_t { dev_link_t link; + dev_node_t node; struct Scsi_Host *host; unsigned short manf_id; - int ndev; - dev_node_t node[8]; } scsi_info_t; static void qlogic_release(u_long arg); @@ -205,8 +204,6 @@ cisparse_t parse; int i, last_ret, last_fn; unsigned short tuple_data[32]; - Scsi_Device *dev; - dev_node_t **tail, *node; struct Scsi_Host *host; DEBUG(0, "qlogic_config(0x%p)\n", link); @@ -263,50 +260,17 @@ else qlogicfas_preset(link->io.BasePort1, link->irq.AssignedIRQ); - tail = &link->dev; - info->ndev = 0; - host = __qlogicfas_detect(&qlogicfas_driver_template); if (!host) { printk(KERN_INFO "qlogic_cs: no SCSI devices found\n"); goto out; } - scsi_add_host(host, NULL); - - list_for_each_entry(dev, &host->my_devices, siblings) { - u_long arg[2], id; - kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg); - id = (arg[0] & 0x0f) + ((arg[0] >> 4) & 0xf0) + ((arg[0] >> 8) & 0xf00) + ((arg[0] >> 12) & 0xf000); - node = &info->node[info->ndev]; - node->minor = 0; - switch (dev->type) { - case TYPE_TAPE: - node->major = SCSI_TAPE_MAJOR; - sprintf(node->dev_name, "st#%04lx", id); - break; - case TYPE_DISK: - case TYPE_MOD: - node->major = SCSI_DISK0_MAJOR; - sprintf(node->dev_name, "sd#%04lx", id); - break; - case TYPE_ROM: - case TYPE_WORM: - node->major = SCSI_CDROM_MAJOR; - sprintf(node->dev_name, "sr#%04lx", id); - break; - default: - node->major = SCSI_GENERIC_MAJOR; - sprintf(node->dev_name, "sg#%04lx", id); - break; - } - *tail = node; - tail = &node->next; - info->ndev++; - } - - *tail = NULL; + sprintf(info->node.dev_name, "scsi%d", host->host_no); + link->dev = &info->node; info->host = host; + + scsi_add_host(host, NULL); out: link->state &= ~DEV_CONFIG_PENDING; diff -Nru a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c --- a/drivers/scsi/pluto.c Thu May 15 15:24:36 2003 +++ b/drivers/scsi/pluto.c Thu May 15 15:24:36 2003 @@ -246,11 +246,6 @@ host->max_channel = inq->channels; host->irq = fc->irq; -#ifdef __sparc_v9__ - host->unchecked_isa_dma = 1; -#endif - - fc->channels = inq->channels + 1; fc->targets = inq->targets; fc->ages = ages; @@ -345,7 +340,23 @@ return 0; } -static Scsi_Host_Template driver_template = PLUTO; +static Scsi_Host_Template driver_template = { + .name = "Sparc Storage Array 100/200", + .detect = pluto_detect, + .release = pluto_release, + .info = pluto_info, + .queuecommand = fcp_scsi_queuecommand, + .slave_configure = pluto_slave_configure, + .can_queue = PLUTO_CAN_QUEUE, + .this_id = -1, + .sg_tablesize = 1, + .cmd_per_lun = 1, + .use_clustering = ENABLE_CLUSTERING, + .eh_abort_handler = fcp_scsi_abort, + .eh_device_reset_handler = fcp_scsi_dev_reset, + .eh_bus_reset_handler = fcp_scsi_bus_reset, + .eh_host_reset_handler = fcp_scsi_host_reset, +}; #include "scsi_module.c" diff -Nru a/drivers/scsi/pluto.h b/drivers/scsi/pluto.h --- a/drivers/scsi/pluto.h Thu May 15 15:24:39 2003 +++ b/drivers/scsi/pluto.h Thu May 15 15:24:39 2003 @@ -43,23 +43,5 @@ const char * pluto_info(struct Scsi_Host *); int pluto_slave_configure(Scsi_Device *); -#define PLUTO { \ - .name = "Sparc Storage Array 100/200", \ - .detect = pluto_detect, \ - .release = pluto_release, \ - .info = pluto_info, \ - .queuecommand = fcp_scsi_queuecommand, \ - .slave_configure = pluto_slave_configure, \ - .can_queue = PLUTO_CAN_QUEUE, \ - .this_id = -1, \ - .sg_tablesize = 1, \ - .cmd_per_lun = 1, \ - .use_clustering = ENABLE_CLUSTERING, \ - .eh_abort_handler = fcp_scsi_abort, \ - .eh_device_reset_handler = fcp_scsi_dev_reset, \ - .eh_bus_reset_handler = fcp_scsi_bus_reset, \ - .eh_host_reset_handler = fcp_scsi_host_reset, \ -} - #endif /* !(_PLUTO_H) */ diff -Nru a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c --- a/drivers/scsi/ppa.c Thu May 15 15:24:40 2003 +++ b/drivers/scsi/ppa.c Thu May 15 15:24:40 2003 @@ -97,7 +97,23 @@ * Parallel port probing routines * ***************************************************************************/ -static Scsi_Host_Template driver_template = PPA; +static Scsi_Host_Template driver_template = { + .proc_name = "ppa", + .proc_info = ppa_proc_info, + .name = "Iomega VPI0 (ppa) interface", + .detect = ppa_detect, + .release = ppa_release, + .command = ppa_command, + .queuecommand = ppa_queuecommand, + .eh_abort_handler = ppa_abort, + .eh_bus_reset_handler = ppa_reset, + .eh_host_reset_handler = ppa_reset, + .bios_param = ppa_biosparam, + .this_id = -1, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 1, + .use_clustering = ENABLE_CLUSTERING, +}; #include "scsi_module.c" /* diff -Nru a/drivers/scsi/ppa.h b/drivers/scsi/ppa.h --- a/drivers/scsi/ppa.h Thu May 15 15:24:43 2003 +++ b/drivers/scsi/ppa.h Thu May 15 15:24:43 2003 @@ -171,21 +171,4 @@ int ppa_biosparam(struct scsi_device *, struct block_device *, sector_t, int *); -#define PPA { .proc_name = "ppa", \ - .proc_info = ppa_proc_info, \ - .name = "Iomega VPI0 (ppa) interface",\ - .detect = ppa_detect, \ - .release = ppa_release, \ - .command = ppa_command, \ - .queuecommand = ppa_queuecommand, \ - .eh_abort_handler = ppa_abort, \ - .eh_device_reset_handler = NULL, \ - .eh_bus_reset_handler = ppa_reset, \ - .eh_host_reset_handler = ppa_reset, \ - .bios_param = ppa_biosparam, \ - .this_id = -1, \ - .sg_tablesize = SG_ALL, \ - .cmd_per_lun = 1, \ - .use_clustering = ENABLE_CLUSTERING \ -} #endif /* _PPA_H */ diff -Nru a/drivers/scsi/psi240i.c b/drivers/scsi/psi240i.c --- a/drivers/scsi/psi240i.c Thu May 15 15:24:41 2003 +++ b/drivers/scsi/psi240i.c Thu May 15 15:24:41 2003 @@ -718,8 +718,19 @@ MODULE_LICENSE("GPL"); -/* Eventually this will go into an include file, but this will be later */ -static Scsi_Host_Template driver_template = PSI240I; - +static Scsi_Host_Template driver_template = { + .proc_name = "psi240i", + .name = "PSI-240I EIDE Disk Controller", + .detect = Psi240i_Detect, + .command = Psi240i_Command, + .queuecommand = Psi240i_QueueCommand, + .abort = Psi240i_Abort, + .reset = Psi240i_Reset, + .bios_param = Psi240i_BiosParam, + .can_queue = 1, + .this_id = -1, + .sg_tablesize = SG_NONE, + .cmd_per_lun = 1, + .use_clustering = DISABLE_CLUSTERING, +}; #include "scsi_module.c" - diff -Nru a/drivers/scsi/psi240i.h b/drivers/scsi/psi240i.h --- a/drivers/scsi/psi240i.h Thu May 15 15:24:43 2003 +++ b/drivers/scsi/psi240i.h Thu May 15 15:24:43 2003 @@ -320,19 +320,4 @@ #ifndef NULL #define NULL 0 #endif - -#define PSI240I { .proc_name = "psi240i", \ - .name = "PSI-240I EIDE Disk Controller",\ - .detect = Psi240i_Detect, \ - .command = Psi240i_Command, \ - .queuecommand = Psi240i_QueueCommand, \ - .abort = Psi240i_Abort, \ - .reset = Psi240i_Reset, \ - .bios_param = Psi240i_BiosParam, \ - .can_queue = 1, \ - .this_id = -1, \ - .sg_tablesize = SG_NONE, \ - .cmd_per_lun = 1, \ - .use_clustering = DISABLE_CLUSTERING } - #endif diff -Nru a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c --- a/drivers/scsi/qla1280.c Thu May 15 15:24:46 2003 +++ b/drivers/scsi/qla1280.c Thu May 15 15:24:46 2003 @@ -5939,15 +5939,24 @@ return ret; } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) -#ifdef MODULE -Scsi_Host_Template driver_template = QLA1280_LINUX_TEMPLATE; +static Scsi_Host_Template driver_template = { + .proc_info = qla1280_proc_info, + .name = "Qlogic ISP 1280/12160", + .detect = qla1280_detect, + .release = qla1280_release, + .info = qla1280_info, + .queuecommand = qla1280_queuecommand, + .abort = qla1280_abort, + .reset = qla1280_reset, + .slave_configure = qla1280_slave_configure, + .bios_param = qla1280_biosparam, + .can_queue = 255, + .this_id = -1, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 3, + .use_clustering = ENABLE_CLUSTERING, \ +}; #include "scsi_module.c" -#endif -#else /* new kernel scsi initialization scheme */ -static Scsi_Host_Template driver_template = QLA1280_LINUX_TEMPLATE; -#include "scsi_module.c" -#endif /************************************************************************ * qla1280_check_for_dead_scsi_bus * diff -Nru a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h --- a/drivers/scsi/qla1280.h Thu May 15 15:24:46 2003 +++ b/drivers/scsi/qla1280.h Thu May 15 15:24:46 2003 @@ -1319,31 +1319,4 @@ irqreturn_t qla1280_intr_handler(int, void *, struct pt_regs *); void qla1280_setup(char *s, int *dummy); -/* - * Scsi_Host_template (see hosts.h) - * Device driver Interfaces to mid-level SCSI driver. - */ - -#define QLA1280_LINUX_TEMPLATE { \ - .proc_info = qla1280_proc_info, \ - .name = "Qlogic ISP 1280/12160", \ - .detect = qla1280_detect, \ - .release = qla1280_release, \ - .info = qla1280_info, \ - .queuecommand = qla1280_queuecommand, \ -/* use_new_eh_code: 0, */ \ - .abort = qla1280_abort, \ - .reset = qla1280_reset, \ - .slave_configure = qla1280_slave_configure, \ - .bios_param = qla1280_biosparam, \ - .can_queue = 255, /* max simultaneous cmds */\ - .this_id = -1, /* scsi id of host adapter */\ - .sg_tablesize = SG_ALL, /* max scatter-gather cmds */\ - .cmd_per_lun = 3, /* cmds per lun (linked cmds) */\ - .present = 0, /* number of 1280's present */\ - .unchecked_isa_dma = 0, /* no memory DMA restrictions */\ - .use_clustering = ENABLE_CLUSTERING, \ - .emulated = 0 \ -} - #endif /* _IO_HBA_QLA1280_H */ diff -Nru a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c --- a/drivers/scsi/qlogicfc.c Thu May 15 15:24:41 2003 +++ b/drivers/scsi/qlogicfc.c Thu May 15 15:24:41 2003 @@ -2228,6 +2228,18 @@ MODULE_LICENSE("GPL"); -static Scsi_Host_Template driver_template = QLOGICFC; - +static Scsi_Host_Template driver_template = { + .detect = isp2x00_detect, + .release = isp2x00_release, + .info = isp2x00_info, + .queuecommand = isp2x00_queuecommand, + .eh_abort_handler = isp2x00_abort, + .bios_param = isp2x00_biosparam, + .can_queue = QLOGICFC_REQ_QUEUE_LEN, + .this_id = -1, + .sg_tablesize = QLOGICFC_MAX_SG(QLOGICFC_REQ_QUEUE_LEN), + .cmd_per_lun = QLOGICFC_CMD_PER_LUN, + .use_clustering = ENABLE_CLUSTERING, + .highmem_io = 1, +}; #include "scsi_module.c" diff -Nru a/drivers/scsi/qlogicfc.h b/drivers/scsi/qlogicfc.h --- a/drivers/scsi/qlogicfc.h Thu May 15 15:24:37 2003 +++ b/drivers/scsi/qlogicfc.h Thu May 15 15:24:37 2003 @@ -82,24 +82,4 @@ #define NULL (0) #endif -#define QLOGICFC { \ - .detect = isp2x00_detect, \ - .release = isp2x00_release, \ - .info = isp2x00_info, \ - .queuecommand = isp2x00_queuecommand, \ - .eh_abort_handler = isp2x00_abort, \ - .bios_param = isp2x00_biosparam, \ - .can_queue = QLOGICFC_REQ_QUEUE_LEN, \ - .this_id = -1, \ - .sg_tablesize = QLOGICFC_MAX_SG(QLOGICFC_REQ_QUEUE_LEN), \ - .cmd_per_lun = QLOGICFC_CMD_PER_LUN, \ - .present = 0, \ - .unchecked_isa_dma = 0, \ - .use_clustering = ENABLE_CLUSTERING, \ - .highmem_io = 1 \ -} - #endif /* _QLOGICFC_H */ - - - diff -Nru a/drivers/scsi/qlogicisp.c b/drivers/scsi/qlogicisp.c --- a/drivers/scsi/qlogicisp.c Thu May 15 15:24:45 2003 +++ b/drivers/scsi/qlogicisp.c Thu May 15 15:24:45 2003 @@ -1985,6 +1985,16 @@ MODULE_LICENSE("GPL"); -static Scsi_Host_Template driver_template = QLOGICISP; - +static Scsi_Host_Template driver_template = { + .detect = isp1020_detect, + .release = isp1020_release, + .info = isp1020_info, + .queuecommand = isp1020_queuecommand, + .bios_param = isp1020_biosparam, + .can_queue = QLOGICISP_REQ_QUEUE_LEN, + .this_id = -1, + .sg_tablesize = QLOGICISP_MAX_SG(QLOGICISP_REQ_QUEUE_LEN), + .cmd_per_lun = 1, + .use_clustering = DISABLE_CLUSTERING, +}; #include "scsi_module.c" diff -Nru a/drivers/scsi/qlogicisp.h b/drivers/scsi/qlogicisp.h --- a/drivers/scsi/qlogicisp.h Thu May 15 15:24:32 2003 +++ b/drivers/scsi/qlogicisp.h Thu May 15 15:24:32 2003 @@ -70,20 +70,4 @@ #ifndef NULL #define NULL (0) #endif - -#define QLOGICISP { \ - .detect = isp1020_detect, \ - .release = isp1020_release, \ - .info = isp1020_info, \ - .queuecommand = isp1020_queuecommand, \ - .bios_param = isp1020_biosparam, \ - .can_queue = QLOGICISP_REQ_QUEUE_LEN, \ - .this_id = -1, \ - .sg_tablesize = QLOGICISP_MAX_SG(QLOGICISP_REQ_QUEUE_LEN), \ - .cmd_per_lun = 1, \ - .present = 0, \ - .unchecked_isa_dma = 0, \ - .use_clustering = DISABLE_CLUSTERING \ -} - #endif /* _QLOGICISP_H */ diff -Nru a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c --- a/drivers/scsi/scsi.c Thu May 15 15:24:39 2003 +++ b/drivers/scsi/scsi.c Thu May 15 15:24:39 2003 @@ -56,6 +56,9 @@ #include "scsi.h" #include "hosts.h" +#include "scsi_priv.h" +#include "scsi_logging.h" + /* * Definitions and constants. @@ -111,16 +114,6 @@ "Enclosure ", }; -static const char * const spaces = " "; /* 16 of them */ - -static unsigned scsi_default_dev_flags; -LIST_HEAD(scsi_dev_info_list); - -/* - * Function prototypes. - */ -extern void scsi_times_out(struct scsi_cmnd *cmd); - MODULE_PARM(scsi_logging_level, "i"); MODULE_PARM_DESC(scsi_logging_level, "SCSI logging level; should be zero or nonzero"); @@ -178,6 +171,16 @@ return sreq; } +void __scsi_release_request(struct scsi_request *sreq) +{ + if (likely(sreq->sr_command != NULL)) { + struct scsi_cmnd *cmd = sreq->sr_command; + + sreq->sr_command = NULL; + scsi_next_command(cmd); + } +} + /* * Function: scsi_release_request * @@ -189,14 +192,7 @@ */ void scsi_release_request(struct scsi_request *sreq) { - if (likely(sreq->sr_command != NULL)) { - struct request_queue *q = sreq->sr_device->request_queue; - - scsi_put_command(sreq->sr_command); - sreq->sr_command = NULL; - scsi_queue_next_request(q, NULL); - } - + __scsi_release_request(sreq); kfree(sreq); } @@ -534,7 +530,6 @@ cmd->request = sreq->sr_request; memcpy(cmd->data_cmnd, sreq->sr_cmnd, sizeof(cmd->data_cmnd)); - cmd->reset_chain = NULL; cmd->serial_number = 0; cmd->serial_number_at_timeout = 0; cmd->bufflen = sreq->sr_bufflen; @@ -936,250 +931,6 @@ return depth; } - -/* - * scsi_strcpy_devinfo: called from scsi_dev_info_list_add to copy into - * devinfo vendor and model strings. - */ -static void scsi_strcpy_devinfo(char *name, char *to, size_t to_length, - char *from, int compatible) -{ - size_t from_length; - - from_length = strlen(from); - strncpy(to, from, min(to_length, from_length)); - if (from_length < to_length) { - if (compatible) { - /* - * NUL terminate the string if it is short. - */ - to[from_length] = '\0'; - } else { - /* - * space pad the string if it is short. - */ - strncpy(&to[from_length], spaces, - to_length - from_length); - } - } - if (from_length > to_length) - printk(KERN_WARNING "%s: %s string '%s' is too long\n", - __FUNCTION__, name, from); -} - -/** - * scsi_dev_info_list_add: add one dev_info list entry. - * @vendor: vendor string - * @model: model (product) string - * @strflags: integer string - * @flag: if strflags NULL, use this flag value - * - * Description: - * Create and add one dev_info entry for @vendor, @model, @strflags or - * @flag. If @compatible, add to the tail of the list, do not space - * pad, and set devinfo->compatible. The scsi_static_device_list entries - * are added with @compatible 1 and @clfags NULL. - * - * Returns: 0 OK, -error on failure. - **/ -static int scsi_dev_info_list_add(int compatible, char *vendor, char *model, - char *strflags, int flags) -{ - struct scsi_dev_info_list *devinfo; - - devinfo = kmalloc(sizeof(*devinfo), GFP_KERNEL); - if (!devinfo) { - printk(KERN_ERR "%s: no memory\n", __FUNCTION__); - return -ENOMEM; - } - - scsi_strcpy_devinfo("vendor", devinfo->vendor, sizeof(devinfo->vendor), - vendor, compatible); - scsi_strcpy_devinfo("model", devinfo->model, sizeof(devinfo->model), - model, compatible); - - if (strflags) - devinfo->flags = simple_strtoul(strflags, NULL, 0); - else - devinfo->flags = flags; - - devinfo->compatible = compatible; - - if (compatible) - list_add_tail(&devinfo->dev_info_list, &scsi_dev_info_list); - else - list_add(&devinfo->dev_info_list, &scsi_dev_info_list); - - return 0; -} - -/** - * scsi_dev_info_list_add_str: parse dev_list and add to the - * scsi_dev_info_list. - * @dev_list: string of device flags to add - * - * Description: - * Parse dev_list, and add entries to the scsi_dev_info_list. - * dev_list is of the form "vendor:product:flag,vendor:product:flag". - * dev_list is modified via strsep. Can be called for command line - * addition, for proc or mabye a sysfs interface. - * - * Returns: 0 if OK, -error on failure. - **/ -int scsi_dev_info_list_add_str (char *dev_list) -{ - char *vendor, *model, *strflags, *next; - char *next_check; - int res = 0; - - next = dev_list; - if (next && next[0] == '"') { - /* - * Ignore both the leading and trailing quote. - */ - next++; - next_check = ",\""; - } else { - next_check = ","; - } - - /* - * For the leading and trailing '"' case, the for loop comes - * through the last time with vendor[0] == '\0'. - */ - for (vendor = strsep(&next, ":"); vendor && (vendor[0] != '\0') - && (res == 0); vendor = strsep(&next, ":")) { - strflags = NULL; - model = strsep(&next, ":"); - if (model) - strflags = strsep(&next, next_check); - if (!model || !strflags) { - printk(KERN_ERR "%s: bad dev info string '%s' '%s'" - " '%s'\n", __FUNCTION__, vendor, model, - strflags); - res = -EINVAL; - } else - res = scsi_dev_info_list_add(0 /* compatible */, vendor, - model, strflags, 0); - } - return res; -} - -/** - * scsi_dev_info_list_delete: called from scsi.c:exit_scsi to remove - * the scsi_dev_info_list. - **/ -static void scsi_dev_info_list_delete (void) -{ - struct list_head *lh, *lh_next; - struct scsi_dev_info_list *devinfo; - - list_for_each_safe(lh, lh_next, &scsi_dev_info_list) { - devinfo = list_entry(lh, struct scsi_dev_info_list, - dev_info_list); - kfree(devinfo); - } -} - -/** - * scsi_dev_list_init: set up the dynamic device list. - * @dev_list: string of device flags to add - * - * Description: - * Add command line @dev_list entries, then add - * scsi_static_device_list entries to the scsi device info list. - **/ -static int scsi_dev_info_list_init (char *dev_list) -{ - int error, i; - - error = scsi_dev_info_list_add_str(dev_list); - if (error) - return error; - - for (i = 0; scsi_static_device_list[i].vendor != NULL; i++) { - error = scsi_dev_info_list_add(1 /* compatibile */, - scsi_static_device_list[i].vendor, - scsi_static_device_list[i].model, - NULL, - scsi_static_device_list[i].flags); - if (error) - break; - } - - if (error) - scsi_dev_info_list_delete(); - return error; -} - -/** - * get_device_flags - get device specific flags from the dynamic device - * list. Called during scan time. - * @vendor: vendor name - * @model: model name - * - * Description: - * Search the scsi_dev_info_list for an entry matching @vendor and - * @model, if found, return the matching flags value, else return - * scsi_default_dev_flags. - **/ -int scsi_get_device_flags(unsigned char *vendor, unsigned char *model) -{ - struct scsi_dev_info_list *devinfo; - - list_for_each_entry(devinfo, &scsi_dev_info_list, dev_info_list) { - if (devinfo->compatible) { - /* - * Behave like the older version of get_device_flags. - */ - size_t max; - /* - * XXX why skip leading spaces? If an odd INQUIRY - * value, that should have been part of the - * scsi_static_device_list[] entry, such as " FOO" - * rather than "FOO". Since this code is already - * here, and we don't know what device it is - * trying to work with, leave it as-is. - */ - max = 8; /* max length of vendor */ - while ((max > 0) && *vendor == ' ') { - max--; - vendor++; - } - /* - * XXX removing the following strlen() would be - * good, using it means that for a an entry not in - * the list, we scan every byte of every vendor - * listed in scsi_static_device_list[], and never match - * a single one (and still have to compare at - * least the first byte of each vendor). - */ - if (memcmp(devinfo->vendor, vendor, - min(max, strlen(devinfo->vendor)))) - continue; - /* - * Skip spaces again. - */ - max = 16; /* max length of model */ - while ((max > 0) && *model == ' ') { - max--; - model++; - } - if (memcmp(devinfo->model, model, - min(max, strlen(devinfo->model)))) - continue; - return devinfo->flags; - } else { - if (!memcmp(devinfo->vendor, vendor, - sizeof(devinfo->vendor)) && - !memcmp(devinfo->model, model, - sizeof(devinfo->model))) - return devinfo->flags; - } - } - return scsi_default_dev_flags; -} - int scsi_attach_device(struct scsi_device *sdev) { struct Scsi_Device_Template *sdt; @@ -1280,39 +1031,6 @@ } /* - * Function: scsi_slave_attach() - * - * Purpose: Called from the upper level driver attach to handle common - * attach code. - * - * Arguments: sdev - scsi_device to attach - * - * Returns: 1 on error, 0 on succes - * - * Lock Status: Protected via scsi_devicelist_mutex. - */ -int scsi_slave_attach(struct scsi_device *sdev) -{ - sdev->attached++; - return 0; -} - -/* - * Function: scsi_slave_detach() - * - * Purpose: Called from the upper level driver attach to handle common - * detach code. - * - * Arguments: sdev - struct scsi_device to detach - * - * Lock Status: Protected via scsi_devicelist_mutex. - */ -void scsi_slave_detach(struct scsi_device *sdev) -{ - sdev->attached--; -} - -/* * This entry point is called from the upper level module's module_init() * routine. That implies that when this function is called, the * scsi_mod module is locked down because of upper module layering and @@ -1377,43 +1095,9 @@ return 0; } -static char *scsi_dev_flags; -MODULE_PARM(scsi_dev_flags, "s"); -MODULE_PARM_DESC(scsi_dev_flags, - "Given scsi_dev_flags=vendor:model:flags, add a black/white list" - " entry for vendor and model with an integer value of flags" - " to the scsi device info list"); -MODULE_PARM(scsi_default_dev_flags, "i"); -MODULE_PARM_DESC(scsi_default_dev_flags, - "scsi default device flag integer value"); MODULE_DESCRIPTION("SCSI core"); MODULE_LICENSE("GPL"); -#ifndef MODULE -static int __init setup_scsi_dev_flags(char *str) -{ - scsi_dev_flags = str; - return 1; -} -__setup("scsi_dev_flags=", setup_scsi_dev_flags); - -static int __init setup_scsi_default_dev_flags(char *str) -{ - unsigned int tmp; - if (get_option(&str, &tmp) == 1) { - scsi_default_dev_flags = tmp; - printk(KERN_WARNING "%s %d\n", __FUNCTION__, - scsi_default_dev_flags); - return 1; - } else { - printk(KERN_WARNING "%s: usage scsi_default_dev_flags=intr\n", - __FUNCTION__); - return 0; - } -} -__setup("scsi_default_dev_flags=", setup_scsi_default_dev_flags); -#endif - static int __init init_scsi(void) { int error, i; @@ -1424,7 +1108,7 @@ error = scsi_init_procfs(); if (error) goto cleanup_queue; - error = scsi_dev_info_list_init(scsi_dev_flags); + error = scsi_init_devinfo(); if (error) goto cleanup_procfs; error = scsi_sysfs_register(); @@ -1441,7 +1125,7 @@ return 0; cleanup_devlist: - scsi_dev_info_list_delete(); + scsi_exit_devinfo(); cleanup_procfs: scsi_exit_procfs(); cleanup_queue: @@ -1454,7 +1138,7 @@ static void __exit exit_scsi(void) { scsi_sysfs_unregister(); - scsi_dev_info_list_delete(); + scsi_exit_devinfo(); devfs_remove("scsi"); scsi_exit_procfs(); scsi_exit_queue(); diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h --- a/drivers/scsi/scsi.h Thu May 15 15:24:35 2003 +++ b/drivers/scsi/scsi.h Thu May 15 15:24:35 2003 @@ -18,7 +18,6 @@ #include /* for CONFIG_SCSI_LOGGING */ #include - /* * These are the values that the SCpnt->sc_data_direction and * SRpnt->sr_data_direction can take. These need to be set @@ -126,144 +125,11 @@ #define SCSI_STATE_BHQUEUE 0x100a #define SCSI_STATE_MLQUEUE 0x100b -/* - * These are the values that the owner field can take. - * They are used as an indication of who the command belongs to. - */ -#define SCSI_OWNER_HIGHLEVEL 0x100 -#define SCSI_OWNER_MIDLEVEL 0x101 -#define SCSI_OWNER_LOWLEVEL 0x102 -#define SCSI_OWNER_ERROR_HANDLER 0x103 -#define SCSI_OWNER_BH_HANDLER 0x104 -#define SCSI_OWNER_NOBODY 0x105 - #define IDENTIFY_BASE 0x80 #define IDENTIFY(can_disconnect, lun) (IDENTIFY_BASE |\ ((can_disconnect) ? 0x40 : 0) |\ ((lun) & 0x07)) - -/* - * This defines the scsi logging feature. It is a means by which the - * user can select how much information they get about various goings on, - * and it can be really useful for fault tracing. The logging word is divided - * into 8 nibbles, each of which describes a loglevel. The division of things - * is somewhat arbitrary, and the division of the word could be changed if it - * were really needed for any reason. The numbers below are the only place where these - * are specified. For a first go-around, 3 bits is more than enough, since this - * gives 8 levels of logging (really 7, since 0 is always off). Cutting to 2 bits - * might be wise at some point. - */ - -#define SCSI_LOG_ERROR_SHIFT 0 -#define SCSI_LOG_TIMEOUT_SHIFT 3 -#define SCSI_LOG_SCAN_SHIFT 6 -#define SCSI_LOG_MLQUEUE_SHIFT 9 -#define SCSI_LOG_MLCOMPLETE_SHIFT 12 -#define SCSI_LOG_LLQUEUE_SHIFT 15 -#define SCSI_LOG_LLCOMPLETE_SHIFT 18 -#define SCSI_LOG_HLQUEUE_SHIFT 21 -#define SCSI_LOG_HLCOMPLETE_SHIFT 24 -#define SCSI_LOG_IOCTL_SHIFT 27 - -#define SCSI_LOG_ERROR_BITS 3 -#define SCSI_LOG_TIMEOUT_BITS 3 -#define SCSI_LOG_SCAN_BITS 3 -#define SCSI_LOG_MLQUEUE_BITS 3 -#define SCSI_LOG_MLCOMPLETE_BITS 3 -#define SCSI_LOG_LLQUEUE_BITS 3 -#define SCSI_LOG_LLCOMPLETE_BITS 3 -#define SCSI_LOG_HLQUEUE_BITS 3 -#define SCSI_LOG_HLCOMPLETE_BITS 3 -#define SCSI_LOG_IOCTL_BITS 3 - -#ifdef CONFIG_SCSI_LOGGING - -#define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) \ -{ \ - unsigned int mask; \ - \ - mask = (1 << (BITS)) - 1; \ - if( ((scsi_logging_level >> (SHIFT)) & mask) > (LEVEL) ) \ - { \ - (CMD); \ - } \ -} - -#define SCSI_SET_LOGGING(SHIFT, BITS, LEVEL) \ -{ \ - unsigned int mask; \ - \ - mask = ((1 << (BITS)) - 1) << SHIFT; \ - scsi_logging_level = ((scsi_logging_level & ~mask) \ - | ((LEVEL << SHIFT) & mask)); \ -} - - - -#else - -/* - * With no logging enabled, stub these out so they don't do anything. - */ -#define SCSI_SET_LOGGING(SHIFT, BITS, LEVEL) - -#define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) -#endif - -/* - * These are the macros that are actually used throughout the code to - * log events. If logging isn't enabled, they are no-ops and will be - * completely absent from the user's code. - * - * The 'set' versions of the macros are really intended to only be called - * from the /proc filesystem, and in production kernels this will be about - * all that is ever used. It could be useful in a debugging environment to - * bump the logging level when certain strange events are detected, however. - */ -#define SCSI_LOG_ERROR_RECOVERY(LEVEL,CMD) \ - SCSI_CHECK_LOGGING(SCSI_LOG_ERROR_SHIFT, SCSI_LOG_ERROR_BITS, LEVEL,CMD); -#define SCSI_LOG_TIMEOUT(LEVEL,CMD) \ - SCSI_CHECK_LOGGING(SCSI_LOG_TIMEOUT_SHIFT, SCSI_LOG_TIMEOUT_BITS, LEVEL,CMD); -#define SCSI_LOG_SCAN_BUS(LEVEL,CMD) \ - SCSI_CHECK_LOGGING(SCSI_LOG_SCAN_SHIFT, SCSI_LOG_SCAN_BITS, LEVEL,CMD); -#define SCSI_LOG_MLQUEUE(LEVEL,CMD) \ - SCSI_CHECK_LOGGING(SCSI_LOG_MLQUEUE_SHIFT, SCSI_LOG_MLQUEUE_BITS, LEVEL,CMD); -#define SCSI_LOG_MLCOMPLETE(LEVEL,CMD) \ - SCSI_CHECK_LOGGING(SCSI_LOG_MLCOMPLETE_SHIFT, SCSI_LOG_MLCOMPLETE_BITS, LEVEL,CMD); -#define SCSI_LOG_LLQUEUE(LEVEL,CMD) \ - SCSI_CHECK_LOGGING(SCSI_LOG_LLQUEUE_SHIFT, SCSI_LOG_LLQUEUE_BITS, LEVEL,CMD); -#define SCSI_LOG_LLCOMPLETE(LEVEL,CMD) \ - SCSI_CHECK_LOGGING(SCSI_LOG_LLCOMPLETE_SHIFT, SCSI_LOG_LLCOMPLETE_BITS, LEVEL,CMD); -#define SCSI_LOG_HLQUEUE(LEVEL,CMD) \ - SCSI_CHECK_LOGGING(SCSI_LOG_HLQUEUE_SHIFT, SCSI_LOG_HLQUEUE_BITS, LEVEL,CMD); -#define SCSI_LOG_HLCOMPLETE(LEVEL,CMD) \ - SCSI_CHECK_LOGGING(SCSI_LOG_HLCOMPLETE_SHIFT, SCSI_LOG_HLCOMPLETE_BITS, LEVEL,CMD); -#define SCSI_LOG_IOCTL(LEVEL,CMD) \ - SCSI_CHECK_LOGGING(SCSI_LOG_IOCTL_SHIFT, SCSI_LOG_IOCTL_BITS, LEVEL,CMD); - - -#define SCSI_SET_ERROR_RECOVERY_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_ERROR_SHIFT, SCSI_LOG_ERROR_BITS, LEVEL); -#define SCSI_SET_TIMEOUT_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_TIMEOUT_SHIFT, SCSI_LOG_TIMEOUT_BITS, LEVEL); -#define SCSI_SET_SCAN_BUS_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_SCAN_SHIFT, SCSI_LOG_SCAN_BITS, LEVEL); -#define SCSI_SET_MLQUEUE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_MLQUEUE_SHIFT, SCSI_LOG_MLQUEUE_BITS, LEVEL); -#define SCSI_SET_MLCOMPLETE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_MLCOMPLETE_SHIFT, SCSI_LOG_MLCOMPLETE_BITS, LEVEL); -#define SCSI_SET_LLQUEUE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_LLQUEUE_SHIFT, SCSI_LOG_LLQUEUE_BITS, LEVEL); -#define SCSI_SET_LLCOMPLETE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_LLCOMPLETE_SHIFT, SCSI_LOG_LLCOMPLETE_BITS, LEVEL); -#define SCSI_SET_HLQUEUE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_HLQUEUE_SHIFT, SCSI_LOG_HLQUEUE_BITS, LEVEL); -#define SCSI_SET_HLCOMPLETE_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_HLCOMPLETE_SHIFT, SCSI_LOG_HLCOMPLETE_BITS, LEVEL); -#define SCSI_SET_IOCTL_LOGGING(LEVEL) \ - SCSI_SET_LOGGING(SCSI_LOG_IOCTL_SHIFT, SCSI_LOG_IOCTL_BITS, LEVEL); - /* host byte codes */ #define DID_OK 0x00 /* NO error */ #define DID_NO_CONNECT 0x01 /* Couldn't connect before timeout period */ @@ -356,6 +222,7 @@ * Forward-declaration of structs for prototypes. */ struct Scsi_Host; +struct scsi_target; struct scatterlist; /* @@ -365,24 +232,12 @@ typedef struct scsi_cmnd Scsi_Cmnd; typedef struct scsi_request Scsi_Request; -#define SCSI_CMND_MAGIC 0xE25C23A5 -#define SCSI_REQ_MAGIC 0x75F6D354 - -/* - * Here is where we prototype most of the mid-layer. - */ - -extern unsigned int scsi_logging_level; /* What do we log? */ - /* * These are the error handling functions defined in scsi_error.c */ -extern void scsi_times_out(Scsi_Cmnd * SCpnt); extern void scsi_add_timer(Scsi_Cmnd * SCset, int timeout, void (*complete) (Scsi_Cmnd *)); extern int scsi_delete_timer(Scsi_Cmnd * SCset); -extern void scsi_error_handler(void *host); -extern int scsi_decide_disposition(Scsi_Cmnd * SCpnt); extern int scsi_block_when_processing_errors(Scsi_Device *); extern void scsi_sleep(int); @@ -396,39 +251,19 @@ /* * Prototypes for functions in scsi_lib.c */ -extern int scsi_maybe_unblock_host(Scsi_Device * SDpnt); -extern void scsi_setup_cmd_retry(Scsi_Cmnd *SCpnt); extern void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors, int block_sectors); -extern int scsi_queue_insert(struct scsi_cmnd *cmd, int reason); -extern void scsi_queue_next_request(request_queue_t *q, struct scsi_cmnd *cmd); -extern request_queue_t *scsi_alloc_queue(struct scsi_device *sdev); -extern void scsi_free_queue(request_queue_t *q); -extern int scsi_init_queue(void); -extern void scsi_exit_queue(void); /* * Prototypes for functions in scsi.c */ -extern int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt); -extern int scsi_setup_command_freelist(struct Scsi_Host *shost); -extern void scsi_destroy_command_freelist(struct Scsi_Host *shost); extern struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, int flags); extern void scsi_put_command(struct scsi_cmnd *cmd); extern void scsi_adjust_queue_depth(Scsi_Device *, int, int); extern int scsi_track_queue_full(Scsi_Device *, int); -extern int scsi_slave_attach(struct scsi_device *); -extern void scsi_slave_detach(struct scsi_device *); extern int scsi_device_get(struct scsi_device *); extern void scsi_device_put(struct scsi_device *); extern void scsi_set_device_offline(struct scsi_device *); -extern void scsi_done(Scsi_Cmnd * SCpnt); -extern void scsi_finish_command(Scsi_Cmnd *); -extern int scsi_retry_command(Scsi_Cmnd *); -extern int scsi_attach_device(struct scsi_device *); -extern void scsi_detach_device(struct scsi_device *); -extern void scsi_rescan_device(struct scsi_device *); -extern int scsi_get_device_flags(unsigned char *vendor, unsigned char *model); /* * Newer request-based interfaces. @@ -438,30 +273,10 @@ extern void scsi_wait_req(Scsi_Request *, const void *cmnd, void *buffer, unsigned bufflen, int timeout, int retries); - extern void scsi_do_req(Scsi_Request *, const void *cmnd, void *buffer, unsigned bufflen, void (*done) (struct scsi_cmnd *), int timeout, int retries); -extern int scsi_insert_special_req(Scsi_Request * SRpnt, int); -extern void scsi_init_cmd_from_req(Scsi_Cmnd *, Scsi_Request *); - -/* - * Prototypes for functions in scsi_proc.c - */ -#ifdef CONFIG_PROC_FS -extern int scsi_init_procfs(void); -extern void scsi_exit_procfs(void); - -extern void scsi_proc_host_add(struct Scsi_Host *); -extern void scsi_proc_host_rm(struct Scsi_Host *); -#else -static inline int scsi_init_procfs(void) { return 0; } -static inline void scsi_exit_procfs(void) { ; } - -static inline void scsi_proc_host_add(struct Scsi_Host *); -static inline void scsi_proc_host_rm(struct Scsi_Host *); -#endif /* CONFIG_PROC_FS */ /* * Prototypes for functions in scsi_scan.c @@ -486,40 +301,6 @@ extern const char *scsi_sense_key_string(unsigned char); extern const char *scsi_extd_sense_format(unsigned char, unsigned char); -/* - * dev_info: for the black/white list in the old scsi_static_device_list - */ -struct dev_info { - char *vendor; - char *model; - char *revision; /* revision known to be bad, unused */ - unsigned flags; -}; - -extern struct dev_info scsi_static_device_list[]; - -/* - * scsi_dev_info_list: structure to hold black/white listed devices. - */ -struct scsi_dev_info_list { - struct list_head dev_info_list; - char vendor[8]; - char model[16]; - unsigned flags; - unsigned compatible; /* for use with scsi_static_device_list entries */ -}; -extern struct list_head scsi_dev_info_list; -extern int scsi_dev_info_list_add_str(char *); - -/* - * scsi_target: representation of a scsi target, for now, this is only - * used for single_lun devices. If no one has active IO to the target, - * starget_sdev_user is NULL, else it points to the active sdev. - */ -struct scsi_target { - struct scsi_device *starget_sdev_user; - unsigned int starget_refcnt; -}; /* * The scsi_device struct contains what we know about each given scsi @@ -540,8 +321,6 @@ */ struct list_head siblings; /* list of all devices on this host */ struct list_head same_target_siblings; /* just the devices sharing same target id */ - wait_queue_head_t scpnt_wait; /* Used to wait if - device is busy */ struct Scsi_Host *host; request_queue_t *request_queue; volatile unsigned short device_busy; /* commands actually active on low-level */ @@ -563,8 +342,6 @@ * vendor-specific cmd's */ unsigned sector_size; /* size in bytes */ - int attached; /* # of high level drivers attached to - * this */ int access_count; /* Count of open channels/mounts */ void *hostdata; /* available to low-level driver */ @@ -619,9 +396,6 @@ /* default value if the device doesn't override */ #define SCSI_DEFAULT_DEVICE_BLOCKED 3 - - // Flag to allow revalidate to succeed in sd_open - int allow_revalidate; struct device sdev_driverfs_dev; }; #define to_scsi_device(d) \ @@ -698,7 +472,6 @@ unsigned short state; unsigned short owner; Scsi_Request *sc_request; - struct scsi_cmnd *reset_chain; struct list_head list; /* scsi_cmnd participates in queue lists */ @@ -783,14 +556,6 @@ unsigned flags; - /* - * Used to indicate that a command which has timed out also - * completed normally. Typically the completion function will - * do nothing but set this flag in this instance because the - * timeout handler is already running. - */ - unsigned done_late:1; - /* Low-level done function - can be used by low-level driver to point * to completion function. Not used by mid/upper level code. */ void (*scsi_done) (struct scsi_cmnd *); @@ -817,11 +582,6 @@ }; /* - * Flag bit for the internal_timeout array - */ -#define NORMAL_TIMEOUT 0 - -/* * Definitions and prototypes used for scsi mid-level queue. */ #define SCSI_MLQUEUE_HOST_BUSY 0x1055 @@ -829,8 +589,7 @@ #define SCSI_MLQUEUE_EH_RETRY 0x1057 /* - * old style reset request from external source - * (private to sg.c and scsi_error.c, supplied by scsi_obsolete.c) + * Reset request from external source */ #define SCSI_TRY_RESET_DEVICE 1 #define SCSI_TRY_RESET_BUS 2 @@ -922,34 +681,6 @@ return (Scsi_Cmnd *)req->special; } -#define scsi_eh_eflags_chk(scp, flags) (scp->eh_eflags & flags) - -#define scsi_eh_eflags_set(scp, flags) do { \ - scp->eh_eflags |= flags; \ - } while(0) - -#define scsi_eh_eflags_clr(scp, flags) do { \ - scp->eh_eflags &= ~flags; \ - } while(0) - -#define scsi_eh_eflags_clr_all(scp) (scp->eh_eflags = 0) - -/* - * Scsi Error Handler Flags - */ -#define SCSI_EH_CANCEL_CMD 0x0001 /* Cancel this cmd */ -#define SCSI_EH_REC_TIMEOUT 0x0002 /* EH retry timed out */ - -#define SCSI_SENSE_VALID(scmd) ((scmd->sense_buffer[0] & 0x70) == 0x70) - -extern int scsi_eh_scmd_add(struct scsi_cmnd *, int); - int scsi_set_medium_removal(Scsi_Device *dev, char state); - -extern int scsi_device_register(struct scsi_device *); -extern void scsi_device_unregister(struct scsi_device *); - -extern int scsi_sysfs_register(void); -extern void scsi_sysfs_unregister(void); #endif /* _SCSI_H */ diff -Nru a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c --- a/drivers/scsi/scsi_debug.c Thu May 15 15:24:40 2003 +++ b/drivers/scsi/scsi_debug.c Thu May 15 15:24:40 2003 @@ -52,9 +52,10 @@ #include #endif +#include "scsi_logging.h" #include "scsi_debug.h" -static const char * scsi_debug_version_str = "Version: 1.69 (20030329)"; +static const char * scsi_debug_version_str = "Version: 1.70 (20030507)"; /* Additional Sense Code (ASC) used */ #define NO_ADDED_SENSE 0x0 @@ -144,10 +145,13 @@ struct sdebug_host_info { struct list_head host_list; struct Scsi_Host *shost; - struct device *dev; + struct device dev; struct list_head dev_info_list; }; +#define to_sdebug_host(d) \ + container_of(d, struct sdebug_host_info, dev) + static LIST_HEAD(sdebug_host_list); static spinlock_t sdebug_host_list_lock = SPIN_LOCK_UNLOCKED; @@ -162,6 +166,30 @@ }; static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE]; +static Scsi_Host_Template sdebug_driver_template = { + .proc_info = scsi_debug_proc_info, + .name = "SCSI DEBUG", + .info = scsi_debug_info, + .slave_alloc = scsi_debug_slave_alloc, + .slave_configure = scsi_debug_slave_configure, + .slave_destroy = scsi_debug_slave_destroy, + .ioctl = scsi_debug_ioctl, + .queuecommand = scsi_debug_queuecommand, + .eh_abort_handler = scsi_debug_abort, + .eh_bus_reset_handler = scsi_debug_bus_reset, + .eh_device_reset_handler = scsi_debug_device_reset, + .eh_host_reset_handler = scsi_debug_host_reset, + .bios_param = scsi_debug_biosparam, + .can_queue = SCSI_DEBUG_CANQUEUE, + .this_id = 7, + .sg_tablesize = 64, + .cmd_per_lun = 3, + .max_sectors = 4096, + .unchecked_isa_dma = 0, + .use_clustering = ENABLE_CLUSTERING, + .module = THIS_MODULE, +}; + static unsigned char * fake_storep; /* ramdisk storage */ static unsigned char spare_buff[SDEBUG_SENSE_LEN]; @@ -178,9 +206,11 @@ static int sdebug_driver_probe(struct device *); static int sdebug_driver_remove(struct device *); +static struct bus_type pseudo_lld_bus; static struct device_driver sdebug_driverfs_driver = { .name = sdebug_proc_name, + .bus = &pseudo_lld_bus, .probe = sdebug_driver_probe, .remove = sdebug_driver_remove, }; @@ -221,24 +251,6 @@ static void sdebug_remove_adapter(void); static struct device pseudo_primary; static struct bus_type pseudo_lld_bus; -static int scsi_debug_register_driver(struct device_driver *); -static int scsi_debug_unregister_driver(struct device_driver *); - -static struct sdebug_host_info * - sdebug_shost_to_host_info(struct Scsi_Host *shost) -{ - struct sdebug_host_info * sdbg_host, * found = NULL; - - spin_lock(&sdebug_host_list_lock); - list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) { - if (sdbg_host->shost == shost) { - found = sdbg_host; - break; - } - } - spin_unlock(&sdebug_host_list_lock); - return found; -} static unsigned char * scatg2virt(const struct scatterlist * sclp) { @@ -283,10 +295,12 @@ bufflen = SDEBUG_SENSE_LEN; } + if(target == sdebug_driver_template.this_id) { - printk(KERN_WARNING - "scsi_debug: initiator's id used as target!\n"); - return schedule_resp(SCpnt, NULL, done, 0, 0); + printk(KERN_INFO "scsi_debug: initiator's id used as " + "target!\n"); + return schedule_resp(SCpnt, NULL, done, + DID_NO_CONNECT << 16, 0); } if (SCpnt->device->lun >= scsi_debug_max_luns) @@ -643,6 +657,15 @@ return sizeof(ctrl_m_pg); } +static int resp_iec_m_pg(unsigned char * p, int pcontrol, int target) +{ /* Informational Exceptions control mode page for mode_sense */ + unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, + 0, 0, 0x0, 0x0}; + memcpy(p, iec_m_pg, sizeof(iec_m_pg)); + if (1 == pcontrol) + memset(p + 2, 0, sizeof(iec_m_pg) - 2); + return sizeof(iec_m_pg); +} #define SDEBUG_MAX_MSENSE_SZ 256 @@ -709,12 +732,17 @@ len = resp_ctrl_m_pg(ap, pcontrol, target); offset += len; break; + case 0x1c: /* Informational Exceptions Mode page, all devices */ + len = resp_iec_m_pg(ap, pcontrol, target); + offset += len; + break; case 0x3f: /* Read all Mode pages */ len = resp_err_recov_pg(ap, pcontrol, target); len += resp_disconnect_pg(ap + len, pcontrol, target); len += resp_format_pg(ap + len, pcontrol, target); len += resp_caching_pg(ap + len, pcontrol, target); len += resp_ctrl_m_pg(ap + len, pcontrol, target); + len += resp_iec_m_pg(ap + len, pcontrol, target); offset += len; break; default: @@ -865,7 +893,7 @@ static void timer_intr_handler(unsigned long indx) { struct sdebug_queued_cmd * sqcp; - unsigned int iflags; + unsigned long iflags; if (indx >= SCSI_DEBUG_CANQUEUE) { printk(KERN_ERR "scsi_debug:timer_intr_handler: indx too " @@ -938,9 +966,9 @@ if (devip) return devip; - sdbg_host = sdebug_shost_to_host_info(sdev->host); + sdbg_host = *(struct sdebug_host_info **) sdev->host->hostdata; if(! sdbg_host) { - printk(KERN_ERR "Unable to locate host info\n"); + printk(KERN_ERR "Host info NULL\n"); return NULL; } list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) { @@ -1040,7 +1068,7 @@ printk(KERN_INFO "scsi_debug: bus_reset\n"); ++num_bus_resets; if (SCpnt && ((sdp = SCpnt->device)) && ((hp = sdp->host))) { - sdbg_host = sdebug_shost_to_host_info(hp); + sdbg_host = *(struct sdebug_host_info **) hp->hostdata; if (sdbg_host) { list_for_each_entry(dev_info, &sdbg_host->dev_info_list, @@ -1496,7 +1524,7 @@ device_register(&pseudo_primary); bus_register(&pseudo_lld_bus); - scsi_debug_register_driver(&sdebug_driverfs_driver); + driver_register(&sdebug_driverfs_driver); do_create_driverfs_files(); sdebug_driver_template.proc_name = (char *)sdebug_proc_name; @@ -1521,10 +1549,13 @@ static void __exit scsi_debug_exit(void) { - /* free up adapters here ?? */ + int k = scsi_debug_add_host; + stop_all_queued(); + for (; k; k--) + sdebug_remove_adapter(); do_remove_driverfs_files(); - scsi_debug_unregister_driver(&sdebug_driverfs_driver); + driver_unregister(&sdebug_driverfs_driver); bus_unregister(&pseudo_lld_bus); device_unregister(&pseudo_primary); @@ -1550,51 +1581,76 @@ .match = pseudo_lld_bus_match, }; -static int scsi_debug_register_driver(struct device_driver *dev_driver) -{ - dev_driver->bus = &pseudo_lld_bus; - driver_register(dev_driver); - - return 0; -} - -static int scsi_debug_unregister_driver(struct device_driver *dev_driver) -{ - driver_unregister(dev_driver); - return 0; -} - static void sdebug_release_adapter(struct device * dev) { - kfree(dev); + struct sdebug_host_info *sdbg_host; + + sdbg_host = to_sdebug_host(dev); + kfree(sdbg_host); } static int sdebug_add_adapter() { - struct device * dev; - int error; + int k, devs_per_host; + int error = 0; + struct sdebug_host_info *sdbg_host; + struct sdebug_dev_info *sdbg_devinfo; + struct list_head *lh, *lh_sf; + + sdbg_host = kmalloc(sizeof(*sdbg_host),GFP_KERNEL); - dev = kmalloc(sizeof(*dev),GFP_KERNEL); - if (NULL == dev) { + if (NULL == sdbg_host) { printk(KERN_ERR "%s: out of memory at line %d\n", __FUNCTION__, __LINE__); return -ENOMEM; } - memset(dev, 0, sizeof(*dev)); - dev->bus = &pseudo_lld_bus; - dev->parent = &pseudo_primary; - dev->release = &sdebug_release_adapter; - sprintf(dev->name, "scsi debug adapter"); - sprintf(dev->bus_id, "adapter%d", scsi_debug_add_host); + memset(sdbg_host, 0, sizeof(*sdbg_host)); + INIT_LIST_HEAD(&sdbg_host->dev_info_list); + + devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns; + for (k = 0; k < devs_per_host; k++) { + sdbg_devinfo = kmalloc(sizeof(*sdbg_devinfo),GFP_KERNEL); + if (NULL == sdbg_devinfo) { + printk(KERN_ERR "%s: out of memory at line %d\n", + __FUNCTION__, __LINE__); + error = -ENOMEM; + goto clean1; + } + memset(sdbg_devinfo, 0, sizeof(*sdbg_devinfo)); + sdbg_devinfo->sdbg_host = sdbg_host; + list_add_tail(&sdbg_devinfo->dev_list, + &sdbg_host->dev_info_list); + } + + spin_lock(&sdebug_host_list_lock); + list_add_tail(&sdbg_host->host_list, &sdebug_host_list); + spin_unlock(&sdebug_host_list_lock); + + sdbg_host->dev.bus = &pseudo_lld_bus; + sdbg_host->dev.parent = &pseudo_primary; + sdbg_host->dev.release = &sdebug_release_adapter; + sprintf(sdbg_host->dev.name, "scsi debug adapter"); + sprintf(sdbg_host->dev.bus_id, "adapter%d", scsi_debug_add_host); - error = device_register(dev); + error = device_register(&sdbg_host->dev); if (error) - kfree(dev); - else - ++scsi_debug_add_host; + goto clean2; + ++scsi_debug_add_host; + return error; + +clean2: + list_for_each_safe(lh, lh_sf, &sdbg_host->dev_info_list) { + sdbg_devinfo = list_entry(lh, struct sdebug_dev_info, + dev_list); + list_del(&sdbg_devinfo->dev_list); + kfree(sdbg_devinfo); + } + +clean1: + kfree(sdbg_host); return error; } @@ -1603,86 +1659,50 @@ struct sdebug_host_info * sdbg_host = NULL; spin_lock(&sdebug_host_list_lock); - if (!list_empty(&sdebug_host_list)) + if (!list_empty(&sdebug_host_list)) { sdbg_host = list_entry(sdebug_host_list.prev, struct sdebug_host_info, host_list); + list_del(&sdbg_host->host_list); + } spin_unlock(&sdebug_host_list_lock); - device_unregister(sdbg_host->dev); + if (!sdbg_host) + return; + + device_unregister(&sdbg_host->dev); --scsi_debug_add_host; } static int sdebug_driver_probe(struct device * dev) { - int k, devs_per_host; int error = 0; struct sdebug_host_info *sdbg_host; - struct sdebug_dev_info *sdbg_devinfo; - struct list_head *lh, *lh_sf; struct Scsi_Host *hpnt; - sdbg_host = kmalloc(sizeof(*sdbg_host),GFP_KERNEL); - if (NULL == sdbg_host) { - printk(KERN_ERR "%s: out of memory at line %d\n", - __FUNCTION__, __LINE__); - return -ENOMEM; - } - memset(sdbg_host, 0, sizeof(*sdbg_host)); - - INIT_LIST_HEAD(&sdbg_host->dev_info_list); - - devs_per_host = scsi_debug_num_tgts * scsi_debug_max_luns; - for (k = 0; k < devs_per_host; k++) { - sdbg_devinfo = kmalloc(sizeof(*sdbg_devinfo),GFP_KERNEL); - if (NULL == sdbg_devinfo) { - printk(KERN_ERR "%s: out of memory at line %d\n", - __FUNCTION__, __LINE__); - error = -ENOMEM; - } - memset(sdbg_devinfo, 0, sizeof(*sdbg_devinfo)); - sdbg_devinfo->sdbg_host = sdbg_host; - list_add_tail(&sdbg_devinfo->dev_list, - &sdbg_host->dev_info_list); - } - - list_add_tail(&sdbg_host->host_list, &sdebug_host_list); + sdbg_host = to_sdebug_host(dev); - hpnt = scsi_register(&sdebug_driver_template, 0); + hpnt = scsi_register(&sdebug_driver_template, sizeof(sdbg_host)); if (NULL == hpnt) { printk(KERN_ERR "%s: scsi_register failed\n", __FUNCTION__); error = -ENODEV; - goto clean1; + return error; } sdbg_host->shost = hpnt; - sdbg_host->dev = dev; + *((struct sdebug_host_info **)hpnt->hostdata) = sdbg_host; if ((hpnt->this_id >= 0) && (scsi_debug_num_tgts > hpnt->this_id)) hpnt->max_id = scsi_debug_num_tgts + 1; else hpnt->max_id = scsi_debug_num_tgts; hpnt->max_lun = scsi_debug_max_luns; - error = scsi_add_host(hpnt, sdbg_host->dev); + error = scsi_add_host(hpnt, &sdbg_host->dev); if (error) { printk(KERN_ERR "%s: scsi_add_host failed\n", __FUNCTION__); error = -ENODEV; - goto clean2; - } - - - return 0; - -clean2: - scsi_unregister(hpnt); -clean1: - list_for_each_safe(lh, lh_sf, &sdbg_host->dev_info_list) { - sdbg_devinfo = list_entry(lh, struct sdebug_dev_info, - dev_list); - list_del(&sdbg_devinfo->dev_list); - kfree(sdbg_devinfo); + scsi_unregister(hpnt); } - kfree(sdbg_host); return error; } @@ -1690,25 +1710,16 @@ static int sdebug_driver_remove(struct device * dev) { struct list_head *lh, *lh_sf; + struct sdebug_host_info *sdbg_host; struct sdebug_dev_info *sdbg_devinfo; - struct sdebug_host_info *sdbg_host, *found = NULL; - spin_lock(&sdebug_host_list_lock); - list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) { - if (sdbg_host->dev == dev) { - list_del(&sdbg_host->host_list); - found = sdbg_host; - break; - } - } - spin_unlock(&sdebug_host_list_lock); - - if (!found) { - printk(KERN_ERR "%s: sdebug_host_info not found\n", - __FUNCTION__); - return -ENODEV; - } + sdbg_host = to_sdebug_host(dev); + if (!sdbg_host) { + printk(KERN_ERR "%s: Unable to locate host info\n", + __FUNCTION__); + return -ENODEV; + } if (scsi_remove_host(sdbg_host->shost)) { printk(KERN_ERR "%s: scsi_remove_host failed\n", __FUNCTION__); @@ -1723,8 +1734,6 @@ list_del(&sdbg_devinfo->dev_list); kfree(sdbg_devinfo); } - - kfree(sdbg_host); return 0; } diff -Nru a/drivers/scsi/scsi_debug.h b/drivers/scsi/scsi_debug.h --- a/drivers/scsi/scsi_debug.h Thu May 15 15:24:38 2003 +++ b/drivers/scsi/scsi_debug.h Thu May 15 15:24:38 2003 @@ -24,28 +24,4 @@ #define SCSI_DEBUG_MAX_CMD_LEN 16 -static Scsi_Host_Template sdebug_driver_template = { - .proc_info = scsi_debug_proc_info, - .name = "SCSI DEBUG", - .info = scsi_debug_info, - .slave_alloc = scsi_debug_slave_alloc, - .slave_configure = scsi_debug_slave_configure, - .slave_destroy = scsi_debug_slave_destroy, - .ioctl = scsi_debug_ioctl, - .queuecommand = scsi_debug_queuecommand, - .eh_abort_handler = scsi_debug_abort, - .eh_bus_reset_handler = scsi_debug_bus_reset, - .eh_device_reset_handler = scsi_debug_device_reset, - .eh_host_reset_handler = scsi_debug_host_reset, - .bios_param = scsi_debug_biosparam, - .can_queue = SCSI_DEBUG_CANQUEUE, - .this_id = 7, - .sg_tablesize = 64, - .cmd_per_lun = 3, - .max_sectors = 4096, - .unchecked_isa_dma = 0, - .use_clustering = ENABLE_CLUSTERING, - .module = THIS_MODULE, -}; - #endif diff -Nru a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/scsi/scsi_devinfo.c Thu May 15 15:24:47 2003 @@ -0,0 +1,542 @@ + +#include +#include +#include +#include +#include +#include + +#include "scsi.h" +#include "scsi_priv.h" +#include "scsi_devinfo.h" + +/* + * scsi_dev_info_list: structure to hold black/white listed devices. + */ +struct scsi_dev_info_list { + struct list_head dev_info_list; + char vendor[8]; + char model[16]; + unsigned flags; + unsigned compatible; /* for use with scsi_static_device_list entries */ +}; + + +static const char spaces[] = " "; /* 16 of them */ +static char *scsi_dev_flags; +static unsigned scsi_default_dev_flags; +static LIST_HEAD(scsi_dev_info_list); + +/* + * scsi_static_device_list: deprecated list of devices that require + * settings that differ from the default, includes black-listed (broken) + * devices. The entries here are added to the tail of scsi_dev_info_list + * via scsi_dev_info_list_init. + * + * Do not add to this list, use the command line or proc interface to add + * to the scsi_dev_info_list. This table will eventually go away. + */ +static struct { + char *vendor; + char *model; + char *revision; /* revision known to be bad, unused */ + unsigned flags; +} scsi_static_device_list[] __initdata = { + /* + * The following devices are known not to tolerate a lun != 0 scan + * for one reason or another. Some will respond to all luns, + * others will lock up. + */ + {"Aashima", "IMAGERY 2400SP", "1.03", BLIST_NOLUN}, /* locks up */ + {"CHINON", "CD-ROM CDS-431", "H42", BLIST_NOLUN}, /* locks up */ + {"CHINON", "CD-ROM CDS-535", "Q14", BLIST_NOLUN}, /* locks up */ + {"DENON", "DRD-25X", "V", BLIST_NOLUN}, /* locks up */ + {"HITACHI", "DK312C", "CM81", BLIST_NOLUN}, /* responds to all lun */ + {"HITACHI", "DK314C", "CR21", BLIST_NOLUN}, /* responds to all lun */ + {"IMS", "CDD521/10", "2.06", BLIST_NOLUN}, /* locks up */ + {"MAXTOR", "XT-3280", "PR02", BLIST_NOLUN}, /* locks up */ + {"MAXTOR", "XT-4380S", "B3C", BLIST_NOLUN}, /* locks up */ + {"MAXTOR", "MXT-1240S", "I1.2", BLIST_NOLUN}, /* locks up */ + {"MAXTOR", "XT-4170S", "B5A", BLIST_NOLUN}, /* locks up */ + {"MAXTOR", "XT-8760S", "B7B", BLIST_NOLUN}, /* locks up */ + {"MEDIAVIS", "RENO CD-ROMX2A", "2.03", BLIST_NOLUN}, /* responds to all lun */ + {"NEC", "CD-ROM DRIVE:841", "1.0", BLIST_NOLUN},/* locks up */ + {"PHILIPS", "PCA80SC", "V4-2", BLIST_NOLUN}, /* responds to all lun */ + {"RODIME", "RO3000S", "2.33", BLIST_NOLUN}, /* locks up */ + {"SUN", "SENA", NULL, BLIST_NOLUN}, /* responds to all luns */ + /* + * The following causes a failed REQUEST SENSE on lun 1 for + * aha152x controller, which causes SCSI code to reset bus. + */ + {"SANYO", "CRD-250S", "1.20", BLIST_NOLUN}, + /* + * The following causes a failed REQUEST SENSE on lun 1 for + * aha152x controller, which causes SCSI code to reset bus. + */ + {"SEAGATE", "ST157N", "\004|j", BLIST_NOLUN}, + {"SEAGATE", "ST296", "921", BLIST_NOLUN}, /* responds to all lun */ + {"SEAGATE", "ST1581", "6538", BLIST_NOLUN}, /* responds to all lun */ + {"SONY", "CD-ROM CDU-541", "4.3d", BLIST_NOLUN}, + {"SONY", "CD-ROM CDU-55S", "1.0i", BLIST_NOLUN}, + {"SONY", "CD-ROM CDU-561", "1.7x", BLIST_NOLUN}, + {"SONY", "CD-ROM CDU-8012", NULL, BLIST_NOLUN}, + {"TANDBERG", "TDC 3600", "U07", BLIST_NOLUN}, /* locks up */ + {"TEAC", "CD-R55S", "1.0H", BLIST_NOLUN}, /* locks up */ + /* + * The following causes a failed REQUEST SENSE on lun 1 for + * seagate controller, which causes SCSI code to reset bus. + */ + {"TEAC", "CD-ROM", "1.06", BLIST_NOLUN}, + {"TEAC", "MT-2ST/45S2-27", "RV M", BLIST_NOLUN}, /* responds to all lun */ + /* + * The following causes a failed REQUEST SENSE on lun 1 for + * seagate controller, which causes SCSI code to reset bus. + */ + {"TEXEL", "CD-ROM", "1.06", BLIST_NOLUN}, + {"QUANTUM", "LPS525S", "3110", BLIST_NOLUN}, /* locks up */ + {"QUANTUM", "PD1225S", "3110", BLIST_NOLUN}, /* locks up */ + {"QUANTUM", "FIREBALL ST4.3S", "0F0C", BLIST_NOLUN}, /* locks up */ + {"MEDIAVIS", "CDR-H93MV", "1.31", BLIST_NOLUN}, /* locks up */ + {"SANKYO", "CP525", "6.64", BLIST_NOLUN}, /* causes failed REQ SENSE, extra reset */ + {"HP", "C1750A", "3226", BLIST_NOLUN}, /* scanjet iic */ + {"HP", "C1790A", "", BLIST_NOLUN}, /* scanjet iip */ + {"HP", "C2500A", "", BLIST_NOLUN}, /* scanjet iicx */ + {"YAMAHA", "CDR100", "1.00", BLIST_NOLUN}, /* locks up */ + {"YAMAHA", "CDR102", "1.00", BLIST_NOLUN}, /* locks up */ + {"YAMAHA", "CRW8424S", "1.0", BLIST_NOLUN}, /* locks up */ + {"YAMAHA", "CRW6416S", "1.0c", BLIST_NOLUN}, /* locks up */ + {"MITSUMI", "CD-R CR-2201CS", "6119", BLIST_NOLUN}, /* locks up */ + {"RELISYS", "Scorpio", NULL, BLIST_NOLUN}, /* responds to all lun */ + {"MICROTEK", "ScanMaker II", "5.61", BLIST_NOLUN}, /* responds to all lun */ + {"NEC", "D3856", "0009", BLIST_NOLUN}, + + /* + * Other types of devices that have special flags. + */ + {"SONY", "CD-ROM CDU-8001", NULL, BLIST_BORKEN}, + {"TEXEL", "CD-ROM", "1.06", BLIST_BORKEN}, + {"IOMEGA", "Io20S *F", NULL, BLIST_KEY}, + {"INSITE", "Floptical F*8I", NULL, BLIST_KEY}, + {"INSITE", "I325VM", NULL, BLIST_KEY}, + {"LASOUND", "CDX7405", "3.10", BLIST_MAX5LUN | BLIST_SINGLELUN}, + {"MICROP", "4110", NULL, BLIST_NOTQ}, + {"NRC", "MBR-7", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"NRC", "MBR-7.4", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN}, + {"NAKAMICH", "MJ-4.8S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"NAKAMICH", "MJ-5.16S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"PIONEER", "CD-ROM DRM-600", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"PIONEER", "CD-ROM DRM-602X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"PIONEER", "CD-ROM DRM-604X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"EMULEX", "MD21/S2 ESDI", NULL, BLIST_SINGLELUN}, + {"CANON", "IPUBJD", NULL, BLIST_SPARSELUN}, + {"nCipher", "Fastness Crypto", NULL, BLIST_FORCELUN}, + {"DEC", "HSG80", NULL, BLIST_FORCELUN}, + {"COMPAQ", "LOGICAL VOLUME", NULL, BLIST_FORCELUN}, + {"COMPAQ", "CR3500", NULL, BLIST_FORCELUN}, + {"NEC", "PD-1 ODX654P", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN}, + {"TOSHIBA", "CDROM", NULL, BLIST_ISROM}, + {"TOSHIBA", "CD-ROM", NULL, BLIST_ISROM}, + {"MegaRAID", "LD", NULL, BLIST_FORCELUN}, + {"DGC", "RAID", NULL, BLIST_SPARSELUN}, /* Dell PV 650F, storage on LUN 0 */ + {"DGC", "DISK", NULL, BLIST_SPARSELUN}, /* Dell PV 650F, no storage on LUN 0 */ + {"DELL", "PV660F", NULL, BLIST_SPARSELUN}, + {"DELL", "PV660F PSEUDO", NULL, BLIST_SPARSELUN}, + {"DELL", "PSEUDO DEVICE .", NULL, BLIST_SPARSELUN}, /* Dell PV 530F */ + {"DELL", "PV530F", NULL, BLIST_SPARSELUN}, + {"EMC", "SYMMETRIX", NULL, BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_FORCELUN}, + {"HP", "A6189A", NULL, BLIST_SPARSELUN | BLIST_LARGELUN}, /* HP VA7400 */ + {"HP", "OPEN-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, /* HP XP Arrays */ + {"CMD", "CRA-7280", NULL, BLIST_SPARSELUN}, /* CMD RAID Controller */ + {"CNSI", "G7324", NULL, BLIST_SPARSELUN}, /* Chaparral G7324 RAID */ + {"CNSi", "G8324", NULL, BLIST_SPARSELUN}, /* Chaparral G8324 RAID */ + {"Zzyzx", "RocketStor 500S", NULL, BLIST_SPARSELUN}, + {"Zzyzx", "RocketStor 2000", NULL, BLIST_SPARSELUN}, + {"SONY", "TSL", NULL, BLIST_FORCELUN}, /* DDS3 & DDS4 autoloaders */ + {"DELL", "PERCRAID", NULL, BLIST_FORCELUN}, + {"HP", "NetRAID-4M", NULL, BLIST_FORCELUN}, + {"ADAPTEC", "AACRAID", NULL, BLIST_FORCELUN}, + {"ADAPTEC", "Adaptec 5400S", NULL, BLIST_FORCELUN}, + {"COMPAQ", "MSA1000", NULL, BLIST_FORCELUN}, + {"HP", "C1557A", NULL, BLIST_FORCELUN}, + {"IBM", "AuSaV1S2", NULL, BLIST_FORCELUN}, + {"FSC", "CentricStor", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, + {"DDN", "SAN DataDirector", "*", BLIST_SPARSELUN}, + {"HITACHI", "DF400", "*", BLIST_SPARSELUN}, + {"HITACHI", "DF500", "*", BLIST_SPARSELUN}, + {"HITACHI", "DF600", "*", BLIST_SPARSELUN}, + {"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, + {"SUN", "T300", "*", BLIST_SPARSELUN}, + {"SUN", "T4", "*", BLIST_SPARSELUN}, + {"SGI", "RAID3", "*", BLIST_SPARSELUN}, + {"SGI", "RAID5", "*", BLIST_SPARSELUN}, + {"SGI", "TP9100", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, + {"SGI", "TP9300", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, + {"SGI", "TP9400", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, + {"SGI", "TP9500", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, + {"MYLEX", "DACARMRB", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, + { NULL, NULL, NULL, 0 }, +}; + +/* + * scsi_strcpy_devinfo: called from scsi_dev_info_list_add to copy into + * devinfo vendor and model strings. + */ +static void scsi_strcpy_devinfo(char *name, char *to, size_t to_length, + char *from, int compatible) +{ + size_t from_length; + + from_length = strlen(from); + strncpy(to, from, min(to_length, from_length)); + if (from_length < to_length) { + if (compatible) { + /* + * NUL terminate the string if it is short. + */ + to[from_length] = '\0'; + } else { + /* + * space pad the string if it is short. + */ + strncpy(&to[from_length], spaces, + to_length - from_length); + } + } + if (from_length > to_length) + printk(KERN_WARNING "%s: %s string '%s' is too long\n", + __FUNCTION__, name, from); +} + +/** + * scsi_dev_info_list_add: add one dev_info list entry. + * @vendor: vendor string + * @model: model (product) string + * @strflags: integer string + * @flag: if strflags NULL, use this flag value + * + * Description: + * Create and add one dev_info entry for @vendor, @model, @strflags or + * @flag. If @compatible, add to the tail of the list, do not space + * pad, and set devinfo->compatible. The scsi_static_device_list entries + * are added with @compatible 1 and @clfags NULL. + * + * Returns: 0 OK, -error on failure. + **/ +static int scsi_dev_info_list_add(int compatible, char *vendor, char *model, + char *strflags, int flags) +{ + struct scsi_dev_info_list *devinfo; + + devinfo = kmalloc(sizeof(*devinfo), GFP_KERNEL); + if (!devinfo) { + printk(KERN_ERR "%s: no memory\n", __FUNCTION__); + return -ENOMEM; + } + + scsi_strcpy_devinfo("vendor", devinfo->vendor, sizeof(devinfo->vendor), + vendor, compatible); + scsi_strcpy_devinfo("model", devinfo->model, sizeof(devinfo->model), + model, compatible); + + if (strflags) + devinfo->flags = simple_strtoul(strflags, NULL, 0); + else + devinfo->flags = flags; + + devinfo->compatible = compatible; + + if (compatible) + list_add_tail(&devinfo->dev_info_list, &scsi_dev_info_list); + else + list_add(&devinfo->dev_info_list, &scsi_dev_info_list); + + return 0; +} + +/** + * scsi_dev_info_list_add_str: parse dev_list and add to the + * scsi_dev_info_list. + * @dev_list: string of device flags to add + * + * Description: + * Parse dev_list, and add entries to the scsi_dev_info_list. + * dev_list is of the form "vendor:product:flag,vendor:product:flag". + * dev_list is modified via strsep. Can be called for command line + * addition, for proc or mabye a sysfs interface. + * + * Returns: 0 if OK, -error on failure. + **/ +static int scsi_dev_info_list_add_str(char *dev_list) +{ + char *vendor, *model, *strflags, *next; + char *next_check; + int res = 0; + + next = dev_list; + if (next && next[0] == '"') { + /* + * Ignore both the leading and trailing quote. + */ + next++; + next_check = ",\""; + } else { + next_check = ","; + } + + /* + * For the leading and trailing '"' case, the for loop comes + * through the last time with vendor[0] == '\0'. + */ + for (vendor = strsep(&next, ":"); vendor && (vendor[0] != '\0') + && (res == 0); vendor = strsep(&next, ":")) { + strflags = NULL; + model = strsep(&next, ":"); + if (model) + strflags = strsep(&next, next_check); + if (!model || !strflags) { + printk(KERN_ERR "%s: bad dev info string '%s' '%s'" + " '%s'\n", __FUNCTION__, vendor, model, + strflags); + res = -EINVAL; + } else + res = scsi_dev_info_list_add(0 /* compatible */, vendor, + model, strflags, 0); + } + return res; +} + +/** + * get_device_flags - get device specific flags from the dynamic device + * list. Called during scan time. + * @vendor: vendor name + * @model: model name + * + * Description: + * Search the scsi_dev_info_list for an entry matching @vendor and + * @model, if found, return the matching flags value, else return + * scsi_default_dev_flags. + **/ +int scsi_get_device_flags(unsigned char *vendor, unsigned char *model) +{ + struct scsi_dev_info_list *devinfo; + + list_for_each_entry(devinfo, &scsi_dev_info_list, dev_info_list) { + if (devinfo->compatible) { + /* + * Behave like the older version of get_device_flags. + */ + size_t max; + /* + * XXX why skip leading spaces? If an odd INQUIRY + * value, that should have been part of the + * scsi_static_device_list[] entry, such as " FOO" + * rather than "FOO". Since this code is already + * here, and we don't know what device it is + * trying to work with, leave it as-is. + */ + max = 8; /* max length of vendor */ + while ((max > 0) && *vendor == ' ') { + max--; + vendor++; + } + /* + * XXX removing the following strlen() would be + * good, using it means that for a an entry not in + * the list, we scan every byte of every vendor + * listed in scsi_static_device_list[], and never match + * a single one (and still have to compare at + * least the first byte of each vendor). + */ + if (memcmp(devinfo->vendor, vendor, + min(max, strlen(devinfo->vendor)))) + continue; + /* + * Skip spaces again. + */ + max = 16; /* max length of model */ + while ((max > 0) && *model == ' ') { + max--; + model++; + } + if (memcmp(devinfo->model, model, + min(max, strlen(devinfo->model)))) + continue; + return devinfo->flags; + } else { + if (!memcmp(devinfo->vendor, vendor, + sizeof(devinfo->vendor)) && + !memcmp(devinfo->model, model, + sizeof(devinfo->model))) + return devinfo->flags; + } + } + return scsi_default_dev_flags; +} + +/* + * proc_scsi_dev_info_read: dump the scsi_dev_info_list via + * /proc/scsi/device_info + */ +static int proc_scsi_devinfo_read(char *buffer, char **start, + off_t offset, int length) +{ + struct scsi_dev_info_list *devinfo; + int size, len = 0; + off_t begin = 0; + off_t pos = 0; + + list_for_each_entry(devinfo, &scsi_dev_info_list, dev_info_list) { + size = sprintf(buffer + len, "'%.8s' '%.16s' 0x%x\n", + devinfo->vendor, devinfo->model, devinfo->flags); + len += size; + pos = begin + len; + if (pos < offset) { + len = 0; + begin = pos; + } + if (pos > offset + length) + goto stop_output; + } + +stop_output: + *start = buffer + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); /* Start slop */ + if (len > length) + len = length; /* Ending slop */ + return (len); +} + +/* + * proc_scsi_dev_info_write: allow additions to the scsi_dev_info_list via + * /proc. + * + * Use: echo "vendor:model:flag" > /proc/scsi/device_info + * + * To add a black/white list entry for vendor and model with an integer + * value of flag to the scsi device info list. + */ +static int proc_scsi_devinfo_write(struct file *file, const char *buf, + unsigned long length, void *data) +{ + char *buffer; + int err = length; + + if (!buf || length>PAGE_SIZE) + return -EINVAL; + if (!(buffer = (char *) __get_free_page(GFP_KERNEL))) + return -ENOMEM; + if (copy_from_user(buffer, buf, length)) { + err =-EFAULT; + goto out; + } + + if (length < PAGE_SIZE) + buffer[length] = '\0'; + else if (buffer[PAGE_SIZE-1]) { + err = -EINVAL; + goto out; + } + + scsi_dev_info_list_add_str(buffer); + +out: + free_page((unsigned long)buffer); + return err; +} + +MODULE_PARM(scsi_dev_flags, "s"); +MODULE_PARM_DESC(scsi_dev_flags, + "Given scsi_dev_flags=vendor:model:flags, add a black/white list" + " entry for vendor and model with an integer value of flags" + " to the scsi device info list"); +MODULE_PARM(scsi_default_dev_flags, "i"); +MODULE_PARM_DESC(scsi_default_dev_flags, + "scsi default device flag integer value"); + +static int __init setup_scsi_dev_flags(char *str) +{ + scsi_dev_flags = str; + return 1; +} + +static int __init setup_scsi_default_dev_flags(char *str) +{ + unsigned int tmp; + if (get_option(&str, &tmp) == 1) { + scsi_default_dev_flags = tmp; + printk(KERN_WARNING "%s %d\n", __FUNCTION__, + scsi_default_dev_flags); + return 1; + } else { + printk(KERN_WARNING "%s: usage scsi_default_dev_flags=intr\n", + __FUNCTION__); + return 0; + } +} + +/** + * scsi_dev_info_list_delete: called from scsi.c:exit_scsi to remove + * the scsi_dev_info_list. + **/ +void scsi_exit_devinfo(void) +{ + struct list_head *lh, *lh_next; + struct scsi_dev_info_list *devinfo; + + remove_proc_entry("scsi/device_info", 0); + + list_for_each_safe(lh, lh_next, &scsi_dev_info_list) { + devinfo = list_entry(lh, struct scsi_dev_info_list, + dev_info_list); + kfree(devinfo); + } +} + +/** + * scsi_dev_list_init: set up the dynamic device list. + * @dev_list: string of device flags to add + * + * Description: + * Add command line @dev_list entries, then add + * scsi_static_device_list entries to the scsi device info list. + **/ +int scsi_init_devinfo(void) +{ + struct proc_dir_entry *p; + int error, i; + + error = scsi_dev_info_list_add_str(scsi_dev_flags); + if (error) + return error; + + for (i = 0; scsi_static_device_list[i].vendor; i++) { + error = scsi_dev_info_list_add(1 /* compatibile */, + scsi_static_device_list[i].vendor, + scsi_static_device_list[i].model, + NULL, + scsi_static_device_list[i].flags); + if (error) + goto out; + } + + p = create_proc_entry("scsi/device_info", 0, NULL); + if (!p) { + error = -ENOMEM; + goto out; + } + + p->owner = THIS_MODULE; + p->get_info = proc_scsi_devinfo_read; + p->write_proc = proc_scsi_devinfo_write; + + out: + if (error) + scsi_exit_devinfo(); + return error; +} + +__setup("scsi_dev_flags=", setup_scsi_dev_flags); +__setup("scsi_default_dev_flags=", setup_scsi_default_dev_flags); diff -Nru a/drivers/scsi/scsi_devinfo.h b/drivers/scsi/scsi_devinfo.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/scsi/scsi_devinfo.h Thu May 15 15:24:46 2003 @@ -0,0 +1,16 @@ + +/* + * Flags for SCSI devices that need special treatment + */ +#define BLIST_NOLUN 0x001 /* Only scan LUN 0 */ +#define BLIST_FORCELUN 0x002 /* Known to have LUNs, force scanning */ +#define BLIST_BORKEN 0x004 /* Flag for broken handshaking */ +#define BLIST_KEY 0x008 /* unlock by special command */ +#define BLIST_SINGLELUN 0x010 /* Do not use LUNs in parallel */ +#define BLIST_NOTQ 0x020 /* Buggy Tagged Command Queuing */ +#define BLIST_SPARSELUN 0x040 /* Non consecutive LUN numbering */ +#define BLIST_MAX5LUN 0x080 /* Avoid LUNS >= 5 */ +#define BLIST_ISROM 0x100 /* Treat as (removable) CD-ROM */ +#define BLIST_LARGELUN 0x200 /* LUNs past 7 on a SCSI-2 device */ +#define BLIST_INQUIRY_36 0x400 /* override additional length field */ +#define BLIST_INQUIRY_58 0x800 /* ... for broken inquiry responses */ diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c --- a/drivers/scsi/scsi_error.c Thu May 15 15:24:32 2003 +++ b/drivers/scsi/scsi_error.c Thu May 15 15:24:32 2003 @@ -28,6 +28,9 @@ #include "scsi.h" #include "hosts.h" +#include "scsi_priv.h" +#include "scsi_logging.h" + #ifdef DEBUG #define SENSE_TIMEOUT SCSI_TIMEOUT #else @@ -188,7 +191,7 @@ return sdev->online; } -#if CONFIG_SCSI_LOGGING +#ifdef CONFIG_SCSI_LOGGING /** * scsi_eh_prt_fail_stats - Log info on failures. * @shost: scsi host being recovered. @@ -916,7 +919,6 @@ **/ static int scsi_try_bus_reset(struct scsi_cmnd *scmd) { - struct scsi_device *sdev; unsigned long flags; int rtn; @@ -934,16 +936,9 @@ if (rtn == SUCCESS) { scsi_sleep(BUS_RESET_SETTLE_TIME); - /* - * Mark all affected devices to expect a unit attention. - */ - list_for_each_entry(sdev, &scmd->device->host->my_devices, - siblings) - if (scmd->device->channel == sdev->channel) { - sdev->was_reset = 1; - sdev->expecting_cc_ua = 1; - } + scsi_report_bus_reset(scmd->device->host, scmd->device->channel); } + return rtn; } @@ -953,7 +948,6 @@ **/ static int scsi_try_host_reset(struct scsi_cmnd *scmd) { - struct scsi_device *sdev; unsigned long flags; int rtn; @@ -971,16 +965,9 @@ if (rtn == SUCCESS) { scsi_sleep(HOST_RESET_SETTLE_TIME); - /* - * Mark all affected devices to expect a unit attention. - */ - list_for_each_entry(sdev, &scmd->device->host->my_devices, - siblings) - if (scmd->device->channel == sdev->channel) { - sdev->was_reset = 1; - sdev->expecting_cc_ua = 1; - } + scsi_report_bus_reset(scmd->device->host, scmd->device->channel); } + return rtn; } @@ -1425,8 +1412,7 @@ * now that error recovery is done, we will need to ensure that these * requests are started. */ - list_for_each_entry(sdev, &shost->my_devices, siblings) - blk_run_queue(sdev->request_queue); + scsi_run_host_queues(shost); } /** @@ -1638,6 +1624,74 @@ complete_and_exit(shost->eh_notify, 0); } +/* + * Function: scsi_report_bus_reset() + * + * Purpose: Utility function used by low-level drivers to report that + * they have observed a bus reset on the bus being handled. + * + * Arguments: shost - Host in question + * channel - channel on which reset was observed. + * + * Returns: Nothing + * + * Lock status: No locks are assumed held. + * + * Notes: This only needs to be called if the reset is one which + * originates from an unknown location. Resets originated + * by the mid-level itself don't need to call this, but there + * should be no harm. + * + * The main purpose of this is to make sure that a CHECK_CONDITION + * is properly treated. + */ +void scsi_report_bus_reset(struct Scsi_Host *shost, int channel) +{ + struct scsi_device *sdev; + + list_for_each_entry(sdev, &shost->my_devices, siblings) { + if (channel == sdev->channel) { + sdev->was_reset = 1; + sdev->expecting_cc_ua = 1; + } + } +} + +/* + * Function: scsi_report_device_reset() + * + * Purpose: Utility function used by low-level drivers to report that + * they have observed a device reset on the device being handled. + * + * Arguments: shost - Host in question + * channel - channel on which reset was observed + * target - target on which reset was observed + * + * Returns: Nothing + * + * Lock status: No locks are assumed held. + * + * Notes: This only needs to be called if the reset is one which + * originates from an unknown location. Resets originated + * by the mid-level itself don't need to call this, but there + * should be no harm. + * + * The main purpose of this is to make sure that a CHECK_CONDITION + * is properly treated. + */ +void scsi_report_device_reset(struct Scsi_Host *shost, int channel, int target) +{ + struct scsi_device *sdev; + + list_for_each_entry(sdev, &shost->my_devices, siblings) { + if (channel == sdev->channel && + target == sdev->id) { + sdev->was_reset = 1; + sdev->expecting_cc_ua = 1; + } + } +} + static void scsi_reset_provider_done_command(struct scsi_cmnd *scmd) { @@ -1662,7 +1716,6 @@ struct scsi_cmnd *scmd = scsi_get_command(dev, GFP_KERNEL); struct request req; int rtn; - struct request_queue *q; scmd->request = &req; memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout)); @@ -1674,13 +1727,10 @@ scmd->scsi_done = scsi_reset_provider_done_command; scmd->done = NULL; - scmd->reset_chain = NULL; - scmd->buffer = NULL; scmd->bufflen = 0; scmd->request_buffer = NULL; scmd->request_bufflen = 0; - scmd->internal_timeout = NORMAL_TIMEOUT; scmd->abort_reason = DID_ABORT; @@ -1717,8 +1767,6 @@ } scsi_delete_timer(scmd); - q = scmd->device->request_queue; - scsi_put_command(scmd); - scsi_queue_next_request(q, NULL); + scsi_next_command(scmd); return rtn; } diff -Nru a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c --- a/drivers/scsi/scsi_ioctl.c Thu May 15 15:24:45 2003 +++ b/drivers/scsi/scsi_ioctl.c Thu May 15 15:24:45 2003 @@ -23,6 +23,8 @@ #include "hosts.h" #include +#include "scsi_logging.h" + #define NORMAL_RETRIES 5 #define IOCTL_NORMAL_TIMEOUT (10 * HZ) #define FORMAT_UNIT_TIMEOUT (2 * 60 * 60 * HZ) diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c --- a/drivers/scsi/scsi_lib.c Thu May 15 15:24:39 2003 +++ b/drivers/scsi/scsi_lib.c Thu May 15 15:24:39 2003 @@ -19,6 +19,9 @@ #include "scsi.h" #include "hosts.h" +#include "scsi_priv.h" +#include "scsi_logging.h" + #define SG_MEMPOOL_NR 5 #define SG_MEMPOOL_SIZE 32 @@ -178,19 +181,12 @@ void (*done)(struct scsi_cmnd *), int timeout, int retries) { - struct request_queue *q; - /* * If the upper level driver is reusing these things, then * we should release the low-level block now. Another one will * be allocated later when this request is getting queued. */ - if (sreq->sr_command) { - q = sreq->sr_command->device->request_queue; - scsi_put_command(sreq->sr_command); - sreq->sr_command = NULL; - scsi_queue_next_request(q, NULL); - } + __scsi_release_request(sreq); /* * Our own function scsi_done (which marks the host as not busy, @@ -236,7 +232,6 @@ void scsi_wait_req(struct scsi_request *sreq, const void *cmnd, void *buffer, unsigned bufflen, int timeout, int retries) { - struct request_queue *q; DECLARE_COMPLETION(wait); sreq->sr_request->waiting = &wait; @@ -247,12 +242,7 @@ wait_for_completion(&wait); sreq->sr_request->waiting = NULL; - if (sreq->sr_command) { - q = sreq->sr_command->device->request_queue; - scsi_put_command(sreq->sr_command); - scsi_queue_next_request(q, NULL); - sreq->sr_command = NULL; - } + __scsi_release_request(sreq); } /* @@ -271,7 +261,6 @@ static int scsi_init_cmd_errh(struct scsi_cmnd *cmd) { cmd->owner = SCSI_OWNER_MIDLEVEL; - cmd->reset_chain = NULL; cmd->serial_number = 0; cmd->serial_number_at_timeout = 0; cmd->flags = 0; @@ -296,7 +285,6 @@ memcpy(cmd->data_cmnd, cmd->cmnd, sizeof(cmd->cmnd)); cmd->buffer = cmd->request_buffer; cmd->bufflen = cmd->request_bufflen; - cmd->reset_chain = NULL; cmd->internal_timeout = NORMAL_TIMEOUT; cmd->abort_reason = 0; @@ -369,77 +357,26 @@ } /* - * Function: scsi_queue_next_request() + * Function: scsi_run_queue() * - * Purpose: Handle post-processing of completed commands. + * Purpose: Select a proper request queue to serve next * - * Arguments: cmd - command that may need to be requeued. + * Arguments: q - last request's queue * * Returns: Nothing * - * Notes: After command completion, there may be blocks left - * over which weren't finished by the previous command - * this can be for a number of reasons - the main one is - * that a medium error occurred, and the sectors after - * the bad block need to be re-read. - * - * If cmd is NULL, it means that the previous command - * was completely finished, and we should simply start - * a new command, if possible. - * - * This is where a lot of special case code has begun to - * accumulate. It doesn't really affect readability or - * anything, but it might be considered architecturally - * inelegant. If more of these special cases start to - * accumulate, I am thinking along the lines of implementing - * an atexit() like technology that gets run when commands - * complete. I am not convinced that it is worth the - * added overhead, however. Right now as things stand, - * there are simple conditional checks, and most hosts - * would skip past. - * - * Another possible solution would be to tailor different - * handler functions, sort of like what we did in scsi_merge.c. - * This is probably a better solution, but the number of different - * permutations grows as 2**N, and if too many more special cases - * get added, we start to get screwed. + * Notes: The previous command was completely finished, start + * a new one if possible. */ -void scsi_queue_next_request(request_queue_t *q, struct scsi_cmnd *cmd) +static void scsi_run_queue(struct request_queue *q) { - struct scsi_device *sdev; - struct Scsi_Host *shost; + struct scsi_device *sdev = q->queuedata; + struct Scsi_Host *shost = sdev->host; unsigned long flags; - if (cmd != NULL) { - - /* - * For some reason, we are not done with this request. - * This happens for I/O errors in the middle of the request, - * in which case we need to request the blocks that come after - * the bad sector. - */ - spin_lock_irqsave(q->queue_lock, flags); - cmd->request->special = cmd; - if (blk_rq_tagged(cmd->request)) - blk_queue_end_tag(q, cmd->request); - - /* - * set REQ_SPECIAL - we have a command - * clear REQ_DONTPREP - we assume the sg table has been - * nuked so we need to set it up again. - */ - cmd->request->flags |= REQ_SPECIAL; - cmd->request->flags &= ~REQ_DONTPREP; - __elv_add_request(q, cmd->request, 0, 0); - spin_unlock_irqrestore(q->queue_lock, flags); - } - - sdev = q->queuedata; - if (sdev->single_lun) scsi_single_lun_run(sdev); - shost = sdev->host; spin_lock_irqsave(shost->host_lock, flags); while (!list_empty(&shost->starved_list) && !shost->host_blocked && !shost->host_self_blocked && @@ -477,6 +414,61 @@ } /* + * Function: scsi_requeue_command() + * + * Purpose: Handle post-processing of completed commands. + * + * Arguments: q - queue to operate on + * cmd - command that may need to be requeued. + * + * Returns: Nothing + * + * Notes: After command completion, there may be blocks left + * over which weren't finished by the previous command + * this can be for a number of reasons - the main one is + * I/O errors in the middle of the request, in which case + * we need to request the blocks that come after the bad + * sector. + */ +static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd) +{ + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); + cmd->request->special = cmd; + if (blk_rq_tagged(cmd->request)) + blk_queue_end_tag(q, cmd->request); + + /* + * set REQ_SPECIAL - we have a command + * clear REQ_DONTPREP - we assume the sg table has been + * nuked so we need to set it up again. + */ + cmd->request->flags |= REQ_SPECIAL; + cmd->request->flags &= ~REQ_DONTPREP; + __elv_add_request(q, cmd->request, 0, 0); + spin_unlock_irqrestore(q->queue_lock, flags); + + scsi_run_queue(q); +} + +void scsi_next_command(struct scsi_cmnd *cmd) +{ + struct request_queue *q = cmd->device->request_queue; + + scsi_put_command(cmd); + scsi_run_queue(q); +} + +void scsi_run_host_queues(struct Scsi_Host *shost) +{ + struct scsi_device *sdev; + + list_for_each_entry(sdev, &shost->my_devices, siblings) + scsi_run_queue(sdev->request_queue); +} + +/* * Function: scsi_end_request() * * Purpose: Post-processing of completed commands called from interrupt @@ -516,7 +508,7 @@ * Bleah. Leftovers again. Stick the leftovers in * the front of the queue, and goose the queue again. */ - scsi_queue_next_request(q, cmd); + scsi_requeue_command(q, cmd); } return cmd; } @@ -533,8 +525,7 @@ * This will goose the queue request function at the end, so we don't * need to worry about launching another command. */ - scsi_put_command(cmd); - scsi_queue_next_request(q, NULL); + scsi_next_command(cmd); return NULL; } @@ -660,6 +651,18 @@ * In other words, if there are no bounce buffers * (the normal case for most drivers), we don't need * the logic to deal with cleaning up afterwards. + * + * We must do one of several things here: + * + * a) Call scsi_end_request. This will finish off the + * specified number of sectors. If we are done, the + * command block will be released, and the queue + * function will be goosed. If we are not done, then + * scsi_end_request will directly goose the queue. + * + * b) We can just use scsi_requeue_command() here. This would + * be used if we just wanted to retry, for example. + * */ void scsi_io_completion(struct scsi_cmnd *cmd, int good_sectors, int block_sectors) @@ -671,19 +674,6 @@ int clear_errors = 1; /* - * We must do one of several things here: - * - * Call scsi_end_request. This will finish off the specified - * number of sectors. If we are done, the command block will - * be released, and the queue function will be goosed. If we - * are not done, then scsi_end_request will directly goose - * the queue. - * - * We can just use scsi_queue_next_request() here. This - * would be used if we just wanted to retry, for example. - * - */ - /* * Free up any indirection buffers we allocated for DMA purposes. * For the case of a READ, we need to copy the data out of the * bounce buffer and into the real buffer. @@ -782,7 +772,7 @@ */ if (cmd->sense_buffer[12] == 0x04 && cmd->sense_buffer[13] == 0x01) { - scsi_queue_next_request(q, cmd); + scsi_requeue_command(q, cmd); return; } if ((cmd->sense_buffer[2] & 0xf) == UNIT_ATTENTION) { @@ -801,7 +791,7 @@ * media change, so we just retry the * request and see what happens. */ - scsi_queue_next_request(q, cmd); + scsi_requeue_command(q, cmd); return; } } @@ -821,7 +811,7 @@ * This will cause a retry with a 6-byte * command. */ - scsi_queue_next_request(q, cmd); + scsi_requeue_command(q, cmd); result = 0; } else { cmd = scsi_end_request(cmd, 0, this_count, 1); @@ -853,7 +843,7 @@ * recovery reasons. Just retry the request * and see what happens. */ - scsi_queue_next_request(q, cmd); + scsi_requeue_command(q, cmd); return; } if (result) { @@ -1140,66 +1130,61 @@ * * Lock status: IO request lock assumed to be held when called. */ -static void scsi_request_fn(request_queue_t *q) +static void scsi_request_fn(struct request_queue *q) { struct scsi_device *sdev = q->queuedata; struct Scsi_Host *shost = sdev->host; struct scsi_cmnd *cmd; struct request *req; - unsigned long flags; /* * To start with, we keep looping until the queue is empty, or until * the host is no longer able to accept any more requests. */ - for (;;) { - if (blk_queue_plugged(q)) - goto completed; - + while (!blk_queue_plugged(q)) { /* * get next queueable request. We do this early to make sure * that the request is fully prepared even if we cannot * accept it. */ req = elv_next_request(q); - - if (!req) - goto completed; - - if (!scsi_dev_queue_ready(q, sdev)) - goto completed; + if (!req || !scsi_dev_queue_ready(q, sdev)) + break; /* * Remove the request from the request list. */ - if (!(blk_queue_tagged(q) && (blk_queue_start_tag(q, req) == 0))) + if (!(blk_queue_tagged(q) && !blk_queue_start_tag(q, req))) blkdev_dequeue_request(req); - sdev->device_busy++; - spin_unlock_irq(q->queue_lock); - spin_lock_irqsave(shost->host_lock, flags); - if (!scsi_host_queue_ready(q, shost, sdev)) - goto host_lock_held; + spin_unlock(q->queue_lock); + spin_lock(shost->host_lock); + if (!scsi_host_queue_ready(q, shost, sdev)) + goto not_ready; if (sdev->single_lun) { if (sdev->sdev_target->starget_sdev_user && - (sdev->sdev_target->starget_sdev_user != sdev)) - goto host_lock_held; - else - sdev->sdev_target->starget_sdev_user = sdev; + sdev->sdev_target->starget_sdev_user != sdev) + goto not_ready; + sdev->sdev_target->starget_sdev_user = sdev; } - shost->host_busy++; - spin_unlock_irqrestore(shost->host_lock, flags); - - cmd = req->special; /* - * Should be impossible for a correctly prepared request - * please mail the stack trace to linux-scsi@vger.kernel.org + * XXX(hch): This is rather suboptimal, scsi_dispatch_cmd will + * take the lock again. */ - BUG_ON(!cmd); + spin_unlock_irq(shost->host_lock); + + cmd = req->special; + if (unlikely(cmd == NULL)) { + printk(KERN_CRIT "impossible request in %s.\n" + "please mail a stack trace to " + "linux-scsi@vger.kernel.org", + __FUNCTION__); + BUG(); + } /* * Finally, initialize any error handling parameters, and set up @@ -1211,18 +1196,14 @@ * Dispatch the command to the low-level driver. */ scsi_dispatch_cmd(cmd); - - /* - * Now we need to grab the lock again. We are about to mess - * with the request queue and try to find another command. - */ spin_lock_irq(q->queue_lock); } -completed: + return; -host_lock_held: - spin_unlock_irqrestore(shost->host_lock, flags); + not_ready: + spin_unlock_irq(shost->host_lock); + /* * lock q, handle tag, requeue req, and decrement device_busy. We * must return with queue_lock held. @@ -1257,28 +1238,15 @@ return BLK_BOUNCE_HIGH; } -request_queue_t *scsi_alloc_queue(struct scsi_device *sdev) +struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) { - request_queue_t *q; - struct Scsi_Host *shost; + struct Scsi_Host *shost = sdev->host; + struct request_queue *q = kmalloc(sizeof(*q), GFP_ATOMIC); - q = kmalloc(sizeof(*q), GFP_ATOMIC); if (!q) return NULL; memset(q, 0, sizeof(*q)); - /* - * XXX move host code to scsi_register - */ - shost = sdev->host; - if (!shost->max_sectors) { - /* - * Driver imposes no hard sector transfer limit. - * start at machine infinity initially. - */ - shost->max_sectors = SCSI_DEFAULT_MAX_SECTORS; - } - blk_init_queue(q, scsi_request_fn, &sdev->sdev_lock); blk_queue_prep_rq(q, scsi_prep_fn); @@ -1289,11 +1257,10 @@ if (!shost->use_clustering) clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); - return q; } -void scsi_free_queue(request_queue_t *q) +void scsi_free_queue(struct request_queue *q) { blk_cleanup_queue(q); kfree(q); @@ -1342,48 +1309,8 @@ */ void scsi_unblock_requests(struct Scsi_Host *shost) { - struct scsi_device *sdev; - shost->host_self_blocked = 0; - - /* - * Now that we are unblocked, try to start the queues. - */ - list_for_each_entry(sdev, &shost->my_devices, siblings) - scsi_queue_next_request(sdev->request_queue, NULL); -} - -/* - * Function: scsi_report_bus_reset() - * - * Purpose: Utility function used by low-level drivers to report that - * they have observed a bus reset on the bus being handled. - * - * Arguments: shost - Host in question - * channel - channel on which reset was observed. - * - * Returns: Nothing - * - * Lock status: No locks are assumed held. - * - * Notes: This only needs to be called if the reset is one which - * originates from an unknown location. Resets originated - * by the mid-level itself don't need to call this, but there - * should be no harm. - * - * The main purpose of this is to make sure that a CHECK_CONDITION - * is properly treated. - */ -void scsi_report_bus_reset(struct Scsi_Host *shost, int channel) -{ - struct scsi_device *sdev; - - list_for_each_entry(sdev, &shost->my_devices, siblings) { - if (channel == sdev->channel) { - sdev->was_reset = 1; - sdev->expecting_cc_ua = 1; - } - } + scsi_run_host_queues(shost); } int __init scsi_init_queue(void) diff -Nru a/drivers/scsi/scsi_logging.h b/drivers/scsi/scsi_logging.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/scsi/scsi_logging.h Thu May 15 15:24:46 2003 @@ -0,0 +1,117 @@ +#ifndef _SCSI_LOGGING_H +#define _SCSI_LOGGING_H + +#include + +/* + * This defines the scsi logging feature. It is a means by which the user + * can select how much information they get about various goings on, and it + * can be really useful for fault tracing. The logging word is divided into + * 8 nibbles, each of which describes a loglevel. The division of things is + * somewhat arbitrary, and the division of the word could be changed if it + * were really needed for any reason. The numbers below are the only place + * where these are specified. For a first go-around, 3 bits is more than + * enough, since this gives 8 levels of logging (really 7, since 0 is always + * off). Cutting to 2 bits might be wise at some point. + */ + +#define SCSI_LOG_ERROR_SHIFT 0 +#define SCSI_LOG_TIMEOUT_SHIFT 3 +#define SCSI_LOG_SCAN_SHIFT 6 +#define SCSI_LOG_MLQUEUE_SHIFT 9 +#define SCSI_LOG_MLCOMPLETE_SHIFT 12 +#define SCSI_LOG_LLQUEUE_SHIFT 15 +#define SCSI_LOG_LLCOMPLETE_SHIFT 18 +#define SCSI_LOG_HLQUEUE_SHIFT 21 +#define SCSI_LOG_HLCOMPLETE_SHIFT 24 +#define SCSI_LOG_IOCTL_SHIFT 27 + +#define SCSI_LOG_ERROR_BITS 3 +#define SCSI_LOG_TIMEOUT_BITS 3 +#define SCSI_LOG_SCAN_BITS 3 +#define SCSI_LOG_MLQUEUE_BITS 3 +#define SCSI_LOG_MLCOMPLETE_BITS 3 +#define SCSI_LOG_LLQUEUE_BITS 3 +#define SCSI_LOG_LLCOMPLETE_BITS 3 +#define SCSI_LOG_HLQUEUE_BITS 3 +#define SCSI_LOG_HLCOMPLETE_BITS 3 +#define SCSI_LOG_IOCTL_BITS 3 + + +#ifdef CONFIG_SCSI_LOGGING +extern unsigned int scsi_logging_level; +#define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) \ +{ \ + unsigned int mask = (1 << (BITS)) - 1; \ + if (((scsi_logging_level >> (SHIFT)) & mask) > (LEVEL)) \ + (CMD); \ +} + +#define SCSI_SET_LOGGING(SHIFT, BITS, LEVEL) \ +{ \ + unsigned int mask = ((1 << (BITS)) - 1) << SHIFT; \ + scsi_logging_level = ((scsi_logging_level & ~mask) \ + | ((LEVEL << SHIFT) & mask)); \ +} +#else +/* + * With no logging enabled, stub these out so they don't do anything. + */ +#define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) +#define SCSI_SET_LOGGING(SHIFT, BITS, LEVEL) +#endif /* CONFIG_SCSI_LOGGING */ + +/* + * These are the macros that are actually used throughout the code to + * log events. If logging isn't enabled, they are no-ops and will be + * completely absent from the user's code. + * + * The 'set' versions of the macros are really intended to only be called + * from the /proc filesystem, and in production kernels this will be about + * all that is ever used. It could be useful in a debugging environment to + * bump the logging level when certain strange events are detected, however. + */ +#define SCSI_LOG_ERROR_RECOVERY(LEVEL,CMD) \ + SCSI_CHECK_LOGGING(SCSI_LOG_ERROR_SHIFT, SCSI_LOG_ERROR_BITS, LEVEL,CMD); +#define SCSI_LOG_TIMEOUT(LEVEL,CMD) \ + SCSI_CHECK_LOGGING(SCSI_LOG_TIMEOUT_SHIFT, SCSI_LOG_TIMEOUT_BITS, LEVEL,CMD); +#define SCSI_LOG_SCAN_BUS(LEVEL,CMD) \ + SCSI_CHECK_LOGGING(SCSI_LOG_SCAN_SHIFT, SCSI_LOG_SCAN_BITS, LEVEL,CMD); +#define SCSI_LOG_MLQUEUE(LEVEL,CMD) \ + SCSI_CHECK_LOGGING(SCSI_LOG_MLQUEUE_SHIFT, SCSI_LOG_MLQUEUE_BITS, LEVEL,CMD); +#define SCSI_LOG_MLCOMPLETE(LEVEL,CMD) \ + SCSI_CHECK_LOGGING(SCSI_LOG_MLCOMPLETE_SHIFT, SCSI_LOG_MLCOMPLETE_BITS, LEVEL,CMD); +#define SCSI_LOG_LLQUEUE(LEVEL,CMD) \ + SCSI_CHECK_LOGGING(SCSI_LOG_LLQUEUE_SHIFT, SCSI_LOG_LLQUEUE_BITS, LEVEL,CMD); +#define SCSI_LOG_LLCOMPLETE(LEVEL,CMD) \ + SCSI_CHECK_LOGGING(SCSI_LOG_LLCOMPLETE_SHIFT, SCSI_LOG_LLCOMPLETE_BITS, LEVEL,CMD); +#define SCSI_LOG_HLQUEUE(LEVEL,CMD) \ + SCSI_CHECK_LOGGING(SCSI_LOG_HLQUEUE_SHIFT, SCSI_LOG_HLQUEUE_BITS, LEVEL,CMD); +#define SCSI_LOG_HLCOMPLETE(LEVEL,CMD) \ + SCSI_CHECK_LOGGING(SCSI_LOG_HLCOMPLETE_SHIFT, SCSI_LOG_HLCOMPLETE_BITS, LEVEL,CMD); +#define SCSI_LOG_IOCTL(LEVEL,CMD) \ + SCSI_CHECK_LOGGING(SCSI_LOG_IOCTL_SHIFT, SCSI_LOG_IOCTL_BITS, LEVEL,CMD); + + +#define SCSI_SET_ERROR_RECOVERY_LOGGING(LEVEL) \ + SCSI_SET_LOGGING(SCSI_LOG_ERROR_SHIFT, SCSI_LOG_ERROR_BITS, LEVEL); +#define SCSI_SET_TIMEOUT_LOGGING(LEVEL) \ + SCSI_SET_LOGGING(SCSI_LOG_TIMEOUT_SHIFT, SCSI_LOG_TIMEOUT_BITS, LEVEL); +#define SCSI_SET_SCAN_BUS_LOGGING(LEVEL) \ + SCSI_SET_LOGGING(SCSI_LOG_SCAN_SHIFT, SCSI_LOG_SCAN_BITS, LEVEL); +#define SCSI_SET_MLQUEUE_LOGGING(LEVEL) \ + SCSI_SET_LOGGING(SCSI_LOG_MLQUEUE_SHIFT, SCSI_LOG_MLQUEUE_BITS, LEVEL); +#define SCSI_SET_MLCOMPLETE_LOGGING(LEVEL) \ + SCSI_SET_LOGGING(SCSI_LOG_MLCOMPLETE_SHIFT, SCSI_LOG_MLCOMPLETE_BITS, LEVEL); +#define SCSI_SET_LLQUEUE_LOGGING(LEVEL) \ + SCSI_SET_LOGGING(SCSI_LOG_LLQUEUE_SHIFT, SCSI_LOG_LLQUEUE_BITS, LEVEL); +#define SCSI_SET_LLCOMPLETE_LOGGING(LEVEL) \ + SCSI_SET_LOGGING(SCSI_LOG_LLCOMPLETE_SHIFT, SCSI_LOG_LLCOMPLETE_BITS, LEVEL); +#define SCSI_SET_HLQUEUE_LOGGING(LEVEL) \ + SCSI_SET_LOGGING(SCSI_LOG_HLQUEUE_SHIFT, SCSI_LOG_HLQUEUE_BITS, LEVEL); +#define SCSI_SET_HLCOMPLETE_LOGGING(LEVEL) \ + SCSI_SET_LOGGING(SCSI_LOG_HLCOMPLETE_SHIFT, SCSI_LOG_HLCOMPLETE_BITS, LEVEL); +#define SCSI_SET_IOCTL_LOGGING(LEVEL) \ + SCSI_SET_LOGGING(SCSI_LOG_IOCTL_SHIFT, SCSI_LOG_IOCTL_BITS, LEVEL); + +#endif /* _SCSI_LOGGING_H */ diff -Nru a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/scsi/scsi_priv.h Thu May 15 15:24:47 2003 @@ -0,0 +1,132 @@ +#ifndef _SCSI_PRIV_H +#define _SCSI_PRIV_H + +/* + * These are the values that the owner field can take. + * They are used as an indication of who the command belongs to. + */ +#define SCSI_OWNER_HIGHLEVEL 0x100 +#define SCSI_OWNER_MIDLEVEL 0x101 +#define SCSI_OWNER_LOWLEVEL 0x102 +#define SCSI_OWNER_ERROR_HANDLER 0x103 +#define SCSI_OWNER_BH_HANDLER 0x104 +#define SCSI_OWNER_NOBODY 0x105 + +/* + * Magic values for certain scsi structs. Shouldn't ever be used. + */ +#define SCSI_CMND_MAGIC 0xE25C23A5 +#define SCSI_REQ_MAGIC 0x75F6D354 + +/* + * Flag bit for the internal_timeout array + */ +#define NORMAL_TIMEOUT 0 + +/* + * Scsi Error Handler Flags + */ +#define scsi_eh_eflags_chk(scp, flags) \ + ((scp)->eh_eflags & (flags)) +#define scsi_eh_eflags_set(scp, flags) \ + do { (scp)->eh_eflags |= (flags); } while(0) +#define scsi_eh_eflags_clr(scp, flags) \ + do { (scp)->eh_eflags &= ~(flags); } while(0) +#define scsi_eh_eflags_clr_all(scp) \ + (scp->eh_eflags = 0) + +#define SCSI_EH_CANCEL_CMD 0x0001 /* Cancel this cmd */ +#define SCSI_EH_REC_TIMEOUT 0x0002 /* EH retry timed out */ + +#define SCSI_SENSE_VALID(scmd) \ + (((scmd)->sense_buffer[0] & 0x70) == 0x70) + +struct Scsi_Device_Template; + + +/* + * scsi_target: representation of a scsi target, for now, this is only + * used for single_lun devices. If no one has active IO to the target, + * starget_sdev_user is NULL, else it points to the active sdev. + */ +struct scsi_target { + struct scsi_device *starget_sdev_user; + unsigned int starget_refcnt; +}; + + +/* hosts.c */ +extern void scsi_host_busy_inc(struct Scsi_Host *, Scsi_Device *); +extern void scsi_host_busy_dec_and_test(struct Scsi_Host *, Scsi_Device *); +extern struct Scsi_Host *scsi_host_get_next(struct Scsi_Host *); +extern void scsi_host_init(void); + +/* scsi.c */ +extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd); +extern int scsi_setup_command_freelist(struct Scsi_Host *shost); +extern void scsi_destroy_command_freelist(struct Scsi_Host *shost); +extern void scsi_done(struct scsi_cmnd *cmd); +extern void scsi_finish_command(struct scsi_cmnd *cmd); +extern int scsi_retry_command(struct scsi_cmnd *cmd); +extern int scsi_attach_device(struct scsi_device *sdev); +extern void scsi_detach_device(struct scsi_device *sdev); +extern void scsi_rescan_device(struct scsi_device *sdev); +extern int scsi_insert_special_req(struct scsi_request *sreq, int); +extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd, + struct scsi_request *sreq); +extern void __scsi_release_request(struct scsi_request *sreq); + +/* scsi_devinfo.c */ +extern int scsi_get_device_flags(unsigned char *vendor, unsigned char *model); +extern int scsi_init_devinfo(void); +extern void scsi_exit_devinfo(void); + +/* scsi_error.c */ +extern void scsi_times_out(struct scsi_cmnd *cmd); +extern void scsi_error_handler(void *host); +extern int scsi_decide_disposition(struct scsi_cmnd *cmd); +extern int scsi_eh_scmd_add(struct scsi_cmnd *, int); + +/* scsi_lib.c */ +extern int scsi_maybe_unblock_host(struct scsi_device *sdev); +extern void scsi_setup_cmd_retry(struct scsi_cmnd *cmd); +extern int scsi_queue_insert(struct scsi_cmnd *cmd, int reason); +extern void scsi_next_command(struct scsi_cmnd *cmd); +extern void scsi_run_host_queues(struct Scsi_Host *shost); +extern struct request_queue *scsi_alloc_queue(struct scsi_device *sdev); +extern void scsi_free_queue(struct request_queue *q); +extern int scsi_init_queue(void); +extern void scsi_exit_queue(void); + +/* scsi_proc.c */ +#ifdef CONFIG_PROC_FS +extern void scsi_proc_host_add(struct Scsi_Host *); +extern void scsi_proc_host_rm(struct Scsi_Host *); +extern int scsi_init_procfs(void); +extern void scsi_exit_procfs(void); +#else +# define scsi_proc_host_add(shost) do { } while (0) +# define scsi_proc_host_rm(shost) do { } while (0) +# define scsi_init_procfs() (0) +# define scsi_exit_procfs do { } while (0) +#endif /* CONFIG_PROC_FS */ + +/* scsi_scan.c */ +extern void scsi_scan_host(struct Scsi_Host *shost); +extern void scsi_forget_host(struct Scsi_Host *shost); +extern void scsi_free_sdev(struct scsi_device *); +extern void scsi_free_shost(struct Scsi_Host *); +extern void scsi_host_get(struct Scsi_Host *); + +/* scsi_sysfs.c */ +extern int scsi_device_register(struct scsi_device *); +extern void scsi_device_unregister(struct scsi_device *); +extern int scsi_upper_driver_register(struct Scsi_Device_Template *); +extern void scsi_upper_driver_unregister(struct Scsi_Device_Template *); +extern void scsi_sysfs_init_host(struct Scsi_Host *); +extern int scsi_sysfs_add_host(struct Scsi_Host *, struct device *); +extern void scsi_sysfs_remove_host(struct Scsi_Host *); +extern int scsi_sysfs_register(void); +extern void scsi_sysfs_unregister(void); + +#endif /* _SCSI_PRIV_H */ diff -Nru a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c --- a/drivers/scsi/scsi_proc.c Thu May 15 15:24:33 2003 +++ b/drivers/scsi/scsi_proc.c Thu May 15 15:24:33 2003 @@ -29,6 +29,10 @@ #include "scsi.h" #include "hosts.h" +#include "scsi_priv.h" +#include "scsi_logging.h" + + /* 4K page size, but our output routines, use some slack for overruns */ #define PROC_BLOCK_SIZE (3*1024) @@ -196,77 +200,6 @@ return; } -/* - * proc_scsi_dev_info_read: dump the scsi_dev_info_list via - * /proc/scsi/device_info - */ -static int proc_scsi_dev_info_read(char *buffer, char **start, off_t offset, - int length) -{ - struct scsi_dev_info_list *devinfo; - int size, len = 0; - off_t begin = 0; - off_t pos = 0; - - list_for_each_entry(devinfo, &scsi_dev_info_list, dev_info_list) { - size = sprintf(buffer + len, "'%.8s' '%.16s' 0x%x\n", - devinfo->vendor, devinfo->model, devinfo->flags); - len += size; - pos = begin + len; - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > offset + length) - goto stop_output; - } - -stop_output: - *start = buffer + (offset - begin); /* Start of wanted data */ - len -= (offset - begin); /* Start slop */ - if (len > length) - len = length; /* Ending slop */ - return (len); -} - -/* - * proc_scsi_dev_info_write: allow additions to the scsi_dev_info_list via - * /proc. - * - * Use: echo "vendor:model:flag" > /proc/scsi/device_info - * - * To add a black/white list entry for vendor and model with an integer - * value of flag to the scsi device info list. - */ -static int proc_scsi_dev_info_write (struct file * file, const char * buf, - unsigned long length, void *data) -{ - char *buffer; - int err = length; - - if (!buf || length>PAGE_SIZE) - return -EINVAL; - if (!(buffer = (char *) __get_free_page(GFP_KERNEL))) - return -ENOMEM; - if (copy_from_user(buffer, buf, length)) { - err =-EFAULT; - goto out; - } - - if (length < PAGE_SIZE) - buffer[length] = '\0'; - else if (buffer[PAGE_SIZE-1]) { - err = -EINVAL; - goto out; - } - - scsi_dev_info_list_add_str(buffer); - -out: - free_page((unsigned long)buffer); - return err; -} - static int scsi_proc_info(char *buffer, char **start, off_t offset, int length) { struct Scsi_Host *shost; @@ -312,91 +245,6 @@ return (len); } -#ifdef CONFIG_SCSI_LOGGING -/* - * Function: scsi_dump_status - * - * Purpose: Brain dump of scsi system, used for problem solving. - * - * Arguments: level - used to indicate level of detail. - * - * Notes: The level isn't used at all yet, but we need to find some - * way of sensibly logging varying degrees of information. - * A quick one-line display of each command, plus the status - * would be most useful. - * - * This does depend upon CONFIG_SCSI_LOGGING - I do want some - * way of turning it all off if the user wants a lean and mean - * kernel. It would probably also be useful to allow the user - * to specify one single host to be dumped. A second argument - * to the function would be useful for that purpose. - * - * FIXME - some formatting of the output into tables would be - * very handy. - */ -static void scsi_dump_status(int level) -{ - int i; - struct Scsi_Host *shpnt; - Scsi_Cmnd *SCpnt; - Scsi_Device *SDpnt; - printk(KERN_INFO "Dump of scsi host parameters:\n"); - i = 0; - for (shpnt = scsi_host_get_next(NULL); shpnt; - shpnt = scsi_host_get_next(shpnt)) { - printk(KERN_INFO " %d %d : %d %d\n", - shpnt->host_failed, - shpnt->host_busy, - shpnt->host_blocked, - shpnt->host_self_blocked); - } - - printk(KERN_INFO "\n\n"); - printk(KERN_INFO "Dump of scsi command parameters:\n"); - for (shpnt = scsi_host_get_next(NULL); shpnt; - shpnt = scsi_host_get_next(shpnt)) { - printk(KERN_INFO "h:c:t:l (dev sect nsect cnumsec sg) " - "(ret all flg) (to/cmd to ito) cmd snse result\n"); - list_for_each_entry(SDpnt, &shpnt->my_devices, siblings) { - unsigned long flags; - - spin_lock_irqsave(&SDpnt->list_lock, flags); - list_for_each_entry(SCpnt, &SDpnt->cmd_list, list) { - /* (0) h:c:t:l (dev sect nsect cnumsec sg) (ret all flg) (to/cmd to ito) cmd snse result %d %x */ - printk(KERN_INFO "(%3d) %2d:%1d:%2d:%2d (%6s %4llu %4ld %4ld %4x %1d) (%1d %1d 0x%2x) (%4d %4d %4d) 0x%2.2x 0x%2.2x 0x%8.8x\n", - i++, - - SCpnt->device->host->host_no, - SCpnt->device->channel, - SCpnt->device->id, - SCpnt->device->lun, - - SCpnt->request->rq_disk ? - SCpnt->request->rq_disk->disk_name : "?", - (unsigned long long)SCpnt->request->sector, - SCpnt->request->nr_sectors, - (long)SCpnt->request->current_nr_sectors, - SCpnt->request->rq_status, - SCpnt->use_sg, - - SCpnt->retries, - SCpnt->allowed, - SCpnt->flags, - - SCpnt->timeout_per_command, - SCpnt->timeout, - SCpnt->internal_timeout, - - SCpnt->cmnd[0], - SCpnt->sense_buffer[2], - SCpnt->result); - } - spin_unlock_irqrestore(&SDpnt->list_lock, flags); - } - } -} -#endif /* CONFIG_SCSI_LOGGING */ - static int scsi_add_single_device(uint host, uint channel, uint id, uint lun) { struct Scsi_Host *shost; @@ -440,7 +288,6 @@ return error; } - static int proc_scsi_gen_write(struct file * file, const char * buf, unsigned long length, void *data) { @@ -471,22 +318,6 @@ #ifdef CONFIG_SCSI_LOGGING /* - * Usage: echo "scsi dump #N" > /proc/scsi/scsi - * to dump status of all scsi commands. The number is used to - * specify the level of detail in the dump. - */ - if (!strncmp("dump", buffer + 5, 4)) { - unsigned int level; - - p = buffer + 10; - - if (*p == '\0') - goto out; - - level = simple_strtoul(p, NULL, 0); - scsi_dump_status(level); - } - /* * Usage: echo "scsi log token #N" > /proc/scsi/scsi * where token is one of [error,scan,mlqueue,mlcomplete,llqueue, * llcomplete,hlqueue,hlcomplete] @@ -614,15 +445,8 @@ goto err2; pde->write_proc = proc_scsi_gen_write; - pde = create_proc_info_entry("scsi/device_info", 0, 0, - proc_scsi_dev_info_read); - if (!pde) - goto err3; - pde->write_proc = proc_scsi_dev_info_write; return 0; -err3: - remove_proc_entry("scsi/scsi", 0); err2: remove_proc_entry("scsi", 0); err1: @@ -631,7 +455,6 @@ void scsi_exit_procfs(void) { - remove_proc_entry("scsi/device_info", 0); remove_proc_entry("scsi/scsi", 0); remove_proc_entry("scsi", 0); } diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c --- a/drivers/scsi/scsi_scan.c Thu May 15 15:24:42 2003 +++ b/drivers/scsi/scsi_scan.c Thu May 15 15:24:42 2003 @@ -33,173 +33,9 @@ #include "scsi.h" #include "hosts.h" -#ifdef CONFIG_KMOD -#include -#endif - -/* - * Flags for SCSI devices that need special treatment - */ -#define BLIST_NOLUN 0x001 /* Only scan LUN 0 */ -#define BLIST_FORCELUN 0x002 /* Known to have LUNs, force scanning */ -#define BLIST_BORKEN 0x004 /* Flag for broken handshaking */ -#define BLIST_KEY 0x008 /* unlock by special command */ -#define BLIST_SINGLELUN 0x010 /* Do not use LUNs in parallel */ -#define BLIST_NOTQ 0x020 /* Buggy Tagged Command Queuing */ -#define BLIST_SPARSELUN 0x040 /* Non consecutive LUN numbering */ -#define BLIST_MAX5LUN 0x080 /* Avoid LUNS >= 5 */ -#define BLIST_ISROM 0x100 /* Treat as (removable) CD-ROM */ -#define BLIST_LARGELUN 0x200 /* LUNs past 7 on a SCSI-2 device */ -#define BLIST_INQUIRY_36 0x400 /* override additional length field */ -#define BLIST_INQUIRY_58 0x800 /* ... for broken inquiry responses */ - -/* - * scsi_static_device_list: deprecated list of devices that require - * settings that differ from the default, includes black-listed (broken) - * devices. The entries here are added to the tail of scsi_dev_info_list - * via scsi_dev_info_list_init. - * - * Do not add to this list, use the command line or proc interface to add - * to the scsi_dev_info_list. This table will eventually go away. - */ -struct dev_info scsi_static_device_list[] __initdata = { - /* - * The following devices are known not to tolerate a lun != 0 scan - * for one reason or another. Some will respond to all luns, - * others will lock up. - */ - {"Aashima", "IMAGERY 2400SP", "1.03", BLIST_NOLUN}, /* locks up */ - {"CHINON", "CD-ROM CDS-431", "H42", BLIST_NOLUN}, /* locks up */ - {"CHINON", "CD-ROM CDS-535", "Q14", BLIST_NOLUN}, /* locks up */ - {"DENON", "DRD-25X", "V", BLIST_NOLUN}, /* locks up */ - {"HITACHI", "DK312C", "CM81", BLIST_NOLUN}, /* responds to all lun */ - {"HITACHI", "DK314C", "CR21", BLIST_NOLUN}, /* responds to all lun */ - {"IMS", "CDD521/10", "2.06", BLIST_NOLUN}, /* locks up */ - {"MAXTOR", "XT-3280", "PR02", BLIST_NOLUN}, /* locks up */ - {"MAXTOR", "XT-4380S", "B3C", BLIST_NOLUN}, /* locks up */ - {"MAXTOR", "MXT-1240S", "I1.2", BLIST_NOLUN}, /* locks up */ - {"MAXTOR", "XT-4170S", "B5A", BLIST_NOLUN}, /* locks up */ - {"MAXTOR", "XT-8760S", "B7B", BLIST_NOLUN}, /* locks up */ - {"MEDIAVIS", "RENO CD-ROMX2A", "2.03", BLIST_NOLUN}, /* responds to all lun */ - {"NEC", "CD-ROM DRIVE:841", "1.0", BLIST_NOLUN},/* locks up */ - {"PHILIPS", "PCA80SC", "V4-2", BLIST_NOLUN}, /* responds to all lun */ - {"RODIME", "RO3000S", "2.33", BLIST_NOLUN}, /* locks up */ - {"SUN", "SENA", NULL, BLIST_NOLUN}, /* responds to all luns */ - /* - * The following causes a failed REQUEST SENSE on lun 1 for - * aha152x controller, which causes SCSI code to reset bus. - */ - {"SANYO", "CRD-250S", "1.20", BLIST_NOLUN}, - /* - * The following causes a failed REQUEST SENSE on lun 1 for - * aha152x controller, which causes SCSI code to reset bus. - */ - {"SEAGATE", "ST157N", "\004|j", BLIST_NOLUN}, - {"SEAGATE", "ST296", "921", BLIST_NOLUN}, /* responds to all lun */ - {"SEAGATE", "ST1581", "6538", BLIST_NOLUN}, /* responds to all lun */ - {"SONY", "CD-ROM CDU-541", "4.3d", BLIST_NOLUN}, - {"SONY", "CD-ROM CDU-55S", "1.0i", BLIST_NOLUN}, - {"SONY", "CD-ROM CDU-561", "1.7x", BLIST_NOLUN}, - {"SONY", "CD-ROM CDU-8012", NULL, BLIST_NOLUN}, - {"TANDBERG", "TDC 3600", "U07", BLIST_NOLUN}, /* locks up */ - {"TEAC", "CD-R55S", "1.0H", BLIST_NOLUN}, /* locks up */ - /* - * The following causes a failed REQUEST SENSE on lun 1 for - * seagate controller, which causes SCSI code to reset bus. - */ - {"TEAC", "CD-ROM", "1.06", BLIST_NOLUN}, - {"TEAC", "MT-2ST/45S2-27", "RV M", BLIST_NOLUN}, /* responds to all lun */ - /* - * The following causes a failed REQUEST SENSE on lun 1 for - * seagate controller, which causes SCSI code to reset bus. - */ - {"TEXEL", "CD-ROM", "1.06", BLIST_NOLUN}, - {"QUANTUM", "LPS525S", "3110", BLIST_NOLUN}, /* locks up */ - {"QUANTUM", "PD1225S", "3110", BLIST_NOLUN}, /* locks up */ - {"QUANTUM", "FIREBALL ST4.3S", "0F0C", BLIST_NOLUN}, /* locks up */ - {"MEDIAVIS", "CDR-H93MV", "1.31", BLIST_NOLUN}, /* locks up */ - {"SANKYO", "CP525", "6.64", BLIST_NOLUN}, /* causes failed REQ SENSE, extra reset */ - {"HP", "C1750A", "3226", BLIST_NOLUN}, /* scanjet iic */ - {"HP", "C1790A", "", BLIST_NOLUN}, /* scanjet iip */ - {"HP", "C2500A", "", BLIST_NOLUN}, /* scanjet iicx */ - {"YAMAHA", "CDR100", "1.00", BLIST_NOLUN}, /* locks up */ - {"YAMAHA", "CDR102", "1.00", BLIST_NOLUN}, /* locks up */ - {"YAMAHA", "CRW8424S", "1.0", BLIST_NOLUN}, /* locks up */ - {"YAMAHA", "CRW6416S", "1.0c", BLIST_NOLUN}, /* locks up */ - {"MITSUMI", "CD-R CR-2201CS", "6119", BLIST_NOLUN}, /* locks up */ - {"RELISYS", "Scorpio", NULL, BLIST_NOLUN}, /* responds to all lun */ - {"MICROTEK", "ScanMaker II", "5.61", BLIST_NOLUN}, /* responds to all lun */ - {"NEC", "D3856", "0009", BLIST_NOLUN}, - - /* - * Other types of devices that have special flags. - */ - {"SONY", "CD-ROM CDU-8001", NULL, BLIST_BORKEN}, - {"TEXEL", "CD-ROM", "1.06", BLIST_BORKEN}, - {"IOMEGA", "Io20S *F", NULL, BLIST_KEY}, - {"INSITE", "Floptical F*8I", NULL, BLIST_KEY}, - {"INSITE", "I325VM", NULL, BLIST_KEY}, - {"LASOUND", "CDX7405", "3.10", BLIST_MAX5LUN | BLIST_SINGLELUN}, - {"MICROP", "4110", NULL, BLIST_NOTQ}, - {"NRC", "MBR-7", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, - {"NRC", "MBR-7.4", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, - {"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN}, - {"NAKAMICH", "MJ-4.8S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, - {"NAKAMICH", "MJ-5.16S", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, - {"PIONEER", "CD-ROM DRM-600", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, - {"PIONEER", "CD-ROM DRM-602X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, - {"PIONEER", "CD-ROM DRM-604X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, - {"EMULEX", "MD21/S2 ESDI", NULL, BLIST_SINGLELUN}, - {"CANON", "IPUBJD", NULL, BLIST_SPARSELUN}, - {"nCipher", "Fastness Crypto", NULL, BLIST_FORCELUN}, - {"DEC", "HSG80", NULL, BLIST_FORCELUN}, - {"COMPAQ", "LOGICAL VOLUME", NULL, BLIST_FORCELUN}, - {"COMPAQ", "CR3500", NULL, BLIST_FORCELUN}, - {"NEC", "PD-1 ODX654P", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, - {"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, - {"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN}, - {"TOSHIBA", "CDROM", NULL, BLIST_ISROM}, - {"TOSHIBA", "CD-ROM", NULL, BLIST_ISROM}, - {"MegaRAID", "LD", NULL, BLIST_FORCELUN}, - {"DGC", "RAID", NULL, BLIST_SPARSELUN}, /* Dell PV 650F, storage on LUN 0 */ - {"DGC", "DISK", NULL, BLIST_SPARSELUN}, /* Dell PV 650F, no storage on LUN 0 */ - {"DELL", "PV660F", NULL, BLIST_SPARSELUN}, - {"DELL", "PV660F PSEUDO", NULL, BLIST_SPARSELUN}, - {"DELL", "PSEUDO DEVICE .", NULL, BLIST_SPARSELUN}, /* Dell PV 530F */ - {"DELL", "PV530F", NULL, BLIST_SPARSELUN}, - {"EMC", "SYMMETRIX", NULL, BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_FORCELUN}, - {"HP", "A6189A", NULL, BLIST_SPARSELUN | BLIST_LARGELUN}, /* HP VA7400 */ - {"HP", "OPEN-", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, /* HP XP Arrays */ - {"CMD", "CRA-7280", NULL, BLIST_SPARSELUN}, /* CMD RAID Controller */ - {"CNSI", "G7324", NULL, BLIST_SPARSELUN}, /* Chaparral G7324 RAID */ - {"CNSi", "G8324", NULL, BLIST_SPARSELUN}, /* Chaparral G8324 RAID */ - {"Zzyzx", "RocketStor 500S", NULL, BLIST_SPARSELUN}, - {"Zzyzx", "RocketStor 2000", NULL, BLIST_SPARSELUN}, - {"SONY", "TSL", NULL, BLIST_FORCELUN}, /* DDS3 & DDS4 autoloaders */ - {"DELL", "PERCRAID", NULL, BLIST_FORCELUN}, - {"HP", "NetRAID-4M", NULL, BLIST_FORCELUN}, - {"ADAPTEC", "AACRAID", NULL, BLIST_FORCELUN}, - {"ADAPTEC", "Adaptec 5400S", NULL, BLIST_FORCELUN}, - {"COMPAQ", "MSA1000", NULL, BLIST_FORCELUN}, - {"HP", "C1557A", NULL, BLIST_FORCELUN}, - {"IBM", "AuSaV1S2", NULL, BLIST_FORCELUN}, - {"FSC", "CentricStor", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"DDN", "SAN DataDirector", "*", BLIST_SPARSELUN}, - {"HITACHI", "DF400", "*", BLIST_SPARSELUN}, - {"HITACHI", "DF500", "*", BLIST_SPARSELUN}, - {"HITACHI", "DF600", "*", BLIST_SPARSELUN}, - {"IBM", "ProFibre 4000R", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"SUN", "T300", "*", BLIST_SPARSELUN}, - {"SUN", "T4", "*", BLIST_SPARSELUN}, - {"SGI", "RAID3", "*", BLIST_SPARSELUN}, - {"SGI", "RAID5", "*", BLIST_SPARSELUN}, - {"SGI", "TP9100", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"SGI", "TP9300", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"SGI", "TP9400", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"SGI", "TP9500", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - {"MYLEX", "DACARMRB", "*", BLIST_SPARSELUN | BLIST_LARGELUN}, - { NULL, NULL, NULL, 0 }, -}; +#include "scsi_priv.h" +#include "scsi_logging.h" +#include "scsi_devinfo.h" #define ALLOC_FAILURE_MSG KERN_ERR "%s: Allocation failure during" \ " SCSI scanning, some SCSI devices might not be configured\n" @@ -429,7 +265,6 @@ sdev->request_queue->queuedata = sdev; scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); - init_waitqueue_head(&sdev->scpnt_wait); if (shost->hostt->slave_alloc) { if (shost->hostt->slave_alloc(sdev)) @@ -481,7 +316,7 @@ * Undo the actions in scsi_alloc_sdev, including removing @sdev from * the list, and freeing @sdev. **/ -static void scsi_free_sdev(struct scsi_device *sdev) +void scsi_free_sdev(struct scsi_device *sdev) { unsigned long flags; @@ -1270,12 +1105,7 @@ int scsi_remove_device(struct scsi_device *sdev) { scsi_detach_device(sdev); - if (sdev->attached) - return -EINVAL; - scsi_device_unregister(sdev); - - scsi_free_sdev(sdev); return 0; } diff -Nru a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c --- a/drivers/scsi/scsi_syms.c Thu May 15 15:24:38 2003 +++ b/drivers/scsi/scsi_syms.c Thu May 15 15:24:38 2003 @@ -21,6 +21,7 @@ #include "scsi.h" #include #include "hosts.h" +#include "scsi_logging.h" #include @@ -64,6 +65,7 @@ EXPORT_SYMBOL(scsi_put_command); EXPORT_SYMBOL(scsi_report_bus_reset); +EXPORT_SYMBOL(scsi_report_device_reset); EXPORT_SYMBOL(scsi_block_requests); EXPORT_SYMBOL(scsi_unblock_requests); EXPORT_SYMBOL(scsi_adjust_queue_depth); @@ -76,8 +78,6 @@ EXPORT_SYMBOL(scsi_io_completion); -EXPORT_SYMBOL(scsi_slave_attach); -EXPORT_SYMBOL(scsi_slave_detach); EXPORT_SYMBOL(scsi_device_get); EXPORT_SYMBOL(scsi_device_put); EXPORT_SYMBOL(scsi_add_device); @@ -104,12 +104,5 @@ /* * Externalize timers so that HBAs can safely start/restart commands. */ -extern void scsi_add_timer(Scsi_Cmnd *, int, void ((*) (Scsi_Cmnd *))); -extern int scsi_delete_timer(Scsi_Cmnd *); EXPORT_SYMBOL(scsi_add_timer); EXPORT_SYMBOL(scsi_delete_timer); - -/* - * sysfs support - */ -EXPORT_SYMBOL(shost_class); diff -Nru a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c --- a/drivers/scsi/scsi_sysfs.c Thu May 15 15:24:34 2003 +++ b/drivers/scsi/scsi_sysfs.c Thu May 15 15:24:34 2003 @@ -14,6 +14,7 @@ #include "scsi.h" #include "hosts.h" +#include "scsi_priv.h" /* * shost_show_function: macro to create an attr function that can be used to @@ -21,9 +22,9 @@ */ #define shost_show_function(field, format_string) \ static ssize_t \ -show_##field (struct device *dev, char *buf) \ +show_##field (struct class_device *class_dev, char *buf) \ { \ - struct Scsi_Host *shost = to_scsi_host(dev); \ + struct Scsi_Host *shost = class_to_shost(class_dev); \ return snprintf (buf, 20, format_string, shost->field); \ } @@ -32,8 +33,8 @@ * read only field. */ #define shost_rd_attr(field, format_string) \ - shost_show_function(field, format_string) \ -static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL) + shost_show_function(field, format_string) \ +static CLASS_DEVICE_ATTR(field, S_IRUGO, show_##field, NULL) /* * Create the actual show/store functions and data structures. @@ -44,39 +45,16 @@ shost_rd_attr(sg_tablesize, "%hu\n"); shost_rd_attr(unchecked_isa_dma, "%d\n"); -static struct device_attribute *const shost_attrs[] = { - &dev_attr_unique_id, - &dev_attr_host_busy, - &dev_attr_cmd_per_lun, - &dev_attr_sg_tablesize, - &dev_attr_unchecked_isa_dma, +static struct class_device_attribute *const shost_attrs[] = { + &class_device_attr_unique_id, + &class_device_attr_host_busy, + &class_device_attr_cmd_per_lun, + &class_device_attr_sg_tablesize, + &class_device_attr_unchecked_isa_dma, }; -/** - * scsi_host_class_name_show - copy out the SCSI host name - * @dev: device to check - * @page: copy data into this area - * @count: number of bytes to copy - * @off: start at this offset in page - * Return: - * number of bytes written into page. - **/ -static ssize_t scsi_host_class_name_show(struct device *dev, char *page) -{ - struct Scsi_Host *shost; - - shost = to_scsi_host(dev); - - if (!shost) - return 0; - - return snprintf(page, 20, "scsi%d\n", shost->host_no); -} - -DEVICE_ATTR(class_name, S_IRUGO, scsi_host_class_name_show, NULL); - -struct class shost_class = { - .name = "scsi-host", +static struct class shost_class = { + .name = "scsi_host", }; /** @@ -113,10 +91,16 @@ int scsi_sysfs_register(void) { - bus_register(&scsi_bus_type); - class_register(&shost_class); + int error; - return 0; + error = bus_register(&scsi_bus_type); + if (error) + return error; + error = class_register(&shost_class); + if (error) + return error; + + return error; } void scsi_sysfs_unregister(void) @@ -272,6 +256,16 @@ &dev_attr_rescan, }; +static void scsi_device_release(struct device *dev) +{ + struct scsi_device *sdev; + + sdev = to_scsi_device(dev); + if (!sdev) + return; + scsi_free_sdev(sdev); +} + /** * scsi_device_register - register a scsi device with the scsi bus * @sdev: scsi_device to register @@ -285,8 +279,9 @@ sprintf(sdev->sdev_driverfs_dev.bus_id,"%d:%d:%d:%d", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); - sdev->sdev_driverfs_dev.parent = sdev->host->host_gendev; + sdev->sdev_driverfs_dev.parent = &sdev->host->host_gendev; sdev->sdev_driverfs_dev.bus = &scsi_bus_type; + sdev->sdev_driverfs_dev.release = scsi_device_release; error = device_register(&sdev->sdev_driverfs_dev); if (error) @@ -314,3 +309,77 @@ device_remove_file(&sdev->sdev_driverfs_dev, sdev_attrs[i]); device_unregister(&sdev->sdev_driverfs_dev); } + +static void scsi_host_release(struct device *dev) +{ + struct Scsi_Host *shost; + + shost = dev_to_shost(dev); + if (!shost) + return; + + scsi_free_shost(shost); +} + +void scsi_sysfs_init_host(struct Scsi_Host *shost) +{ + device_initialize(&shost->host_gendev); + snprintf(shost->host_gendev.bus_id, BUS_ID_SIZE, "host%d", + shost->host_no); + snprintf(shost->host_gendev.name, DEVICE_NAME_SIZE, "%s", + shost->hostt->proc_name); + shost->host_gendev.release = scsi_host_release; + + class_device_initialize(&shost->class_dev); + shost->class_dev.dev = &shost->host_gendev; + shost->class_dev.class = &shost_class; + snprintf(shost->class_dev.class_id, BUS_ID_SIZE, "host%d", + shost->host_no); +} + +/** + * scsi_sysfs_add_host - add scsi host to subsystem + * @shost: scsi host struct to add to subsystem + * @dev: parent struct device pointer + **/ +int scsi_sysfs_add_host(struct Scsi_Host *shost, struct device *dev) +{ + int i, error; + + if (!shost->host_gendev.parent) + shost->host_gendev.parent = (dev) ? dev : &legacy_bus; + + error = device_add(&shost->host_gendev); + if (error) + return error; + + error = class_device_add(&shost->class_dev); + if (error) + goto clean_device; + + for (i = 0; !error && i < ARRAY_SIZE(shost_attrs); i++) + error = class_device_create_file(&shost->class_dev, + shost_attrs[i]); + if (error) + goto clean_class; + + return error; + +clean_class: + class_device_del(&shost->class_dev); +clean_device: + device_del(&shost->host_gendev); + + return error; +} + +/** + * scsi_sysfs_remove_host - remove scsi host from subsystem + * @shost: scsi host to remove from subsystem + **/ +void scsi_sysfs_remove_host(struct Scsi_Host *shost) +{ + class_device_del(&shost->class_dev); + device_del(&shost->host_gendev); +} + diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c --- a/drivers/scsi/sd.c Thu May 15 15:24:42 2003 +++ b/drivers/scsi/sd.c Thu May 15 15:24:42 2003 @@ -52,6 +52,9 @@ #include #include +#include "scsi_logging.h" + + /* * Remaining dev_t-handling stuff */ @@ -696,7 +699,7 @@ int good_sectors = (result == 0 ? this_count : 0); sector_t block_sectors = 1; sector_t error_sector; -#if CONFIG_SCSI_LOGGING +#ifdef CONFIG_SCSI_LOGGING SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: %s: res=0x%x\n", SCpnt->request->rq_disk->disk_name, result)); if (0 != result) { @@ -808,7 +811,8 @@ struct scsi_request *SRpnt, unsigned char *buffer) { unsigned char cmd[10]; unsigned long spintime_value = 0; - int the_result, retries, spintime; + int retries, spintime; + unsigned int the_result; spintime = 0; @@ -817,7 +821,7 @@ do { retries = 0; - while (retries < 3) { + do { cmd[0] = TEST_UNIT_READY; memset((void *) &cmd[1], 0, 9); @@ -831,10 +835,9 @@ the_result = SRpnt->sr_result; retries++; - if (the_result == 0 - || SRpnt->sr_sense_buffer[2] != UNIT_ATTENTION) - break; - } + } while (retries < 3 && !scsi_status_is_good(the_result) + && ((driver_byte(the_result) & DRIVER_SENSE) + && SRpnt->sr_sense_buffer[2] == UNIT_ATTENTION)); /* * If the drive has indicated to us that it doesn't have @@ -844,8 +847,15 @@ if (media_not_present(sdkp, SRpnt)) return; - if (the_result == 0) - break; /* all is well now */ + if ((driver_byte(the_result) & DRIVER_SENSE) == 0) { + /* no sense, TUR either succeeded or failed + * with a status error */ + if(!spintime && !scsi_status_is_good(the_result)) + printk(KERN_NOTICE "%s: Unit Not Ready, error = 0x%x\n", diskname, the_result); + break; + } + + /* * If manual intervention is required, or this is an @@ -853,13 +863,13 @@ */ if (SRpnt->sr_sense_buffer[2] == NOT_READY && SRpnt->sr_sense_buffer[12] == 4 /* not ready */ && - SRpnt->sr_sense_buffer[13] == 3) + SRpnt->sr_sense_buffer[13] == 3) { break; /* manual intervention required */ /* * Issue command to spin up drive when not ready */ - if (SRpnt->sr_sense_buffer[2] == NOT_READY) { + } else if (SRpnt->sr_sense_buffer[2] == NOT_READY) { unsigned long time1; if (!spintime) { printk(KERN_NOTICE "%s: Spinning up disk...", @@ -886,15 +896,24 @@ time1 = schedule_timeout(time1); } while(time1); printk("."); + } else { + /* we don't understand the sense code, so it's + * probably pointless to loop */ + if(!spintime) { + printk(KERN_NOTICE "%s: Unit Not Ready, sense:\n", diskname); + print_req_sense("", SRpnt); + } + break; } + } while (spintime && time_after(spintime_value + 100 * HZ, jiffies)); if (spintime) { - if (the_result) - printk("not responding...\n"); - else + if (scsi_status_is_good(the_result)) printk("ready\n"); + else + printk("not responding...\n"); } } @@ -1299,14 +1318,10 @@ SCSI_LOG_HLQUEUE(3, printk("sd_attach: scsi device: <%d,%d,%d,%d>\n", sdp->host->host_no, sdp->channel, sdp->id, sdp->lun)); - error = scsi_slave_attach(sdp); - if (error) - goto out; - error = -ENOMEM; sdkp = kmalloc(sizeof(*sdkp), GFP_KERNEL); if (!sdkp) - goto out_detach; + goto out; gd = alloc_disk(16); if (!gd) @@ -1365,8 +1380,6 @@ put_disk(gd); out_free: kfree(sdkp); -out_detach: - scsi_slave_detach(sdp); out: return error; } @@ -1403,7 +1416,6 @@ sd_devlist_remove(sdkp); del_gendisk(sdkp->disk); - scsi_slave_detach(sdp); spin_lock(&sd_index_lock); clear_bit(sdkp->index, sd_index_bits); @@ -1502,7 +1514,8 @@ printk("FAILED\n No memory for request\n"); return 0; } - + + SRpnt->sr_data_direction = SCSI_DATA_NONE; for(retries = 3; retries > 0; --retries) { unsigned char cmd[10] = { 0 }; diff -Nru a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c --- a/drivers/scsi/seagate.c Thu May 15 15:24:37 2003 +++ b/drivers/scsi/seagate.c Thu May 15 15:24:37 2003 @@ -1700,7 +1700,20 @@ return 0; } -/* Eventually this will go into an include file, but this will be later */ -static Scsi_Host_Template driver_template = SEAGATE_ST0X; - +static Scsi_Host_Template driver_template = { + .detect = seagate_st0x_detect, + .release = seagate_st0x_release, + .info = seagate_st0x_info, + .command = seagate_st0x_command, + .queuecommand = seagate_st0x_queue_command, + .eh_abort_handler = seagate_st0x_abort, + .eh_bus_reset_handler = seagate_st0x_bus_reset, + .eh_host_reset_handler = seagate_st0x_host_reset, + .eh_device_reset_handler = seagate_st0x_device_reset, + .can_queue = 1, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 1, + .use_clustering = DISABLE_CLUSTERING, +}; #include "scsi_module.c" diff -Nru a/drivers/scsi/seagate.h b/drivers/scsi/seagate.h --- a/drivers/scsi/seagate.h Thu May 15 15:24:42 2003 +++ b/drivers/scsi/seagate.h Thu May 15 15:24:42 2003 @@ -19,19 +19,4 @@ static int seagate_st0x_device_reset(Scsi_Cmnd *); static int seagate_st0x_host_reset(Scsi_Cmnd *); -#define SEAGATE_ST0X { .detect = seagate_st0x_detect, \ - .release = seagate_st0x_release, \ - .info = seagate_st0x_info, \ - .command = seagate_st0x_command, \ - .queuecommand = seagate_st0x_queue_command, \ - .eh_abort_handler = seagate_st0x_abort, \ - .eh_bus_reset_handler = seagate_st0x_bus_reset, \ - .eh_host_reset_handler = seagate_st0x_host_reset, \ - .eh_device_reset_handler = seagate_st0x_device_reset, \ - .can_queue = 1, \ - .this_id = 7, \ - .sg_tablesize = SG_ALL, \ - .cmd_per_lun = 1, \ - .use_clustering = DISABLE_CLUSTERING} - #endif /* _SEAGATE_H */ diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c --- a/drivers/scsi/sg.c Thu May 15 15:24:38 2003 +++ b/drivers/scsi/sg.c Thu May 15 15:24:38 2003 @@ -67,6 +67,8 @@ #include #include +#include "scsi_logging.h" + #ifdef CONFIG_PROC_FS #include static int sg_proc_init(void); @@ -1350,17 +1352,12 @@ struct gendisk *disk; Sg_device *sdp = NULL; unsigned long iflags; - char devfs_name[64]; int k, error; disk = alloc_disk(1); if (!disk) return -ENOMEM; - error = scsi_slave_attach(scsidp); - if (error) - goto out_put; - write_lock_irqsave(&sg_dev_arr_lock, iflags); if (sg_nr_dev >= sg_dev_max) { /* try to resize */ Sg_device **tmp_da; @@ -1373,7 +1370,7 @@ printk(KERN_ERR "sg_attach: device array cannot be resized\n"); error = -ENOMEM; - goto out_detach; + goto out; } write_lock_irqsave(&sg_dev_arr_lock, iflags); memset(tmp_da, 0, tmp_dev_max * sizeof (Sg_device *)); @@ -1398,7 +1395,7 @@ if (NULL != sdp) vfree((char *) sdp); error = -ENODEV; - goto out_detach; + goto out; } if (k < sg_dev_max) { if (NULL == sdp) { @@ -1414,7 +1411,7 @@ write_unlock_irqrestore(&sg_dev_arr_lock, iflags); printk(KERN_ERR "sg_attach: Sg_device cannot be allocated\n"); error = -ENOMEM; - goto out_detach; + goto out; } SCSI_LOG_TIMEOUT(3, printk("sg_attach: dev=%d \n", k)); @@ -1449,11 +1446,9 @@ device_create_file(&sdp->sg_driverfs_dev, &dev_attr_type); device_create_file(&sdp->sg_driverfs_dev, &dev_attr_kdev); - sprintf(devfs_name, "%s/generic", scsidp->devfs_name); - devfs_register(NULL, devfs_name, 0, - SCSI_GENERIC_MAJOR, k, + devfs_mk_cdev(MKDEV(SCSI_GENERIC_MAJOR, k), S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, - &sg_fops, sdp); + "%s/generic", scsidp->devfs_name); switch (scsidp->type) { case TYPE_DISK: @@ -1471,9 +1466,7 @@ } return 0; -out_detach: - scsi_slave_detach(scsidp); -out_put: +out: put_disk(disk); return error; } @@ -1524,7 +1517,6 @@ SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d\n", k)); sg_dev_arr[k] = NULL; } - scsi_slave_detach(scsidp); sg_nr_dev--; break; } diff -Nru a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c --- a/drivers/scsi/sgiwd93.c Thu May 15 15:24:45 2003 +++ b/drivers/scsi/sgiwd93.c Thu May 15 15:24:45 2003 @@ -227,9 +227,7 @@ if (request_irq(SGI_WD93_0_IRQ, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host)) { printk(KERN_WARNING "sgiwd93: Could not register IRQ %d (for host 0).\n", SGI_WD93_0_IRQ); -#ifdef MODULE wd33c93_release(); -#endif free_page((unsigned long)buf); scsi_unregister(sgiwd93_host); return 0; @@ -263,9 +261,7 @@ if (request_irq(SGI_WD93_1_IRQ, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host1)) { printk(KERN_WARNING "sgiwd93: Could not allocate irq %d (for host1).\n", SGI_WD93_1_IRQ); -#ifdef MODULE wd33c93_release(); -#endif free_page((unsigned long)buf); scsi_unregister(sgiwd93_host1); /* Fall through since host0 registered OK */ @@ -278,17 +274,8 @@ return 1; /* Found one. */ } -#define HOSTS_C - -#include "sgiwd93.h" - -static Scsi_Host_Template driver_template = SGIWD93_SCSI; - -#include "scsi_module.c" - int sgiwd93_release(struct Scsi_Host *instance) { -#ifdef MODULE free_irq(SGI_WD93_0_IRQ, sgiwd93_intr); free_page(KSEG0ADDR(hdata->dma_bounce_buffer)); wd33c93_release(); @@ -297,6 +284,21 @@ free_page(KSEG0ADDR(hdata1->dma_bounce_buffer)); wd33c93_release(); } -#endif return 1; } + +static Scsi_Host_Template driver_template = { + .proc_name = "SGIWD93", + .name = "SGI WD93", + .detect = sgiwd93_detect, + .release = sgiwd93_release, + .queuecommand = wd33c93_queuecommand, + .abort = wd33c93_abort, + .reset = wd33c93_reset, + .can_queue = CAN_QUEUE, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = CMD_PER_LUN, + .use_clustering = DISABLE_CLUSTERING, +}; +#include "scsi_module.c" diff -Nru a/drivers/scsi/sgiwd93.h b/drivers/scsi/sgiwd93.h --- a/drivers/scsi/sgiwd93.h Thu May 15 15:24:37 2003 +++ b/drivers/scsi/sgiwd93.h Thu May 15 15:24:37 2003 @@ -25,17 +25,4 @@ int wd33c93_abort(Scsi_Cmnd *); int wd33c93_reset(Scsi_Cmnd *, unsigned int); -#define SGIWD93_SCSI {.proc_name = "SGIWD93", \ - .name = "SGI WD93", \ - .detect = sgiwd93_detect, \ - .release = sgiwd93_release, \ - .queuecommand = wd33c93_queuecommand, \ - .abort = wd33c93_abort, \ - .reset = wd33c93_reset, \ - .can_queue = CAN_QUEUE, \ - .this_id = 7, \ - .sg_tablesize = SG_ALL, \ - .cmd_per_lun = CMD_PER_LUN, \ - .use_clustering = DISABLE_CLUSTERING } - #endif /* !(_SGIWD93_H) */ diff -Nru a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c --- a/drivers/scsi/sim710.c Thu May 15 15:24:42 2003 +++ b/drivers/scsi/sim710.c Thu May 15 15:24:42 2003 @@ -155,7 +155,7 @@ static __devexit int sim710_device_remove(struct device *dev) { - struct Scsi_Host *host = to_scsi_host(dev); + struct Scsi_Host *host = dev_to_shost(dev); struct NCR_700_Host_Parameters *hostdata = (struct NCR_700_Host_Parameters *)host->hostdata[0]; diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c --- a/drivers/scsi/sr.c Thu May 15 15:24:35 2003 +++ b/drivers/scsi/sr.c Thu May 15 15:24:35 2003 @@ -50,6 +50,7 @@ #include "hosts.h" #include /* For the door lock/unlock commands */ +#include "scsi_logging.h" #include "sr.h" @@ -514,10 +515,6 @@ if (sdev->type != TYPE_ROM && sdev->type != TYPE_WORM) return 1; - error = scsi_slave_attach(sdev); - if (error) - return error; - error = -ENOMEM; cd = kmalloc(sizeof(*cd), GFP_KERNEL); if (!cd) @@ -591,7 +588,6 @@ fail_free: kfree(cd); fail: - scsi_slave_detach(sdev); return error; } @@ -819,7 +815,6 @@ return; sr_devlist_remove(cd); - scsi_slave_detach(SDp); del_gendisk(cd->disk); spin_lock(&sr_index_lock); diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c --- a/drivers/scsi/st.c Thu May 15 15:24:40 2003 +++ b/drivers/scsi/st.c Thu May 15 15:24:40 2003 @@ -3725,16 +3725,13 @@ return 1; } - if (scsi_slave_attach(SDp)) - return 1; - i = SDp->host->sg_tablesize; if (st_max_sg_segs < i) i = st_max_sg_segs; buffer = new_tape_buffer(TRUE, (SDp->host)->unchecked_isa_dma, i); if (buffer == NULL) { printk(KERN_ERR "st: Can't allocate new tape buffer. Device not attached.\n"); - goto out_slave_detach; + goto out; } disk = alloc_disk(1); @@ -3865,11 +3862,10 @@ write_unlock(&st_dev_arr_lock); for (mode = 0; mode < ST_NBR_MODES; ++mode) { - char name[8], devfs_name[64]; + char name[8]; /* Rewind entry */ sprintf(name, "mt%s", st_formats[mode]); - sprintf(devfs_name, "%s/mt%s", SDp->devfs_name, st_formats[mode]); sprintf(tpnt->driverfs_dev_r[mode].bus_id, "%s:%s", SDp->sdev_driverfs_dev.bus_id, name); @@ -3883,13 +3879,12 @@ device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_type); device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_kdev); - devfs_register(NULL, devfs_name, 0, - SCSI_TAPE_MAJOR, dev_num + (mode << 5), + devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, dev_num + (mode << 5)), S_IFCHR | S_IRUGO | S_IWUGO, - &st_fops, NULL); + "%s/mt%s", SDp->devfs_name, st_formats[mode]); + /* No-rewind entry */ sprintf (name, "mt%sn", st_formats[mode]); - sprintf(devfs_name, "%s/mt%sn", SDp->devfs_name, st_formats[mode]); sprintf(tpnt->driverfs_dev_n[mode].bus_id, "%s:%s", SDp->sdev_driverfs_dev.bus_id, name); @@ -3904,10 +3899,9 @@ &dev_attr_type); device_create_file(&tpnt->driverfs_dev_n[mode], &dev_attr_kdev); - devfs_register(NULL, devfs_name, 0, - SCSI_TAPE_MAJOR, dev_num + (mode << 5) + 128, + devfs_mk_cdev(MKDEV(SCSI_TAPE_MAJOR, dev_num + (mode << 5) + 128), S_IFCHR | S_IRUGO | S_IWUGO, - &st_fops, NULL); + "%s/mt%sn", SDp->devfs_name, st_formats[mode]); } disk->number = devfs_register_tape(SDp->devfs_name); @@ -3923,8 +3917,7 @@ put_disk(disk); out_buffer_free: kfree(buffer); -out_slave_detach: - scsi_slave_detach(SDp); +out: return 1; }; @@ -3962,7 +3955,6 @@ normalize_buffer(tpnt->buffer); kfree(tpnt->buffer); } - scsi_slave_detach(SDp); put_disk(tpnt->disk); kfree(tpnt); return; diff -Nru a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c --- a/drivers/scsi/sym53c416.c Thu May 15 15:24:34 2003 +++ b/drivers/scsi/sym53c416.c Thu May 15 15:24:34 2003 @@ -875,6 +875,24 @@ #endif -static Scsi_Host_Template driver_template = SYM53C416; - +static Scsi_Host_Template driver_template = { + .proc_name = "sym53c416", + .name = "Symbios Logic 53c416", + .detect = sym53c416_detect, + .info = sym53c416_info, + .command = sym53c416_command, + .queuecommand = sym53c416_queuecommand, + .eh_abort_handler = sym53c416_abort, + .eh_host_reset_handler =sym53c416_host_reset, + .eh_bus_reset_handler = sym53c416_bus_reset, + .eh_device_reset_handler =sym53c416_device_reset, + .release = sym53c416_release, + .bios_param = sym53c416_bios_param, + .can_queue = 1, + .this_id = SYM53C416_SCSI_ID, + .sg_tablesize = 32, + .cmd_per_lun = 1, + .unchecked_isa_dma = 1, + .use_clustering = ENABLE_CLUSTERING, +}; #include "scsi_module.c" diff -Nru a/drivers/scsi/sym53c416.h b/drivers/scsi/sym53c416.h --- a/drivers/scsi/sym53c416.h Thu May 15 15:24:42 2003 +++ b/drivers/scsi/sym53c416.h Thu May 15 15:24:42 2003 @@ -34,25 +34,4 @@ static int sym53c416_bios_param(struct scsi_device *, struct block_device *, sector_t, int *); static void sym53c416_setup(char *str, int *ints); - -#define SYM53C416 { \ - .proc_name = "sym53c416", \ - .name = "Symbios Logic 53c416", \ - .detect = sym53c416_detect, \ - .info = sym53c416_info, \ - .command = sym53c416_command, \ - .queuecommand = sym53c416_queuecommand, \ - .eh_abort_handler = sym53c416_abort, \ - .eh_host_reset_handler =sym53c416_host_reset, \ - .eh_bus_reset_handler = sym53c416_bus_reset, \ - .eh_device_reset_handler =sym53c416_device_reset,\ - .release = sym53c416_release, \ - .bios_param = sym53c416_bios_param, \ - .can_queue = 1, \ - .this_id = SYM53C416_SCSI_ID, \ - .sg_tablesize = 32, \ - .cmd_per_lun = 1, \ - .unchecked_isa_dma = 1, \ - .use_clustering = ENABLE_CLUSTERING \ - } #endif diff -Nru a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c --- a/drivers/scsi/sym53c8xx.c Thu May 15 15:24:41 2003 +++ b/drivers/scsi/sym53c8xx.c Thu May 15 15:24:41 2003 @@ -14718,10 +14718,21 @@ MODULE_LICENSE("GPL"); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) -static -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) || defined(MODULE) -Scsi_Host_Template driver_template = SYM53C8XX; +static Scsi_Host_Template driver_template = { + .name = "sym53c8xx", + .detect = sym53c8xx_detect, + .release = sym53c8xx_release, + .info = sym53c8xx_info, + .queuecommand = sym53c8xx_queue_command, + .slave_configure = sym53c8xx_slave_configure, + .abort = sym53c8xx_abort, + .reset = sym53c8xx_reset, + .can_queue = SCSI_NCR_CAN_QUEUE, + .this_id = 7, + .sg_tablesize = SCSI_NCR_SG_TABLESIZE, + .cmd_per_lun = SCSI_NCR_CMD_PER_LUN, + .max_sectors = MAX_HW_SEGMENTS*8, + .use_clustering = DISABLE_CLUSTERING, + .highmem_io = 1 +}; #include "scsi_module.c" -#endif diff -Nru a/drivers/scsi/sym53c8xx.h b/drivers/scsi/sym53c8xx.h --- a/drivers/scsi/sym53c8xx.h Thu May 15 15:24:37 2003 +++ b/drivers/scsi/sym53c8xx.h Thu May 15 15:24:37 2003 @@ -77,37 +77,6 @@ int sym53c8xx_slave_configure(Scsi_Device *); int sym53c8xx_release(struct Scsi_Host *); -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,75) - -#define SYM53C8XX { .name = "sym53c8xx", \ - .detect = sym53c8xx_detect, \ - .release = sym53c8xx_release, \ - .info = sym53c8xx_info, \ - .queuecommand = sym53c8xx_queue_command,\ - .slave_configure = sym53c8xx_slave_configure,\ - .abort = sym53c8xx_abort, \ - .reset = sym53c8xx_reset, \ - .can_queue = SCSI_NCR_CAN_QUEUE, \ - .this_id = 7, \ - .sg_tablesize = SCSI_NCR_SG_TABLESIZE, \ - .cmd_per_lun = SCSI_NCR_CMD_PER_LUN, \ - .max_sectors = MAX_HW_SEGMENTS*8, \ - .use_clustering = DISABLE_CLUSTERING, \ - .highmem_io = 1} - -#else - -#define SYM53C8XX { NULL, NULL, NULL, NULL, \ - NULL, sym53c8xx_detect, \ - sym53c8xx_release, sym53c8xx_info, NULL, \ - sym53c8xx_queue_command,sym53c8xx_abort, \ - sym53c8xx_reset, NULL, scsicam_bios_param, \ - SCSI_NCR_CAN_QUEUE, 7, \ - SCSI_NCR_SG_TABLESIZE, SCSI_NCR_CMD_PER_LUN, \ - 0, 0, DISABLE_CLUSTERING} - -#endif /* LINUX_VERSION_CODE */ - #endif /* defined(HOSTS_C) || defined(MODULE) */ #endif /* SYM53C8XX_H */ diff -Nru a/drivers/scsi/sym53c8xx_2/sym53c8xx.h b/drivers/scsi/sym53c8xx_2/sym53c8xx.h --- a/drivers/scsi/sym53c8xx_2/sym53c8xx.h Thu May 15 15:24:46 2003 +++ b/drivers/scsi/sym53c8xx_2/sym53c8xx.h Thu May 15 15:24:46 2003 @@ -79,57 +79,10 @@ #endif #endif -int sym53c8xx_detect(Scsi_Host_Template *tpnt); -const char *sym53c8xx_info(struct Scsi_Host *host); - -int sym53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); - -int sym53c8xx_eh_abort_handler(Scsi_Cmnd *); -int sym53c8xx_eh_device_reset_handler(Scsi_Cmnd *); -int sym53c8xx_eh_bus_reset_handler(Scsi_Cmnd *); -int sym53c8xx_eh_host_reset_handler(Scsi_Cmnd *); - -int sym53c8xx_slave_configure(Scsi_Device *); - -#ifdef MODULE -int sym53c8xx_release(struct Scsi_Host *); -#else -#define sym53c8xx_release NULL -#endif - - -/* - * Host template defintion - */ -#if (LINUX_VERSION_CODE >= 0x020400) || defined(HOSTS_C) || defined(MODULE) - -#include - -#define SYM53C8XX { \ - .name = "sym53c8xx", \ - .detect = sym53c8xx_detect, \ - .release = sym53c8xx_release, \ - .info = sym53c8xx_info, \ - .queuecommand = sym53c8xx_queue_command, \ - .slave_configure = sym53c8xx_slave_configure, \ - .eh_abort_handler = sym53c8xx_eh_abort_handler, \ - .eh_device_reset_handler = sym53c8xx_eh_device_reset_handler,\ - .eh_bus_reset_handler = sym53c8xx_eh_bus_reset_handler, \ - .eh_host_reset_handler = sym53c8xx_eh_host_reset_handler, \ - .can_queue = 0, \ - .this_id = 7, \ - .sg_tablesize = 0, \ - .cmd_per_lun = 0, \ - .use_clustering = DISABLE_CLUSTERING, \ - .highmem_io = 1} - -#endif /* defined(HOSTS_C) || defined(MODULE) */ - /* * Translate kernel configuration parameters * into corresponding driver parameters. */ -#if !defined(HOSTS_C) /* * Use normal IO if configured. @@ -366,7 +319,5 @@ #define DEBUG_FLAGS sym_debug_flags #endif #define boot_verbose sym_driver_setup.verbose - -#endif /* !defined(HOSTS_C) */ #endif /* SYM53C8XX_H */ diff -Nru a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c --- a/drivers/scsi/sym53c8xx_2/sym_glue.c Thu May 15 15:24:46 2003 +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c Thu May 15 15:24:46 2003 @@ -2558,35 +2558,17 @@ bcopy(chip, &device->chip, sizeof(device->chip)); device->chip.revision_id = revision; + if (pci_enable_device(pdev)) + return -1; + + pci_set_master(pdev); + /* * Read additionnal info from the configuration space. */ - pci_read_config_word(pdev, PCI_COMMAND, &command); pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line_size); /* - * Enable missing capabilities in the PCI COMMAND register. - */ -#ifdef SYM_CONF_IOMAPPED -#define PCI_COMMAND_BITS_TO_ENABLE (PCI_COMMAND_IO | \ - PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_PARITY) -#else -#define PCI_COMMAND_BITS_TO_ENABLE \ - (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_PARITY) -#endif - if ((command & PCI_COMMAND_BITS_TO_ENABLE) - != PCI_COMMAND_BITS_TO_ENABLE) { - printf_info("%s: setting%s%s%s%s...\n", sym_name(device), - (command & PCI_COMMAND_IO) ? "" : " PCI_COMMAND_IO", - (command & PCI_COMMAND_MEMORY) ? "" : " PCI_COMMAND_MEMORY", - (command & PCI_COMMAND_MASTER) ? "" : " PCI_COMMAND_MASTER", - (command & PCI_COMMAND_PARITY) ? "" : " PCI_COMMAND_PARITY"); - command |= PCI_COMMAND_BITS_TO_ENABLE; - pci_write_config_word(pdev, PCI_COMMAND, command); - } -#undef PCI_COMMAND_BITS_TO_ENABLE - - /* * If cache line size is not configured, suggest * a value for well known CPUs. */ @@ -2625,6 +2607,7 @@ sym_name(device), cache_line_size); } + pci_read_config_word(pdev, PCI_COMMAND, &command); if ((pci_fix_up & 2) && cache_line_size && (chip->features & FE_WRIE) && !(command & PCI_COMMAND_INVALIDATE)) { printf_info("%s: setting PCI_COMMAND_INVALIDATE.\n", @@ -2725,15 +2708,6 @@ /* * Initialize driver general stuff. */ -#ifdef SYM_LINUX_PROC_INFO_SUPPORT -#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27) - tpnt->proc_dir = &proc_scsi_sym53c8xx; -#else - tpnt->proc_name = NAME53C8XX; -#endif - tpnt->proc_info = sym53c8xx_proc_info; -#endif - #ifdef SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT #ifdef MODULE if (sym53c8xx) @@ -2916,7 +2890,6 @@ -#ifdef MODULE /* * Linux release module stuff. * @@ -2980,7 +2953,6 @@ return 0; } -#endif /* MODULE */ /* * For bigots to keep silent. :) @@ -2992,10 +2964,27 @@ /* * Driver host template. */ -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) -static +static Scsi_Host_Template driver_template = { + .name = "sym53c8xx", + .detect = sym53c8xx_detect, + .release = sym53c8xx_release, + .info = sym53c8xx_info, + .queuecommand = sym53c8xx_queue_command, + .slave_configure = sym53c8xx_slave_configure, + .eh_abort_handler = sym53c8xx_eh_abort_handler, + .eh_device_reset_handler = sym53c8xx_eh_device_reset_handler, + .eh_bus_reset_handler = sym53c8xx_eh_bus_reset_handler, + .eh_host_reset_handler = sym53c8xx_eh_host_reset_handler, + .this_id = 7, + .use_clustering = DISABLE_CLUSTERING, + .highmem_io = 1, +#ifdef SYM_LINUX_PROC_INFO_SUPPORT + .proc_info = sym53c8xx_proc_info, +#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27) + .proc_dir = &proc_scsi_sym53c8xx, +#else + .proc_name = NAME53C8XX, #endif -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,0) || defined(MODULE) -Scsi_Host_Template driver_template = SYM53C8XX; -#include "../scsi_module.c" #endif +}; +#include "../scsi_module.c" diff -Nru a/drivers/scsi/t128.c b/drivers/scsi/t128.c --- a/drivers/scsi/t128.c Thu May 15 15:24:43 2003 +++ b/drivers/scsi/t128.c Thu May 15 15:24:43 2003 @@ -400,7 +400,19 @@ #include "NCR5380.c" -/* Eventually this will go into an include file, but this will be later */ -static Scsi_Host_Template driver_template = TRANTOR_T128; - +static Scsi_Host_Template driver_template = { + .name = "Trantor T128/T128F/T228", + .detect = t128_detect, + .queuecommand = t128_queue_command, + .eh_abort_handler = t128_abort, + .eh_bus_reset_handler = t128_bus_reset, + .eh_host_reset_handler = t128_host_reset, + .eh_device_reset_handler = t128_device_reset, + .bios_param = t128_biosparam, + .can_queue = CAN_QUEUE, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = CMD_PER_LUN, + .use_clustering = DISABLE_CLUSTERING, +}; #include "scsi_module.c" diff -Nru a/drivers/scsi/t128.h b/drivers/scsi/t128.h --- a/drivers/scsi/t128.h Thu May 15 15:24:35 2003 +++ b/drivers/scsi/t128.h Thu May 15 15:24:35 2003 @@ -114,27 +114,6 @@ #define CAN_QUEUE 32 #endif -/* - * I hadn't thought of this with the earlier drivers - but to prevent - * macro definition conflicts, we shouldn't define all of the internal - * macros when this is being used solely for the host stub. - */ - -#define TRANTOR_T128 { \ - .name = "Trantor T128/T128F/T228", \ - .detect = t128_detect, \ - .queuecommand = t128_queue_command, \ - .eh_abort_handler = t128_abort, \ - .eh_bus_reset_handler = t128_bus_reset, \ - .eh_host_reset_handler = t128_host_reset, \ - .eh_device_reset_handler = t128_device_reset, \ - .bios_param = t128_biosparam, \ - .can_queue = CAN_QUEUE, \ - .this_id = 7, \ - .sg_tablesize = SG_ALL, \ - .cmd_per_lun = CMD_PER_LUN, \ - .use_clustering = DISABLE_CLUSTERING} - #ifndef HOSTS_C #define NCR5380_implementation_fields \ diff -Nru a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c --- a/drivers/scsi/tmscsim.c Thu May 15 15:24:46 2003 +++ b/drivers/scsi/tmscsim.c Thu May 15 15:24:46 2003 @@ -3059,7 +3059,20 @@ } #endif /* def MODULE */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,99) static Scsi_Host_Template driver_template = DC390_T; + .proc_name = "tmscsim", + .proc_info = DC390_proc_info, + .name = DC390_BANNER " V" DC390_VERSION, + .detect = DC390_detect, + .release = DC390_release, + .queuecommand = DC390_queue_command, + .abort = DC390_abort, + .reset = DC390_reset, + .bios_param = DC390_bios_param, + .can_queue = 42, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 16, + .use_clustering = DISABLE_CLUSTERING, +}; #include "scsi_module.c" -#endif diff -Nru a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c --- a/drivers/scsi/u14-34f.c Thu May 15 15:24:36 2003 +++ b/drivers/scsi/u14-34f.c Thu May 15 15:24:36 2003 @@ -1897,7 +1897,8 @@ unsigned long spin_flags; /* Check if the interrupt must be processed by this handler */ - if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return; + if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) + return IRQ_NONE; spin_lock_irqsave(sh[j]->host_lock, spin_flags); ihdlr(irq, j); @@ -1929,8 +1930,19 @@ return FALSE; } -static Scsi_Host_Template driver_template = ULTRASTOR_14_34F; - +static Scsi_Host_Template driver_template = { + .name = "UltraStor 14F/34F rev. " U14_34F_VERSION " ", + .detect = u14_34f_detect, + .release = u14_34f_release, + .queuecommand = u14_34f_queuecommand, + .eh_abort_handler = u14_34f_eh_abort, + .eh_host_reset_handler = u14_34f_eh_host_reset, + .bios_param = u14_34f_bios_param, + .slave_configure = u14_34f_slave_configure, + .this_id = 7, + .unchecked_isa_dma = 1, + .use_clustering = ENABLE_CLUSTERING, +}; #include "scsi_module.c" #ifndef MODULE diff -Nru a/drivers/scsi/u14-34f.h b/drivers/scsi/u14-34f.h --- a/drivers/scsi/u14-34f.h Thu May 15 15:24:43 2003 +++ b/drivers/scsi/u14-34f.h Thu May 15 15:24:43 2003 @@ -12,19 +12,3 @@ static int u14_34f_slave_configure(Scsi_Device *); #define U14_34F_VERSION "8.03.00" - -#define ULTRASTOR_14_34F { \ - .name = "UltraStor 14F/34F rev. " U14_34F_VERSION " ", \ - .detect = u14_34f_detect, \ - .release = u14_34f_release, \ - .queuecommand = u14_34f_queuecommand, \ - .eh_abort_handler = u14_34f_eh_abort, \ - .eh_device_reset_handler = NULL, \ - .eh_bus_reset_handler = NULL, \ - .eh_host_reset_handler = u14_34f_eh_host_reset, \ - .bios_param = u14_34f_bios_param, \ - .slave_configure = u14_34f_slave_configure, \ - .this_id = 7, \ - .unchecked_isa_dma = 1, \ - .use_clustering = ENABLE_CLUSTERING \ - } diff -Nru a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c --- a/drivers/scsi/ultrastor.c Thu May 15 15:24:39 2003 +++ b/drivers/scsi/ultrastor.c Thu May 15 15:24:39 2003 @@ -252,7 +252,7 @@ #if ULTRASTOR_MAX_CMDS == 1 unsigned char mscp_busy; #else - unsigned short mscp_free; + unsigned long mscp_free; #endif volatile unsigned char aborted[ULTRASTOR_MAX_CMDS]; struct mscp mscp[ULTRASTOR_MAX_CMDS]; @@ -1174,7 +1174,18 @@ MODULE_LICENSE("GPL"); -/* Eventually this will go into an include file, but this will be later */ -static Scsi_Host_Template driver_template = ULTRASTOR_14F; - +static Scsi_Host_Template driver_template = { + .name = "UltraStor 14F/24F/34F", + .detect = ultrastor_detect, + .info = ultrastor_info, + .queuecommand = ultrastor_queuecommand, + .eh_abort_handler = ultrastor_abort, + .eh_host_reset_handler = ultrastor_host_reset, + .bios_param = ultrastor_biosparam, + .can_queue = ULTRASTOR_MAX_CMDS, + .sg_tablesize = ULTRASTOR_14F_MAX_SG, + .cmd_per_lun = ULTRASTOR_MAX_CMDS_PER_LUN, + .unchecked_isa_dma = 1, + .use_clustering = ENABLE_CLUSTERING, +}; #include "scsi_module.c" diff -Nru a/drivers/scsi/ultrastor.h b/drivers/scsi/ultrastor.h --- a/drivers/scsi/ultrastor.h Thu May 15 15:24:37 2003 +++ b/drivers/scsi/ultrastor.h Thu May 15 15:24:37 2003 @@ -30,21 +30,6 @@ #define ULTRASTOR_24F_PORT 0xC80 -#define ULTRASTOR_14F { .name = "UltraStor 14F/24F/34F", \ - .detect = ultrastor_detect, \ - .info = ultrastor_info, \ - .queuecommand = ultrastor_queuecommand, \ - .eh_abort_handler = ultrastor_abort, \ - .eh_host_reset_handler = ultrastor_host_reset, \ - .bios_param = ultrastor_biosparam, \ - .can_queue = ULTRASTOR_MAX_CMDS, \ - .this_id = 0, \ - .sg_tablesize = ULTRASTOR_14F_MAX_SG, \ - .cmd_per_lun = ULTRASTOR_MAX_CMDS_PER_LUN,\ - .unchecked_isa_dma = 1, \ - .use_clustering = ENABLE_CLUSTERING } - - #ifdef ULTRASTOR_PRIVATE #define UD_ABORT 0x0001 diff -Nru a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c --- a/drivers/scsi/wd7000.c Thu May 15 15:24:45 2003 +++ b/drivers/scsi/wd7000.c Thu May 15 15:24:45 2003 @@ -1375,7 +1375,6 @@ static int wd7000_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout) { struct Scsi_Host *host = NULL; - Scsi_Device *scd; Adapter *adapter; unsigned long flags; char *pos = buffer; @@ -1449,27 +1448,6 @@ SPRINTF(count ? "\n" : "none\n"); #endif - - /* - * Display driver information for each device attached to the board. - */ - SPRINTF("\nAttached devices: %s\n", !list_empty(&host->my_devices) ? - "" : "none"); - - list_for_each_entry (scd, &host->my_devices, siblings) { - SPRINTF(" [Channel: %02d, Id: %02d, Lun: %02d] ", scd->channel, scd->id, scd->lun); - SPRINTF("%s ", (scd->type < MAX_SCSI_DEVICE_CODE) ? scsi_device_types[(short) scd->type] : "Unknown device"); - - for (i = 0; (i < 8) && (scd->vendor[i] >= 0x20); i++) - SPRINTF("%c", scd->vendor[i]); - SPRINTF(" "); - - for (i = 0; (i < 16) && (scd->model[i] >= 0x20); i++) - SPRINTF("%c", scd->model[i]); - SPRINTF("\n"); - } - - SPRINTF("\n"); spin_unlock_irqrestore(host->host_lock, flags); diff -Nru a/drivers/serial/21285.c b/drivers/serial/21285.c --- a/drivers/serial/21285.c Thu May 15 15:24:42 2003 +++ b/drivers/serial/21285.c Thu May 15 15:24:42 2003 @@ -85,7 +85,7 @@ { } -static void serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *regs) { struct uart_port *port = dev_id; struct tty_struct *tty = port->info->tty; @@ -97,7 +97,7 @@ tty->flip.work.func((void *)tty); if (tty->flip.count >= TTY_FLIPBUF_SIZE) { printk(KERN_WARNING "TTY_DONT_FLIP set\n"); - return; + goto out; } } @@ -143,9 +143,12 @@ status = *CSR_UARTFLG; } tty_flip_buffer_push(tty); + + out: + return IRQ_HANDLED; } -static void serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *regs) { struct uart_port *port = dev_id; struct circ_buf *xmit = &port->info->xmit; @@ -155,11 +158,11 @@ *CSR_UARTDR = port->x_char; port->icount.tx++; port->x_char = 0; - return; + goto out; } if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { serial21285_stop_tx(port, 0); - return; + goto out; } do { @@ -175,6 +178,9 @@ if (uart_circ_empty(xmit)) serial21285_stop_tx(port, 0); + + out: + return IRQ_HANDLED; } static unsigned int serial21285_tx_empty(struct uart_port *port) diff -Nru a/drivers/serial/amba.c b/drivers/serial/amba.c --- a/drivers/serial/amba.c Thu May 15 15:24:33 2003 +++ b/drivers/serial/amba.c Thu May 15 15:24:33 2003 @@ -278,7 +278,7 @@ wake_up_interruptible(&uap->port.info->delta_msr_wait); } -static void ambauart_int(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t ambauart_int(int irq, void *dev_id, struct pt_regs *regs) { struct uart_port *port = dev_id; unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT; @@ -302,6 +302,8 @@ status = UART_GET_INT_STATUS(port); } while (status & (AMBA_UARTIIR_RTIS | AMBA_UARTIIR_RIS | AMBA_UARTIIR_TIS)); + + return IRQ_HANDLED; } static unsigned int ambauart_tx_empty(struct uart_port *port) diff -Nru a/drivers/serial/core.c b/drivers/serial/core.c --- a/drivers/serial/core.c Thu May 15 15:24:35 2003 +++ b/drivers/serial/core.c Thu May 15 15:24:35 2003 @@ -2242,7 +2242,7 @@ * Register the port whether it's detected or not. This allows * setserial to be used to alter this ports parameters. */ - tty_register_device(drv->tty_driver, port->line); + tty_register_device(drv->tty_driver, port->line, NULL); out: up(&port_sem); diff -Nru a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c --- a/drivers/serial/sa1100.c Thu May 15 15:24:34 2003 +++ b/drivers/serial/sa1100.c Thu May 15 15:24:34 2003 @@ -312,7 +312,7 @@ sa1100_stop_tx(&sport->port, 0); } -static void sa1100_int(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t sa1100_int(int irq, void *dev_id, struct pt_regs *regs) { struct sa1100_port *sport = dev_id; unsigned int status, pass_counter = 0; @@ -347,6 +347,8 @@ ~UTSR0_TFS; } while (status & (UTSR0_TFS | UTSR0_RFS | UTSR0_RID)); spin_unlock(&sport->port.lock); + + return IRQ_HANDLED; } /* @@ -830,7 +832,7 @@ .setup = sa1100_console_setup, .flags = CON_PRINTBUFFER, .index = -1, - .data = sa1100_reg, + .data = &sa1100_reg, }; static int __init sa1100_rs_console_init(void) diff -Nru a/drivers/sgi/char/sgiserial.c b/drivers/sgi/char/sgiserial.c --- a/drivers/sgi/char/sgiserial.c Thu May 15 15:24:35 2003 +++ b/drivers/sgi/char/sgiserial.c Thu May 15 15:24:35 2003 @@ -1232,7 +1232,7 @@ tmp.close_delay = info->close_delay; tmp.closing_wait = info->closing_wait; tmp.custom_divisor = info->custom_divisor; - return copy_to_user(retinfo,&tmp,sizeof(*retinfo)); + return copy_to_user(retinfo,&tmp,sizeof(*retinfo)) ? -EFAULT : 0; } static int set_serial_info(struct sgi_serial * info, @@ -1867,6 +1867,7 @@ memset(&serial_driver, 0, sizeof(struct tty_driver)); serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.owner = THIS_MODULE; serial_driver.name = "ttyS"; serial_driver.major = TTY_MAJOR; serial_driver.minor_start = 64; diff -Nru a/drivers/sgi/char/shmiq.c b/drivers/sgi/char/shmiq.c --- a/drivers/sgi/char/shmiq.c Thu May 15 15:24:42 2003 +++ b/drivers/sgi/char/shmiq.c Thu May 15 15:24:42 2003 @@ -470,9 +470,8 @@ printk ("SHMIQ setup\n"); register_chrdev(SHMIQ_MAJOR, "shmiq", &shmiq_fops); for (i = 0; i < 3; i++) { - devfs_register (NULL, names[i], DEVFS_FL_DEFAULT, - SHMIQ_MAJOR, i, S_IFCHR | S_IRUSR | S_IWUSR, - &shmiq_fops, NULL); + devfs_mk_cdev(MKDEV(SHMIQ_MAJOR, i), + S_IFCHR | S_IRUSR | S_IWUSR, names[i]); } } diff -Nru a/drivers/tc/zs.c b/drivers/tc/zs.c --- a/drivers/tc/zs.c Thu May 15 15:24:43 2003 +++ b/drivers/tc/zs.c Thu May 15 15:24:43 2003 @@ -1872,6 +1872,7 @@ memset(&serial_driver, 0, sizeof(struct tty_driver)); serial_driver.magic = TTY_DRIVER_MAGIC; + serial_driver.owner = THIS_MODULE; #if (LINUX_VERSION_CODE > 0x2032D && defined(CONFIG_DEVFS_FS)) serial_driver.name = "tts/"; #else @@ -1970,8 +1971,8 @@ printk("ttyS%02d at 0x%08x (irq = %d)", info->line, info->port, info->irq); printk(" is a Z85C30 SCC\n"); - tty_register_device(&serial_driver, info->line); - tty_register_device(&callout_driver, info->line); + tty_register_device(&serial_driver, info->line, NULL); + tty_register_device(&callout_driver, info->line, NULL); } diff -Nru a/drivers/usb/Kconfig b/drivers/usb/Kconfig --- a/drivers/usb/Kconfig Thu May 15 15:24:34 2003 +++ b/drivers/usb/Kconfig Thu May 15 15:24:34 2003 @@ -91,5 +91,7 @@ source "drivers/usb/misc/Kconfig" +source "drivers/usb/gadget/Kconfig" + endmenu diff -Nru a/drivers/usb/Makefile b/drivers/usb/Makefile --- a/drivers/usb/Makefile Thu May 15 15:24:45 2003 +++ b/drivers/usb/Makefile Thu May 15 15:24:45 2003 @@ -58,3 +58,4 @@ obj-$(CONFIG_USB_TEST) += misc/ obj-$(CONFIG_USB_TIGL) += misc/ obj-$(CONFIG_USB_USS720) += misc/ + diff -Nru a/drivers/usb/class/Kconfig b/drivers/usb/class/Kconfig --- a/drivers/usb/class/Kconfig Thu May 15 15:24:33 2003 +++ b/drivers/usb/class/Kconfig Thu May 15 15:24:33 2003 @@ -90,6 +90,6 @@ This code is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). - The module will be called printer. If you want to compile it as a + The module will be called usblp. If you want to compile it as a module, say M here and read . diff -Nru a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c --- a/drivers/usb/class/bluetty.c Thu May 15 15:24:42 2003 +++ b/drivers/usb/class/bluetty.c Thu May 15 15:24:42 2003 @@ -1198,7 +1198,7 @@ bluetooth, endpoint->bInterval); /* initialize the devfs nodes for this device and let the user know what bluetooths we are bound to */ - tty_register_device (&bluetooth_tty_driver, minor); + tty_register_device (&bluetooth_tty_driver, minor, &intf->dev); info("Bluetooth converter now attached to ttyUB%d (or usb/ttub/%d for devfs)", minor, minor); bluetooth_table[minor] = bluetooth; diff -Nru a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c --- a/drivers/usb/class/cdc-acm.c Thu May 15 15:24:40 2003 +++ b/drivers/usb/class/cdc-acm.c Thu May 15 15:24:40 2003 @@ -252,7 +252,8 @@ unsigned char *data = urb->transfer_buffer; int i = 0; - if (!ACM_READY(acm)) return; + if (!ACM_READY(acm)) + return; if (urb->status) dbg("nonzero read bulk status received: %d", urb->status); @@ -286,7 +287,8 @@ { struct acm *acm = (struct acm *)urb->context; - if (!ACM_READY(acm)) return; + if (!ACM_READY(acm)) + return; if (urb->status) dbg("nonzero write bulk status received: %d", urb->status); @@ -299,7 +301,8 @@ struct acm *acm = private; struct tty_struct *tty = acm->tty; - if (!ACM_READY(acm)) return; + if (!ACM_READY(acm)) + return; if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) (tty->ldisc.write_wakeup)(tty); @@ -315,7 +318,8 @@ { struct acm *acm = acm_table[tty->index]; - if (!acm || !acm->dev) return -EINVAL; + if (!acm || !acm->dev) + return -EINVAL; tty->driver_data = acm; acm->tty = tty; @@ -350,7 +354,8 @@ { struct acm *acm = tty->driver_data; - if (!acm || !acm->used) return; + if (!acm || !acm->used) + return; if (!--acm->used) { if (acm->dev) { @@ -373,9 +378,12 @@ { struct acm *acm = tty->driver_data; - if (!ACM_READY(acm)) return -EINVAL; - if (acm->writeurb->status == -EINPROGRESS) return 0; - if (!count) return 0; + if (!ACM_READY(acm)) + return -EINVAL; + if (acm->writeurb->status == -EINPROGRESS) + return 0; + if (!count) + return 0; count = (count > acm->writesize) ? acm->writesize : count; @@ -397,28 +405,32 @@ static int acm_tty_write_room(struct tty_struct *tty) { struct acm *acm = tty->driver_data; - if (!ACM_READY(acm)) return -EINVAL; + if (!ACM_READY(acm)) + return -EINVAL; return acm->writeurb->status == -EINPROGRESS ? 0 : acm->writesize; } static int acm_tty_chars_in_buffer(struct tty_struct *tty) { struct acm *acm = tty->driver_data; - if (!ACM_READY(acm)) return -EINVAL; + if (!ACM_READY(acm)) + return -EINVAL; return acm->writeurb->status == -EINPROGRESS ? acm->writeurb->transfer_buffer_length : 0; } static void acm_tty_throttle(struct tty_struct *tty) { struct acm *acm = tty->driver_data; - if (!ACM_READY(acm)) return; + if (!ACM_READY(acm)) + return; acm->throttle = 1; } static void acm_tty_unthrottle(struct tty_struct *tty) { struct acm *acm = tty->driver_data; - if (!ACM_READY(acm)) return; + if (!ACM_READY(acm)) + return; acm->throttle = 0; if (acm->readurb->status != -EINPROGRESS) acm_read_bulk(acm->readurb, NULL); @@ -427,7 +439,8 @@ static void acm_tty_break_ctl(struct tty_struct *tty, int state) { struct acm *acm = tty->driver_data; - if (!ACM_READY(acm)) return; + if (!ACM_READY(acm)) + return; if (acm_send_break(acm, state ? 0xffff : 0)) dbg("send break failed"); } @@ -496,7 +509,8 @@ struct acm_line newline; int newctrl = acm->ctrlout; - if (!ACM_READY(acm)) return; + if (!ACM_READY(acm)) + return; newline.speed = cpu_to_le32p(acm_tty_speed + (termios->c_cflag & CBAUD & ~CBAUDEX) + (termios->c_cflag & CBAUDEX ? 15 : 0)); @@ -653,7 +667,7 @@ usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm); usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm); - tty_register_device(&acm_tty_driver, minor); + tty_register_device(&acm_tty_driver, minor, &intf->dev); acm_table[minor] = acm; usb_set_intfdata (intf, acm); diff -Nru a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c --- a/drivers/usb/class/usb-midi.c Thu May 15 15:24:33 2003 +++ b/drivers/usb/class/usb-midi.c Thu May 15 15:24:33 2003 @@ -1355,8 +1355,10 @@ next = p2 + p2[0]; length -= p2[0]; - if (p2[0] < 2 ) break; - if (p2[1] != USB_DT_CS_INTERFACE) break; + if (p2[0] < 2 ) + break; + if (p2[1] != USB_DT_CS_INTERFACE) + break; if (p2[2] == MIDI_IN_JACK && p2[0] >= 6 ) { jack = p2[4]; #ifdef HAVE_JACK_STRINGS @@ -1366,7 +1368,8 @@ jack, (p2[3] == EMBEDDED_JACK)?"EMBEDDED":"EXTERNAL" ); } else if ( p2[2] == MIDI_OUT_JACK && p2[0] >= 6) { pins = p2[5]; - if ( p2[0] < (6 + 2 * pins) ) continue; + if ( p2[0] < (6 + 2 * pins) ) + continue; jack = p2[4]; #ifdef HAVE_JACK_STRINGS jack2string[jack] = p2[5 + 2 * pins]; @@ -1375,9 +1378,11 @@ jack, (p2[3] == EMBEDDED_JACK)?"EMBEDDED":"EXTERNAL", pins ); } else if ( p2[2] == ELEMENT_DESCRIPTOR && p2[0] >= 10) { pins = p2[4]; - if ( p2[0] < (9 + 2 * pins ) ) continue; + if ( p2[0] < (9 + 2 * pins ) ) + continue; nbytes = p2[8 + 2 * pins ]; - if ( p2[0] < (10 + 2 * pins + nbytes) ) continue; + if ( p2[0] < (10 + 2 * pins + nbytes) ) + continue; longBits = 0L; for ( offset = 0, shift = 0; offset < nbytes && offset < 8; offset ++, shift += 8) { longBits |= ((long)(p2[9 + 2 * pins + offset])) << shift; @@ -1408,7 +1413,8 @@ if ( p2 && next && ( p2 > next ) ) p2 = 0; - if ( p1[0] < 9 || !p2 || p2[0] < 4 ) continue; + if ( p1[0] < 9 || !p2 || p2[0] < 4 ) + continue; if ( (p1[2] & 0x80) == 0x80 ) { if ( iep < 15 ) { @@ -1417,7 +1423,8 @@ pins = 16; u->in[iep].endpoint = p1[2]; u->in[iep].cableId = ( 1 << pins ) - 1; - if ( u->in[iep].cableId ) iep ++; + if ( u->in[iep].cableId ) + iep ++; if ( iep < 15 ) { u->in[iep].endpoint = -1; u->in[iep].cableId = -1; @@ -1430,7 +1437,8 @@ pins = 16; u->out[oep].endpoint = p1[2]; u->out[oep].cableId = ( 1 << pins ) - 1; - if ( u->out[oep].cableId ) oep ++; + if ( u->out[oep].cableId ) + oep ++; if ( oep < 15 ) { u->out[oep].endpoint = -1; u->out[oep].cableId = -1; @@ -1446,7 +1454,8 @@ next = find_descriptor(buffer, bufSize, p1, USB_DT_ENDPOINT, ifnum, altSetting ); - if ( p1[0] < 7 ) continue; + if ( p1[0] < 7 ) + continue; if ( (p1[2] & 0x80) == 0x80 ) { if ( iep < 15 ) { @@ -1455,7 +1464,8 @@ pins = 16; u->in[iep].endpoint = p1[2]; u->in[iep].cableId = ( 1 << pins ) - 1; - if ( u->in[iep].cableId ) iep ++; + if ( u->in[iep].cableId ) + iep ++; if ( iep < 15 ) { u->in[iep].endpoint = -1; u->in[iep].cableId = -1; @@ -1468,7 +1478,8 @@ pins = 16; u->out[oep].endpoint = p1[2]; u->out[oep].cableId = ( 1 << pins ) - 1; - if ( u->out[oep].cableId ) oep ++; + if ( u->out[oep].cableId ) + oep ++; if ( oep < 15 ) { u->out[oep].endpoint = -1; u->out[oep].cableId = -1; @@ -1486,7 +1497,7 @@ return u; error_end: - if ( u ) kfree(u); + kfree(u); return NULL; } @@ -1501,7 +1512,8 @@ int ret=0; for ( i=0 ; i<16 ; i++ ) { - if ( v & (1<interface ); } - if ( alt < 0 ) { return -ENXIO; } + if ( alt < 0 ) + return -ENXIO; /* Configure interface */ if ( usb_set_interface( d, u->interface, alt ) < 0 ) { @@ -1596,7 +1609,8 @@ && u->in[inEndpoints].cableId >= 0 ) { inDevs += on_bits((unsigned short)u->in[inEndpoints].cableId); mins[inEndpoints] = alloc_midi_in_endpoint( d, u->in[inEndpoints].endpoint ); - if ( mins[inEndpoints] == NULL ) { goto error_end; } + if ( mins[inEndpoints] == NULL ) + goto error_end; inEndpoints++; } @@ -1605,7 +1619,8 @@ && u->out[outEndpoints].cableId >= 0 ) { outDevs += on_bits((unsigned short)u->out[outEndpoints].cableId); mouts[outEndpoints] = alloc_midi_out_endpoint( d, u->out[outEndpoints].endpoint ); - if ( mouts[outEndpoints] == NULL ) { goto error_end; } + if ( mouts[outEndpoints] == NULL ) + goto error_end; outEndpoints++; } @@ -1707,7 +1722,8 @@ mout = mouts[outEndpoint]; mdevs[i] = allocMidiDev( s, min, mout, inCableId, outCableId ); - if ( mdevs[i] == NULL ) { goto error_end; } + if ( mdevs[i] == NULL ) + goto error_end; } @@ -1962,11 +1978,15 @@ return -EINVAL; } - if ( ualt < 0 ) { ualt = -1; } + if ( ualt < 0 ) + ualt = -1; - if ( umin < 0 || umin > 15 ) { umin = 0x01 | USB_DIR_IN; } - if ( umout < 0 || umout > 15 ) { umout = 0x01; } - if ( ucable < 0 || ucable > 15 ) { ucable = 0; } + if ( umin < 0 || umin > 15 ) + umin = 0x01 | USB_DIR_IN; + if ( umout < 0 || umout > 15 ) + umout = 0x01; + if ( ucable < 0 || ucable > 15 ) + ucable = 0; u.deviceName = 0; /* A flag for alloc_usb_midi_device to get device name from device. */ diff -Nru a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c --- a/drivers/usb/class/usblp.c Thu May 15 15:24:34 2003 +++ b/drivers/usb/class/usblp.c Thu May 15 15:24:34 2003 @@ -54,7 +54,6 @@ #include #include #include -#include #undef DEBUG #include @@ -109,11 +108,7 @@ #define USBLP_REQ_RESET 0x02 #define USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST 0x00 /* HP Vendor-specific */ -#ifdef CONFIG_USB_DYNAMIC_MINORS -#define USBLP_MINORS 256 -#else #define USBLP_MINORS 16 -#endif #define USBLP_MINOR_BASE 0 #define USBLP_WRITE_TIMEOUT (5*HZ) /* 5 seconds */ @@ -303,8 +298,10 @@ status = *usblp->statusbuf; if (~status & LP_PERRORP) { newerr = 3; - if (status & LP_POUTPA) newerr = 1; - if (~status & LP_PSELECD) newerr = 2; + if (status & LP_POUTPA) + newerr = 1; + if (~status & LP_PSELECD) + newerr = 2; } if (newerr != err) @@ -324,13 +321,13 @@ struct usb_interface *intf; int retval; - if (minor < 0 || minor >= USBLP_MINORS) + if (minor < 0) return -ENODEV; lock_kernel(); retval = -ENODEV; - intf = usb_find_interface(&usblp_driver, mk_kdev(USB_MAJOR,minor)); + intf = usb_find_interface(&usblp_driver, minor); if (!intf) { goto out; } @@ -380,8 +377,6 @@ static void usblp_cleanup (struct usblp *usblp) { - devfs_remove ("usb/lp%d", usblp->minor); - usb_deregister_dev (1, usblp->minor); info("usblp%d: removed", usblp->minor); usb_buffer_free (usblp->dev, USBLP_BUF_SIZE, @@ -809,6 +804,13 @@ .release = usblp_release, }; +static struct usb_class_driver usblp_class = { + .name = "usb/lp%d", + .fops = &usblp_fops, + .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, + .minor_base = USBLP_MINOR_BASE, +}; + static int usblp_probe(struct usb_interface *intf, const struct usb_device_id *id) { @@ -816,7 +818,6 @@ struct usblp *usblp = 0; int protocol; int retval; - char name[10]; /* Malloc and start initializing usblp structure so we can use it * directly. */ @@ -830,11 +831,12 @@ init_waitqueue_head(&usblp->wait); usblp->ifnum = intf->altsetting->desc.bInterfaceNumber; - retval = usb_register_dev(&usblp_fops, USBLP_MINOR_BASE, 1, &usblp->minor); + retval = usb_register_dev(intf, &usblp_class); if (retval) { err("Not able to get a minor for this device."); goto abort; } + usblp->minor = intf->minor; usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL); if (!usblp->writeurb) { @@ -904,13 +906,6 @@ usblp_check_status(usblp, 0); #endif - /* If we have devfs, create with perms=660. */ - sprintf(name, "usb/lp%d", usblp->minor); - devfs_register(NULL, name, 0, USB_MAJOR, - usblp->minor, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | - S_IWGRP, &usblp_fops, NULL); - info("usblp%d: USB %sdirectional printer dev %d " "if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X", usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum, @@ -921,13 +916,10 @@ usb_set_intfdata (intf, usblp); - /* add device id so the device works when advertised */ - intf->kdev = mk_kdev(USB_MAJOR,usblp->minor); - return 0; abort_minor: - usb_deregister_dev (1, usblp->minor); + usb_deregister_dev(intf, &usblp_class); abort: if (usblp) { if (usblp->writebuf) @@ -936,8 +928,8 @@ if (usblp->readbuf) usb_buffer_free (usblp->dev, USBLP_BUF_SIZE, usblp->readbuf, usblp->writeurb->transfer_dma); - if (usblp->statusbuf) kfree(usblp->statusbuf); - if (usblp->device_id_string) kfree(usblp->device_id_string); + kfree(usblp->statusbuf); + kfree(usblp->device_id_string); usb_free_urb(usblp->writeurb); usb_free_urb(usblp->readurb); kfree(usblp); @@ -997,10 +989,12 @@ continue; if (!(epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK)) { - if (!epwrite) epwrite=epd; + if (!epwrite) + epwrite = epd; } else { - if (!epread) epread=epd; + if (!epread) + epread = epd; } } @@ -1030,9 +1024,12 @@ return proto_bias; /* Ordering is important here. */ - if (usblp->protocol[2].alt_setting != -1) return 2; - if (usblp->protocol[1].alt_setting != -1) return 1; - if (usblp->protocol[3].alt_setting != -1) return 3; + if (usblp->protocol[2].alt_setting != -1) + return 2; + if (usblp->protocol[1].alt_setting != -1) + return 1; + if (usblp->protocol[3].alt_setting != -1) + return 3; /* If nothing is available, then don't bind to this device. */ return -1; @@ -1046,7 +1043,8 @@ return -EINVAL; alts = usblp->protocol[protocol].alt_setting; - if (alts < 0) return -EINVAL; + if (alts < 0) + return -EINVAL; r = usb_set_interface(usblp->dev, usblp->ifnum, alts); if (r < 0) { err("can't set desired altsetting %d on interface %d", @@ -1108,8 +1106,7 @@ { struct usblp *usblp = usb_get_intfdata (intf); - /* remove device id to disable open() */ - intf->kdev = NODEV; + usb_deregister_dev(intf, &usblp_class); if (!usblp || !usblp->dev) { err("bogus disconnect"); diff -Nru a/drivers/usb/core/file.c b/drivers/usb/core/file.c --- a/drivers/usb/core/file.c Thu May 15 15:24:46 2003 +++ b/drivers/usb/core/file.c Thu May 15 15:24:46 2003 @@ -11,7 +11,7 @@ more docs, etc) * (C) Copyright Yggdrasil Computing, Inc. 2000 * (usb_device_id matching changes by Adam J. Richter) - * (C) Copyright Greg Kroah-Hartman 2002 + * (C) Copyright Greg Kroah-Hartman 2002-2003 * */ @@ -66,6 +66,10 @@ .open = usb_open, }; +static struct class usb_class = { + .name = "usb", +}; + int usb_major_init(void) { if (register_chrdev(USB_MAJOR, "usb", &usb_fops)) { @@ -74,41 +78,53 @@ } devfs_mk_dir("usb"); + class_register(&usb_class); return 0; } void usb_major_cleanup(void) { + class_unregister(&usb_class); devfs_remove("usb"); unregister_chrdev(USB_MAJOR, "usb"); } +static ssize_t show_dev(struct class_device *class_dev, char *buf) +{ + struct usb_interface *intf = class_dev_to_usb_interface(class_dev); + dev_t dev = MKDEV(USB_MAJOR, intf->minor); + return sprintf(buf, "%04x\n", dev); +} +static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL); + /** * usb_register_dev - register a USB device, and ask for a minor number - * @fops: the file operations for this USB device - * @minor: the requested starting minor for this device. - * @num_minors: number of minor numbers requested for this device - * @start_minor: place to put the new starting minor number + * @intf: pointer to the usb_interface that is being registered + * @class_driver: pointer to the usb_class_driver for this device * * This should be called by all USB drivers that use the USB major number. * If CONFIG_USB_DYNAMIC_MINORS is enabled, the minor number will be * dynamically allocated out of the list of available ones. If it is not * enabled, the minor number will be based on the next available free minor, - * starting at the requested @minor. + * starting at the class_driver->minor_base. + * + * This function also creates the devfs file for the usb device, if devfs + * is enabled, and creates a usb class device in the sysfs tree. * * usb_deregister_dev() must be called when the driver is done with * the minor numbers given out by this function. * * Returns -EINVAL if something bad happens with trying to register a - * device, and 0 on success, alone with a value that the driver should - * use in start_minor. + * device, and 0 on success. */ -int usb_register_dev (struct file_operations *fops, int minor, int num_minors, int *start_minor) +int usb_register_dev(struct usb_interface *intf, + struct usb_class_driver *class_driver) { - int i; - int j; - int good_spot; int retval = -EINVAL; + int minor_base = class_driver->minor_base; + int minor = 0; + char name[DEVICE_ID_SIZE]; + char *temp; #ifdef CONFIG_USB_DYNAMIC_MINORS /* @@ -116,65 +132,93 @@ * at zero to pack the devices into the smallest available space with * no holes in the minor range. */ - minor = 0; + minor_base = 0; #endif + intf->minor = -1; - dbg ("asking for %d minors, starting at %d", num_minors, minor); + dbg ("looking for a minor, starting at %d", minor_base); - if (fops == NULL) + if (class_driver->fops == NULL) goto exit; - *start_minor = 0; spin_lock (&minor_lock); - for (i = minor; i < MAX_USB_MINORS; ++i) { - if (usb_minors[i]) + for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) { + if (usb_minors[minor]) continue; - good_spot = 1; - for (j = 1; j <= num_minors-1; ++j) - if (usb_minors[i+j]) { - good_spot = 0; - break; - } - if (good_spot == 0) - continue; - - *start_minor = i; - dbg("found a minor chunk free, starting at %d", i); - for (i = *start_minor; i < (*start_minor + num_minors); ++i) - usb_minors[i] = fops; + usb_minors[minor] = class_driver->fops; retval = 0; - goto exit; + break; } -exit: spin_unlock (&minor_lock); + + if (retval) + goto exit; + + intf->minor = minor; + + /* handle the devfs registration */ + snprintf(name, DEVICE_ID_SIZE, class_driver->name, minor - minor_base); + devfs_mk_cdev(MKDEV(USB_MAJOR, minor), class_driver->mode, name); + + /* create a usb class device for this usb interface */ + memset(&intf->class_dev, 0x00, sizeof(struct class_device)); + intf->class_dev.class = &usb_class; + intf->class_dev.dev = &intf->dev; + + temp = strrchr(name, '/'); + if (temp && (temp[1] != 0x00)) + ++temp; + else + temp = name; + snprintf(intf->class_dev.class_id, BUS_ID_SIZE, "%s", temp); + class_device_register(&intf->class_dev); + class_device_create_file (&intf->class_dev, &class_device_attr_dev); +exit: return retval; } EXPORT_SYMBOL(usb_register_dev); /** * usb_deregister_dev - deregister a USB device's dynamic minor. - * @num_minors: number of minor numbers to put back. - * @start_minor: the starting minor number + * @intf: pointer to the usb_interface that is being deregistered + * @class_driver: pointer to the usb_class_driver for this device * * Used in conjunction with usb_register_dev(). This function is called * when the USB driver is finished with the minor numbers gotten from a * call to usb_register_dev() (usually when the device is disconnected * from the system.) + * + * This function also cleans up the devfs file for the usb device, if devfs + * is enabled, and removes the usb class device from the sysfs tree. * * This should be called by all drivers that use the USB major number. */ -void usb_deregister_dev (int num_minors, int start_minor) +void usb_deregister_dev(struct usb_interface *intf, + struct usb_class_driver *class_driver) { - int i; + int minor_base = class_driver->minor_base; + char name[DEVICE_ID_SIZE]; - dbg ("removing %d minors starting at %d", num_minors, start_minor); +#ifdef CONFIG_USB_DYNAMIC_MINORS + minor_base = 0; +#endif + + if (intf->minor == -1) + return; + + dbg ("removing %d minor", intf->minor); spin_lock (&minor_lock); - for (i = start_minor; i < (start_minor + num_minors); ++i) - usb_minors[i] = NULL; + usb_minors[intf->minor] = NULL; spin_unlock (&minor_lock); + + snprintf(name, DEVICE_ID_SIZE, class_driver->name, intf->minor - minor_base); + devfs_remove (name); + + class_device_unregister(&intf->class_dev); + intf->minor = -1; } EXPORT_SYMBOL(usb_deregister_dev); diff -Nru a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c --- a/drivers/usb/core/hcd-pci.c Thu May 15 15:24:38 2003 +++ b/drivers/usb/core/hcd-pci.c Thu May 15 15:24:38 2003 @@ -209,7 +209,8 @@ return; dev_info (hcd->controller, "remove, state %x\n", hcd->state); - if (in_interrupt ()) BUG (); + if (in_interrupt ()) + BUG (); hub = hcd->self.root_hub; hcd->state = USB_STATE_QUIESCING; diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c --- a/drivers/usb/core/usb.c Thu May 15 15:24:39 2003 +++ b/drivers/usb/core/usb.c Thu May 15 15:24:39 2003 @@ -457,12 +457,13 @@ /** * usb_find_interface - find usb_interface pointer for driver and device * @drv: the driver whose current configuration is considered - * @kdev: the desired device + * @minor: the minor number of the desired device * * This walks the driver device list and returns a pointer to the interface - * with the matching kdev_t. + * with the matching minor. Note, this only works for devices that share the + * USB major number. */ -struct usb_interface *usb_find_interface(struct usb_driver *drv, kdev_t kdev) +struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor) { struct list_head *entry; struct device *dev; @@ -476,9 +477,10 @@ continue; intf = to_usb_interface(dev); - if (kdev_same(intf->kdev,kdev)) { + if (intf->minor == -1) + continue; + if (intf->minor == minor) return intf; - } } /* no device found that matches */ diff -Nru a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/usb/gadget/Kconfig Thu May 15 15:24:47 2003 @@ -0,0 +1,152 @@ +# +# USB Gadget support on a system involves +# (a) a peripheral controller, and +# (b) the gadget driver using it. +# +# for 2.5 kbuild, drivers/usb/gadget/Kconfig +# source this at the end of drivers/usb/Kconfig +# +menuconfig USB_GADGET + tristate "Support for USB Gadgets" + depends on EXPERIMENTAL + help + USB is a master/slave protocol, organized with one master + host (such as a PC) controlling up to 127 peripheral devices. + The USB hardware is asymmetric, which makes it easier to set up: + you can't connect two "to-the-host" connectors to each other. + + Linux can run in the host, or in the peripheral. In both cases + you need a low level bus controller driver, and some software + talking to it. Peripheral controllers are often discrete silicon, + or are integrated with the CPU in a microcontroller. The more + familiar host side controllers have names like like "EHCI", "OHCI", + or "UHCI", and are usually integrated into southbridges on PC + motherboards. + + Enable this configuration option if you want to run Linux inside + a USB peripheral device. Configure one hardware driver for your + peripheral/device side bus controller, and a "gadget driver" for + your peripheral protocol. (If you use modular gadget drivers, + you may configure more than one.) + + If in doubt, say "N" and don't enable these drivers; most people + don't have this kind of hardware (except maybe inside Linux PDAs). + +# +# USB Peripheral Controller Support +# +choice + prompt "USB Peripheral Controller Support" + depends on USB_GADGET + +config USB_NET2280 + tristate "NetChip 2280 USB Peripheral Controller" + depends on PCI && USB_GADGET + help + NetChip 2280 is a PCI based USB peripheral controller which + supports both full and high speed USB 2.0 data transfers. + + It has six configurable endpoints, as well as endpoint zero + (for control transfers) and several endpoints with dedicated + functions. + + Say "y" to link the driver statically, or "m" to build a + dynamically linked module called "net2280" and force all + gadget drivers to also be dynamically linked. + +endchoice + +# +# USB Gadget Drivers +# +choice + prompt "USB Gadget Drivers" + depends on USB_GADGET + default USB_ETH + +# FIXME want a cleaner dependency/config approach for drivers. + +config USB_ZERO + tristate "Gadget Zero (DEVELOPMENT)" + depends on USB_GADGET && (USB_DUMMY_HCD || USB_NET2280 || USB_PXA250 || USB_SA1100) + help + Gadget Zero is a two-configuration device. It either sinks and + sources bulk data; or it loops back a configurable number of + transfers. It also implements control requests, for "chapter 9" + conformance. The driver needs only two bulk-capable endpoints, so + it can work on top of most device-side usb controllers. It's + useful for testing, and is also a working example showing how + USB "gadget drivers" can be written. + + Make this be the first driver you try using on top of any new + USB peripheral controller driver. Then you can use host-side + test software, like the "usbtest" driver, to put your hardware + and its driver through a basic set of functional tests. + + Gadget Zero also works with the host-side "usb-skeleton" driver, + and with many kinds of host-side test software. You may need + to tweak product and vendor IDs before host software knows about + this device, and arrange to select an appropriate configuration. + + Say "y" to link the driver statically, or "m" to build a + dynamically linked module called "g_zero". + +config USB_ZERO_NET2280 + bool + # for now, treat the "dummy" hcd as if it were a net2280 + depends on USB_ZERO && (USB_NET2280 || USB_DUMMY_HCD) + default y + +config USB_ZERO_PXA250 + bool + depends on USB_ZERO && USB_PXA250 + default y + +config USB_ZERO_SA1100 + bool + depends on USB_ZERO && USB_SA1100 + default y + + +config USB_ETH + tristate "Ethernet Gadget" + depends on USB_GADGET && (USB_DUMMY_HCD || USB_NET2280 || USB_PXA250 || USB_SA1100) + help + This driver implements the "Communication Device Class" (CDC) + Ethernet Control Model. That protocol is often avoided with pure + Ethernet adapters, in favor of simpler vendor-specific hardware, + but is widely supported by firmware for smart network devices. + + Within the USB device, this gadget driver exposes a network device + "usbX", where X depends on what other networking devices you have. + Treat it like a two-node Ethernet link: host, and gadget. + + The Linux-USB host-side "usbnet" driver interoperates with this + driver, so that deep I/O queues can be supported. (On 2.4 kernels, + use "CDCEther" instead.) Deep queues are especially important with + high speed devices. It should also interoperate with standard CDC + Ethernet class drivers on other host operating systems. + + Say "y" to link the driver statically, or "m" to build a + dynamically linked module called "g_ether". + + +config USB_ETH_NET2280 + bool + # for now, treat the "dummy" hcd as if it were a net2280 + depends on USB_ETH && (USB_NET2280 || USB_DUMMY_HCD) + default y + +config USB_ETH_PXA250 + bool + depends on USB_ETH && USB_PXA250 + default y + +config USB_ETH_SA1100 + bool + depends on USB_ETH && USB_SA1100 + default y + +endchoice + +# endmenuconfig diff -Nru a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/usb/gadget/Makefile Thu May 15 15:24:46 2003 @@ -0,0 +1,14 @@ +# +# USB peripheral controller drivers +# +obj-$(CONFIG_USB_NET2280) += net2280.o + +# +# USB gadget drivers +# +g_zero-objs := zero.o usbstring.o +g_ether-objs := ether.o usbstring.o + +obj-$(CONFIG_USB_ZERO) += g_zero.o +obj-$(CONFIG_USB_ETH) += g_ether.o + diff -Nru a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/usb/gadget/ether.c Thu May 15 15:24:47 2003 @@ -0,0 +1,1640 @@ +/* + * ether.c -- CDC 1.1 Ethernet gadget driver + * + * Copyright (C) 2003 David Brownell + * + * 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 + */ + + +#define DEBUG 1 +// #define VERBOSE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +/*-------------------------------------------------------------------------*/ + +/* + * "Communications Device Class" (CDC) Ethernet class driver + * + * CDC Ethernet is the standard USB solution for sending Ethernet frames + * using USB. Real hardware tends to use the same framing protocol but look + * different for control features. And Microsoft pushes their own approach + * (RNDIS) instead of the standard. + */ + +#define DRIVER_DESC "CDC Ethernet Gadget" +#define DRIVER_VERSION "29 April 2003" + +static const char shortname [] = "ether"; +static const char driver_desc [] = DRIVER_DESC; +static const char control_name [] = "Communications Control"; +static const char data_name [] = "CDC Ethernet Data"; + +#define MIN_PACKET sizeof(struct ethhdr) +#define MAX_PACKET ETH_DATA_LEN /* biggest packet we'll rx/tx */ + +/* FIXME allow high speed jumbograms */ + +/*-------------------------------------------------------------------------*/ + +struct eth_dev { + spinlock_t lock; + struct usb_gadget *gadget; + struct usb_request *req; /* for control responses */ + + u8 config; + struct usb_ep *in_ep, *out_ep, *status_ep; + const struct usb_endpoint_descriptor + *in, *out, *status; + + struct semaphore mutex; + struct net_device net; + struct net_device_stats stats; + atomic_t tx_qlen; + + struct work_struct work; + unsigned long todo; +#define WORK_RX_MEMORY 0 +}; + +/*-------------------------------------------------------------------------*/ + +/* This driver keeps a variable number of requests queued, more at + * high speeds. (Numbers are just educated guesses, untuned.) + * Shrink the queue if memory is tight, or make it bigger to + * handle bigger traffic bursts between IRQs. + */ + +static unsigned qmult = 4; + +#define HS_FACTOR 15 + +#define qlen(gadget) \ + (qmult*((gadget->speed == USB_SPEED_HIGH) ? HS_FACTOR : 1)) + +/* defer IRQs on highspeed TX */ +#define TX_DELAY 8 + + +module_param (qmult, uint, S_IRUGO|S_IWUSR); + + +/*-------------------------------------------------------------------------*/ + +/* Thanks to NetChip Technologies for donating this product ID. + * + * DO NOT REUSE THESE IDs with any other driver!! Ever!! + * Instead: allocate your own, using normal USB-IF procedures. + */ +#define DRIVER_VENDOR_NUM 0x0525 /* NetChip */ +#define DRIVER_PRODUCT_NUM 0xa4a1 /* Linux-USB Ethernet Gadget */ + +/*-------------------------------------------------------------------------*/ + +/* + * hardware-specific configuration, controlled by which device + * controller driver was configured. + * + * CHIP ... hardware identifier + * DRIVER_VERSION_NUM ... alerts the host side driver to differences + * EP0_MAXPACKET ... controls packetization of control requests + * EP_*_NAME ... which endpoints do we use for which purpose? + * EP_*_NUM ... numbers for them (often limited by hardware) + * HIGHSPEED ... define if ep0 and descriptors need high speed support + * MAX_USB_POWER ... define if we use other than 100 mA bus current + * SELFPOWER ... unless we can run on bus power, USB_CONFIG_ATT_SELFPOWER + * WAKEUP ... if hardware supports remote wakeup AND we will issue the + * usb_gadget_wakeup() call to initiate it, USB_CONFIG_ATT_WAKEUP + * + * hw_optimize(gadget) ... for any hardware tweaks we want to kick in + * before we enable our endpoints + * + * add other defines for other portability issues, like hardware that + * for some reason doesn't handle full speed bulk maxpacket of 64. + */ + +/* + * NetChip 2280, PCI based. + * + * use DMA with fat fifos for all data traffic, PIO for the status channel + * where its 64 byte maxpacket ceiling is no issue. + * + * performance note: only PIO needs per-usb-packet IRQs (ep0, ep-e, ep-f) + * otherwise IRQs are per-Ethernet-packet unless TX_DELAY and chaining help. + */ +#ifdef CONFIG_USB_ETH_NET2280 +#define CHIP "net2280" +#define DRIVER_VERSION_NUM 0x0101 +#define EP0_MAXPACKET 64 +static const char EP_OUT_NAME [] = "ep-a"; +#define EP_OUT_NUM 2 +static const char EP_IN_NAME [] = "ep-b"; +#define EP_IN_NUM 2 +static const char EP_STATUS_NAME [] = "ep-f"; +#define EP_STATUS_NUM 3 +#define HIGHSPEED +/* specific hardware configs could be bus-powered */ +#define SELFPOWER USB_CONFIG_ATT_SELFPOWER +/* supports remote wakeup, but this driver doesn't */ + +extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode); + +static inline void hw_optimize (struct usb_gadget *gadget) +{ + /* we can have bigger ep-a/ep-b fifos (2KB each, 4 USB packets + * for highspeed bulk) because we're not using ep-c/ep-d. + */ + net2280_set_fifo_mode (gadget, 1); +} +#endif + +/* + * PXA-250 UDC: widely used in second gen Linux-capable PDAs. + * + * no limitations except from set_interface: docs say "no" to a third + * interface. and the interrupt-only endpoints don't toggle, so we'll + * just use a bulk-capable one instead. + */ +#ifdef CONFIG_USB_ETH_PXA250 +#define CHIP "pxa250" +#define DRIVER_VERSION_NUM 0x0103 +#define EP0_MAXPACKET 16 +static const char EP_OUT_NAME [] = "ep12out-bulk"; +#define EP_OUT_NUM 12 +static const char EP_IN_NAME [] = "ep11in-bulk"; +#define EP_IN_NUM 11 +static const char EP_STATUS_NAME [] = "ep6in-bulk"; +#define EP_STATUS_NUM 6 +/* doesn't support bus-powered operation */ +#define SELFPOWER USB_CONFIG_ATT_SELFPOWER +/* supports remote wakeup, but this driver doesn't */ + +/* no hw optimizations to apply */ +#define hw_optimize(g) do {} while (0); +#endif + +/* + * SA-1100 UDC: widely used in first gen Linux-capable PDAs. + * + * can't have a notification endpoint, since there are only the two + * bulk-capable ones. the CDC spec allows that. + */ +#ifdef CONFIG_USB_ETH_SA1100 +#define CHIP "sa1100" +#define DRIVER_VERSION_NUM 0x0105 +#define EP0_MAXPACKET 8 +static const char EP_OUT_NAME [] = "ep1out-bulk"; +#define EP_OUT_NUM 1 +static const char EP_IN_NAME [] = "ep2in-bulk"; +#define EP_IN_NUM 2 +// EP_STATUS_NUM is undefined +/* doesn't support bus-powered operation */ +#define SELFPOWER USB_CONFIG_ATT_SELFPOWER +/* doesn't support remote wakeup? */ + +/* no hw optimizations to apply */ +#define hw_optimize(g) do {} while (0); +#endif + +/*-------------------------------------------------------------------------*/ + +#ifndef EP0_MAXPACKET +# error Configure some USB peripheral controller driver! +#endif + +/* power usage is config specific. + * hardware that supports remote wakeup defaults to disabling it. + */ + +#ifndef SELFPOWER +/* default: say we rely on bus power */ +#define SELFPOWER 0 +/* else: + * - SELFPOWER value must be USB_CONFIG_ATT_SELFPOWER + * - MAX_USB_POWER may be nonzero. + */ +#endif + +#ifndef MAX_USB_POWER +/* any hub supports this steady state bus power consumption */ +#define MAX_USB_POWER 100 /* mA */ +#endif + +#ifndef WAKEUP +/* default: this driver won't do remote wakeup */ +#define WAKEUP 0 +/* else value must be USB_CONFIG_ATT_WAKEUP */ +#endif + +/*-------------------------------------------------------------------------*/ + +#define xprintk(d,level,fmt,args...) \ + dev_printk(level , &(d)->gadget->dev , fmt , ## args) + +#ifdef DEBUG +#undef DEBUG +#define DEBUG(dev,fmt,args...) \ + xprintk(dev , KERN_DEBUG , fmt , ## args) +#else +#define DEBUG(dev,fmt,args...) \ + do { } while (0) +#endif /* DEBUG */ + +#ifdef VERBOSE +#define VDEBUG DEBUG +#else +#define VDEBUG(dev,fmt,args...) \ + do { } while (0) +#endif /* DEBUG */ + +#define ERROR(dev,fmt,args...) \ + xprintk(dev , KERN_ERR , fmt , ## args) +#define WARN(dev,fmt,args...) \ + xprintk(dev , KERN_WARNING , fmt , ## args) +#define INFO(dev,fmt,args...) \ + xprintk(dev , KERN_INFO , fmt , ## args) + +/*-------------------------------------------------------------------------*/ + +/* USB DRIVER HOOKUP (to the hardware driver, below us), mostly + * ep0 implementation: descriptors, config management, setup(). + * also optional class-specific notification interrupt transfer. + */ + +/* + * DESCRIPTORS ... most are static, but strings and (full) configuration + * descriptors are built on demand. Notice how most of the cdc descriptors + * add no value to simple (typical) configurations. + */ + +#define STRING_MANUFACTURER 1 +#define STRING_PRODUCT 2 +#define STRING_ETHADDR 3 +#define STRING_DATA 4 +#define STRING_CONTROL 5 + +#define USB_BUFSIZ 256 /* holds our biggest descriptor */ + +/* + * This device advertises one configuration. + */ +#define CONFIG_CDC_ETHER 3 + +static const struct usb_device_descriptor +device_desc = { + .bLength = sizeof device_desc, + .bDescriptorType = USB_DT_DEVICE, + + .bcdUSB = __constant_cpu_to_le16 (0x0200), + .bDeviceClass = USB_CLASS_COMM, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .bMaxPacketSize0 = EP0_MAXPACKET, + + .idVendor = __constant_cpu_to_le16 (DRIVER_VENDOR_NUM), + .idProduct = __constant_cpu_to_le16 (DRIVER_PRODUCT_NUM), + .bcdDevice = __constant_cpu_to_le16 (DRIVER_VERSION_NUM), + .iManufacturer = STRING_MANUFACTURER, + .iProduct = STRING_PRODUCT, + .bNumConfigurations = 1, +}; + +static const struct usb_config_descriptor +eth_config = { + .bLength = sizeof eth_config, + .bDescriptorType = USB_DT_CONFIG, + + /* compute wTotalLength on the fly */ + .bNumInterfaces = 2, + .bConfigurationValue = CONFIG_CDC_ETHER, + .iConfiguration = STRING_PRODUCT, + .bmAttributes = USB_CONFIG_ATT_ONE | SELFPOWER | WAKEUP, + .bMaxPower = (MAX_USB_POWER + 1) / 2, +}; + +/* master comm interface optionally has a status notification endpoint */ + +static const struct usb_interface_descriptor +control_intf = { + .bLength = sizeof control_intf, + .bDescriptorType = USB_DT_INTERFACE, + + .bInterfaceNumber = 0, +#ifdef EP_STATUS_NUM + .bNumEndpoints = 1, +#else + .bNumEndpoints = 0, +#endif + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = 6, /* ethernet control model */ + .bInterfaceProtocol = 0, + .iInterface = STRING_CONTROL, +}; + +/* "Header Functional Descriptor" from CDC spec 5.2.3.1 */ +struct header_desc { + u8 bLength; + u8 bDescriptorType; + u8 bDescriptorSubType; + + u16 bcdCDC; +} __attribute__ ((packed)); + +static const struct header_desc header_desc = { + .bLength = sizeof header_desc, + .bDescriptorType = 0x24, + .bDescriptorSubType = 0, + + .bcdCDC = __constant_cpu_to_le16 (0x0110), +}; + +/* "Union Functional Descriptor" from CDC spec 5.2.3.X */ +struct union_desc { + u8 bLength; + u8 bDescriptorType; + u8 bDescriptorSubType; + + u8 bMasterInterface0; + u8 bSlaveInterface0; + /* ... and there could be other slave interfaces */ +} __attribute__ ((packed)); + +static const struct union_desc union_desc = { + .bLength = sizeof union_desc, + .bDescriptorType = 0x24, + .bDescriptorSubType = 6, + + .bMasterInterface0 = 0, /* index of control interface */ + .bSlaveInterface0 = 1, /* index of DATA interface */ +}; + +/* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */ +struct ether_desc {